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:
parent
879844d300
commit
f0279b0d31
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue