mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	Move OCSP/PKI interop test to PKI engine (#20273)
This prevents SDK from having a circular import on the main Vault package. Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
This commit is contained in:
		| @@ -14,9 +14,14 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/hashicorp/vault/api" | ||||||
|  | 	vaulthttp "github.com/hashicorp/vault/http" | ||||||
|  | 	vaultocsp "github.com/hashicorp/vault/sdk/helper/ocsp" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/testhelpers/schema" | 	"github.com/hashicorp/vault/sdk/helper/testhelpers/schema" | ||||||
|  |  | ||||||
| 	"github.com/hashicorp/vault/sdk/logical" | 	"github.com/hashicorp/vault/sdk/logical" | ||||||
|  | 	"github.com/hashicorp/vault/vault" | ||||||
|  |  | ||||||
|  | 	"github.com/hashicorp/go-hclog" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -469,6 +474,169 @@ func TestIntegration_AutoIssuer(t *testing.T) { | |||||||
| 	require.Equal(t, issuerIdOneReimported, resp.Data["default"]) | 	require.Equal(t, issuerIdOneReimported, resp.Data["default"]) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestIntegrationOCSPClientWithPKI(t *testing.T) { | ||||||
|  | 	t.Parallel() | ||||||
|  |  | ||||||
|  | 	coreConfig := &vault.CoreConfig{ | ||||||
|  | 		LogicalBackends: map[string]logical.Factory{ | ||||||
|  | 			"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 | ||||||
|  |  | ||||||
|  | 	err := client.Sys().Mount("pki", &api.MountInput{ | ||||||
|  | 		Type: "pki", | ||||||
|  | 		Config: api.MountConfigInput{ | ||||||
|  | 			DefaultLeaseTTL: "16h", | ||||||
|  | 			MaxLeaseTTL:     "32h", | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	resp, err := client.Logical().Write("pki/root/generate/internal", map[string]interface{}{ | ||||||
|  | 		"ttl":         "40h", | ||||||
|  | 		"common_name": "Root R1", | ||||||
|  | 		"key_type":    "ec", | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.NotNil(t, resp) | ||||||
|  | 	require.NotNil(t, resp.Data) | ||||||
|  | 	require.NotEmpty(t, resp.Data["issuer_id"]) | ||||||
|  | 	rootIssuerId := resp.Data["issuer_id"].(string) | ||||||
|  |  | ||||||
|  | 	// Set URLs pointing to the issuer. | ||||||
|  | 	_, err = client.Logical().Write("pki/config/cluster", map[string]interface{}{ | ||||||
|  | 		"path":     client.Address() + "/v1/pki", | ||||||
|  | 		"aia_path": client.Address() + "/v1/pki", | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	_, err = client.Logical().Write("pki/config/urls", map[string]interface{}{ | ||||||
|  | 		"enable_templating":       true, | ||||||
|  | 		"crl_distribution_points": "{{cluster_aia_path}}/issuer/{{issuer_id}}/crl/der", | ||||||
|  | 		"issuing_certificates":    "{{cluster_aia_path}}/issuer/{{issuer_id}}/der", | ||||||
|  | 		"ocsp_servers":            "{{cluster_aia_path}}/ocsp", | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Build an intermediate CA | ||||||
|  | 	resp, err = client.Logical().Write("pki/intermediate/generate/internal", map[string]interface{}{ | ||||||
|  | 		"common_name": "Int X1", | ||||||
|  | 		"key_type":    "ec", | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.NotNil(t, resp) | ||||||
|  | 	require.NotNil(t, resp.Data) | ||||||
|  | 	require.NotEmpty(t, resp.Data["csr"]) | ||||||
|  | 	intermediateCSR := resp.Data["csr"].(string) | ||||||
|  |  | ||||||
|  | 	resp, err = client.Logical().Write("pki/root/sign-intermediate", map[string]interface{}{ | ||||||
|  | 		"csr": intermediateCSR, | ||||||
|  | 		"ttl": "20h", | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.NotNil(t, resp) | ||||||
|  | 	require.NotNil(t, resp.Data) | ||||||
|  | 	require.NotEmpty(t, resp.Data["certificate"]) | ||||||
|  | 	intermediateCert := resp.Data["certificate"] | ||||||
|  |  | ||||||
|  | 	resp, err = client.Logical().Write("pki/intermediate/set-signed", map[string]interface{}{ | ||||||
|  | 		"certificate": intermediateCert, | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.NotNil(t, resp) | ||||||
|  | 	require.NotNil(t, resp.Data) | ||||||
|  | 	require.NotEmpty(t, resp.Data["imported_issuers"]) | ||||||
|  | 	rawImportedIssuers := resp.Data["imported_issuers"].([]interface{}) | ||||||
|  | 	require.Equal(t, len(rawImportedIssuers), 1) | ||||||
|  | 	importedIssuer := rawImportedIssuers[0].(string) | ||||||
|  | 	require.NotEmpty(t, importedIssuer) | ||||||
|  |  | ||||||
|  | 	// Set intermediate as default. | ||||||
|  | 	_, err = client.Logical().Write("pki/config/issuers", map[string]interface{}{ | ||||||
|  | 		"default": importedIssuer, | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Setup roles for root, intermediate. | ||||||
|  | 	_, err = client.Logical().Write("pki/roles/example-root", map[string]interface{}{ | ||||||
|  | 		"allowed_domains":  "example.com", | ||||||
|  | 		"allow_subdomains": "true", | ||||||
|  | 		"max_ttl":          "1h", | ||||||
|  | 		"key_type":         "ec", | ||||||
|  | 		"issuer_ref":       rootIssuerId, | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	_, err = client.Logical().Write("pki/roles/example-int", map[string]interface{}{ | ||||||
|  | 		"allowed_domains":  "example.com", | ||||||
|  | 		"allow_subdomains": "true", | ||||||
|  | 		"max_ttl":          "1h", | ||||||
|  | 		"key_type":         "ec", | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Issue certs and validate them against OCSP. | ||||||
|  | 	for _, path := range []string{"pki/issue/example-int", "pki/issue/example-root"} { | ||||||
|  | 		t.Logf("Validating against path: %v", path) | ||||||
|  | 		resp, err = client.Logical().Write(path, map[string]interface{}{ | ||||||
|  | 			"common_name": "test.example.com", | ||||||
|  | 			"ttl":         "5m", | ||||||
|  | 		}) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 		require.NotNil(t, resp) | ||||||
|  | 		require.NotNil(t, resp.Data) | ||||||
|  | 		require.NotEmpty(t, resp.Data["certificate"]) | ||||||
|  | 		require.NotEmpty(t, resp.Data["issuing_ca"]) | ||||||
|  | 		require.NotEmpty(t, resp.Data["serial_number"]) | ||||||
|  |  | ||||||
|  | 		certPEM := resp.Data["certificate"].(string) | ||||||
|  | 		certBlock, _ := pem.Decode([]byte(certPEM)) | ||||||
|  | 		require.NotNil(t, certBlock) | ||||||
|  | 		cert, err := x509.ParseCertificate(certBlock.Bytes) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 		require.NotNil(t, cert) | ||||||
|  |  | ||||||
|  | 		issuerPEM := resp.Data["issuing_ca"].(string) | ||||||
|  | 		issuerBlock, _ := pem.Decode([]byte(issuerPEM)) | ||||||
|  | 		require.NotNil(t, issuerBlock) | ||||||
|  | 		issuer, err := x509.ParseCertificate(issuerBlock.Bytes) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 		require.NotNil(t, issuer) | ||||||
|  |  | ||||||
|  | 		serialNumber := resp.Data["serial_number"].(string) | ||||||
|  |  | ||||||
|  | 		testLogger := hclog.New(hclog.DefaultOptions) | ||||||
|  |  | ||||||
|  | 		conf := &vaultocsp.VerifyConfig{ | ||||||
|  | 			OcspFailureMode: vaultocsp.FailOpenFalse, | ||||||
|  | 			ExtraCas:        []*x509.Certificate{cluster.CACert}, | ||||||
|  | 		} | ||||||
|  | 		ocspClient := vaultocsp.New(func() hclog.Logger { | ||||||
|  | 			return testLogger | ||||||
|  | 		}, 10) | ||||||
|  |  | ||||||
|  | 		err = ocspClient.VerifyLeafCertificate(context.Background(), cert, issuer, conf) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 		_, err = client.Logical().Write("pki/revoke", map[string]interface{}{ | ||||||
|  | 			"serial_number": serialNumber, | ||||||
|  | 		}) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 		err = ocspClient.VerifyLeafCertificate(context.Background(), cert, issuer, conf) | ||||||
|  | 		require.Error(t, err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func genTestRootCa(t *testing.T, b *backend, s logical.Storage) (issuerID, keyID) { | func genTestRootCa(t *testing.T, b *backend, s logical.Storage) (issuerID, keyID) { | ||||||
| 	return genTestRootCaWithIssuerName(t, b, s, "") | 	return genTestRootCaWithIssuerName(t, b, s, "") | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,7 +8,6 @@ import ( | |||||||
| 	"crypto" | 	"crypto" | ||||||
| 	"crypto/tls" | 	"crypto/tls" | ||||||
| 	"crypto/x509" | 	"crypto/x509" | ||||||
| 	"encoding/pem" |  | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
| @@ -19,16 +18,9 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/hashicorp/vault/api" |  | ||||||
| 	"github.com/hashicorp/vault/builtin/logical/pki" |  | ||||||
| 	vaulthttp "github.com/hashicorp/vault/http" |  | ||||||
| 	"github.com/hashicorp/vault/sdk/logical" |  | ||||||
| 	"github.com/hashicorp/vault/vault" |  | ||||||
|  |  | ||||||
| 	"github.com/hashicorp/go-hclog" | 	"github.com/hashicorp/go-hclog" | ||||||
| 	"github.com/hashicorp/go-retryablehttp" | 	"github.com/hashicorp/go-retryablehttp" | ||||||
| 	lru "github.com/hashicorp/golang-lru" | 	lru "github.com/hashicorp/golang-lru" | ||||||
| 	"github.com/stretchr/testify/require" |  | ||||||
| 	"golang.org/x/crypto/ocsp" | 	"golang.org/x/crypto/ocsp" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -432,165 +424,6 @@ func TestCanEarlyExitForOCSP(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestWithVaultPKI(t *testing.T) { |  | ||||||
| 	t.Parallel() |  | ||||||
|  |  | ||||||
| 	coreConfig := &vault.CoreConfig{ |  | ||||||
| 		LogicalBackends: map[string]logical.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 |  | ||||||
|  |  | ||||||
| 	err := client.Sys().Mount("pki", &api.MountInput{ |  | ||||||
| 		Type: "pki", |  | ||||||
| 		Config: api.MountConfigInput{ |  | ||||||
| 			DefaultLeaseTTL: "16h", |  | ||||||
| 			MaxLeaseTTL:     "32h", |  | ||||||
| 		}, |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
|  |  | ||||||
| 	resp, err := client.Logical().Write("pki/root/generate/internal", map[string]interface{}{ |  | ||||||
| 		"ttl":         "40h", |  | ||||||
| 		"common_name": "Root R1", |  | ||||||
| 		"key_type":    "ec", |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
| 	require.NotNil(t, resp) |  | ||||||
| 	require.NotNil(t, resp.Data) |  | ||||||
| 	require.NotEmpty(t, resp.Data["issuer_id"]) |  | ||||||
| 	rootIssuerId := resp.Data["issuer_id"].(string) |  | ||||||
|  |  | ||||||
| 	// Set URLs pointing to the issuer. |  | ||||||
| 	_, err = client.Logical().Write("pki/config/cluster", map[string]interface{}{ |  | ||||||
| 		"path":     client.Address() + "/v1/pki", |  | ||||||
| 		"aia_path": client.Address() + "/v1/pki", |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
|  |  | ||||||
| 	_, err = client.Logical().Write("pki/config/urls", map[string]interface{}{ |  | ||||||
| 		"enable_templating":       true, |  | ||||||
| 		"crl_distribution_points": "{{cluster_aia_path}}/issuer/{{issuer_id}}/crl/der", |  | ||||||
| 		"issuing_certificates":    "{{cluster_aia_path}}/issuer/{{issuer_id}}/der", |  | ||||||
| 		"ocsp_servers":            "{{cluster_aia_path}}/ocsp", |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
|  |  | ||||||
| 	// Build an intermediate CA |  | ||||||
| 	resp, err = client.Logical().Write("pki/intermediate/generate/internal", map[string]interface{}{ |  | ||||||
| 		"common_name": "Int X1", |  | ||||||
| 		"key_type":    "ec", |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
| 	require.NotNil(t, resp) |  | ||||||
| 	require.NotNil(t, resp.Data) |  | ||||||
| 	require.NotEmpty(t, resp.Data["csr"]) |  | ||||||
| 	intermediateCSR := resp.Data["csr"].(string) |  | ||||||
|  |  | ||||||
| 	resp, err = client.Logical().Write("pki/root/sign-intermediate", map[string]interface{}{ |  | ||||||
| 		"csr": intermediateCSR, |  | ||||||
| 		"ttl": "20h", |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
| 	require.NotNil(t, resp) |  | ||||||
| 	require.NotNil(t, resp.Data) |  | ||||||
| 	require.NotEmpty(t, resp.Data["certificate"]) |  | ||||||
| 	intermediateCert := resp.Data["certificate"] |  | ||||||
|  |  | ||||||
| 	resp, err = client.Logical().Write("pki/intermediate/set-signed", map[string]interface{}{ |  | ||||||
| 		"certificate": intermediateCert, |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
| 	require.NotNil(t, resp) |  | ||||||
| 	require.NotNil(t, resp.Data) |  | ||||||
| 	require.NotEmpty(t, resp.Data["imported_issuers"]) |  | ||||||
| 	rawImportedIssuers := resp.Data["imported_issuers"].([]interface{}) |  | ||||||
| 	require.Equal(t, len(rawImportedIssuers), 1) |  | ||||||
| 	importedIssuer := rawImportedIssuers[0].(string) |  | ||||||
| 	require.NotEmpty(t, importedIssuer) |  | ||||||
|  |  | ||||||
| 	// Set intermediate as default. |  | ||||||
| 	_, err = client.Logical().Write("pki/config/issuers", map[string]interface{}{ |  | ||||||
| 		"default": importedIssuer, |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
|  |  | ||||||
| 	// Setup roles for root, intermediate. |  | ||||||
| 	_, err = client.Logical().Write("pki/roles/example-root", map[string]interface{}{ |  | ||||||
| 		"allowed_domains":  "example.com", |  | ||||||
| 		"allow_subdomains": "true", |  | ||||||
| 		"max_ttl":          "1h", |  | ||||||
| 		"key_type":         "ec", |  | ||||||
| 		"issuer_ref":       rootIssuerId, |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
|  |  | ||||||
| 	_, err = client.Logical().Write("pki/roles/example-int", map[string]interface{}{ |  | ||||||
| 		"allowed_domains":  "example.com", |  | ||||||
| 		"allow_subdomains": "true", |  | ||||||
| 		"max_ttl":          "1h", |  | ||||||
| 		"key_type":         "ec", |  | ||||||
| 	}) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
|  |  | ||||||
| 	// Issue certs and validate them against OCSP. |  | ||||||
| 	for _, path := range []string{"pki/issue/example-int", "pki/issue/example-root"} { |  | ||||||
| 		t.Logf("Validating against path: %v", path) |  | ||||||
| 		resp, err = client.Logical().Write(path, map[string]interface{}{ |  | ||||||
| 			"common_name": "test.example.com", |  | ||||||
| 			"ttl":         "5m", |  | ||||||
| 		}) |  | ||||||
| 		require.NoError(t, err) |  | ||||||
| 		require.NotNil(t, resp) |  | ||||||
| 		require.NotNil(t, resp.Data) |  | ||||||
| 		require.NotEmpty(t, resp.Data["certificate"]) |  | ||||||
| 		require.NotEmpty(t, resp.Data["issuing_ca"]) |  | ||||||
| 		require.NotEmpty(t, resp.Data["serial_number"]) |  | ||||||
|  |  | ||||||
| 		certPEM := resp.Data["certificate"].(string) |  | ||||||
| 		certBlock, _ := pem.Decode([]byte(certPEM)) |  | ||||||
| 		require.NotNil(t, certBlock) |  | ||||||
| 		cert, err := x509.ParseCertificate(certBlock.Bytes) |  | ||||||
| 		require.NoError(t, err) |  | ||||||
| 		require.NotNil(t, cert) |  | ||||||
|  |  | ||||||
| 		issuerPEM := resp.Data["issuing_ca"].(string) |  | ||||||
| 		issuerBlock, _ := pem.Decode([]byte(issuerPEM)) |  | ||||||
| 		require.NotNil(t, issuerBlock) |  | ||||||
| 		issuer, err := x509.ParseCertificate(issuerBlock.Bytes) |  | ||||||
| 		require.NoError(t, err) |  | ||||||
| 		require.NotNil(t, issuer) |  | ||||||
|  |  | ||||||
| 		serialNumber := resp.Data["serial_number"].(string) |  | ||||||
|  |  | ||||||
| 		conf := &VerifyConfig{ |  | ||||||
| 			OcspFailureMode: FailOpenFalse, |  | ||||||
| 			ExtraCas:        []*x509.Certificate{cluster.CACert}, |  | ||||||
| 		} |  | ||||||
| 		ocspClient := New(testLogFactory, 10) |  | ||||||
|  |  | ||||||
| 		err = ocspClient.VerifyLeafCertificate(context.Background(), cert, issuer, conf) |  | ||||||
| 		require.NoError(t, err) |  | ||||||
|  |  | ||||||
| 		_, err = client.Logical().Write("pki/revoke", map[string]interface{}{ |  | ||||||
| 			"serial_number": serialNumber, |  | ||||||
| 		}) |  | ||||||
| 		require.NoError(t, err) |  | ||||||
|  |  | ||||||
| 		err = ocspClient.VerifyLeafCertificate(context.Background(), cert, issuer, conf) |  | ||||||
| 		require.Error(t, err) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| var testLogger = hclog.New(hclog.DefaultOptions) | var testLogger = hclog.New(hclog.DefaultOptions) | ||||||
|  |  | ||||||
| func testLogFactory() hclog.Logger { | func testLogFactory() hclog.Logger { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Alexander Scheel
					Alexander Scheel