use provider specific env variable and add precedence

pull/17981/head
Ville Vesilehto 2023-07-12 09:12:54 +03:00
parent 977e90dfda
commit 0aa03f71ca
No known key found for this signature in database
GPG Key ID: 35DFD9623B53B041
4 changed files with 55 additions and 43 deletions

View File

@ -1,3 +1,3 @@
```release-note:improvement
connect: add support for setting Vault address and token from VAULT_ADDR and VAULT_TOKEN environment variables for the Connect CA provider
connect: add support for setting Vault address and token through environment variables CONSUL_MESH_CA_VAULT_ADDR and CONSUL_MESH_CA_VAULT_TOKEN for the CA provider
```

View File

@ -29,6 +29,9 @@ import (
const (
VaultCALeafCertRole = "leaf-cert"
VaultCAEnvAddr = "CONSUL_MESH_CA_VAULT_ADDR"
VaultCAEnvToken = "CONSUL_MESH_CA_VAULT_TOKEN"
VaultAuthMethodTypeAliCloud = "alicloud"
VaultAuthMethodTypeAppRole = "approle"
VaultAuthMethodTypeAWS = "aws"
@ -925,36 +928,28 @@ func ParseVaultCAConfig(raw map[string]interface{}, isPrimary bool) (*structs.Va
return nil, fmt.Errorf("error decoding config: %s", err)
}
envAddr := os.Getenv(vaultapi.EnvVaultAddress)
envAddr := os.Getenv(VaultCAEnvAddr)
if config.Address == "" && envAddr == "" {
return nil, fmt.Errorf("must provide a Vault address")
}
if config.Address != "" && envAddr != "" {
return nil, fmt.Errorf("only one Vault address can be provided")
}
if envAddr != "" {
config.Address = envAddr
}
envToken := os.Getenv(vaultapi.EnvVaultToken)
envToken := os.Getenv(VaultCAEnvToken)
if config.Token == "" && envToken == "" && config.AuthMethod == nil {
return nil, fmt.Errorf("must provide a Vault token or configure a Vault auth method")
}
if config.Token != "" && envToken != "" {
return nil, fmt.Errorf("only one Vault token can be provided")
if envToken != "" {
config.Token = envToken
}
if config.Token != "" && config.AuthMethod != nil {
return nil, fmt.Errorf("only one of Vault token or Vault auth method can be provided, but not both")
}
if envToken != "" {
config.Token = envToken
}
if isPrimary && config.RootPKIPath == "" {
return nil, fmt.Errorf("must provide a valid path to a root PKI backend")
}

View File

@ -68,39 +68,44 @@ func TestVaultCAProvider_ParseVaultCAConfig(t *testing.T) {
rawConfig: map[string]interface{}{},
expError: "must provide a Vault address",
},
"no token and no auth method provided": {
rawConfig: map[string]interface{}{"Address": "http://127.0.0.1:8200"},
"no token or auth method provided": {
rawConfig: map[string]interface{}{"Address": "http://vaultConfigAddr:8200"},
expError: "must provide a Vault token or configure a Vault auth method",
},
"both token and auth method provided": {
rawConfig: map[string]interface{}{"Token": "test", "AuthMethod": map[string]interface{}{"Type": "test"}, "Address": "http://127.0.0.1:8200"},
rawConfig: map[string]interface{}{"Token": "test", "AuthMethod": map[string]interface{}{"Type": "test"}, "Address": "http://vaultConfigAddr:8200"},
expError: "only one of Vault token or Vault auth method can be provided, but not both",
},
"both env token and auth method provided": {
rawConfig: map[string]interface{}{"AuthMethod": map[string]interface{}{"Type": "test"}, "Address": "http://vaultConfigAddr:8200"},
envConfig: map[string]string{"CONSUL_MESH_CA_VAULT_TOKEN": "test"},
expError: "only one of Vault token or Vault auth method can be provided, but not both",
},
"primary no root PKI path": {
rawConfig: map[string]interface{}{"Token": "test", "IntermediatePKIPath": "test", "Address": "http://127.0.0.1:8200"},
rawConfig: map[string]interface{}{"Token": "test", "IntermediatePKIPath": "test", "Address": "http://vaultConfigAddr:8200"},
isPrimary: true,
expError: "must provide a valid path to a root PKI backend",
},
"secondary no root PKI path": {
rawConfig: map[string]interface{}{"Token": "test", "IntermediatePKIPath": "test", "Address": "http://127.0.0.1:8200"},
rawConfig: map[string]interface{}{"Token": "test", "IntermediatePKIPath": "test", "Address": "http://vaultConfigAddr:8200"},
isPrimary: false,
expConfig: &structs.VaultCAProviderConfig{
CommonCAProviderConfig: defaultCommonConfig(),
Address: "http://127.0.0.1:8200",
Address: "http://vaultConfigAddr:8200",
Token: "test",
IntermediatePKIPath: "test/",
},
},
"no root intermediate path": {
rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test", "Address": "http://127.0.0.1:8200"},
rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test", "Address": "http://vaultconfigAddr:8200"},
expError: "must provide a valid path for the intermediate PKI backend",
},
"adds a slash to RootPKIPath and IntermediatePKIPath": {
isPrimary: true,
rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test", "IntermediatePKIPath": "test", "Address": "http://127.0.0.1:8200"},
rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test", "IntermediatePKIPath": "test", "Address": "http://vaultConfigAddr:8200"},
expConfig: &structs.VaultCAProviderConfig{
CommonCAProviderConfig: defaultCommonConfig(),
Address: "http://127.0.0.1:8200",
Address: "http://vaultConfigAddr:8200",
Token: "test",
RootPKIPath: "test/",
IntermediatePKIPath: "test/",
@ -108,42 +113,54 @@ func TestVaultCAProvider_ParseVaultCAConfig(t *testing.T) {
},
"vault address provided from env": {
rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test", "IntermediatePKIPath": "test"},
envConfig: map[string]string{"VAULT_ADDR": "http://127.0.0.1:8200"},
envConfig: map[string]string{"CONSUL_MESH_CA_VAULT_ADDR": "http://vaultEnvAddr:8200"},
expConfig: &structs.VaultCAProviderConfig{
CommonCAProviderConfig: defaultCommonConfig(),
Address: "http://127.0.0.1:8200",
Address: "http://vaultEnvAddr:8200",
Token: "test",
RootPKIPath: "test/",
IntermediatePKIPath: "test/",
},
},
"vault address provided from env and config": {
rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test", "IntermediatePKIPath": "test", "Address": "http://127.0.0.1:8200"},
envConfig: map[string]string{"VAULT_ADDR": "http://127.0.0.1:8200"},
expError: "only one Vault address can be provided",
"vault address precedence when provided from env and config": {
rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test", "IntermediatePKIPath": "test", "Address": "http://vaultConfigAddr:8200"},
envConfig: map[string]string{"CONSUL_MESH_CA_VAULT_ADDR": "http://vaultEnvAddr:8200"},
expConfig: &structs.VaultCAProviderConfig{
CommonCAProviderConfig: defaultCommonConfig(),
Address: "http://vaultEnvAddr:8200",
Token: "test",
RootPKIPath: "test/",
IntermediatePKIPath: "test/",
},
},
"vault token provided from env": {
rawConfig: map[string]interface{}{"RootPKIPath": "test", "IntermediatePKIPath": "test", "Address": "http://127.0.0.1:8200"},
envConfig: map[string]string{"VAULT_TOKEN": "test"},
rawConfig: map[string]interface{}{"RootPKIPath": "test", "IntermediatePKIPath": "test", "Address": "http://vaultConfigAddr:8200"},
envConfig: map[string]string{"CONSUL_MESH_CA_VAULT_TOKEN": "test"},
expConfig: &structs.VaultCAProviderConfig{
CommonCAProviderConfig: defaultCommonConfig(),
Address: "http://127.0.0.1:8200",
Address: "http://vaultConfigAddr:8200",
Token: "test",
RootPKIPath: "test/",
IntermediatePKIPath: "test/",
},
},
"vault token provided from env and config": {
rawConfig: map[string]interface{}{"Token": "test", "RootPKIPath": "test", "IntermediatePKIPath": "test", "Address": "http://127.0.0.1:8200"},
envConfig: map[string]string{"VAULT_TOKEN": "test"},
expError: "only one Vault token can be provided",
"vault token precedence when provided from env and config": {
rawConfig: map[string]interface{}{"Token": "tokenFromConfig", "RootPKIPath": "test", "IntermediatePKIPath": "test", "Address": "http://vaultConfigAddr:8200"},
envConfig: map[string]string{"CONSUL_MESH_CA_VAULT_TOKEN": "tokenFromEnv"},
expConfig: &structs.VaultCAProviderConfig{
CommonCAProviderConfig: defaultCommonConfig(),
Address: "http://vaultConfigAddr:8200",
Token: "tokenFromEnv",
RootPKIPath: "test/",
IntermediatePKIPath: "test/",
},
},
"vault token and addr provided from env": {
rawConfig: map[string]interface{}{"RootPKIPath": "test", "IntermediatePKIPath": "test"},
envConfig: map[string]string{"VAULT_ADDR": "http://127.0.0.1:8200", "VAULT_TOKEN": "test"},
envConfig: map[string]string{"CONSUL_MESH_CA_VAULT_ADDR": "http://vaultEnvAddr:8200", "CONSUL_MESH_CA_VAULT_TOKEN": "test"},
expConfig: &structs.VaultCAProviderConfig{
CommonCAProviderConfig: defaultCommonConfig(),
Address: "http://127.0.0.1:8200",
Address: "http://vaultEnvAddr:8200",
Token: "test",
RootPKIPath: "test/",
IntermediatePKIPath: "test/",
@ -328,13 +345,13 @@ func TestVaultCAProvider_ConfigureFromEnv(t *testing.T) {
"DefaultConfigWithEnvTokenMissing": {
envOnlyToken: true,
envOnlyAddr: false,
envConfigOverride: map[string]string{"VAULT_TOKEN": ""},
envConfigOverride: map[string]string{"CONSUL_MESH_CA_VAULT_TOKEN": ""},
expError: "must provide a Vault token or configure a Vault auth method",
},
"DefaultConfigWithEnvAddrMissing": {
envOnlyToken: true,
envOnlyAddr: true,
envConfigOverride: map[string]string{"VAULT_ADDR": ""},
envConfigOverride: map[string]string{"CONSUL_MESH_CA_VAULT_ADDR": ""},
expError: "must provide a Vault address",
},
}
@ -345,12 +362,12 @@ func TestVaultCAProvider_ConfigureFromEnv(t *testing.T) {
token := CreateVaultTokenWithAttrs(t, testVault.client, attr)
if c.envOnlyToken {
t.Setenv(vaultapi.EnvVaultToken, token)
t.Setenv(VaultCAEnvToken, token)
token = ""
}
if c.envOnlyAddr {
t.Setenv(vaultapi.EnvVaultAddress, testVault.Addr)
t.Setenv(VaultCAEnvAddr, testVault.Addr)
testVault.Addr = ""
}

View File

@ -86,14 +86,14 @@ The first key refers to the option name for use in API calls.
The key after the slash refers to the corresponding option name in the agent configuration file.
- `Address` / `address` (`string: <required>`) - The address of the Vault
server. You can also provide the address through the `VAULT_ADDR` environment variable. The address must be provided either through the configuration file or through the environment variable, but you cannot provide the address using both methods at the same time.
server. You can also provide the address through the `CONSUL_MESH_CA_VAULT_ADDR` environment variable. If the address is provided through the environment variable it takes precedence over the value set in the configuration file.
- `Token` / `token` (`string: ""`) - A token for accessing Vault.
This is write-only and will not be exposed when reading the CA configuration.
This token must have [proper privileges](#vault-acl-policies) for the PKI
paths configured. In Consul 1.8.5 and later, if the token has the [renewable](/vault/api-docs/auth/token#renewable)
flag set, Consul will attempt to renew its lease periodically after half the
duration has expired. You can also provide the token through the `VAULT_TOKEN` environment variable. The token must be provided either through the configuration file or through the environment variable, but you cannot provide the token using both methods at the same time.
duration has expired. You can also provide the token through the `CONSUL_MESH_CA_VAULT_TOKEN` environment variable. If the token is provided through the environment variable it takes precedence over the value set in the configuration file.
!> **Warning:** You must either provide a token or configure an auth method below.