open-vault/builtin/logical/transit/backend_test.go

2271 lines
65 KiB
Go
Raw Normal View History

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
2015-04-16 00:08:12 +00:00
package transit
import (
"context"
Create CSR in Transit, sign with PKI (#17630) Execute with: $ go test -v -run=TestTransitPKICSR github.com/hashicorp/vault/builtin/logical/transit ... backend_test.go:1843: csr: -----BEGIN CERTIFICATE REQUEST----- MIICXjCCAUYCAQAwGTEXMBUGA1UEAxMOZGFkZ2FyY29ycC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD8GUy2Rut9ILPXH/Ef7lEaYijuBB9wogd hKD3uJyfK5PqBqM8166UsrP7Y+bWkwDrMke3aDxXRNybys33kIc8KfGwS3omNYd3 17KN1D4ZgQ+oW6xISa3ISOl4D7XeFtHeTP0U1plVXBd9kqTlo4YPlUF/kTfqmxDu 2a41BIS5HlORdLLG+jQ3shRgwHANONBhlaUnIqEeykdW8/iEBlqoYlMzty9W724R 2mKk0FzrVAZ/X5ZO992dAMrQDvc3Nofl+ddzbElBJLumrcDSwALFVge+ag1N48kE CCfxjizEykGdCrR+VELb8b33IgFf6EOVRnS5Qy8whmw943v5Oru5AgMBAAGgADAN BgkqhkiG9w0BAQsFAAOCAQEAdg9SwbrWszMmz60JWQPPfwW+XhzR0MdY82adK8P6 9xpWyJU+U649tAFQb+PCT1OcU7ETd59QcEV38VLndBPWhotTXl5oB5XAqg2bkKHV nLc0cGwyxBSs77LALc//m2f5v2otO9fLOmuM2RMfD02ZUliBmZUzeaUIJYEfT+cS M60uLKJvnNBu5xH1q0oG9P0uNkpEX+QGx6SwhR1/41pmygiUR+uwJxxuRGMvECoN dsHZtzi7ftEHBJ9tk94hd/RFnDsvWlHGyfRWhALNtbo6QjHxjBJIFKh+GHlI8Tnf 6YWvD0VIodE609+RlCrhFlGd+3NUSt0b/f0bgkMJLzLqEw== -----END CERTIFICATE REQUEST----- backend_test.go:1878: root: -----BEGIN CERTIFICATE----- MIIDHTCCAgWgAwIBAgIUIwCzCdrsgkcNOi5liRNHeH+n+tUwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MTIyMTQ1NzExWjAWMRQwEgYDVQQDEwtQS0kgUm9vdCBYMTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMdM65f5p3fLwQP1sezBRFqAxUZhOQwnnnp8mFXp 3fIF9pqLMzNvyd+bCUXv+aFalX4KY1iOoKVHJWwtpXMoKn40U+DZkapR9CsVQt5Q 9xzIcuPPuI+/oNwU4qB9mAuwG+U7KLosGnQOR3NI02A4dnl5I0z8Y/DJLz29GP/P 1zPYMBRBpkMz4F2Xr0w6tTXWDsmqZ9j7ukBDoizmnB2xfKzSjCVmQvXa71UlqbG9 td75LCgpiQh/50mHFHs6RKtqrlFUY5BtPPs+tHUf4nklieIzbAEwA8Fbq4d/Xpq1 HRoRvWj3nelX/h/IRlj/VKJssd1ZL+1kdzxKB4N6AFC1nusCAwEAAaNjMGEwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCniHbjHy/UG ShROBOiikqxCe+OkMB8GA1UdIwQYMBaAFCniHbjHy/UGShROBOiikqxCe+OkMA0G CSqGSIb3DQEBCwUAA4IBAQBSKnl154oyc1Rncm4sr/1f1QM5rCaw/lqgISfvki8m t6yyxQL+9lDpebFjBDTL5teRzuMYyqN4pRkIhpITDGmFXRpEOv14mcbASX7nPBEN bYXhOh1UC8a0CLzT2ll0ERFNnUEPRi0s0ONRm3lIZAV3Mzf4sOdwfRwmP33hBe/1 V9D7Lcx5N84EPrvGC/r8F/PsVKHyKFS46qB1MvhMppRG6fJ2cFmg5UGwdKdmxuvz FoT+RaTLkgcQgkDuYClNco5OVIM7Bd4JTNK3WbqvtGklOHslrz+ND0eMYM/LK+ZS zNM35nzK6QaN2M4IO4Wuy3y2yu8xllEfmssXwAtTi4wk -----END CERTIFICATE----- backend_test.go:1879: leaf: -----BEGIN CERTIFICATE----- MIIDDzCCAfegAwIBAgIUBGeUSi0p3ffndZqgvlBvMvn8qgMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MDIxMTUwNzEyWjAZMRcwFQYDVQQDEw5kYWRnYXJjb3JwLmNvbTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMPwZTLZG630gs9cf8R/uURpiKO4EH3CiB2E oPe4nJ8rk+oGozzXrpSys/tj5taTAOsyR7doPFdE3JvKzfeQhzwp8bBLeiY1h3fX so3UPhmBD6hbrEhJrchI6XgPtd4W0d5M/RTWmVVcF32SpOWjhg+VQX+RN+qbEO7Z rjUEhLkeU5F0ssb6NDeyFGDAcA040GGVpScioR7KR1bz+IQGWqhiUzO3L1bvbhHa YqTQXOtUBn9flk733Z0AytAO9zc2h+X513NsSUEku6atwNLAAsVWB75qDU3jyQQI J/GOLMTKQZ0KtH5UQtvxvfciAV/oQ5VGdLlDLzCGbD3je/k6u7kCAwEAAaNSMFAw DgYDVR0PAQH/BAQDAgOoMB0GA1UdDgQWBBSRCRR/62DjS1kjWHrVQ0Y58leUbDAf BgNVHSMEGDAWgBQp4h24x8v1BkoUTgToopKsQnvjpDANBgkqhkiG9w0BAQsFAAOC AQEAvWPLGqtC1SRy61Y17HtJ0giDUwpCZbOUkAwtdDAnKIhR1v4wrlY3sKUBLuhK xOJIWfVlCnPUt5uTnPaWyVyUfry6YNerish1k7ny/R1n58PjsPhUg8GJB9HHsME+ gQQ22z6D/87n0bEE8PaTzIU6+cVHoIBJ0rqzjZVkBs0cEjf+l40RPP1h+ZiTw27u CR2iXmHJ9TQ8ZBWygIhxB9JOMbk5jpH6w6wJqq8XK9zuC1hlYbXH1K5KvZJxAPlh CJkoq2KxaIwByTHjRdGjDogSibsyY+CxQUnktefXb6tYKvFTpUFsh1fjQRCwUrlD SExMRHhFJBHfyPD1w26N3IjRlg== -----END CERTIFICATE----- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-23 17:57:23 +00:00
"crypto"
cryptoRand "crypto/rand"
Create CSR in Transit, sign with PKI (#17630) Execute with: $ go test -v -run=TestTransitPKICSR github.com/hashicorp/vault/builtin/logical/transit ... backend_test.go:1843: csr: -----BEGIN CERTIFICATE REQUEST----- MIICXjCCAUYCAQAwGTEXMBUGA1UEAxMOZGFkZ2FyY29ycC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD8GUy2Rut9ILPXH/Ef7lEaYijuBB9wogd hKD3uJyfK5PqBqM8166UsrP7Y+bWkwDrMke3aDxXRNybys33kIc8KfGwS3omNYd3 17KN1D4ZgQ+oW6xISa3ISOl4D7XeFtHeTP0U1plVXBd9kqTlo4YPlUF/kTfqmxDu 2a41BIS5HlORdLLG+jQ3shRgwHANONBhlaUnIqEeykdW8/iEBlqoYlMzty9W724R 2mKk0FzrVAZ/X5ZO992dAMrQDvc3Nofl+ddzbElBJLumrcDSwALFVge+ag1N48kE CCfxjizEykGdCrR+VELb8b33IgFf6EOVRnS5Qy8whmw943v5Oru5AgMBAAGgADAN BgkqhkiG9w0BAQsFAAOCAQEAdg9SwbrWszMmz60JWQPPfwW+XhzR0MdY82adK8P6 9xpWyJU+U649tAFQb+PCT1OcU7ETd59QcEV38VLndBPWhotTXl5oB5XAqg2bkKHV nLc0cGwyxBSs77LALc//m2f5v2otO9fLOmuM2RMfD02ZUliBmZUzeaUIJYEfT+cS M60uLKJvnNBu5xH1q0oG9P0uNkpEX+QGx6SwhR1/41pmygiUR+uwJxxuRGMvECoN dsHZtzi7ftEHBJ9tk94hd/RFnDsvWlHGyfRWhALNtbo6QjHxjBJIFKh+GHlI8Tnf 6YWvD0VIodE609+RlCrhFlGd+3NUSt0b/f0bgkMJLzLqEw== -----END CERTIFICATE REQUEST----- backend_test.go:1878: root: -----BEGIN CERTIFICATE----- MIIDHTCCAgWgAwIBAgIUIwCzCdrsgkcNOi5liRNHeH+n+tUwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MTIyMTQ1NzExWjAWMRQwEgYDVQQDEwtQS0kgUm9vdCBYMTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMdM65f5p3fLwQP1sezBRFqAxUZhOQwnnnp8mFXp 3fIF9pqLMzNvyd+bCUXv+aFalX4KY1iOoKVHJWwtpXMoKn40U+DZkapR9CsVQt5Q 9xzIcuPPuI+/oNwU4qB9mAuwG+U7KLosGnQOR3NI02A4dnl5I0z8Y/DJLz29GP/P 1zPYMBRBpkMz4F2Xr0w6tTXWDsmqZ9j7ukBDoizmnB2xfKzSjCVmQvXa71UlqbG9 td75LCgpiQh/50mHFHs6RKtqrlFUY5BtPPs+tHUf4nklieIzbAEwA8Fbq4d/Xpq1 HRoRvWj3nelX/h/IRlj/VKJssd1ZL+1kdzxKB4N6AFC1nusCAwEAAaNjMGEwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCniHbjHy/UG ShROBOiikqxCe+OkMB8GA1UdIwQYMBaAFCniHbjHy/UGShROBOiikqxCe+OkMA0G CSqGSIb3DQEBCwUAA4IBAQBSKnl154oyc1Rncm4sr/1f1QM5rCaw/lqgISfvki8m t6yyxQL+9lDpebFjBDTL5teRzuMYyqN4pRkIhpITDGmFXRpEOv14mcbASX7nPBEN bYXhOh1UC8a0CLzT2ll0ERFNnUEPRi0s0ONRm3lIZAV3Mzf4sOdwfRwmP33hBe/1 V9D7Lcx5N84EPrvGC/r8F/PsVKHyKFS46qB1MvhMppRG6fJ2cFmg5UGwdKdmxuvz FoT+RaTLkgcQgkDuYClNco5OVIM7Bd4JTNK3WbqvtGklOHslrz+ND0eMYM/LK+ZS zNM35nzK6QaN2M4IO4Wuy3y2yu8xllEfmssXwAtTi4wk -----END CERTIFICATE----- backend_test.go:1879: leaf: -----BEGIN CERTIFICATE----- MIIDDzCCAfegAwIBAgIUBGeUSi0p3ffndZqgvlBvMvn8qgMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MDIxMTUwNzEyWjAZMRcwFQYDVQQDEw5kYWRnYXJjb3JwLmNvbTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMPwZTLZG630gs9cf8R/uURpiKO4EH3CiB2E oPe4nJ8rk+oGozzXrpSys/tj5taTAOsyR7doPFdE3JvKzfeQhzwp8bBLeiY1h3fX so3UPhmBD6hbrEhJrchI6XgPtd4W0d5M/RTWmVVcF32SpOWjhg+VQX+RN+qbEO7Z rjUEhLkeU5F0ssb6NDeyFGDAcA040GGVpScioR7KR1bz+IQGWqhiUzO3L1bvbhHa YqTQXOtUBn9flk733Z0AytAO9zc2h+X513NsSUEku6atwNLAAsVWB75qDU3jyQQI J/GOLMTKQZ0KtH5UQtvxvfciAV/oQ5VGdLlDLzCGbD3je/k6u7kCAwEAAaNSMFAw DgYDVR0PAQH/BAQDAgOoMB0GA1UdDgQWBBSRCRR/62DjS1kjWHrVQ0Y58leUbDAf BgNVHSMEGDAWgBQp4h24x8v1BkoUTgToopKsQnvjpDANBgkqhkiG9w0BAQsFAAOC AQEAvWPLGqtC1SRy61Y17HtJ0giDUwpCZbOUkAwtdDAnKIhR1v4wrlY3sKUBLuhK xOJIWfVlCnPUt5uTnPaWyVyUfry6YNerish1k7ny/R1n58PjsPhUg8GJB9HHsME+ gQQ22z6D/87n0bEE8PaTzIU6+cVHoIBJ0rqzjZVkBs0cEjf+l40RPP1h+ZiTw27u CR2iXmHJ9TQ8ZBWygIhxB9JOMbk5jpH6w6wJqq8XK9zuC1hlYbXH1K5KvZJxAPlh CJkoq2KxaIwByTHjRdGjDogSibsyY+CxQUnktefXb6tYKvFTpUFsh1fjQRCwUrlD SExMRHhFJBHfyPD1w26N3IjRlg== -----END CERTIFICATE----- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-23 17:57:23 +00:00
"crypto/x509"
2015-04-16 00:08:12 +00:00
"encoding/base64"
Create CSR in Transit, sign with PKI (#17630) Execute with: $ go test -v -run=TestTransitPKICSR github.com/hashicorp/vault/builtin/logical/transit ... backend_test.go:1843: csr: -----BEGIN CERTIFICATE REQUEST----- MIICXjCCAUYCAQAwGTEXMBUGA1UEAxMOZGFkZ2FyY29ycC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD8GUy2Rut9ILPXH/Ef7lEaYijuBB9wogd hKD3uJyfK5PqBqM8166UsrP7Y+bWkwDrMke3aDxXRNybys33kIc8KfGwS3omNYd3 17KN1D4ZgQ+oW6xISa3ISOl4D7XeFtHeTP0U1plVXBd9kqTlo4YPlUF/kTfqmxDu 2a41BIS5HlORdLLG+jQ3shRgwHANONBhlaUnIqEeykdW8/iEBlqoYlMzty9W724R 2mKk0FzrVAZ/X5ZO992dAMrQDvc3Nofl+ddzbElBJLumrcDSwALFVge+ag1N48kE CCfxjizEykGdCrR+VELb8b33IgFf6EOVRnS5Qy8whmw943v5Oru5AgMBAAGgADAN BgkqhkiG9w0BAQsFAAOCAQEAdg9SwbrWszMmz60JWQPPfwW+XhzR0MdY82adK8P6 9xpWyJU+U649tAFQb+PCT1OcU7ETd59QcEV38VLndBPWhotTXl5oB5XAqg2bkKHV nLc0cGwyxBSs77LALc//m2f5v2otO9fLOmuM2RMfD02ZUliBmZUzeaUIJYEfT+cS M60uLKJvnNBu5xH1q0oG9P0uNkpEX+QGx6SwhR1/41pmygiUR+uwJxxuRGMvECoN dsHZtzi7ftEHBJ9tk94hd/RFnDsvWlHGyfRWhALNtbo6QjHxjBJIFKh+GHlI8Tnf 6YWvD0VIodE609+RlCrhFlGd+3NUSt0b/f0bgkMJLzLqEw== -----END CERTIFICATE REQUEST----- backend_test.go:1878: root: -----BEGIN CERTIFICATE----- MIIDHTCCAgWgAwIBAgIUIwCzCdrsgkcNOi5liRNHeH+n+tUwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MTIyMTQ1NzExWjAWMRQwEgYDVQQDEwtQS0kgUm9vdCBYMTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMdM65f5p3fLwQP1sezBRFqAxUZhOQwnnnp8mFXp 3fIF9pqLMzNvyd+bCUXv+aFalX4KY1iOoKVHJWwtpXMoKn40U+DZkapR9CsVQt5Q 9xzIcuPPuI+/oNwU4qB9mAuwG+U7KLosGnQOR3NI02A4dnl5I0z8Y/DJLz29GP/P 1zPYMBRBpkMz4F2Xr0w6tTXWDsmqZ9j7ukBDoizmnB2xfKzSjCVmQvXa71UlqbG9 td75LCgpiQh/50mHFHs6RKtqrlFUY5BtPPs+tHUf4nklieIzbAEwA8Fbq4d/Xpq1 HRoRvWj3nelX/h/IRlj/VKJssd1ZL+1kdzxKB4N6AFC1nusCAwEAAaNjMGEwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCniHbjHy/UG ShROBOiikqxCe+OkMB8GA1UdIwQYMBaAFCniHbjHy/UGShROBOiikqxCe+OkMA0G CSqGSIb3DQEBCwUAA4IBAQBSKnl154oyc1Rncm4sr/1f1QM5rCaw/lqgISfvki8m t6yyxQL+9lDpebFjBDTL5teRzuMYyqN4pRkIhpITDGmFXRpEOv14mcbASX7nPBEN bYXhOh1UC8a0CLzT2ll0ERFNnUEPRi0s0ONRm3lIZAV3Mzf4sOdwfRwmP33hBe/1 V9D7Lcx5N84EPrvGC/r8F/PsVKHyKFS46qB1MvhMppRG6fJ2cFmg5UGwdKdmxuvz FoT+RaTLkgcQgkDuYClNco5OVIM7Bd4JTNK3WbqvtGklOHslrz+ND0eMYM/LK+ZS zNM35nzK6QaN2M4IO4Wuy3y2yu8xllEfmssXwAtTi4wk -----END CERTIFICATE----- backend_test.go:1879: leaf: -----BEGIN CERTIFICATE----- MIIDDzCCAfegAwIBAgIUBGeUSi0p3ffndZqgvlBvMvn8qgMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MDIxMTUwNzEyWjAZMRcwFQYDVQQDEw5kYWRnYXJjb3JwLmNvbTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMPwZTLZG630gs9cf8R/uURpiKO4EH3CiB2E oPe4nJ8rk+oGozzXrpSys/tj5taTAOsyR7doPFdE3JvKzfeQhzwp8bBLeiY1h3fX so3UPhmBD6hbrEhJrchI6XgPtd4W0d5M/RTWmVVcF32SpOWjhg+VQX+RN+qbEO7Z rjUEhLkeU5F0ssb6NDeyFGDAcA040GGVpScioR7KR1bz+IQGWqhiUzO3L1bvbhHa YqTQXOtUBn9flk733Z0AytAO9zc2h+X513NsSUEku6atwNLAAsVWB75qDU3jyQQI J/GOLMTKQZ0KtH5UQtvxvfciAV/oQ5VGdLlDLzCGbD3je/k6u7kCAwEAAaNSMFAw DgYDVR0PAQH/BAQDAgOoMB0GA1UdDgQWBBSRCRR/62DjS1kjWHrVQ0Y58leUbDAf BgNVHSMEGDAWgBQp4h24x8v1BkoUTgToopKsQnvjpDANBgkqhkiG9w0BAQsFAAOC AQEAvWPLGqtC1SRy61Y17HtJ0giDUwpCZbOUkAwtdDAnKIhR1v4wrlY3sKUBLuhK xOJIWfVlCnPUt5uTnPaWyVyUfry6YNerish1k7ny/R1n58PjsPhUg8GJB9HHsME+ gQQ22z6D/87n0bEE8PaTzIU6+cVHoIBJ0rqzjZVkBs0cEjf+l40RPP1h+ZiTw27u CR2iXmHJ9TQ8ZBWygIhxB9JOMbk5jpH6w6wJqq8XK9zuC1hlYbXH1K5KvZJxAPlh CJkoq2KxaIwByTHjRdGjDogSibsyY+CxQUnktefXb6tYKvFTpUFsh1fjQRCwUrlD SExMRHhFJBHfyPD1w26N3IjRlg== -----END CERTIFICATE----- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-23 17:57:23 +00:00
"encoding/pem"
2015-04-16 00:08:12 +00:00
"fmt"
Create CSR in Transit, sign with PKI (#17630) Execute with: $ go test -v -run=TestTransitPKICSR github.com/hashicorp/vault/builtin/logical/transit ... backend_test.go:1843: csr: -----BEGIN CERTIFICATE REQUEST----- MIICXjCCAUYCAQAwGTEXMBUGA1UEAxMOZGFkZ2FyY29ycC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD8GUy2Rut9ILPXH/Ef7lEaYijuBB9wogd hKD3uJyfK5PqBqM8166UsrP7Y+bWkwDrMke3aDxXRNybys33kIc8KfGwS3omNYd3 17KN1D4ZgQ+oW6xISa3ISOl4D7XeFtHeTP0U1plVXBd9kqTlo4YPlUF/kTfqmxDu 2a41BIS5HlORdLLG+jQ3shRgwHANONBhlaUnIqEeykdW8/iEBlqoYlMzty9W724R 2mKk0FzrVAZ/X5ZO992dAMrQDvc3Nofl+ddzbElBJLumrcDSwALFVge+ag1N48kE CCfxjizEykGdCrR+VELb8b33IgFf6EOVRnS5Qy8whmw943v5Oru5AgMBAAGgADAN BgkqhkiG9w0BAQsFAAOCAQEAdg9SwbrWszMmz60JWQPPfwW+XhzR0MdY82adK8P6 9xpWyJU+U649tAFQb+PCT1OcU7ETd59QcEV38VLndBPWhotTXl5oB5XAqg2bkKHV nLc0cGwyxBSs77LALc//m2f5v2otO9fLOmuM2RMfD02ZUliBmZUzeaUIJYEfT+cS M60uLKJvnNBu5xH1q0oG9P0uNkpEX+QGx6SwhR1/41pmygiUR+uwJxxuRGMvECoN dsHZtzi7ftEHBJ9tk94hd/RFnDsvWlHGyfRWhALNtbo6QjHxjBJIFKh+GHlI8Tnf 6YWvD0VIodE609+RlCrhFlGd+3NUSt0b/f0bgkMJLzLqEw== -----END CERTIFICATE REQUEST----- backend_test.go:1878: root: -----BEGIN CERTIFICATE----- MIIDHTCCAgWgAwIBAgIUIwCzCdrsgkcNOi5liRNHeH+n+tUwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MTIyMTQ1NzExWjAWMRQwEgYDVQQDEwtQS0kgUm9vdCBYMTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMdM65f5p3fLwQP1sezBRFqAxUZhOQwnnnp8mFXp 3fIF9pqLMzNvyd+bCUXv+aFalX4KY1iOoKVHJWwtpXMoKn40U+DZkapR9CsVQt5Q 9xzIcuPPuI+/oNwU4qB9mAuwG+U7KLosGnQOR3NI02A4dnl5I0z8Y/DJLz29GP/P 1zPYMBRBpkMz4F2Xr0w6tTXWDsmqZ9j7ukBDoizmnB2xfKzSjCVmQvXa71UlqbG9 td75LCgpiQh/50mHFHs6RKtqrlFUY5BtPPs+tHUf4nklieIzbAEwA8Fbq4d/Xpq1 HRoRvWj3nelX/h/IRlj/VKJssd1ZL+1kdzxKB4N6AFC1nusCAwEAAaNjMGEwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCniHbjHy/UG ShROBOiikqxCe+OkMB8GA1UdIwQYMBaAFCniHbjHy/UGShROBOiikqxCe+OkMA0G CSqGSIb3DQEBCwUAA4IBAQBSKnl154oyc1Rncm4sr/1f1QM5rCaw/lqgISfvki8m t6yyxQL+9lDpebFjBDTL5teRzuMYyqN4pRkIhpITDGmFXRpEOv14mcbASX7nPBEN bYXhOh1UC8a0CLzT2ll0ERFNnUEPRi0s0ONRm3lIZAV3Mzf4sOdwfRwmP33hBe/1 V9D7Lcx5N84EPrvGC/r8F/PsVKHyKFS46qB1MvhMppRG6fJ2cFmg5UGwdKdmxuvz FoT+RaTLkgcQgkDuYClNco5OVIM7Bd4JTNK3WbqvtGklOHslrz+ND0eMYM/LK+ZS zNM35nzK6QaN2M4IO4Wuy3y2yu8xllEfmssXwAtTi4wk -----END CERTIFICATE----- backend_test.go:1879: leaf: -----BEGIN CERTIFICATE----- MIIDDzCCAfegAwIBAgIUBGeUSi0p3ffndZqgvlBvMvn8qgMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MDIxMTUwNzEyWjAZMRcwFQYDVQQDEw5kYWRnYXJjb3JwLmNvbTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMPwZTLZG630gs9cf8R/uURpiKO4EH3CiB2E oPe4nJ8rk+oGozzXrpSys/tj5taTAOsyR7doPFdE3JvKzfeQhzwp8bBLeiY1h3fX so3UPhmBD6hbrEhJrchI6XgPtd4W0d5M/RTWmVVcF32SpOWjhg+VQX+RN+qbEO7Z rjUEhLkeU5F0ssb6NDeyFGDAcA040GGVpScioR7KR1bz+IQGWqhiUzO3L1bvbhHa YqTQXOtUBn9flk733Z0AytAO9zc2h+X513NsSUEku6atwNLAAsVWB75qDU3jyQQI J/GOLMTKQZ0KtH5UQtvxvfciAV/oQ5VGdLlDLzCGbD3je/k6u7kCAwEAAaNSMFAw DgYDVR0PAQH/BAQDAgOoMB0GA1UdDgQWBBSRCRR/62DjS1kjWHrVQ0Y58leUbDAf BgNVHSMEGDAWgBQp4h24x8v1BkoUTgToopKsQnvjpDANBgkqhkiG9w0BAQsFAAOC AQEAvWPLGqtC1SRy61Y17HtJ0giDUwpCZbOUkAwtdDAnKIhR1v4wrlY3sKUBLuhK xOJIWfVlCnPUt5uTnPaWyVyUfry6YNerish1k7ny/R1n58PjsPhUg8GJB9HHsME+ gQQ22z6D/87n0bEE8PaTzIU6+cVHoIBJ0rqzjZVkBs0cEjf+l40RPP1h+ZiTw27u CR2iXmHJ9TQ8ZBWygIhxB9JOMbk5jpH6w6wJqq8XK9zuC1hlYbXH1K5KvZJxAPlh CJkoq2KxaIwByTHjRdGjDogSibsyY+CxQUnktefXb6tYKvFTpUFsh1fjQRCwUrlD SExMRHhFJBHfyPD1w26N3IjRlg== -----END CERTIFICATE----- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-23 17:57:23 +00:00
"io"
2016-02-03 22:25:48 +00:00
"math/rand"
"os"
2018-06-05 22:51:35 +00:00
"path"
"reflect"
"strconv"
"strings"
2016-02-03 22:25:48 +00:00
"sync"
2015-04-16 00:08:12 +00:00
"testing"
2016-02-03 22:25:48 +00:00
"time"
2015-04-16 00:08:12 +00:00
Create CSR in Transit, sign with PKI (#17630) Execute with: $ go test -v -run=TestTransitPKICSR github.com/hashicorp/vault/builtin/logical/transit ... backend_test.go:1843: csr: -----BEGIN CERTIFICATE REQUEST----- MIICXjCCAUYCAQAwGTEXMBUGA1UEAxMOZGFkZ2FyY29ycC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD8GUy2Rut9ILPXH/Ef7lEaYijuBB9wogd hKD3uJyfK5PqBqM8166UsrP7Y+bWkwDrMke3aDxXRNybys33kIc8KfGwS3omNYd3 17KN1D4ZgQ+oW6xISa3ISOl4D7XeFtHeTP0U1plVXBd9kqTlo4YPlUF/kTfqmxDu 2a41BIS5HlORdLLG+jQ3shRgwHANONBhlaUnIqEeykdW8/iEBlqoYlMzty9W724R 2mKk0FzrVAZ/X5ZO992dAMrQDvc3Nofl+ddzbElBJLumrcDSwALFVge+ag1N48kE CCfxjizEykGdCrR+VELb8b33IgFf6EOVRnS5Qy8whmw943v5Oru5AgMBAAGgADAN BgkqhkiG9w0BAQsFAAOCAQEAdg9SwbrWszMmz60JWQPPfwW+XhzR0MdY82adK8P6 9xpWyJU+U649tAFQb+PCT1OcU7ETd59QcEV38VLndBPWhotTXl5oB5XAqg2bkKHV nLc0cGwyxBSs77LALc//m2f5v2otO9fLOmuM2RMfD02ZUliBmZUzeaUIJYEfT+cS M60uLKJvnNBu5xH1q0oG9P0uNkpEX+QGx6SwhR1/41pmygiUR+uwJxxuRGMvECoN dsHZtzi7ftEHBJ9tk94hd/RFnDsvWlHGyfRWhALNtbo6QjHxjBJIFKh+GHlI8Tnf 6YWvD0VIodE609+RlCrhFlGd+3NUSt0b/f0bgkMJLzLqEw== -----END CERTIFICATE REQUEST----- backend_test.go:1878: root: -----BEGIN CERTIFICATE----- MIIDHTCCAgWgAwIBAgIUIwCzCdrsgkcNOi5liRNHeH+n+tUwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MTIyMTQ1NzExWjAWMRQwEgYDVQQDEwtQS0kgUm9vdCBYMTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMdM65f5p3fLwQP1sezBRFqAxUZhOQwnnnp8mFXp 3fIF9pqLMzNvyd+bCUXv+aFalX4KY1iOoKVHJWwtpXMoKn40U+DZkapR9CsVQt5Q 9xzIcuPPuI+/oNwU4qB9mAuwG+U7KLosGnQOR3NI02A4dnl5I0z8Y/DJLz29GP/P 1zPYMBRBpkMz4F2Xr0w6tTXWDsmqZ9j7ukBDoizmnB2xfKzSjCVmQvXa71UlqbG9 td75LCgpiQh/50mHFHs6RKtqrlFUY5BtPPs+tHUf4nklieIzbAEwA8Fbq4d/Xpq1 HRoRvWj3nelX/h/IRlj/VKJssd1ZL+1kdzxKB4N6AFC1nusCAwEAAaNjMGEwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCniHbjHy/UG ShROBOiikqxCe+OkMB8GA1UdIwQYMBaAFCniHbjHy/UGShROBOiikqxCe+OkMA0G CSqGSIb3DQEBCwUAA4IBAQBSKnl154oyc1Rncm4sr/1f1QM5rCaw/lqgISfvki8m t6yyxQL+9lDpebFjBDTL5teRzuMYyqN4pRkIhpITDGmFXRpEOv14mcbASX7nPBEN bYXhOh1UC8a0CLzT2ll0ERFNnUEPRi0s0ONRm3lIZAV3Mzf4sOdwfRwmP33hBe/1 V9D7Lcx5N84EPrvGC/r8F/PsVKHyKFS46qB1MvhMppRG6fJ2cFmg5UGwdKdmxuvz FoT+RaTLkgcQgkDuYClNco5OVIM7Bd4JTNK3WbqvtGklOHslrz+ND0eMYM/LK+ZS zNM35nzK6QaN2M4IO4Wuy3y2yu8xllEfmssXwAtTi4wk -----END CERTIFICATE----- backend_test.go:1879: leaf: -----BEGIN CERTIFICATE----- MIIDDzCCAfegAwIBAgIUBGeUSi0p3ffndZqgvlBvMvn8qgMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MDIxMTUwNzEyWjAZMRcwFQYDVQQDEw5kYWRnYXJjb3JwLmNvbTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMPwZTLZG630gs9cf8R/uURpiKO4EH3CiB2E oPe4nJ8rk+oGozzXrpSys/tj5taTAOsyR7doPFdE3JvKzfeQhzwp8bBLeiY1h3fX so3UPhmBD6hbrEhJrchI6XgPtd4W0d5M/RTWmVVcF32SpOWjhg+VQX+RN+qbEO7Z rjUEhLkeU5F0ssb6NDeyFGDAcA040GGVpScioR7KR1bz+IQGWqhiUzO3L1bvbhHa YqTQXOtUBn9flk733Z0AytAO9zc2h+X513NsSUEku6atwNLAAsVWB75qDU3jyQQI J/GOLMTKQZ0KtH5UQtvxvfciAV/oQ5VGdLlDLzCGbD3je/k6u7kCAwEAAaNSMFAw DgYDVR0PAQH/BAQDAgOoMB0GA1UdDgQWBBSRCRR/62DjS1kjWHrVQ0Y58leUbDAf BgNVHSMEGDAWgBQp4h24x8v1BkoUTgToopKsQnvjpDANBgkqhkiG9w0BAQsFAAOC AQEAvWPLGqtC1SRy61Y17HtJ0giDUwpCZbOUkAwtdDAnKIhR1v4wrlY3sKUBLuhK xOJIWfVlCnPUt5uTnPaWyVyUfry6YNerish1k7ny/R1n58PjsPhUg8GJB9HHsME+ gQQ22z6D/87n0bEE8PaTzIU6+cVHoIBJ0rqzjZVkBs0cEjf+l40RPP1h+ZiTw27u CR2iXmHJ9TQ8ZBWygIhxB9JOMbk5jpH6w6wJqq8XK9zuC1hlYbXH1K5KvZJxAPlh CJkoq2KxaIwByTHjRdGjDogSibsyY+CxQUnktefXb6tYKvFTpUFsh1fjQRCwUrlD SExMRHhFJBHfyPD1w26N3IjRlg== -----END CERTIFICATE----- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-23 17:57:23 +00:00
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/builtin/logical/pki"
logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical"
Create CSR in Transit, sign with PKI (#17630) Execute with: $ go test -v -run=TestTransitPKICSR github.com/hashicorp/vault/builtin/logical/transit ... backend_test.go:1843: csr: -----BEGIN CERTIFICATE REQUEST----- MIICXjCCAUYCAQAwGTEXMBUGA1UEAxMOZGFkZ2FyY29ycC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD8GUy2Rut9ILPXH/Ef7lEaYijuBB9wogd hKD3uJyfK5PqBqM8166UsrP7Y+bWkwDrMke3aDxXRNybys33kIc8KfGwS3omNYd3 17KN1D4ZgQ+oW6xISa3ISOl4D7XeFtHeTP0U1plVXBd9kqTlo4YPlUF/kTfqmxDu 2a41BIS5HlORdLLG+jQ3shRgwHANONBhlaUnIqEeykdW8/iEBlqoYlMzty9W724R 2mKk0FzrVAZ/X5ZO992dAMrQDvc3Nofl+ddzbElBJLumrcDSwALFVge+ag1N48kE CCfxjizEykGdCrR+VELb8b33IgFf6EOVRnS5Qy8whmw943v5Oru5AgMBAAGgADAN BgkqhkiG9w0BAQsFAAOCAQEAdg9SwbrWszMmz60JWQPPfwW+XhzR0MdY82adK8P6 9xpWyJU+U649tAFQb+PCT1OcU7ETd59QcEV38VLndBPWhotTXl5oB5XAqg2bkKHV nLc0cGwyxBSs77LALc//m2f5v2otO9fLOmuM2RMfD02ZUliBmZUzeaUIJYEfT+cS M60uLKJvnNBu5xH1q0oG9P0uNkpEX+QGx6SwhR1/41pmygiUR+uwJxxuRGMvECoN dsHZtzi7ftEHBJ9tk94hd/RFnDsvWlHGyfRWhALNtbo6QjHxjBJIFKh+GHlI8Tnf 6YWvD0VIodE609+RlCrhFlGd+3NUSt0b/f0bgkMJLzLqEw== -----END CERTIFICATE REQUEST----- backend_test.go:1878: root: -----BEGIN CERTIFICATE----- MIIDHTCCAgWgAwIBAgIUIwCzCdrsgkcNOi5liRNHeH+n+tUwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MTIyMTQ1NzExWjAWMRQwEgYDVQQDEwtQS0kgUm9vdCBYMTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMdM65f5p3fLwQP1sezBRFqAxUZhOQwnnnp8mFXp 3fIF9pqLMzNvyd+bCUXv+aFalX4KY1iOoKVHJWwtpXMoKn40U+DZkapR9CsVQt5Q 9xzIcuPPuI+/oNwU4qB9mAuwG+U7KLosGnQOR3NI02A4dnl5I0z8Y/DJLz29GP/P 1zPYMBRBpkMz4F2Xr0w6tTXWDsmqZ9j7ukBDoizmnB2xfKzSjCVmQvXa71UlqbG9 td75LCgpiQh/50mHFHs6RKtqrlFUY5BtPPs+tHUf4nklieIzbAEwA8Fbq4d/Xpq1 HRoRvWj3nelX/h/IRlj/VKJssd1ZL+1kdzxKB4N6AFC1nusCAwEAAaNjMGEwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCniHbjHy/UG ShROBOiikqxCe+OkMB8GA1UdIwQYMBaAFCniHbjHy/UGShROBOiikqxCe+OkMA0G CSqGSIb3DQEBCwUAA4IBAQBSKnl154oyc1Rncm4sr/1f1QM5rCaw/lqgISfvki8m t6yyxQL+9lDpebFjBDTL5teRzuMYyqN4pRkIhpITDGmFXRpEOv14mcbASX7nPBEN bYXhOh1UC8a0CLzT2ll0ERFNnUEPRi0s0ONRm3lIZAV3Mzf4sOdwfRwmP33hBe/1 V9D7Lcx5N84EPrvGC/r8F/PsVKHyKFS46qB1MvhMppRG6fJ2cFmg5UGwdKdmxuvz FoT+RaTLkgcQgkDuYClNco5OVIM7Bd4JTNK3WbqvtGklOHslrz+ND0eMYM/LK+ZS zNM35nzK6QaN2M4IO4Wuy3y2yu8xllEfmssXwAtTi4wk -----END CERTIFICATE----- backend_test.go:1879: leaf: -----BEGIN CERTIFICATE----- MIIDDzCCAfegAwIBAgIUBGeUSi0p3ffndZqgvlBvMvn8qgMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MDIxMTUwNzEyWjAZMRcwFQYDVQQDEw5kYWRnYXJjb3JwLmNvbTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMPwZTLZG630gs9cf8R/uURpiKO4EH3CiB2E oPe4nJ8rk+oGozzXrpSys/tj5taTAOsyR7doPFdE3JvKzfeQhzwp8bBLeiY1h3fX so3UPhmBD6hbrEhJrchI6XgPtd4W0d5M/RTWmVVcF32SpOWjhg+VQX+RN+qbEO7Z rjUEhLkeU5F0ssb6NDeyFGDAcA040GGVpScioR7KR1bz+IQGWqhiUzO3L1bvbhHa YqTQXOtUBn9flk733Z0AytAO9zc2h+X513NsSUEku6atwNLAAsVWB75qDU3jyQQI J/GOLMTKQZ0KtH5UQtvxvfciAV/oQ5VGdLlDLzCGbD3je/k6u7kCAwEAAaNSMFAw DgYDVR0PAQH/BAQDAgOoMB0GA1UdDgQWBBSRCRR/62DjS1kjWHrVQ0Y58leUbDAf BgNVHSMEGDAWgBQp4h24x8v1BkoUTgToopKsQnvjpDANBgkqhkiG9w0BAQsFAAOC AQEAvWPLGqtC1SRy61Y17HtJ0giDUwpCZbOUkAwtdDAnKIhR1v4wrlY3sKUBLuhK xOJIWfVlCnPUt5uTnPaWyVyUfry6YNerish1k7ny/R1n58PjsPhUg8GJB9HHsME+ gQQ22z6D/87n0bEE8PaTzIU6+cVHoIBJ0rqzjZVkBs0cEjf+l40RPP1h+ZiTw27u CR2iXmHJ9TQ8ZBWygIhxB9JOMbk5jpH6w6wJqq8XK9zuC1hlYbXH1K5KvZJxAPlh CJkoq2KxaIwByTHjRdGjDogSibsyY+CxQUnktefXb6tYKvFTpUFsh1fjQRCwUrlD SExMRHhFJBHfyPD1w26N3IjRlg== -----END CERTIFICATE----- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-23 17:57:23 +00:00
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/keysutil"
"github.com/hashicorp/vault/sdk/logical"
Create CSR in Transit, sign with PKI (#17630) Execute with: $ go test -v -run=TestTransitPKICSR github.com/hashicorp/vault/builtin/logical/transit ... backend_test.go:1843: csr: -----BEGIN CERTIFICATE REQUEST----- MIICXjCCAUYCAQAwGTEXMBUGA1UEAxMOZGFkZ2FyY29ycC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD8GUy2Rut9ILPXH/Ef7lEaYijuBB9wogd hKD3uJyfK5PqBqM8166UsrP7Y+bWkwDrMke3aDxXRNybys33kIc8KfGwS3omNYd3 17KN1D4ZgQ+oW6xISa3ISOl4D7XeFtHeTP0U1plVXBd9kqTlo4YPlUF/kTfqmxDu 2a41BIS5HlORdLLG+jQ3shRgwHANONBhlaUnIqEeykdW8/iEBlqoYlMzty9W724R 2mKk0FzrVAZ/X5ZO992dAMrQDvc3Nofl+ddzbElBJLumrcDSwALFVge+ag1N48kE CCfxjizEykGdCrR+VELb8b33IgFf6EOVRnS5Qy8whmw943v5Oru5AgMBAAGgADAN BgkqhkiG9w0BAQsFAAOCAQEAdg9SwbrWszMmz60JWQPPfwW+XhzR0MdY82adK8P6 9xpWyJU+U649tAFQb+PCT1OcU7ETd59QcEV38VLndBPWhotTXl5oB5XAqg2bkKHV nLc0cGwyxBSs77LALc//m2f5v2otO9fLOmuM2RMfD02ZUliBmZUzeaUIJYEfT+cS M60uLKJvnNBu5xH1q0oG9P0uNkpEX+QGx6SwhR1/41pmygiUR+uwJxxuRGMvECoN dsHZtzi7ftEHBJ9tk94hd/RFnDsvWlHGyfRWhALNtbo6QjHxjBJIFKh+GHlI8Tnf 6YWvD0VIodE609+RlCrhFlGd+3NUSt0b/f0bgkMJLzLqEw== -----END CERTIFICATE REQUEST----- backend_test.go:1878: root: -----BEGIN CERTIFICATE----- MIIDHTCCAgWgAwIBAgIUIwCzCdrsgkcNOi5liRNHeH+n+tUwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MTIyMTQ1NzExWjAWMRQwEgYDVQQDEwtQS0kgUm9vdCBYMTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMdM65f5p3fLwQP1sezBRFqAxUZhOQwnnnp8mFXp 3fIF9pqLMzNvyd+bCUXv+aFalX4KY1iOoKVHJWwtpXMoKn40U+DZkapR9CsVQt5Q 9xzIcuPPuI+/oNwU4qB9mAuwG+U7KLosGnQOR3NI02A4dnl5I0z8Y/DJLz29GP/P 1zPYMBRBpkMz4F2Xr0w6tTXWDsmqZ9j7ukBDoizmnB2xfKzSjCVmQvXa71UlqbG9 td75LCgpiQh/50mHFHs6RKtqrlFUY5BtPPs+tHUf4nklieIzbAEwA8Fbq4d/Xpq1 HRoRvWj3nelX/h/IRlj/VKJssd1ZL+1kdzxKB4N6AFC1nusCAwEAAaNjMGEwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCniHbjHy/UG ShROBOiikqxCe+OkMB8GA1UdIwQYMBaAFCniHbjHy/UGShROBOiikqxCe+OkMA0G CSqGSIb3DQEBCwUAA4IBAQBSKnl154oyc1Rncm4sr/1f1QM5rCaw/lqgISfvki8m t6yyxQL+9lDpebFjBDTL5teRzuMYyqN4pRkIhpITDGmFXRpEOv14mcbASX7nPBEN bYXhOh1UC8a0CLzT2ll0ERFNnUEPRi0s0ONRm3lIZAV3Mzf4sOdwfRwmP33hBe/1 V9D7Lcx5N84EPrvGC/r8F/PsVKHyKFS46qB1MvhMppRG6fJ2cFmg5UGwdKdmxuvz FoT+RaTLkgcQgkDuYClNco5OVIM7Bd4JTNK3WbqvtGklOHslrz+ND0eMYM/LK+ZS zNM35nzK6QaN2M4IO4Wuy3y2yu8xllEfmssXwAtTi4wk -----END CERTIFICATE----- backend_test.go:1879: leaf: -----BEGIN CERTIFICATE----- MIIDDzCCAfegAwIBAgIUBGeUSi0p3ffndZqgvlBvMvn8qgMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MDIxMTUwNzEyWjAZMRcwFQYDVQQDEw5kYWRnYXJjb3JwLmNvbTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMPwZTLZG630gs9cf8R/uURpiKO4EH3CiB2E oPe4nJ8rk+oGozzXrpSys/tj5taTAOsyR7doPFdE3JvKzfeQhzwp8bBLeiY1h3fX so3UPhmBD6hbrEhJrchI6XgPtd4W0d5M/RTWmVVcF32SpOWjhg+VQX+RN+qbEO7Z rjUEhLkeU5F0ssb6NDeyFGDAcA040GGVpScioR7KR1bz+IQGWqhiUzO3L1bvbhHa YqTQXOtUBn9flk733Z0AytAO9zc2h+X513NsSUEku6atwNLAAsVWB75qDU3jyQQI J/GOLMTKQZ0KtH5UQtvxvfciAV/oQ5VGdLlDLzCGbD3je/k6u7kCAwEAAaNSMFAw DgYDVR0PAQH/BAQDAgOoMB0GA1UdDgQWBBSRCRR/62DjS1kjWHrVQ0Y58leUbDAf BgNVHSMEGDAWgBQp4h24x8v1BkoUTgToopKsQnvjpDANBgkqhkiG9w0BAQsFAAOC AQEAvWPLGqtC1SRy61Y17HtJ0giDUwpCZbOUkAwtdDAnKIhR1v4wrlY3sKUBLuhK xOJIWfVlCnPUt5uTnPaWyVyUfry6YNerish1k7ny/R1n58PjsPhUg8GJB9HHsME+ gQQ22z6D/87n0bEE8PaTzIU6+cVHoIBJ0rqzjZVkBs0cEjf+l40RPP1h+ZiTw27u CR2iXmHJ9TQ8ZBWygIhxB9JOMbk5jpH6w6wJqq8XK9zuC1hlYbXH1K5KvZJxAPlh CJkoq2KxaIwByTHjRdGjDogSibsyY+CxQUnktefXb6tYKvFTpUFsh1fjQRCwUrlD SExMRHhFJBHfyPD1w26N3IjRlg== -----END CERTIFICATE----- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-23 17:57:23 +00:00
"github.com/hashicorp/vault/vault"
uuid "github.com/hashicorp/go-uuid"
2015-04-16 00:08:12 +00:00
"github.com/mitchellh/mapstructure"
Create CSR in Transit, sign with PKI (#17630) Execute with: $ go test -v -run=TestTransitPKICSR github.com/hashicorp/vault/builtin/logical/transit ... backend_test.go:1843: csr: -----BEGIN CERTIFICATE REQUEST----- MIICXjCCAUYCAQAwGTEXMBUGA1UEAxMOZGFkZ2FyY29ycC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD8GUy2Rut9ILPXH/Ef7lEaYijuBB9wogd hKD3uJyfK5PqBqM8166UsrP7Y+bWkwDrMke3aDxXRNybys33kIc8KfGwS3omNYd3 17KN1D4ZgQ+oW6xISa3ISOl4D7XeFtHeTP0U1plVXBd9kqTlo4YPlUF/kTfqmxDu 2a41BIS5HlORdLLG+jQ3shRgwHANONBhlaUnIqEeykdW8/iEBlqoYlMzty9W724R 2mKk0FzrVAZ/X5ZO992dAMrQDvc3Nofl+ddzbElBJLumrcDSwALFVge+ag1N48kE CCfxjizEykGdCrR+VELb8b33IgFf6EOVRnS5Qy8whmw943v5Oru5AgMBAAGgADAN BgkqhkiG9w0BAQsFAAOCAQEAdg9SwbrWszMmz60JWQPPfwW+XhzR0MdY82adK8P6 9xpWyJU+U649tAFQb+PCT1OcU7ETd59QcEV38VLndBPWhotTXl5oB5XAqg2bkKHV nLc0cGwyxBSs77LALc//m2f5v2otO9fLOmuM2RMfD02ZUliBmZUzeaUIJYEfT+cS M60uLKJvnNBu5xH1q0oG9P0uNkpEX+QGx6SwhR1/41pmygiUR+uwJxxuRGMvECoN dsHZtzi7ftEHBJ9tk94hd/RFnDsvWlHGyfRWhALNtbo6QjHxjBJIFKh+GHlI8Tnf 6YWvD0VIodE609+RlCrhFlGd+3NUSt0b/f0bgkMJLzLqEw== -----END CERTIFICATE REQUEST----- backend_test.go:1878: root: -----BEGIN CERTIFICATE----- MIIDHTCCAgWgAwIBAgIUIwCzCdrsgkcNOi5liRNHeH+n+tUwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MTIyMTQ1NzExWjAWMRQwEgYDVQQDEwtQS0kgUm9vdCBYMTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMdM65f5p3fLwQP1sezBRFqAxUZhOQwnnnp8mFXp 3fIF9pqLMzNvyd+bCUXv+aFalX4KY1iOoKVHJWwtpXMoKn40U+DZkapR9CsVQt5Q 9xzIcuPPuI+/oNwU4qB9mAuwG+U7KLosGnQOR3NI02A4dnl5I0z8Y/DJLz29GP/P 1zPYMBRBpkMz4F2Xr0w6tTXWDsmqZ9j7ukBDoizmnB2xfKzSjCVmQvXa71UlqbG9 td75LCgpiQh/50mHFHs6RKtqrlFUY5BtPPs+tHUf4nklieIzbAEwA8Fbq4d/Xpq1 HRoRvWj3nelX/h/IRlj/VKJssd1ZL+1kdzxKB4N6AFC1nusCAwEAAaNjMGEwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCniHbjHy/UG ShROBOiikqxCe+OkMB8GA1UdIwQYMBaAFCniHbjHy/UGShROBOiikqxCe+OkMA0G CSqGSIb3DQEBCwUAA4IBAQBSKnl154oyc1Rncm4sr/1f1QM5rCaw/lqgISfvki8m t6yyxQL+9lDpebFjBDTL5teRzuMYyqN4pRkIhpITDGmFXRpEOv14mcbASX7nPBEN bYXhOh1UC8a0CLzT2ll0ERFNnUEPRi0s0ONRm3lIZAV3Mzf4sOdwfRwmP33hBe/1 V9D7Lcx5N84EPrvGC/r8F/PsVKHyKFS46qB1MvhMppRG6fJ2cFmg5UGwdKdmxuvz FoT+RaTLkgcQgkDuYClNco5OVIM7Bd4JTNK3WbqvtGklOHslrz+ND0eMYM/LK+ZS zNM35nzK6QaN2M4IO4Wuy3y2yu8xllEfmssXwAtTi4wk -----END CERTIFICATE----- backend_test.go:1879: leaf: -----BEGIN CERTIFICATE----- MIIDDzCCAfegAwIBAgIUBGeUSi0p3ffndZqgvlBvMvn8qgMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MDIxMTUwNzEyWjAZMRcwFQYDVQQDEw5kYWRnYXJjb3JwLmNvbTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMPwZTLZG630gs9cf8R/uURpiKO4EH3CiB2E oPe4nJ8rk+oGozzXrpSys/tj5taTAOsyR7doPFdE3JvKzfeQhzwp8bBLeiY1h3fX so3UPhmBD6hbrEhJrchI6XgPtd4W0d5M/RTWmVVcF32SpOWjhg+VQX+RN+qbEO7Z rjUEhLkeU5F0ssb6NDeyFGDAcA040GGVpScioR7KR1bz+IQGWqhiUzO3L1bvbhHa YqTQXOtUBn9flk733Z0AytAO9zc2h+X513NsSUEku6atwNLAAsVWB75qDU3jyQQI J/GOLMTKQZ0KtH5UQtvxvfciAV/oQ5VGdLlDLzCGbD3je/k6u7kCAwEAAaNSMFAw DgYDVR0PAQH/BAQDAgOoMB0GA1UdDgQWBBSRCRR/62DjS1kjWHrVQ0Y58leUbDAf BgNVHSMEGDAWgBQp4h24x8v1BkoUTgToopKsQnvjpDANBgkqhkiG9w0BAQsFAAOC AQEAvWPLGqtC1SRy61Y17HtJ0giDUwpCZbOUkAwtdDAnKIhR1v4wrlY3sKUBLuhK xOJIWfVlCnPUt5uTnPaWyVyUfry6YNerish1k7ny/R1n58PjsPhUg8GJB9HHsME+ gQQ22z6D/87n0bEE8PaTzIU6+cVHoIBJ0rqzjZVkBs0cEjf+l40RPP1h+ZiTw27u CR2iXmHJ9TQ8ZBWygIhxB9JOMbk5jpH6w6wJqq8XK9zuC1hlYbXH1K5KvZJxAPlh CJkoq2KxaIwByTHjRdGjDogSibsyY+CxQUnktefXb6tYKvFTpUFsh1fjQRCwUrlD SExMRHhFJBHfyPD1w26N3IjRlg== -----END CERTIFICATE----- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-23 17:57:23 +00:00
"github.com/stretchr/testify/require"
2015-04-16 00:08:12 +00:00
)
const (
testPlaintext = "The quick brown fox"
2015-04-16 00:08:12 +00:00
)
func createBackendWithStorage(t testing.TB) (*backend, logical.Storage) {
Transit: Support batch encryption and decryption (#2143) * Transit: Support batch encryption * Address review feedback * Make the normal flow go through as a batch request * Transit: Error out if encryption fails during batch processing * Transit: Infer the 'derived' parameter based on 'context' being set * Transit: Batch encryption doc updates * Transit: Return a JSON string instead of []byte * Transit: Add batch encryption tests * Remove plaintext empty check * Added tests for batch encryption, more coming.. * Added more batch encryption tests * Check for base64 decoding of plaintext before encrypting * Transit: Support batch decryption * Transit: Added tests for batch decryption * Transit: Doc update for batch decryption * Transit: Sync the path-help and website docs for decrypt endpoint * Add batch processing for rewrap * transit: input validation for context * transit: add rewrap batch option to docs * Remove unnecessary variables from test * transit: Added tests for rewrap use cases * Address review feedback * Address review feedback * Address review feedback * transit: move input checking out of critical path * transit: allow empty plaintexts for batch encryption * transit: use common structs for batch processing * transit: avoid duplicate creation of structs; add omitempty to response structs * transit: address review feedback * transit: fix tests * address review feedback * transit: fix tests * transit: rewrap encrypt user error should not error out * transit: error out for internal errors
2017-02-02 19:24:20 +00:00
config := logical.TestBackendConfig()
config.StorageView = &logical.InmemStorage{}
b, _ := Backend(context.Background(), config)
Transit: Support batch encryption and decryption (#2143) * Transit: Support batch encryption * Address review feedback * Make the normal flow go through as a batch request * Transit: Error out if encryption fails during batch processing * Transit: Infer the 'derived' parameter based on 'context' being set * Transit: Batch encryption doc updates * Transit: Return a JSON string instead of []byte * Transit: Add batch encryption tests * Remove plaintext empty check * Added tests for batch encryption, more coming.. * Added more batch encryption tests * Check for base64 decoding of plaintext before encrypting * Transit: Support batch decryption * Transit: Added tests for batch decryption * Transit: Doc update for batch decryption * Transit: Sync the path-help and website docs for decrypt endpoint * Add batch processing for rewrap * transit: input validation for context * transit: add rewrap batch option to docs * Remove unnecessary variables from test * transit: Added tests for rewrap use cases * Address review feedback * Address review feedback * Address review feedback * transit: move input checking out of critical path * transit: allow empty plaintexts for batch encryption * transit: use common structs for batch processing * transit: avoid duplicate creation of structs; add omitempty to response structs * transit: address review feedback * transit: fix tests * address review feedback * transit: fix tests * transit: rewrap encrypt user error should not error out * transit: error out for internal errors
2017-02-02 19:24:20 +00:00
if b == nil {
t.Fatalf("failed to create backend")
}
err := b.Backend.Setup(context.Background(), config)
Transit: Support batch encryption and decryption (#2143) * Transit: Support batch encryption * Address review feedback * Make the normal flow go through as a batch request * Transit: Error out if encryption fails during batch processing * Transit: Infer the 'derived' parameter based on 'context' being set * Transit: Batch encryption doc updates * Transit: Return a JSON string instead of []byte * Transit: Add batch encryption tests * Remove plaintext empty check * Added tests for batch encryption, more coming.. * Added more batch encryption tests * Check for base64 decoding of plaintext before encrypting * Transit: Support batch decryption * Transit: Added tests for batch decryption * Transit: Doc update for batch decryption * Transit: Sync the path-help and website docs for decrypt endpoint * Add batch processing for rewrap * transit: input validation for context * transit: add rewrap batch option to docs * Remove unnecessary variables from test * transit: Added tests for rewrap use cases * Address review feedback * Address review feedback * Address review feedback * transit: move input checking out of critical path * transit: allow empty plaintexts for batch encryption * transit: use common structs for batch processing * transit: avoid duplicate creation of structs; add omitempty to response structs * transit: address review feedback * transit: fix tests * address review feedback * transit: fix tests * transit: rewrap encrypt user error should not error out * transit: error out for internal errors
2017-02-02 19:24:20 +00:00
if err != nil {
t.Fatal(err)
}
return b, config.StorageView
}
func createBackendWithSysView(t testing.TB) (*backend, logical.Storage) {
sysView := logical.TestSystemView()
storage := &logical.InmemStorage{}
conf := &logical.BackendConfig{
StorageView: storage,
System: sysView,
}
b, _ := Backend(context.Background(), conf)
if b == nil {
t.Fatal("failed to create backend")
}
err := b.Backend.Setup(context.Background(), conf)
if err != nil {
t.Fatal(err)
}
return b, storage
}
func createBackendWithSysViewWithStorage(t testing.TB, s logical.Storage) *backend {
sysView := logical.TestSystemView()
conf := &logical.BackendConfig{
StorageView: s,
System: sysView,
}
b, _ := Backend(context.Background(), conf)
if b == nil {
t.Fatal("failed to create backend")
}
err := b.Backend.Setup(context.Background(), conf)
if err != nil {
t.Fatal(err)
}
return b
}
func createBackendWithForceNoCacheWithSysViewWithStorage(t testing.TB, s logical.Storage) *backend {
sysView := logical.TestSystemView()
sysView.CachingDisabledVal = true
conf := &logical.BackendConfig{
StorageView: s,
System: sysView,
}
b, _ := Backend(context.Background(), conf)
if b == nil {
t.Fatal("failed to create backend")
}
err := b.Backend.Setup(context.Background(), conf)
if err != nil {
t.Fatal(err)
}
return b
}
func TestTransit_RSA(t *testing.T) {
testTransit_RSA(t, "rsa-2048")
testTransit_RSA(t, "rsa-3072")
testTransit_RSA(t, "rsa-4096")
}
func testTransit_RSA(t *testing.T, keyType string) {
var resp *logical.Response
var err error
b, storage := createBackendWithStorage(t)
keyReq := &logical.Request{
Path: "keys/rsa",
Operation: logical.UpdateOperation,
Data: map[string]interface{}{
"type": keyType,
},
Storage: storage,
}
resp, err = b.HandleRequest(context.Background(), keyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA==" // "the quick brown fox"
encryptReq := &logical.Request{
Path: "encrypt/rsa",
Operation: logical.UpdateOperation,
Storage: storage,
Data: map[string]interface{}{
"plaintext": plaintext,
},
}
resp, err = b.HandleRequest(context.Background(), encryptReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
ciphertext1 := resp.Data["ciphertext"].(string)
decryptReq := &logical.Request{
Path: "decrypt/rsa",
Operation: logical.UpdateOperation,
Storage: storage,
Data: map[string]interface{}{
"ciphertext": ciphertext1,
},
}
resp, err = b.HandleRequest(context.Background(), decryptReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
decryptedPlaintext := resp.Data["plaintext"]
if plaintext != decryptedPlaintext {
t.Fatalf("bad: plaintext; expected: %q\nactual: %q", plaintext, decryptedPlaintext)
}
// Rotate the key
rotateReq := &logical.Request{
Path: "keys/rsa/rotate",
Operation: logical.UpdateOperation,
Storage: storage,
}
resp, err = b.HandleRequest(context.Background(), rotateReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
// Encrypt again
resp, err = b.HandleRequest(context.Background(), encryptReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
ciphertext2 := resp.Data["ciphertext"].(string)
if ciphertext1 == ciphertext2 {
t.Fatalf("expected different ciphertexts")
}
// See if the older ciphertext can still be decrypted
resp, err = b.HandleRequest(context.Background(), decryptReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
if resp.Data["plaintext"].(string) != plaintext {
t.Fatal("failed to decrypt old ciphertext after rotating the key")
}
// Decrypt the new ciphertext
decryptReq.Data = map[string]interface{}{
"ciphertext": ciphertext2,
}
resp, err = b.HandleRequest(context.Background(), decryptReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
if resp.Data["plaintext"].(string) != plaintext {
t.Fatal("failed to decrypt ciphertext after rotating the key")
}
signReq := &logical.Request{
Path: "sign/rsa",
Operation: logical.UpdateOperation,
Storage: storage,
Data: map[string]interface{}{
"input": plaintext,
},
}
resp, err = b.HandleRequest(context.Background(), signReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
signature := resp.Data["signature"].(string)
verifyReq := &logical.Request{
Path: "verify/rsa",
Operation: logical.UpdateOperation,
Storage: storage,
Data: map[string]interface{}{
"input": plaintext,
"signature": signature,
},
}
resp, err = b.HandleRequest(context.Background(), verifyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
if !resp.Data["valid"].(bool) {
t.Fatalf("failed to verify the RSA signature")
}
signReq.Data = map[string]interface{}{
"input": plaintext,
"hash_algorithm": "invalid",
}
resp, err = b.HandleRequest(context.Background(), signReq)
if err == nil {
t.Fatal(err)
}
signReq.Data = map[string]interface{}{
"input": plaintext,
"hash_algorithm": "sha2-512",
}
resp, err = b.HandleRequest(context.Background(), signReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
signature = resp.Data["signature"].(string)
verifyReq.Data = map[string]interface{}{
"input": plaintext,
"signature": signature,
}
resp, err = b.HandleRequest(context.Background(), verifyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
if resp.Data["valid"].(bool) {
t.Fatalf("expected validation to fail")
}
verifyReq.Data = map[string]interface{}{
"input": plaintext,
"signature": signature,
"hash_algorithm": "sha2-512",
}
resp, err = b.HandleRequest(context.Background(), verifyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
if !resp.Data["valid"].(bool) {
t.Fatalf("failed to verify the RSA signature")
}
// Take a random hash and sign it using PKCSv1_5_NoOID.
hash := "P8m2iUWdc4+MiKOkiqnjNUIBa3pAUuABqqU2/KdIE8s="
signReq.Data = map[string]interface{}{
"input": hash,
"hash_algorithm": "none",
"signature_algorithm": "pkcs1v15",
"prehashed": true,
}
resp, err = b.HandleRequest(context.Background(), signReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
signature = resp.Data["signature"].(string)
verifyReq.Data = map[string]interface{}{
"input": hash,
"signature": signature,
"hash_algorithm": "none",
"signature_algorithm": "pkcs1v15",
"prehashed": true,
}
resp, err = b.HandleRequest(context.Background(), verifyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
if !resp.Data["valid"].(bool) {
t.Fatalf("failed to verify the RSA signature")
}
}
2015-04-16 00:08:12 +00:00
func TestBackend_basic(t *testing.T) {
decryptData := make(map[string]interface{})
logicaltest.Test(t, logicaltest.TestCase{
2018-11-07 01:21:24 +00:00
LogicalFactory: Factory,
2015-04-16 00:08:12 +00:00
Steps: []logicaltest.TestStep{
testAccStepListPolicy(t, "test", true),
2015-07-05 21:30:45 +00:00
testAccStepWritePolicy(t, "test", false),
testAccStepListPolicy(t, "test", false),
2015-07-05 21:30:45 +00:00
testAccStepReadPolicy(t, "test", false, false),
2015-04-16 00:08:12 +00:00
testAccStepEncrypt(t, "test", testPlaintext, decryptData),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepEncrypt(t, "test", "", decryptData),
testAccStepDecrypt(t, "test", "", decryptData),
testAccStepDeleteNotDisabledPolicy(t, "test"),
testAccStepEnableDeletion(t, "test"),
testAccStepDeletePolicy(t, "test"),
testAccStepWritePolicy(t, "test", false),
testAccStepEnableDeletion(t, "test"),
testAccStepDisableDeletion(t, "test"),
testAccStepDeleteNotDisabledPolicy(t, "test"),
testAccStepEnableDeletion(t, "test"),
testAccStepDeletePolicy(t, "test"),
testAccStepReadPolicy(t, "test", true, false),
},
})
}
func TestBackend_upsert(t *testing.T) {
decryptData := make(map[string]interface{})
logicaltest.Test(t, logicaltest.TestCase{
2018-11-07 01:21:24 +00:00
LogicalFactory: Factory,
Steps: []logicaltest.TestStep{
testAccStepReadPolicy(t, "test", true, false),
testAccStepListPolicy(t, "test", true),
testAccStepEncryptUpsert(t, "test", testPlaintext, decryptData),
testAccStepListPolicy(t, "test", false),
testAccStepReadPolicy(t, "test", false, false),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
},
})
}
func TestBackend_datakey(t *testing.T) {
dataKeyInfo := make(map[string]interface{})
logicaltest.Test(t, logicaltest.TestCase{
2018-11-07 01:21:24 +00:00
LogicalFactory: Factory,
Steps: []logicaltest.TestStep{
testAccStepListPolicy(t, "test", true),
testAccStepWritePolicy(t, "test", false),
testAccStepListPolicy(t, "test", false),
testAccStepReadPolicy(t, "test", false, false),
testAccStepWriteDatakey(t, "test", false, 256, dataKeyInfo),
testAccStepDecryptDatakey(t, "test", dataKeyInfo),
testAccStepWriteDatakey(t, "test", true, 128, dataKeyInfo),
},
})
}
func TestBackend_rotation(t *testing.T) {
defer os.Setenv("TRANSIT_ACC_KEY_TYPE", "")
testBackendRotation(t)
os.Setenv("TRANSIT_ACC_KEY_TYPE", "CHACHA")
testBackendRotation(t)
}
func testBackendRotation(t *testing.T) {
decryptData := make(map[string]interface{})
encryptHistory := make(map[int]map[string]interface{})
logicaltest.Test(t, logicaltest.TestCase{
2018-11-07 01:21:24 +00:00
LogicalFactory: Factory,
Steps: []logicaltest.TestStep{
testAccStepListPolicy(t, "test", true),
testAccStepWritePolicy(t, "test", false),
testAccStepListPolicy(t, "test", false),
testAccStepEncryptVX(t, "test", testPlaintext, decryptData, 0, encryptHistory),
testAccStepEncryptVX(t, "test", testPlaintext, decryptData, 1, encryptHistory),
testAccStepRotate(t, "test"), // now v2
testAccStepEncryptVX(t, "test", testPlaintext, decryptData, 2, encryptHistory),
testAccStepRotate(t, "test"), // now v3
testAccStepEncryptVX(t, "test", testPlaintext, decryptData, 3, encryptHistory),
testAccStepRotate(t, "test"), // now v4
testAccStepEncryptVX(t, "test", testPlaintext, decryptData, 4, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepEncryptVX(t, "test", testPlaintext, decryptData, 99, encryptHistory),
testAccStepDecryptExpectFailure(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 0, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 1, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 2, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 3, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 99, encryptHistory),
testAccStepDecryptExpectFailure(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 4, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepDeleteNotDisabledPolicy(t, "test"),
testAccStepAdjustPolicyMinDecryption(t, "test", 3),
testAccStepAdjustPolicyMinEncryption(t, "test", 4),
testAccStepReadPolicyWithVersions(t, "test", false, false, 3, 4),
testAccStepLoadVX(t, "test", decryptData, 0, encryptHistory),
testAccStepDecryptExpectFailure(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 1, encryptHistory),
testAccStepDecryptExpectFailure(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 2, encryptHistory),
testAccStepDecryptExpectFailure(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 3, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 4, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepAdjustPolicyMinDecryption(t, "test", 1),
testAccStepReadPolicyWithVersions(t, "test", false, false, 1, 4),
testAccStepLoadVX(t, "test", decryptData, 0, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 1, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepLoadVX(t, "test", decryptData, 2, encryptHistory),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepRewrap(t, "test", decryptData, 4),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepEnableDeletion(t, "test"),
2015-04-16 00:08:12 +00:00
testAccStepDeletePolicy(t, "test"),
2015-07-05 21:30:45 +00:00
testAccStepReadPolicy(t, "test", true, false),
testAccStepListPolicy(t, "test", true),
2015-04-16 00:08:12 +00:00
},
})
}
2015-07-05 21:30:45 +00:00
func TestBackend_basic_derived(t *testing.T) {
decryptData := make(map[string]interface{})
logicaltest.Test(t, logicaltest.TestCase{
2018-11-07 01:21:24 +00:00
LogicalFactory: Factory,
2015-07-05 21:30:45 +00:00
Steps: []logicaltest.TestStep{
testAccStepListPolicy(t, "test", true),
2015-07-05 21:30:45 +00:00
testAccStepWritePolicy(t, "test", true),
testAccStepListPolicy(t, "test", false),
2015-07-05 21:30:45 +00:00
testAccStepReadPolicy(t, "test", false, true),
testAccStepEncryptContext(t, "test", testPlaintext, "my-cool-context", decryptData),
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
testAccStepEnableDeletion(t, "test"),
2015-07-05 21:30:45 +00:00
testAccStepDeletePolicy(t, "test"),
testAccStepReadPolicy(t, "test", true, true),
},
})
}
func testAccStepWritePolicy(t *testing.T, name string, derived bool) logicaltest.TestStep {
ts := logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
2015-04-27 20:52:47 +00:00
Path: "keys/" + name,
2015-07-05 21:30:45 +00:00
Data: map[string]interface{}{
"derived": derived,
},
2015-04-16 00:08:12 +00:00
}
if os.Getenv("TRANSIT_ACC_KEY_TYPE") == "CHACHA" {
ts.Data["type"] = "chacha20-poly1305"
}
return ts
2015-04-16 00:08:12 +00:00
}
func testAccStepListPolicy(t *testing.T, name string, expectNone bool) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.ListOperation,
Path: "keys",
Check: func(resp *logical.Response) error {
if resp == nil {
return fmt.Errorf("missing response")
}
if expectNone {
keysRaw, ok := resp.Data["keys"]
if ok || keysRaw != nil {
return fmt.Errorf("response data when expecting none")
}
return nil
}
if len(resp.Data) == 0 {
return fmt.Errorf("no data returned")
}
var d struct {
Keys []string `mapstructure:"keys"`
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
if len(d.Keys) > 0 && d.Keys[0] != name {
return fmt.Errorf("bad name: %#v", d)
}
if len(d.Keys) != 1 {
return fmt.Errorf("only 1 key expected, %d returned", len(d.Keys))
}
return nil
},
}
}
func testAccStepAdjustPolicyMinDecryption(t *testing.T, name string, minVer int) logicaltest.TestStep {
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
Path: "keys/" + name + "/config",
Data: map[string]interface{}{
"min_decryption_version": minVer,
},
}
}
func testAccStepAdjustPolicyMinEncryption(t *testing.T, name string, minVer int) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.UpdateOperation,
Path: "keys/" + name + "/config",
Data: map[string]interface{}{
"min_encryption_version": minVer,
},
}
}
func testAccStepDisableDeletion(t *testing.T, name string) logicaltest.TestStep {
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
Path: "keys/" + name + "/config",
Data: map[string]interface{}{
"deletion_allowed": false,
},
}
}
func testAccStepEnableDeletion(t *testing.T, name string) logicaltest.TestStep {
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
Path: "keys/" + name + "/config",
Data: map[string]interface{}{
"deletion_allowed": true,
},
}
}
2015-04-16 00:08:12 +00:00
func testAccStepDeletePolicy(t *testing.T, name string) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.DeleteOperation,
2015-04-27 20:52:47 +00:00
Path: "keys/" + name,
2015-04-16 00:08:12 +00:00
}
}
func testAccStepDeleteNotDisabledPolicy(t *testing.T, name string) logicaltest.TestStep {
2015-04-16 00:08:12 +00:00
return logicaltest.TestStep{
Operation: logical.DeleteOperation,
2015-04-27 20:52:47 +00:00
Path: "keys/" + name,
ErrorOk: true,
2015-04-16 00:08:12 +00:00
Check: func(resp *logical.Response) error {
if resp == nil {
return fmt.Errorf("got nil response instead of error")
}
if resp.IsError() {
return nil
}
return fmt.Errorf("expected error but did not get one")
},
}
}
func testAccStepReadPolicy(t *testing.T, name string, expectNone, derived bool) logicaltest.TestStep {
return testAccStepReadPolicyWithVersions(t, name, expectNone, derived, 1, 0)
}
func testAccStepReadPolicyWithVersions(t *testing.T, name string, expectNone, derived bool, minDecryptionVersion int, minEncryptionVersion int) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.ReadOperation,
Path: "keys/" + name,
Check: func(resp *logical.Response) error {
if resp == nil && !expectNone {
2015-04-16 00:08:12 +00:00
return fmt.Errorf("missing response")
} else if expectNone {
if resp != nil {
return fmt.Errorf("response when expecting none")
}
return nil
}
var d struct {
Name string `mapstructure:"name"`
Key []byte `mapstructure:"key"`
Keys map[string]int64 `mapstructure:"keys"`
2016-09-21 14:29:42 +00:00
Type string `mapstructure:"type"`
Derived bool `mapstructure:"derived"`
KDF string `mapstructure:"kdf"`
DeletionAllowed bool `mapstructure:"deletion_allowed"`
ConvergentEncryption bool `mapstructure:"convergent_encryption"`
MinDecryptionVersion int `mapstructure:"min_decryption_version"`
MinEncryptionVersion int `mapstructure:"min_encryption_version"`
2015-04-16 00:08:12 +00:00
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
if d.Name != name {
2016-09-21 14:29:42 +00:00
return fmt.Errorf("bad name: %#v", d)
2015-04-16 00:08:12 +00:00
}
if os.Getenv("TRANSIT_ACC_KEY_TYPE") == "CHACHA" {
if d.Type != keysutil.KeyType(keysutil.KeyType_ChaCha20_Poly1305).String() {
return fmt.Errorf("bad key type: %#v", d)
}
} else if d.Type != keysutil.KeyType(keysutil.KeyType_AES256_GCM96).String() {
2016-09-21 14:29:42 +00:00
return fmt.Errorf("bad key type: %#v", d)
2015-04-16 00:08:12 +00:00
}
// Should NOT get a key back
if d.Key != nil {
return fmt.Errorf("bad: %#v", d)
}
if d.Keys == nil {
return fmt.Errorf("bad: %#v", d)
}
if d.MinDecryptionVersion != minDecryptionVersion {
return fmt.Errorf("bad: %#v", d)
}
if d.MinEncryptionVersion != minEncryptionVersion {
return fmt.Errorf("bad: %#v", d)
}
if d.DeletionAllowed {
2015-04-16 00:08:12 +00:00
return fmt.Errorf("bad: %#v", d)
}
2015-07-05 21:30:45 +00:00
if d.Derived != derived {
return fmt.Errorf("bad: %#v", d)
}
if derived && d.KDF != "hkdf_sha256" {
2015-07-05 21:30:45 +00:00
return fmt.Errorf("bad: %#v", d)
}
2015-04-16 00:08:12 +00:00
return nil
},
}
}
func testAccStepEncrypt(
t *testing.T, name, plaintext string, decryptData map[string]interface{},
) logicaltest.TestStep {
2015-04-16 00:08:12 +00:00
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
2015-04-16 00:08:12 +00:00
Path: "encrypt/" + name,
Data: map[string]interface{}{
"plaintext": base64.StdEncoding.EncodeToString([]byte(plaintext)),
},
Check: func(resp *logical.Response) error {
var d struct {
Ciphertext string `mapstructure:"ciphertext"`
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
if d.Ciphertext == "" {
return fmt.Errorf("missing ciphertext")
}
decryptData["ciphertext"] = d.Ciphertext
return nil
},
}
}
func testAccStepEncryptUpsert(
t *testing.T, name, plaintext string, decryptData map[string]interface{},
) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.CreateOperation,
Path: "encrypt/" + name,
Data: map[string]interface{}{
"plaintext": base64.StdEncoding.EncodeToString([]byte(plaintext)),
},
Check: func(resp *logical.Response) error {
var d struct {
Ciphertext string `mapstructure:"ciphertext"`
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
if d.Ciphertext == "" {
return fmt.Errorf("missing ciphertext")
}
decryptData["ciphertext"] = d.Ciphertext
return nil
},
}
}
2015-07-05 21:30:45 +00:00
func testAccStepEncryptContext(
t *testing.T, name, plaintext, context string, decryptData map[string]interface{},
) logicaltest.TestStep {
2015-07-05 21:30:45 +00:00
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
2015-07-05 21:30:45 +00:00
Path: "encrypt/" + name,
Data: map[string]interface{}{
"plaintext": base64.StdEncoding.EncodeToString([]byte(plaintext)),
"context": base64.StdEncoding.EncodeToString([]byte(context)),
2015-07-05 21:30:45 +00:00
},
Check: func(resp *logical.Response) error {
var d struct {
Ciphertext string `mapstructure:"ciphertext"`
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
if d.Ciphertext == "" {
return fmt.Errorf("missing ciphertext")
}
decryptData["ciphertext"] = d.Ciphertext
decryptData["context"] = base64.StdEncoding.EncodeToString([]byte(context))
2015-07-05 21:30:45 +00:00
return nil
},
}
}
2015-04-16 00:08:12 +00:00
func testAccStepDecrypt(
t *testing.T, name, plaintext string, decryptData map[string]interface{},
) logicaltest.TestStep {
2015-04-16 00:08:12 +00:00
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
2015-04-16 00:08:12 +00:00
Path: "decrypt/" + name,
Data: decryptData,
Check: func(resp *logical.Response) error {
var d struct {
Plaintext string `mapstructure:"plaintext"`
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
// Decode the base64
plainRaw, err := base64.StdEncoding.DecodeString(d.Plaintext)
if err != nil {
return err
}
if string(plainRaw) != plaintext {
return fmt.Errorf("plaintext mismatch: %s expect: %s, decryptData was %#v", plainRaw, plaintext, decryptData)
}
return nil
},
}
}
func testAccStepRewrap(
t *testing.T, name string, decryptData map[string]interface{}, expectedVer int,
) logicaltest.TestStep {
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
Path: "rewrap/" + name,
Data: decryptData,
Check: func(resp *logical.Response) error {
var d struct {
Ciphertext string `mapstructure:"ciphertext"`
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
if d.Ciphertext == "" {
return fmt.Errorf("missing ciphertext")
}
splitStrings := strings.Split(d.Ciphertext, ":")
verString := splitStrings[1][1:]
ver, err := strconv.Atoi(verString)
if err != nil {
return fmt.Errorf("error pulling out version from verString %q, ciphertext was %s", verString, d.Ciphertext)
2015-04-16 00:08:12 +00:00
}
if ver != expectedVer {
return fmt.Errorf("did not get expected version")
}
decryptData["ciphertext"] = d.Ciphertext
2015-04-16 00:08:12 +00:00
return nil
},
}
}
func testAccStepEncryptVX(
t *testing.T, name, plaintext string, decryptData map[string]interface{},
ver int, encryptHistory map[int]map[string]interface{},
) logicaltest.TestStep {
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
Path: "encrypt/" + name,
Data: map[string]interface{}{
"plaintext": base64.StdEncoding.EncodeToString([]byte(plaintext)),
},
Check: func(resp *logical.Response) error {
var d struct {
Ciphertext string `mapstructure:"ciphertext"`
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
if d.Ciphertext == "" {
return fmt.Errorf("missing ciphertext")
}
splitStrings := strings.Split(d.Ciphertext, ":")
splitStrings[1] = "v" + strconv.Itoa(ver)
ciphertext := strings.Join(splitStrings, ":")
decryptData["ciphertext"] = ciphertext
encryptHistory[ver] = map[string]interface{}{
"ciphertext": ciphertext,
}
return nil
},
}
}
func testAccStepLoadVX(
t *testing.T, name string, decryptData map[string]interface{},
ver int, encryptHistory map[int]map[string]interface{},
) logicaltest.TestStep {
// This is really a no-op to allow us to do data manip in the check function
return logicaltest.TestStep{
Operation: logical.ReadOperation,
Path: "keys/" + name,
Check: func(resp *logical.Response) error {
decryptData["ciphertext"] = encryptHistory[ver]["ciphertext"].(string)
return nil
},
}
}
func testAccStepDecryptExpectFailure(
t *testing.T, name, plaintext string, decryptData map[string]interface{},
) logicaltest.TestStep {
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
Path: "decrypt/" + name,
Data: decryptData,
ErrorOk: true,
Check: func(resp *logical.Response) error {
if !resp.IsError() {
return fmt.Errorf("expected error")
}
return nil
},
}
}
func testAccStepRotate(t *testing.T, name string) logicaltest.TestStep {
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
Path: "keys/" + name + "/rotate",
}
}
func testAccStepWriteDatakey(t *testing.T, name string,
noPlaintext bool, bits int,
dataKeyInfo map[string]interface{},
) logicaltest.TestStep {
data := map[string]interface{}{}
subPath := "plaintext"
if noPlaintext {
subPath = "wrapped"
}
if bits != 256 {
data["bits"] = bits
}
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
Path: "datakey/" + subPath + "/" + name,
Data: data,
Check: func(resp *logical.Response) error {
var d struct {
Plaintext string `mapstructure:"plaintext"`
Ciphertext string `mapstructure:"ciphertext"`
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
if noPlaintext && len(d.Plaintext) != 0 {
return fmt.Errorf("received plaintxt when we disabled it")
}
if !noPlaintext {
if len(d.Plaintext) == 0 {
return fmt.Errorf("did not get plaintext when we expected it")
}
dataKeyInfo["plaintext"] = d.Plaintext
plainBytes, err := base64.StdEncoding.DecodeString(d.Plaintext)
if err != nil {
return fmt.Errorf("could not base64 decode plaintext string %q", d.Plaintext)
}
if len(plainBytes)*8 != bits {
return fmt.Errorf("returned key does not have correct bit length")
}
}
dataKeyInfo["ciphertext"] = d.Ciphertext
return nil
},
}
}
func testAccStepDecryptDatakey(t *testing.T, name string,
dataKeyInfo map[string]interface{},
) logicaltest.TestStep {
return logicaltest.TestStep{
2016-01-07 15:30:47 +00:00
Operation: logical.UpdateOperation,
Path: "decrypt/" + name,
Data: dataKeyInfo,
Check: func(resp *logical.Response) error {
var d struct {
Plaintext string `mapstructure:"plaintext"`
}
if err := mapstructure.Decode(resp.Data, &d); err != nil {
return err
}
if d.Plaintext != dataKeyInfo["plaintext"].(string) {
return fmt.Errorf("plaintext mismatch: got %q, expected %q, decryptData was %#v", d.Plaintext, dataKeyInfo["plaintext"].(string), resp.Data)
}
return nil
},
}
}
func TestKeyUpgrade(t *testing.T) {
key, _ := uuid.GenerateRandomBytes(32)
p := &keysutil.Policy{
2016-09-21 14:29:42 +00:00
Name: "test",
Key: key,
Type: keysutil.KeyType_AES256_GCM96,
}
p.MigrateKeyToKeysMap()
if p.Key != nil ||
p.Keys == nil ||
len(p.Keys) != 1 ||
!reflect.DeepEqual(p.Keys[strconv.Itoa(1)].Key, key) {
t.Errorf("bad key migration, result is %#v", p.Keys)
}
}
2016-02-03 22:25:48 +00:00
func TestDerivedKeyUpgrade(t *testing.T) {
testDerivedKeyUpgrade(t, keysutil.KeyType_AES256_GCM96)
testDerivedKeyUpgrade(t, keysutil.KeyType_ChaCha20_Poly1305)
}
func testDerivedKeyUpgrade(t *testing.T, keyType keysutil.KeyType) {
storage := &logical.InmemStorage{}
key, _ := uuid.GenerateRandomBytes(32)
keyContext, _ := uuid.GenerateRandomBytes(32)
p := &keysutil.Policy{
2016-09-21 14:29:42 +00:00
Name: "test",
Key: key,
Type: keyType,
2016-09-21 14:29:42 +00:00
Derived: true,
}
p.MigrateKeyToKeysMap()
p.Upgrade(context.Background(), storage, cryptoRand.Reader) // Need to run the upgrade code to make the migration stick
if p.KDF != keysutil.Kdf_hmac_sha256_counter {
t.Fatalf("bad KDF value by default; counter val is %d, KDF val is %d, policy is %#v", keysutil.Kdf_hmac_sha256_counter, p.KDF, *p)
}
derBytesOld, err := p.GetKey(keyContext, 1, 0)
if err != nil {
t.Fatal(err)
}
derBytesOld2, err := p.GetKey(keyContext, 1, 0)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(derBytesOld, derBytesOld2) {
t.Fatal("mismatch of same context alg")
}
p.KDF = keysutil.Kdf_hkdf_sha256
if p.NeedsUpgrade() {
t.Fatal("expected no upgrade needed")
}
derBytesNew, err := p.GetKey(keyContext, 1, 64)
if err != nil {
t.Fatal(err)
}
derBytesNew2, err := p.GetKey(keyContext, 1, 64)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(derBytesNew, derBytesNew2) {
t.Fatal("mismatch of same context alg")
}
if reflect.DeepEqual(derBytesOld, derBytesNew) {
t.Fatal("match of different context alg")
}
}
func TestConvergentEncryption(t *testing.T) {
testConvergentEncryptionCommon(t, 0, keysutil.KeyType_AES256_GCM96)
testConvergentEncryptionCommon(t, 2, keysutil.KeyType_AES128_GCM96)
testConvergentEncryptionCommon(t, 2, keysutil.KeyType_AES256_GCM96)
testConvergentEncryptionCommon(t, 2, keysutil.KeyType_ChaCha20_Poly1305)
testConvergentEncryptionCommon(t, 3, keysutil.KeyType_AES128_GCM96)
2018-06-05 22:51:35 +00:00
testConvergentEncryptionCommon(t, 3, keysutil.KeyType_AES256_GCM96)
testConvergentEncryptionCommon(t, 3, keysutil.KeyType_ChaCha20_Poly1305)
}
func testConvergentEncryptionCommon(t *testing.T, ver int, keyType keysutil.KeyType) {
b, storage := createBackendWithSysView(t)
req := &logical.Request{
Storage: storage,
Operation: logical.UpdateOperation,
Path: "keys/testkeynonderived",
Data: map[string]interface{}{
"derived": false,
"convergent_encryption": true,
"type": keyType.String(),
},
}
resp, err := b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if !resp.IsError() {
t.Fatalf("bad: expected error response, got %#v", *resp)
}
2018-06-05 22:51:35 +00:00
req = &logical.Request{
Storage: storage,
Operation: logical.UpdateOperation,
Path: "keys/testkey",
Data: map[string]interface{}{
"derived": true,
"convergent_encryption": true,
"type": keyType.String(),
2018-06-05 22:51:35 +00:00
},
}
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
require.NotNil(t, resp, "expected populated request")
2018-06-05 22:51:35 +00:00
p, err := keysutil.LoadPolicy(context.Background(), storage, path.Join("policy", "testkey"))
if err != nil {
t.Fatal(err)
}
if p == nil {
t.Fatal("got nil policy")
}
2018-06-05 22:51:35 +00:00
if ver > 2 {
p.ConvergentVersion = -1
} else {
p.ConvergentVersion = ver
}
err = p.Persist(context.Background(), storage)
if err != nil {
t.Fatal(err)
}
2018-06-05 22:51:35 +00:00
b.invalidate(context.Background(), "policy/testkey")
if ver < 3 {
// There will be an embedded key version of 3, so specifically clear it
key := p.Keys[strconv.Itoa(p.LatestVersion)]
key.ConvergentVersion = 0
p.Keys[strconv.Itoa(p.LatestVersion)] = key
err = p.Persist(context.Background(), storage)
if err != nil {
t.Fatal(err)
}
b.invalidate(context.Background(), "policy/testkey")
// Verify it
p, err = keysutil.LoadPolicy(context.Background(), storage, path.Join(p.StoragePrefix, "policy", "testkey"))
if err != nil {
t.Fatal(err)
}
if p == nil {
t.Fatal("got nil policy")
}
if p.ConvergentVersion != ver {
t.Fatalf("bad convergent version %d", p.ConvergentVersion)
}
key = p.Keys[strconv.Itoa(p.LatestVersion)]
if key.ConvergentVersion != 0 {
t.Fatalf("bad convergent key version %d", key.ConvergentVersion)
}
}
// First, test using an invalid length of nonce -- this is only used for v1 convergent
req.Path = "encrypt/testkey"
if ver < 2 {
req.Data = map[string]interface{}{
"plaintext": "emlwIHphcA==", // "zip zap"
"nonce": "Zm9vIGJhcg==", // "foo bar"
"context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S",
}
resp, err = b.HandleRequest(context.Background(), req)
if err == nil {
2018-06-05 22:51:35 +00:00
t.Fatalf("expected error, got nil, version is %d", ver)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if !resp.IsError() {
t.Fatalf("expected error response, got %#v", *resp)
}
// Ensure we fail if we do not provide a nonce
req.Data = map[string]interface{}{
"plaintext": "emlwIHphcA==", // "zip zap"
"context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S",
}
resp, err = b.HandleRequest(context.Background(), req)
if err == nil && (resp == nil || !resp.IsError()) {
t.Fatal("expected error response")
}
}
// Now test encrypting the same value twice
req.Data = map[string]interface{}{
"plaintext": "emlwIHphcA==", // "zip zap"
"nonce": "b25ldHdvdGhyZWVl", // "onetwothreee"
"context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S",
}
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext1 := resp.Data["ciphertext"].(string)
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext2 := resp.Data["ciphertext"].(string)
if ciphertext1 != ciphertext2 {
t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext1, ciphertext2)
}
// For sanity, also check a different nonce value...
req.Data = map[string]interface{}{
"plaintext": "emlwIHphcA==", // "zip zap"
"nonce": "dHdvdGhyZWVmb3Vy", // "twothreefour"
"context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S",
}
if ver < 2 {
req.Data["nonce"] = "dHdvdGhyZWVmb3Vy" // "twothreefour"
} else {
req.Data["context"] = "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOldandSdd7S"
}
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext3 := resp.Data["ciphertext"].(string)
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext4 := resp.Data["ciphertext"].(string)
if ciphertext3 != ciphertext4 {
t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext3, ciphertext4)
}
if ciphertext1 == ciphertext3 {
t.Fatalf("expected different ciphertexts")
}
// ...and a different context value
req.Data = map[string]interface{}{
"plaintext": "emlwIHphcA==", // "zip zap"
"nonce": "dHdvdGhyZWVmb3Vy", // "twothreefour"
"context": "qV4h9iQyvn+raODOer4JNAsOhkXBwdT4HZ677Ql4KLqXSU+Jk4C/fXBWbv6xkSYT",
}
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext5 := resp.Data["ciphertext"].(string)
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext6 := resp.Data["ciphertext"].(string)
if ciphertext5 != ciphertext6 {
t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext5, ciphertext6)
}
if ciphertext1 == ciphertext5 {
t.Fatalf("expected different ciphertexts")
}
if ciphertext3 == ciphertext5 {
t.Fatalf("expected different ciphertexts")
}
2018-06-05 22:51:35 +00:00
// If running version 2, check upgrade handling
if ver == 2 {
curr, err := keysutil.LoadPolicy(context.Background(), storage, path.Join(p.StoragePrefix, "policy", "testkey"))
if err != nil {
t.Fatal(err)
}
if curr == nil {
t.Fatal("got nil policy")
}
if curr.ConvergentVersion != 2 {
t.Fatalf("bad convergent version %d", curr.ConvergentVersion)
}
key := curr.Keys[strconv.Itoa(curr.LatestVersion)]
if key.ConvergentVersion != 0 {
t.Fatalf("bad convergent key version %d", key.ConvergentVersion)
}
curr.ConvergentVersion = 3
err = curr.Persist(context.Background(), storage)
if err != nil {
t.Fatal(err)
}
b.invalidate(context.Background(), "policy/testkey")
// Different algorithm, should be different value
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext7 := resp.Data["ciphertext"].(string)
// Now do it via key-specified version
if len(curr.Keys) != 1 {
t.Fatalf("unexpected length of keys %d", len(curr.Keys))
}
key = curr.Keys[strconv.Itoa(curr.LatestVersion)]
key.ConvergentVersion = 3
curr.Keys[strconv.Itoa(curr.LatestVersion)] = key
curr.ConvergentVersion = 2
err = curr.Persist(context.Background(), storage)
if err != nil {
t.Fatal(err)
}
b.invalidate(context.Background(), "policy/testkey")
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext8 := resp.Data["ciphertext"].(string)
if ciphertext7 != ciphertext8 {
t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext7, ciphertext8)
}
if ciphertext6 == ciphertext7 {
t.Fatalf("expected different ciphertexts")
}
if ciphertext3 == ciphertext7 {
t.Fatalf("expected different ciphertexts")
}
}
// Finally, check operations on empty values
// First, check without setting a plaintext at all
req.Data = map[string]interface{}{
"nonce": "b25ldHdvdGhyZWVl", // "onetwothreee"
"context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S",
}
resp, err = b.HandleRequest(context.Background(), req)
if err == nil {
t.Fatal("expected error, got nil")
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if !resp.IsError() {
t.Fatalf("expected error response, got: %#v", *resp)
}
// Now set plaintext to empty
req.Data = map[string]interface{}{
"plaintext": "",
"nonce": "b25ldHdvdGhyZWVl", // "onetwothreee"
"context": "pWZ6t/im3AORd0lVYE0zBdKpX6Bl3/SvFtoVTPWbdkzjG788XmMAnOlxandSdd7S",
}
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext7 := resp.Data["ciphertext"].(string)
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.IsError() {
t.Fatalf("got error response: %#v", *resp)
}
ciphertext8 := resp.Data["ciphertext"].(string)
if ciphertext7 != ciphertext8 {
t.Fatalf("expected the same ciphertext but got %s and %s", ciphertext7, ciphertext8)
}
}
2016-02-03 22:25:48 +00:00
func TestPolicyFuzzing(t *testing.T) {
var be *backend
sysView := logical.TestSystemView()
sysView.CachingDisabledVal = true
conf := &logical.BackendConfig{
System: sysView,
}
be, _ = Backend(context.Background(), conf)
be.Setup(context.Background(), conf)
testPolicyFuzzingCommon(t, be)
sysView.CachingDisabledVal = true
be, _ = Backend(context.Background(), conf)
be.Setup(context.Background(), conf)
testPolicyFuzzingCommon(t, be)
}
func testPolicyFuzzingCommon(t *testing.T, be *backend) {
storage := &logical.InmemStorage{}
2016-02-03 22:25:48 +00:00
wg := sync.WaitGroup{}
funcs := []string{"encrypt", "decrypt", "rotate", "change_min_version"}
// keys := []string{"test1", "test2", "test3", "test4", "test5"}
2016-02-03 22:25:48 +00:00
keys := []string{"test1", "test2", "test3"}
// This is the goroutine loop
doFuzzy := func(id int) {
2016-02-03 22:25:48 +00:00
// Check for panics, otherwise notify we're done
defer func() {
wg.Done()
}()
// Holds the latest encrypted value for each key
latestEncryptedText := map[string]string{}
startTime := time.Now()
req := &logical.Request{
Storage: storage,
Data: map[string]interface{}{},
}
fd := &framework.FieldData{}
var chosenFunc, chosenKey string
// t.Errorf("Starting %d", id)
2016-02-03 22:25:48 +00:00
for {
// Stop after 10 seconds
if time.Now().Sub(startTime) > 10*time.Second {
return
}
// Pick a function and a key
chosenFunc = funcs[rand.Int()%len(funcs)]
chosenKey = keys[rand.Int()%len(keys)]
2016-02-03 22:25:48 +00:00
fd.Raw = map[string]interface{}{
"name": chosenKey,
}
fd.Schema = be.pathKeys().Fields
// Try to write the key to make sure it exists
_, err := be.pathPolicyWrite(context.Background(), req, fd)
2016-02-03 22:25:48 +00:00
if err != nil {
t.Errorf("got an error: %v", err)
2016-02-03 22:25:48 +00:00
}
switch chosenFunc {
// Encrypt our plaintext and store the result
case "encrypt":
// t.Errorf("%s, %s, %d", chosenFunc, chosenKey, id)
2016-02-03 22:25:48 +00:00
fd.Raw["plaintext"] = base64.StdEncoding.EncodeToString([]byte(testPlaintext))
fd.Schema = be.pathEncrypt().Fields
resp, err := be.pathEncryptWrite(context.Background(), req, fd)
2016-02-03 22:25:48 +00:00
if err != nil {
t.Errorf("got an error: %v, resp is %#v", err, *resp)
2016-02-03 22:25:48 +00:00
}
latestEncryptedText[chosenKey] = resp.Data["ciphertext"].(string)
// Rotate to a new key version
case "rotate":
// t.Errorf("%s, %s, %d", chosenFunc, chosenKey, id)
2016-02-03 22:25:48 +00:00
fd.Schema = be.pathRotate().Fields
resp, err := be.pathRotateWrite(context.Background(), req, fd)
2016-02-03 22:25:48 +00:00
if err != nil {
t.Errorf("got an error: %v, resp is %#v, chosenKey is %s", err, *resp, chosenKey)
2016-02-03 22:25:48 +00:00
}
// Decrypt the ciphertext and compare the result
case "decrypt":
// t.Errorf("%s, %s, %d", chosenFunc, chosenKey, id)
2016-02-03 22:25:48 +00:00
ct := latestEncryptedText[chosenKey]
if ct == "" {
continue
}
fd.Raw["ciphertext"] = ct
fd.Schema = be.pathDecrypt().Fields
resp, err := be.pathDecryptWrite(context.Background(), req, fd)
2016-02-03 22:25:48 +00:00
if err != nil {
// This could well happen since the min version is jumping around
if resp.Data["error"].(string) == keysutil.ErrTooOld {
2016-02-03 22:25:48 +00:00
continue
}
t.Errorf("got an error: %v, resp is %#v, ciphertext was %s, chosenKey is %s, id is %d", err, *resp, ct, chosenKey, id)
}
ptb64, ok := resp.Data["plaintext"].(string)
if !ok {
t.Errorf("no plaintext found, response was %#v", *resp)
return
2016-02-03 22:25:48 +00:00
}
pt, err := base64.StdEncoding.DecodeString(ptb64)
if err != nil {
t.Errorf("got an error decoding base64 plaintext: %v", err)
2016-02-03 22:25:48 +00:00
return
}
if string(pt) != testPlaintext {
t.Errorf("got bad plaintext back: %s", pt)
2016-02-03 22:25:48 +00:00
}
// Change the min version, which also tests the archive functionality
case "change_min_version":
// t.Errorf("%s, %s, %d", chosenFunc, chosenKey, id)
resp, err := be.pathPolicyRead(context.Background(), req, fd)
2016-02-03 22:25:48 +00:00
if err != nil {
t.Errorf("got an error reading policy %s: %v", chosenKey, err)
2016-02-03 22:25:48 +00:00
}
latestVersion := resp.Data["latest_version"].(int)
// keys start at version 1 so we want [1, latestVersion] not [0, latestVersion)
setVersion := (rand.Int() % latestVersion) + 1
fd.Raw["min_decryption_version"] = setVersion
fd.Schema = be.pathKeysConfig().Fields
resp, err = be.pathKeysConfigWrite(context.Background(), req, fd)
2016-02-03 22:25:48 +00:00
if err != nil {
t.Errorf("got an error setting min decryption version: %v", err)
2016-02-03 22:25:48 +00:00
}
}
}
}
// Spawn 1000 of these workers for 10 seconds
for i := 0; i < 1000; i++ {
wg.Add(1)
go doFuzzy(i)
2016-02-03 22:25:48 +00:00
}
// Wait for them all to finish
wg.Wait()
}
func TestBadInput(t *testing.T) {
b, storage := createBackendWithSysView(t)
req := &logical.Request{
Storage: storage,
Operation: logical.UpdateOperation,
Path: "keys/test",
}
resp, err := b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
require.NotNil(t, resp, "expected populated request")
req.Path = "decrypt/test"
req.Data = map[string]interface{}{
"ciphertext": "vault:v1:abcd",
}
_, err = b.HandleRequest(context.Background(), req)
if err == nil {
t.Fatal("expected error")
}
}
func TestTransit_AutoRotateKeys(t *testing.T) {
tests := map[string]struct {
isDRSecondary bool
isPerfSecondary bool
isStandby bool
isLocal bool
shouldRotate bool
}{
"primary, no local mount": {
shouldRotate: true,
},
"DR secondary, no local mount": {
isDRSecondary: true,
shouldRotate: false,
},
"perf standby, no local mount": {
isStandby: true,
shouldRotate: false,
},
"perf secondary, no local mount": {
isPerfSecondary: true,
shouldRotate: false,
},
"perf secondary, local mount": {
isPerfSecondary: true,
isLocal: true,
shouldRotate: true,
},
}
for name, test := range tests {
t.Run(
name,
func(t *testing.T) {
var repState consts.ReplicationState
if test.isDRSecondary {
repState.AddState(consts.ReplicationDRSecondary)
}
if test.isPerfSecondary {
repState.AddState(consts.ReplicationPerformanceSecondary)
}
if test.isStandby {
repState.AddState(consts.ReplicationPerformanceStandby)
}
sysView := logical.TestSystemView()
sysView.ReplicationStateVal = repState
sysView.LocalMountVal = test.isLocal
storage := &logical.InmemStorage{}
conf := &logical.BackendConfig{
StorageView: storage,
System: sysView,
}
b, _ := Backend(context.Background(), conf)
if b == nil {
t.Fatal("failed to create backend")
}
err := b.Backend.Setup(context.Background(), conf)
if err != nil {
t.Fatal(err)
}
// Write a key with the default auto rotate value (0/disabled)
req := &logical.Request{
Storage: storage,
Operation: logical.UpdateOperation,
Path: "keys/test1",
}
resp, err := b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
require.NotNil(t, resp, "expected populated request")
// Write a key with an auto rotate value one day in the future
req = &logical.Request{
Storage: storage,
Operation: logical.UpdateOperation,
Path: "keys/test2",
Data: map[string]interface{}{
"auto_rotate_period": 24 * time.Hour,
},
}
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
require.NotNil(t, resp, "expected populated request")
// Run the rotation check and ensure none of the keys have rotated
b.checkAutoRotateAfter = time.Now()
if err = b.autoRotateKeys(context.Background(), &logical.Request{Storage: storage}); err != nil {
t.Fatal(err)
}
req = &logical.Request{
Storage: storage,
Operation: logical.ReadOperation,
Path: "keys/test1",
}
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.Data["latest_version"] != 1 {
t.Fatalf("incorrect latest_version found, got: %d, want: %d", resp.Data["latest_version"], 1)
}
req.Path = "keys/test2"
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.Data["latest_version"] != 1 {
t.Fatalf("incorrect latest_version found, got: %d, want: %d", resp.Data["latest_version"], 1)
}
// Update auto rotate period on one key to be one nanosecond
p, _, err := b.GetPolicy(context.Background(), keysutil.PolicyRequest{
Storage: storage,
Name: "test2",
}, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
if p == nil {
t.Fatal("expected non-nil policy")
}
p.AutoRotatePeriod = time.Nanosecond
err = p.Persist(context.Background(), storage)
if err != nil {
t.Fatal(err)
}
// Run the rotation check and validate the state of key rotations
b.checkAutoRotateAfter = time.Now()
if err = b.autoRotateKeys(context.Background(), &logical.Request{Storage: storage}); err != nil {
t.Fatal(err)
}
req = &logical.Request{
Storage: storage,
Operation: logical.ReadOperation,
Path: "keys/test1",
}
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
if resp.Data["latest_version"] != 1 {
t.Fatalf("incorrect latest_version found, got: %d, want: %d", resp.Data["latest_version"], 1)
}
req.Path = "keys/test2"
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp == nil {
t.Fatal("expected non-nil response")
}
expectedVersion := 1
if test.shouldRotate {
expectedVersion = 2
}
if resp.Data["latest_version"] != expectedVersion {
t.Fatalf("incorrect latest_version found, got: %d, want: %d", resp.Data["latest_version"], expectedVersion)
}
},
)
}
}
func TestTransit_AEAD(t *testing.T) {
testTransit_AEAD(t, "aes128-gcm96")
testTransit_AEAD(t, "aes256-gcm96")
testTransit_AEAD(t, "chacha20-poly1305")
}
func testTransit_AEAD(t *testing.T, keyType string) {
var resp *logical.Response
var err error
b, storage := createBackendWithStorage(t)
keyReq := &logical.Request{
Path: "keys/aead",
Operation: logical.UpdateOperation,
Data: map[string]interface{}{
"type": keyType,
},
Storage: storage,
}
resp, err = b.HandleRequest(context.Background(), keyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA==" // "the quick brown fox"
associated := "U3BoaW54IG9mIGJsYWNrIHF1YXJ0eiwganVkZ2UgbXkgdm93Lgo=" // "Sphinx of black quartz, judge my vow."
// Basic encrypt/decrypt should work.
encryptReq := &logical.Request{
Path: "encrypt/aead",
Operation: logical.UpdateOperation,
Storage: storage,
Data: map[string]interface{}{
"plaintext": plaintext,
},
}
resp, err = b.HandleRequest(context.Background(), encryptReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
ciphertext1 := resp.Data["ciphertext"].(string)
decryptReq := &logical.Request{
Path: "decrypt/aead",
Operation: logical.UpdateOperation,
Storage: storage,
Data: map[string]interface{}{
"ciphertext": ciphertext1,
},
}
resp, err = b.HandleRequest(context.Background(), decryptReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
decryptedPlaintext := resp.Data["plaintext"]
if plaintext != decryptedPlaintext {
t.Fatalf("bad: plaintext; expected: %q\nactual: %q", plaintext, decryptedPlaintext)
}
// Using associated as ciphertext should fail.
decryptReq.Data["ciphertext"] = associated
resp, err = b.HandleRequest(context.Background(), decryptReq)
if err == nil || (resp != nil && !resp.IsError()) {
t.Fatalf("bad expected error: err: %v\nresp: %#v", err, resp)
}
// Redoing the above with additional data should work.
encryptReq.Data["associated_data"] = associated
resp, err = b.HandleRequest(context.Background(), encryptReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
ciphertext2 := resp.Data["ciphertext"].(string)
decryptReq.Data["ciphertext"] = ciphertext2
decryptReq.Data["associated_data"] = associated
resp, err = b.HandleRequest(context.Background(), decryptReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: err: %v\nresp: %#v", err, resp)
}
decryptedPlaintext = resp.Data["plaintext"]
if plaintext != decryptedPlaintext {
t.Fatalf("bad: plaintext; expected: %q\nactual: %q", plaintext, decryptedPlaintext)
}
// Removing the associated_data should break the decryption.
decryptReq.Data = map[string]interface{}{
"ciphertext": ciphertext2,
}
resp, err = b.HandleRequest(context.Background(), decryptReq)
if err == nil || (resp != nil && !resp.IsError()) {
t.Fatalf("bad expected error: err: %v\nresp: %#v", err, resp)
}
// Using a valid ciphertext with associated_data should also break the
// decryption.
decryptReq.Data["ciphertext"] = ciphertext1
decryptReq.Data["associated_data"] = associated
resp, err = b.HandleRequest(context.Background(), decryptReq)
if err == nil || (resp != nil && !resp.IsError()) {
t.Fatalf("bad expected error: err: %v\nresp: %#v", err, resp)
}
}
Create CSR in Transit, sign with PKI (#17630) Execute with: $ go test -v -run=TestTransitPKICSR github.com/hashicorp/vault/builtin/logical/transit ... backend_test.go:1843: csr: -----BEGIN CERTIFICATE REQUEST----- MIICXjCCAUYCAQAwGTEXMBUGA1UEAxMOZGFkZ2FyY29ycC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD8GUy2Rut9ILPXH/Ef7lEaYijuBB9wogd hKD3uJyfK5PqBqM8166UsrP7Y+bWkwDrMke3aDxXRNybys33kIc8KfGwS3omNYd3 17KN1D4ZgQ+oW6xISa3ISOl4D7XeFtHeTP0U1plVXBd9kqTlo4YPlUF/kTfqmxDu 2a41BIS5HlORdLLG+jQ3shRgwHANONBhlaUnIqEeykdW8/iEBlqoYlMzty9W724R 2mKk0FzrVAZ/X5ZO992dAMrQDvc3Nofl+ddzbElBJLumrcDSwALFVge+ag1N48kE CCfxjizEykGdCrR+VELb8b33IgFf6EOVRnS5Qy8whmw943v5Oru5AgMBAAGgADAN BgkqhkiG9w0BAQsFAAOCAQEAdg9SwbrWszMmz60JWQPPfwW+XhzR0MdY82adK8P6 9xpWyJU+U649tAFQb+PCT1OcU7ETd59QcEV38VLndBPWhotTXl5oB5XAqg2bkKHV nLc0cGwyxBSs77LALc//m2f5v2otO9fLOmuM2RMfD02ZUliBmZUzeaUIJYEfT+cS M60uLKJvnNBu5xH1q0oG9P0uNkpEX+QGx6SwhR1/41pmygiUR+uwJxxuRGMvECoN dsHZtzi7ftEHBJ9tk94hd/RFnDsvWlHGyfRWhALNtbo6QjHxjBJIFKh+GHlI8Tnf 6YWvD0VIodE609+RlCrhFlGd+3NUSt0b/f0bgkMJLzLqEw== -----END CERTIFICATE REQUEST----- backend_test.go:1878: root: -----BEGIN CERTIFICATE----- MIIDHTCCAgWgAwIBAgIUIwCzCdrsgkcNOi5liRNHeH+n+tUwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MTIyMTQ1NzExWjAWMRQwEgYDVQQDEwtQS0kgUm9vdCBYMTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMdM65f5p3fLwQP1sezBRFqAxUZhOQwnnnp8mFXp 3fIF9pqLMzNvyd+bCUXv+aFalX4KY1iOoKVHJWwtpXMoKn40U+DZkapR9CsVQt5Q 9xzIcuPPuI+/oNwU4qB9mAuwG+U7KLosGnQOR3NI02A4dnl5I0z8Y/DJLz29GP/P 1zPYMBRBpkMz4F2Xr0w6tTXWDsmqZ9j7ukBDoizmnB2xfKzSjCVmQvXa71UlqbG9 td75LCgpiQh/50mHFHs6RKtqrlFUY5BtPPs+tHUf4nklieIzbAEwA8Fbq4d/Xpq1 HRoRvWj3nelX/h/IRlj/VKJssd1ZL+1kdzxKB4N6AFC1nusCAwEAAaNjMGEwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCniHbjHy/UG ShROBOiikqxCe+OkMB8GA1UdIwQYMBaAFCniHbjHy/UGShROBOiikqxCe+OkMA0G CSqGSIb3DQEBCwUAA4IBAQBSKnl154oyc1Rncm4sr/1f1QM5rCaw/lqgISfvki8m t6yyxQL+9lDpebFjBDTL5teRzuMYyqN4pRkIhpITDGmFXRpEOv14mcbASX7nPBEN bYXhOh1UC8a0CLzT2ll0ERFNnUEPRi0s0ONRm3lIZAV3Mzf4sOdwfRwmP33hBe/1 V9D7Lcx5N84EPrvGC/r8F/PsVKHyKFS46qB1MvhMppRG6fJ2cFmg5UGwdKdmxuvz FoT+RaTLkgcQgkDuYClNco5OVIM7Bd4JTNK3WbqvtGklOHslrz+ND0eMYM/LK+ZS zNM35nzK6QaN2M4IO4Wuy3y2yu8xllEfmssXwAtTi4wk -----END CERTIFICATE----- backend_test.go:1879: leaf: -----BEGIN CERTIFICATE----- MIIDDzCCAfegAwIBAgIUBGeUSi0p3ffndZqgvlBvMvn8qgMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLUEtJIFJvb3QgWDEwHhcNMjIxMDIxMTQ1NjQyWhcNMjIx MDIxMTUwNzEyWjAZMRcwFQYDVQQDEw5kYWRnYXJjb3JwLmNvbTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMPwZTLZG630gs9cf8R/uURpiKO4EH3CiB2E oPe4nJ8rk+oGozzXrpSys/tj5taTAOsyR7doPFdE3JvKzfeQhzwp8bBLeiY1h3fX so3UPhmBD6hbrEhJrchI6XgPtd4W0d5M/RTWmVVcF32SpOWjhg+VQX+RN+qbEO7Z rjUEhLkeU5F0ssb6NDeyFGDAcA040GGVpScioR7KR1bz+IQGWqhiUzO3L1bvbhHa YqTQXOtUBn9flk733Z0AytAO9zc2h+X513NsSUEku6atwNLAAsVWB75qDU3jyQQI J/GOLMTKQZ0KtH5UQtvxvfciAV/oQ5VGdLlDLzCGbD3je/k6u7kCAwEAAaNSMFAw DgYDVR0PAQH/BAQDAgOoMB0GA1UdDgQWBBSRCRR/62DjS1kjWHrVQ0Y58leUbDAf BgNVHSMEGDAWgBQp4h24x8v1BkoUTgToopKsQnvjpDANBgkqhkiG9w0BAQsFAAOC AQEAvWPLGqtC1SRy61Y17HtJ0giDUwpCZbOUkAwtdDAnKIhR1v4wrlY3sKUBLuhK xOJIWfVlCnPUt5uTnPaWyVyUfry6YNerish1k7ny/R1n58PjsPhUg8GJB9HHsME+ gQQ22z6D/87n0bEE8PaTzIU6+cVHoIBJ0rqzjZVkBs0cEjf+l40RPP1h+ZiTw27u CR2iXmHJ9TQ8ZBWygIhxB9JOMbk5jpH6w6wJqq8XK9zuC1hlYbXH1K5KvZJxAPlh CJkoq2KxaIwByTHjRdGjDogSibsyY+CxQUnktefXb6tYKvFTpUFsh1fjQRCwUrlD SExMRHhFJBHfyPD1w26N3IjRlg== -----END CERTIFICATE----- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-11-23 17:57:23 +00:00
// Hack: use Transit as a signer.
type transitKey struct {
public any
mount string
name string
t *testing.T
client *api.Client
}
func (k *transitKey) Public() crypto.PublicKey {
return k.public
}
func (k *transitKey) Sign(_ io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
hash := opts.(crypto.Hash)
if hash.String() != "SHA-256" {
return nil, fmt.Errorf("unknown hash algorithm: %v", opts)
}
resp, err := k.client.Logical().Write(k.mount+"/sign/"+k.name, map[string]interface{}{
"hash_algorithm": "sha2-256",
"input": base64.StdEncoding.EncodeToString(digest),
"prehashed": true,
"signature_algorithm": "pkcs1v15",
})
if err != nil {
return nil, fmt.Errorf("failed to sign data: %w", err)
}
require.NotNil(k.t, resp)
require.NotNil(k.t, resp.Data)
require.NotNil(k.t, resp.Data["signature"])
rawSig := resp.Data["signature"].(string)
sigParts := strings.Split(rawSig, ":")
decoded, err := base64.StdEncoding.DecodeString(sigParts[2])
if err != nil {
return nil, fmt.Errorf("failed to decode signature (%v): %w", rawSig, err)
}
return decoded, nil
}
func TestTransitPKICSR(t *testing.T) {
coreConfig := &vault.CoreConfig{
LogicalBackends: map[string]logical.Factory{
"transit": Factory,
"pki": pki.Factory,
},
}
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
HandlerFunc: vaulthttp.Handler,
})
cluster.Start()
defer cluster.Cleanup()
cores := cluster.Cores
vault.TestWaitActive(t, cores[0].Core)
client := cores[0].Client
// Mount transit, write a key.
err := client.Sys().Mount("transit", &api.MountInput{
Type: "transit",
})
require.NoError(t, err)
_, err = client.Logical().Write("transit/keys/leaf", map[string]interface{}{
"type": "rsa-2048",
})
require.NoError(t, err)
resp, err := client.Logical().Read("transit/keys/leaf")
require.NoError(t, err)
require.NotNil(t, resp)
keys := resp.Data["keys"].(map[string]interface{})
require.NotNil(t, keys)
keyData := keys["1"].(map[string]interface{})
require.NotNil(t, keyData)
keyPublic := keyData["public_key"].(string)
require.NotEmpty(t, keyPublic)
pemBlock, _ := pem.Decode([]byte(keyPublic))
require.NotNil(t, pemBlock)
pubKey, err := x509.ParsePKIXPublicKey(pemBlock.Bytes)
require.NoError(t, err)
require.NotNil(t, pubKey)
// Setup a new CSR...
var reqTemplate x509.CertificateRequest
reqTemplate.PublicKey = pubKey
reqTemplate.PublicKeyAlgorithm = x509.RSA
reqTemplate.Subject.CommonName = "dadgarcorp.com"
var k transitKey
k.public = pubKey
k.mount = "transit"
k.name = "leaf"
k.t = t
k.client = client
req, err := x509.CreateCertificateRequest(cryptoRand.Reader, &reqTemplate, &k)
require.NoError(t, err)
require.NotNil(t, req)
reqPEM := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE REQUEST",
Bytes: req,
})
t.Logf("csr: %v", string(reqPEM))
// Mount PKI, generate a root, sign this CSR.
err = client.Sys().Mount("pki", &api.MountInput{
Type: "pki",
})
require.NoError(t, err)
resp, err = client.Logical().Write("pki/root/generate/internal", map[string]interface{}{
"common_name": "PKI Root X1",
})
require.NoError(t, err)
require.NotNil(t, resp)
rootCertPEM := resp.Data["certificate"].(string)
pemBlock, _ = pem.Decode([]byte(rootCertPEM))
require.NotNil(t, pemBlock)
rootCert, err := x509.ParseCertificate(pemBlock.Bytes)
require.NoError(t, err)
resp, err = client.Logical().Write("pki/issuer/default/sign-verbatim", map[string]interface{}{
"csr": string(reqPEM),
"ttl": "10m",
})
require.NoError(t, err)
require.NotNil(t, resp)
leafCertPEM := resp.Data["certificate"].(string)
pemBlock, _ = pem.Decode([]byte(leafCertPEM))
require.NotNil(t, pemBlock)
leafCert, err := x509.ParseCertificate(pemBlock.Bytes)
require.NoError(t, err)
require.NoError(t, leafCert.CheckSignatureFrom(rootCert))
t.Logf("root: %v", rootCertPEM)
t.Logf("leaf: %v", leafCertPEM)
}
Provide public key encryption via transit engine (#17934) * import rsa and ecdsa public keys * allow import_version to update public keys - wip * allow import_version to update public keys * move check key fields into func * put private/public keys in same switch cases * fix method in UpdateKeyVersion * move asymmetrics keys switch to its own method - WIP * test import public and update it with private counterpart * test import public keys * use public_key to encrypt if RSAKey is not present and failed to decrypt if key version does not have a private key * move key to KeyEntry parsing from Policy to KeyEntry method * move extracting of key from input fields into helper function * change back policy Import signature to keep backwards compatibility and add new method to import private or public keys * test import with imported public rsa and ecdsa keys * descriptions and error messages * error messages, remove comments and unused code * changelog * documentation - wip * suggested changes - error messages/typos and unwrap public key passed * fix unwrap key error * fail if both key fields have been set * fix in extractKeyFromFields, passing a PolicyRequest wouldn't not work * checks for read, sign and verify endpoints so they don't return errors when a private key was not imported and tests * handle panic on "export key" endpoint if imported key is public * fmt * remove 'isPrivateKey' argument from 'UpdateKeyVersion' and 'parseFromKey' methods also: rename 'UpdateKeyVersion' method to 'ImportPrivateKeyForVersion' and 'IsPublicKeyImported' to 'IsPrivateKeyMissing' * delete 'RSAPublicKey' when private key is imported * path_export: return public_key for ecdsa and rsa when there's no private key imported * allow signed data validation with pss algorithm * remove NOTE comment * fix typo in EC public key export where empty derBytes was being used * export rsa public key in pkcs8 format instead of pkcs1 and improve test * change logic on how check for is private key missing is calculated --------- Co-authored-by: Alexander Scheel <alex.scheel@hashicorp.com>
2023-05-11 11:56:46 +00:00
func TestTransit_ReadPublicKeyImported(t *testing.T) {
testTransit_ReadPublicKeyImported(t, "rsa-2048")
testTransit_ReadPublicKeyImported(t, "ecdsa-p256")
}
func testTransit_ReadPublicKeyImported(t *testing.T, keyType string) {
generateKeys(t)
b, s := createBackendWithStorage(t)
keyID, err := uuid.GenerateUUID()
if err != nil {
t.Fatalf("failed to generate key ID: %s", err)
}
// Get key
privateKey := getKey(t, keyType)
publicKeyBytes, err := getPublicKey(privateKey, keyType)
if err != nil {
t.Fatalf("failed to extract the public key: %s", err)
}
// Import key
importReq := &logical.Request{
Storage: s,
Operation: logical.UpdateOperation,
Path: fmt.Sprintf("keys/%s/import", keyID),
Data: map[string]interface{}{
"public_key": publicKeyBytes,
"type": keyType,
},
}
importResp, err := b.HandleRequest(context.Background(), importReq)
if err != nil || (importResp != nil && importResp.IsError()) {
t.Fatalf("failed to import public key. err: %s\nresp: %#v", err, importResp)
}
// Read key
readReq := &logical.Request{
Operation: logical.ReadOperation,
Path: "keys/" + keyID,
Storage: s,
}
readResp, err := b.HandleRequest(context.Background(), readReq)
if err != nil || (readResp != nil && readResp.IsError()) {
t.Fatalf("failed to read key. err: %s\nresp: %#v", err, readResp)
}
}
func TestTransit_SignWithImportedPublicKey(t *testing.T) {
testTransit_SignWithImportedPublicKey(t, "rsa-2048")
testTransit_SignWithImportedPublicKey(t, "ecdsa-p256")
}
func testTransit_SignWithImportedPublicKey(t *testing.T, keyType string) {
generateKeys(t)
b, s := createBackendWithStorage(t)
keyID, err := uuid.GenerateUUID()
if err != nil {
t.Fatalf("failed to generate key ID: %s", err)
}
// Get key
privateKey := getKey(t, keyType)
publicKeyBytes, err := getPublicKey(privateKey, keyType)
if err != nil {
t.Fatalf("failed to extract the public key: %s", err)
}
// Import key
importReq := &logical.Request{
Storage: s,
Operation: logical.UpdateOperation,
Path: fmt.Sprintf("keys/%s/import", keyID),
Data: map[string]interface{}{
"public_key": publicKeyBytes,
"type": keyType,
},
}
importResp, err := b.HandleRequest(context.Background(), importReq)
if err != nil || (importResp != nil && importResp.IsError()) {
t.Fatalf("failed to import public key. err: %s\nresp: %#v", err, importResp)
}
// Sign text
signReq := &logical.Request{
Path: "sign/" + keyID,
Operation: logical.UpdateOperation,
Storage: s,
Data: map[string]interface{}{
"plaintext": base64.StdEncoding.EncodeToString([]byte(testPlaintext)),
},
}
_, err = b.HandleRequest(context.Background(), signReq)
if err == nil {
t.Fatalf("expected error, should have failed to sign input")
}
}
func TestTransit_VerifyWithImportedPublicKey(t *testing.T) {
generateKeys(t)
keyType := "rsa-2048"
b, s := createBackendWithStorage(t)
keyID, err := uuid.GenerateUUID()
if err != nil {
t.Fatalf("failed to generate key ID: %s", err)
}
// Get key
privateKey := getKey(t, keyType)
publicKeyBytes, err := getPublicKey(privateKey, keyType)
if err != nil {
t.Fatal(err)
}
// Retrieve public wrapping key
wrappingKey, err := b.getWrappingKey(context.Background(), s)
if err != nil || wrappingKey == nil {
t.Fatalf("failed to retrieve public wrapping key: %s", err)
}
privWrappingKey := wrappingKey.Keys[strconv.Itoa(wrappingKey.LatestVersion)].RSAKey
pubWrappingKey := &privWrappingKey.PublicKey
// generate ciphertext
importBlob := wrapTargetKeyForImport(t, pubWrappingKey, privateKey, keyType, "SHA256")
// Import private key
importReq := &logical.Request{
Storage: s,
Operation: logical.UpdateOperation,
Path: fmt.Sprintf("keys/%s/import", keyID),
Data: map[string]interface{}{
"ciphertext": importBlob,
"type": keyType,
},
}
importResp, err := b.HandleRequest(context.Background(), importReq)
if err != nil || (importResp != nil && importResp.IsError()) {
t.Fatalf("failed to import key. err: %s\nresp: %#v", err, importResp)
}
// Sign text
signReq := &logical.Request{
Storage: s,
Path: "sign/" + keyID,
Operation: logical.UpdateOperation,
Data: map[string]interface{}{
"plaintext": base64.StdEncoding.EncodeToString([]byte(testPlaintext)),
},
}
signResp, err := b.HandleRequest(context.Background(), signReq)
if err != nil || (signResp != nil && signResp.IsError()) {
t.Fatalf("failed to sign plaintext. err: %s\nresp: %#v", err, signResp)
}
// Get signature
signature := signResp.Data["signature"].(string)
// Import new key as public key
importPubReq := &logical.Request{
Storage: s,
Operation: logical.UpdateOperation,
Path: fmt.Sprintf("keys/%s/import", "public-key-rsa"),
Data: map[string]interface{}{
"public_key": publicKeyBytes,
"type": keyType,
},
}
importPubResp, err := b.HandleRequest(context.Background(), importPubReq)
if err != nil || (importPubResp != nil && importPubResp.IsError()) {
t.Fatalf("failed to import public key. err: %s\nresp: %#v", err, importPubResp)
}
// Verify signed text
verifyReq := &logical.Request{
Path: "verify/public-key-rsa",
Operation: logical.UpdateOperation,
Storage: s,
Data: map[string]interface{}{
"input": base64.StdEncoding.EncodeToString([]byte(testPlaintext)),
"signature": signature,
},
}
verifyResp, err := b.HandleRequest(context.Background(), verifyReq)
if err != nil || (importResp != nil && verifyResp.IsError()) {
t.Fatalf("failed to verify signed data. err: %s\nresp: %#v", err, importResp)
}
}
func TestTransit_ExportPublicKeyImported(t *testing.T) {
testTransit_ExportPublicKeyImported(t, "rsa-2048")
testTransit_ExportPublicKeyImported(t, "ecdsa-p256")
}
func testTransit_ExportPublicKeyImported(t *testing.T, keyType string) {
generateKeys(t)
b, s := createBackendWithStorage(t)
keyID, err := uuid.GenerateUUID()
if err != nil {
t.Fatalf("failed to generate key ID: %s", err)
}
// Get key
privateKey := getKey(t, keyType)
publicKeyBytes, err := getPublicKey(privateKey, keyType)
if err != nil {
t.Fatalf("failed to extract the public key: %s", err)
}
// Import key
importReq := &logical.Request{
Storage: s,
Operation: logical.UpdateOperation,
Path: fmt.Sprintf("keys/%s/import", keyID),
Data: map[string]interface{}{
"public_key": publicKeyBytes,
"type": keyType,
"exportable": true,
},
}
importResp, err := b.HandleRequest(context.Background(), importReq)
if err != nil || (importResp != nil && importResp.IsError()) {
t.Fatalf("failed to import public key. err: %s\nresp: %#v", err, importResp)
}
// Export key
exportReq := &logical.Request{
Operation: logical.ReadOperation,
Path: fmt.Sprintf("export/signing-key/%s/latest", keyID),
Storage: s,
}
exportResp, err := b.HandleRequest(context.Background(), exportReq)
if err != nil || (exportResp != nil && exportResp.IsError()) {
t.Fatalf("failed to export key. err: %v\nresp: %#v", err, exportResp)
}
responseKeys, exist := exportResp.Data["keys"]
if !exist {
t.Fatal("expected response data to hold a 'keys' field")
}
exportedKeyBytes := responseKeys.(map[string]string)["1"]
exportedKeyBlock, _ := pem.Decode([]byte(exportedKeyBytes))
publicKeyBlock, _ := pem.Decode(publicKeyBytes)
if !reflect.DeepEqual(publicKeyBlock.Bytes, exportedKeyBlock.Bytes) {
t.Fatal("exported key bytes should have matched with imported key")
}
}