Skip to content

Commit

Permalink
release/1.14.x: Manual backport of #19095 (#19148)
Browse files Browse the repository at this point in the history
  • Loading branch information
cthain authored Oct 11, 2023
1 parent 020fffa commit 0587997
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .changelog/19095.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
ca: ensure Vault CA provider respects Vault Enterprise namespace configuration.
```
104 changes: 98 additions & 6 deletions agent/connect/ca/provider_vault_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,85 @@ func TestVaultCAProvider_ConsulManaged(t *testing.T) {
})
}

func TestVaultCAProvider_EnterpriseNamespace(t *testing.T) {
SkipIfVaultNotPresent(t, vaultRequirements{Enterprise: true})
t.Parallel()

cases := map[string]struct {
namespaces map[string]string
}{
"no configured namespaces": {},
"only base namespace provided": {namespaces: map[string]string{"Namespace": "base-ns"}},
"only root namespace provided": {namespaces: map[string]string{"RootPKINamespace": "root-pki-ns"}},
"only intermediate namespace provided": {namespaces: map[string]string{"IntermediatePKINamespace": "int-pki-ns"}},
"base and root namespace provided": {
namespaces: map[string]string{
"Namespace": "base-ns",
"RootPKINamespace": "root-pki-ns",
},
},
"base and intermediate namespace provided": {
namespaces: map[string]string{
"Namespace": "base-ns",
"IntermediatePKINamespace": "int-pki-ns",
},
},
"root and intermediate namespace provided": {
namespaces: map[string]string{
"RootPKINamespace": "root-pki-ns",
"IntermediatePKINamespace": "int-pki-ns",
},
},
"all namespaces provided": {
namespaces: map[string]string{
"Namespace": "base-ns",
"RootPKINamespace": "root-pki-ns",
"IntermediatePKINamespace": "int-pki-ns",
},
},
}

for name, c := range cases {
c := c
t.Run(name, func(t *testing.T) {
t.Parallel()

testVault := NewTestVaultServer(t)
token := "root"

providerConfig := map[string]any{
"RootPKIPath": "pki-root/",
"IntermediatePKIPath": "pki-intermediate/",
}
for k, v := range c.namespaces {
providerConfig[k] = v
}

if len(c.namespaces) > 0 {
// If explicit namespaces are provided, try to create the provider before any of the namespaces
// have been created. Verify that the provider fails to initialize.
provider, err := createVaultProviderE(t, true, testVault.Addr, token, providerConfig)
require.Error(t, err)
require.NotNil(t, provider)
}

// Create the namespaces
client := testVault.Client()
client.SetToken(token)

for _, ns := range c.namespaces {
_, err := client.Logical().Write(fmt.Sprintf("/sys/namespaces/%s", ns), map[string]any{})
require.NoError(t, err)
}

// Verify that once the namespaces have been created we are able to initialize the provider.
provider, err := createVaultProviderE(t, true, testVault.Addr, token, providerConfig)
require.NoError(t, err)
require.NotNil(t, provider)
})
}
}

func getIntermediateCertTTL(t *testing.T, caConf *structs.CAConfiguration) time.Duration {
t.Helper()

Expand All @@ -1373,6 +1452,15 @@ func getIntermediateCertTTL(t *testing.T, caConf *structs.CAConfiguration) time.

func createVaultProvider(t *testing.T, isPrimary bool, addr, token string, rawConf map[string]any) *VaultProvider {
t.Helper()

provider, err := createVaultProviderE(t, isPrimary, addr, token, rawConf)
require.NoError(t, err)

return provider
}

func createVaultProviderE(t *testing.T, isPrimary bool, addr, token string, rawConf map[string]any) (*VaultProvider, error) {
t.Helper()
cfg := vaultProviderConfig(t, addr, token, rawConf)

provider := NewVaultProvider(hclog.New(nil))
Expand All @@ -1383,15 +1471,19 @@ func createVaultProvider(t *testing.T, isPrimary bool, addr, token string, rawCo
}

t.Cleanup(provider.Stop)
require.NoError(t, provider.Configure(cfg))
if err := provider.Configure(cfg); err != nil {
return provider, err
}
if isPrimary {
_, err := provider.GenerateRoot()
require.NoError(t, err)
_, err = provider.GenerateIntermediate()
require.NoError(t, err)
if _, err := provider.GenerateRoot(); err != nil {
return provider, err
}
if _, err := provider.GenerateIntermediate(); err != nil {
return provider, err
}
}

return provider
return provider, nil
}

func vaultProviderConfig(t *testing.T, addr, token string, rawConf map[string]any) ProviderConfig {
Expand Down
23 changes: 22 additions & 1 deletion agent/connect/ca/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ type CASigningKeyTypes struct {
CSRKeyBits int
}

type vaultRequirements struct {
Enterprise bool
}

// CASigningKeyTypeCases returns the cross-product of the important supported CA
// key types for generating table tests for CA signing tests (CrossSignCA and
// SignIntermediate).
Expand Down Expand Up @@ -90,7 +94,7 @@ func TestConsulProvider(t testing.T, d ConsulProviderStateDelegate) *ConsulProvi
//
// These tests may be skipped in CI. They are run as part of a separate
// integration test suite.
func SkipIfVaultNotPresent(t testing.T) {
func SkipIfVaultNotPresent(t testing.T, reqs ...vaultRequirements) {
// Try to safeguard against tests that will never run in CI.
// This substring should match the pattern used by the
// test-connect-ca-providers CI job.
Expand All @@ -107,6 +111,16 @@ func SkipIfVaultNotPresent(t testing.T) {
if err != nil || path == "" {
t.Skipf("%q not found on $PATH - download and install to run this test", vaultBinaryName)
}

// Check for any additional Vault requirements.
for _, r := range reqs {
if r.Enterprise {
ver := vaultVersion(t, vaultBinaryName)
if !strings.Contains(ver, "+ent") {
t.Skipf("%q is not a Vault Enterprise version", ver)
}
}
}
}

func NewTestVaultServer(t testing.T) *TestVaultServer {
Expand Down Expand Up @@ -362,3 +376,10 @@ func createVaultTokenAndPolicy(t testing.T, client *vaultapi.Client, policyName,
require.NoError(t, err)
return tok.Auth.ClientToken
}

func vaultVersion(t testing.T, vaultBinaryName string) string {
cmd := exec.Command(vaultBinaryName, []string{"version"}...)
output, err := cmd.Output()
require.NoError(t, err)
return string(output[:len(output)-1])
}

0 comments on commit 0587997

Please sign in to comment.