From b3af482e092d199ad2455ed9c26c6ab9f9de76e4 Mon Sep 17 00:00:00 2001 From: Connor Date: Fri, 5 Nov 2021 11:42:28 -0500 Subject: [PATCH] Support Vault Namespaces explicitly in CA config (#11477) * Support Vault Namespaces explicitly in CA config If there is a Namespace entry included in the Vault CA configuration, set it as the Vault Namespace on the Vault client Currently the only way to support Vault namespaces in the Consul CA config is by doing one of the following: 1) Set the VAULT_NAMESPACE environment variable which will be picked up by the Vault API client 2) Prefix all Vault paths with the namespace Neither of these are super pleasant. The first requires direct access and modification to the Consul runtime environment. It's possible and expected, not super pleasant. The second requires more indepth knowledge of Vault and how it uses Namespaces and could be confusing for anyone without that context. It also infers that it is not supported * Add changelog * Remove fmt.Fprint calls * Make comment clearer * Add next consul version to website docs * Add new test for default configuration * go mod tidy * Add skip if vault not present * Tweak changelog text --- .changelog/11477.txt | 3 ++ agent/connect/ca/provider_vault.go | 8 +++++ agent/connect/ca/provider_vault_test.go | 41 +++++++++++++++++++++++ agent/structs/connect_ca.go | 1 + go.mod | 1 + website/content/docs/connect/ca/vault.mdx | 4 +++ 6 files changed, 58 insertions(+) create mode 100644 .changelog/11477.txt diff --git a/.changelog/11477.txt b/.changelog/11477.txt new file mode 100644 index 000000000..12b6745fc --- /dev/null +++ b/.changelog/11477.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: add Namespace configuration setting for Vault CA provider +``` diff --git a/agent/connect/ca/provider_vault.go b/agent/connect/ca/provider_vault.go index 872ca2e5e..0f174f1a5 100644 --- a/agent/connect/ca/provider_vault.go +++ b/agent/connect/ca/provider_vault.go @@ -75,6 +75,14 @@ func (v *VaultProvider) Configure(cfg ProviderConfig) error { } client.SetToken(config.Token) + + // We don't want to set the namespace if it's empty to prevent potential + // unknown behavior (what does Vault do with an empty namespace). The Vault + // client also makes sure the inputs are not empty strings so let's do the + // same. + if config.Namespace != "" { + client.SetNamespace(config.Namespace) + } v.config = config v.client = client v.isPrimary = cfg.IsPrimary diff --git a/agent/connect/ca/provider_vault_test.go b/agent/connect/ca/provider_vault_test.go index a670effd2..ccb7fc01c 100644 --- a/agent/connect/ca/provider_vault_test.go +++ b/agent/connect/ca/provider_vault_test.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/go-hclog" vaultapi "github.com/hashicorp/vault/api" + vaultconst "github.com/hashicorp/vault/sdk/helper/consts" "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/connect" @@ -36,6 +37,46 @@ func TestVaultCAProvider_VaultTLSConfig(t *testing.T) { require.Equal(config.TLSSkipVerify, tlsConfig.Insecure) } +func TestVaultCAProvider_Configure(t *testing.T) { + SkipIfVaultNotPresent(t) + + testcases := []struct { + name string + rawConfig map[string]interface{} + expectedValue func(t *testing.T, v *VaultProvider) + }{ + { + name: "DefaultConfig", + rawConfig: map[string]interface{}{}, + expectedValue: func(t *testing.T, v *VaultProvider) { + headers := v.client.Headers() + require.Equal(t, "", headers.Get(vaultconst.NamespaceHeaderName)) + require.Equal(t, "pki-root/", v.config.RootPKIPath) + require.Equal(t, "pki-intermediate/", v.config.IntermediatePKIPath) + }, + }, + { + name: "TestConfigWithNamespace", + rawConfig: map[string]interface{}{"namespace": "ns1"}, + expectedValue: func(t *testing.T, v *VaultProvider) { + + h := v.client.Headers() + require.Equal(t, "ns1", h.Get(vaultconst.NamespaceHeaderName)) + }, + }, + } + + for _, testcase := range testcases { + t.Run(testcase.name, func(t *testing.T) { + provider, _ := testVaultProviderWithConfig(t, true, testcase.rawConfig) + + testcase.expectedValue(t, provider) + }) + } + + return +} + func TestVaultCAProvider_SecondaryActiveIntermediate(t *testing.T) { SkipIfVaultNotPresent(t) diff --git a/agent/structs/connect_ca.go b/agent/structs/connect_ca.go index 8c2186498..e7e9822bc 100644 --- a/agent/structs/connect_ca.go +++ b/agent/structs/connect_ca.go @@ -473,6 +473,7 @@ type VaultCAProviderConfig struct { Token string RootPKIPath string IntermediatePKIPath string + Namespace string CAFile string CAPath string diff --git a/go.mod b/go.mod index aea4264ed..a697ac7ab 100644 --- a/go.mod +++ b/go.mod @@ -57,6 +57,7 @@ require ( github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea github.com/hashicorp/serf v0.9.6-0.20210609195804-2b5dd0cd2de9 github.com/hashicorp/vault/api v1.0.5-0.20200717191844-f687267c8086 + github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493 github.com/imdario/mergo v0.3.6 github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f // indirect diff --git a/website/content/docs/connect/ca/vault.mdx b/website/content/docs/connect/ca/vault.mdx index e562df62e..622bf47c3 100644 --- a/website/content/docs/connect/ca/vault.mdx +++ b/website/content/docs/connect/ca/vault.mdx @@ -132,6 +132,10 @@ The configuration options are listed below. - `TLSSkipVerify` / `tls_skip_verify` (`bool: false`) - Specifies if SSL peer validation should be enforced. +- `Namespace` / `namespace` (`string: `) - The Vault Namespace that + the `Token` and PKI Certificates are a part of. Vault Namespaces are a Vault + Enterprise feature. Added in Consul 1.11.0 + @include 'http_api_connect_ca_common_options.mdx' ## Root and Intermediate PKI Paths