mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +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" | ||||
| 	"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/logical" | ||||
| 	"github.com/hashicorp/vault/vault" | ||||
|  | ||||
| 	"github.com/hashicorp/go-hclog" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
|  | ||||
| @@ -469,6 +474,169 @@ func TestIntegration_AutoIssuer(t *testing.T) { | ||||
| 	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) { | ||||
| 	return genTestRootCaWithIssuerName(t, b, s, "") | ||||
| } | ||||
|   | ||||
| @@ -8,7 +8,6 @@ import ( | ||||
| 	"crypto" | ||||
| 	"crypto/tls" | ||||
| 	"crypto/x509" | ||||
| 	"encoding/pem" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| @@ -19,16 +18,9 @@ import ( | ||||
| 	"testing" | ||||
| 	"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-retryablehttp" | ||||
| 	lru "github.com/hashicorp/golang-lru" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"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) | ||||
|  | ||||
| func testLogFactory() hclog.Logger { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Alexander Scheel
					Alexander Scheel