From fa2d4beb026e5117158b89cbf8346d2b4c7f1c17 Mon Sep 17 00:00:00 2001 From: Hans Hasselberg Date: Thu, 20 Dec 2018 14:51:38 +0100 Subject: [PATCH 1/4] add tlsconfig for vault connect ca provider. --- agent/config/builder.go | 6 ++++++ agent/connect/ca/provider_vault.go | 11 +++++++++++ agent/structs/connect_ca.go | 7 +++++++ 3 files changed, 24 insertions(+) diff --git a/agent/config/builder.go b/agent/config/builder.go index 8c4beff7908f..4fb20fe3771e 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -568,6 +568,12 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) { "token": "Token", "root_pki_path": "RootPKIPath", "intermediate_pki_path": "IntermediatePKIPath", + "ca_file": "CAFile", + "ca_path": "CAPath", + "cert_file": "CertFile", + "key_file": "KeyFile", + "tls_server_name": "TLSServerName", + "tls_skip_verify": "TLSSkipVerify", // Common CA config "leaf_cert_ttl": "LeafCertTTL", diff --git a/agent/connect/ca/provider_vault.go b/agent/connect/ca/provider_vault.go index a583f9197fc6..cd35f7aa0772 100644 --- a/agent/connect/ca/provider_vault.go +++ b/agent/connect/ca/provider_vault.go @@ -38,6 +38,17 @@ func (v *VaultProvider) Configure(clusterId string, isRoot bool, rawConfig map[s clientConf := &vaultapi.Config{ Address: config.Address, } + err = clientConf.ConfigureTLS(&vaultapi.TLSConfig{ + CACert: config.CAFile, + CAPath: config.CAPath, + ClientCert: config.CertFile, + ClientKey: config.KeyFile, + Insecure: config.SkipValidate, + TLSServerName: config.TLSServerName, + }) + if err != nil { + return err + } client, err := vaultapi.NewClient(clientConf) if err != nil { return err diff --git a/agent/structs/connect_ca.go b/agent/structs/connect_ca.go index a5a78aac1ad0..a51f9b4bd373 100644 --- a/agent/structs/connect_ca.go +++ b/agent/structs/connect_ca.go @@ -286,6 +286,13 @@ type VaultCAProviderConfig struct { Token string RootPKIPath string IntermediatePKIPath string + + CAFile string + CAPath string + CertFile string + KeyFile string + TLSServerName string + TLSSkipVerify bool } // ParseDurationFunc is a mapstructure hook for decoding a string or From 2f236b0a2ed95b33d6e3cc4664bc34a5c855d2c5 Mon Sep 17 00:00:00 2001 From: Hans Hasselberg Date: Thu, 20 Dec 2018 14:58:35 +0100 Subject: [PATCH 2/4] add options to the docs --- website/source/docs/connect/ca/vault.html.md | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/website/source/docs/connect/ca/vault.html.md b/website/source/docs/connect/ca/vault.html.md index 43440bc584c3..70af12336cf5 100644 --- a/website/source/docs/connect/ca/vault.html.md +++ b/website/source/docs/connect/ca/vault.html.md @@ -68,6 +68,29 @@ is used if configuring in an agent configuration file. path doesn't exist, Consul will attempt to mount and configure this automatically. + * `CAFile` / `ca_file` (`string: ""`) - Specifies an optional path to the CA + certificate used for Vault communication. If unspecified, this will fallback + to the default system CA bundle, which varies by OS and version. + + * `CAPath` / `ca_path` (`string: ""`) - Specifies an optional path to a folder + containing CA certificates to be used for Vault communication. If + unspecified, this will fallback to the default system CA bundle, which + varies by OS and version. + + * `CertFile` / `cert_file` (`string: ""`) - Specifies the path to the + certificate used for Vault communication. If this is set then you need to + also set tls_key_file. + + * `KeyFile` / `key_file` (`string: ""`) - Specifies the path to the private + key used for Vault communication. If this is set then you need to also set + cert_file. + + * `TLSServerName` / `tls_server_name` (`string: ""`) - Specifies an optional + string used to set the SNI host when connecting to Vault via TLS. + + * `TLSSkipVerify` / `tls_skip_verify` (`bool: false`) - Specifies if SSL peer + validation should be enforced. + ## Root and Intermediate PKI Paths The Vault CA provider uses two separately configured From 6aad2ab02326129ea4803c2df77a431e7e7e9f48 Mon Sep 17 00:00:00 2001 From: Hans Hasselberg Date: Thu, 3 Jan 2019 16:46:04 +0100 Subject: [PATCH 3/4] use TLSSkipVerify --- agent/connect/ca/provider_vault.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/connect/ca/provider_vault.go b/agent/connect/ca/provider_vault.go index cd35f7aa0772..e9c1bf7dacd1 100644 --- a/agent/connect/ca/provider_vault.go +++ b/agent/connect/ca/provider_vault.go @@ -43,7 +43,7 @@ func (v *VaultProvider) Configure(clusterId string, isRoot bool, rawConfig map[s CAPath: config.CAPath, ClientCert: config.CertFile, ClientKey: config.KeyFile, - Insecure: config.SkipValidate, + Insecure: config.TLSSkipVerify, TLSServerName: config.TLSServerName, }) if err != nil { From c272ce5fe1fcf37ac1518f408d374ed718338587 Mon Sep 17 00:00:00 2001 From: Hans Hasselberg Date: Tue, 8 Jan 2019 11:17:29 +0100 Subject: [PATCH 4/4] add tests for new configuration --- agent/config/runtime_test.go | 56 +++++++++++++++++++++++++ agent/connect/ca/provider_vault.go | 20 +++++---- agent/connect/ca/provider_vault_test.go | 20 +++++++++ 3 files changed, 88 insertions(+), 8 deletions(-) diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index 26408d67ea8d..b1f2c1631c84 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -2637,6 +2637,62 @@ func TestConfigFlagsAndEdgecases(t *testing.T) { rt.VerifyOutgoing = true }, }, + { + desc: "test connect vault provider configuration", + args: []string{ + `-data-dir=` + dataDir, + }, + json: []string{`{ + "connect": { + "enabled": true, + "ca_provider": "vault", + "ca_config": { + "ca_file": "/capath/ca.pem", + "ca_path": "/capath/", + "cert_file": "/certpath/cert.pem", + "key_file": "/certpath/key.pem", + "tls_server_name": "server.name", + "tls_skip_verify": true, + "token": "abc", + "root_pki_path": "consul-vault", + "intermediate_pki_path": "connect-intermediate" + } + } + }`}, + hcl: []string{` + connect { + enabled = true + ca_provider = "vault" + ca_config { + ca_file = "/capath/ca.pem" + ca_path = "/capath/" + cert_file = "/certpath/cert.pem" + key_file = "/certpath/key.pem" + tls_server_name = "server.name" + tls_skip_verify = true + token = "abc" + root_pki_path = "consul-vault" + intermediate_pki_path = "connect-intermediate" + } + } + `}, + patch: func(rt *RuntimeConfig) { + rt.DataDir = dataDir + rt.ConnectEnabled = true + rt.ConnectCAProvider = "vault" + rt.ConnectCAConfig = map[string]interface{}{ + "CAFile": "/capath/ca.pem", + "CAPath": "/capath/", + "CertFile": "/certpath/cert.pem", + "KeyFile": "/certpath/key.pem", + "TLSServerName": "server.name", + "TLSSkipVerify": true, + "Token": "abc", + "RootPKIPath": "consul-vault", + "IntermediatePKIPath": "connect-intermediate", + } + }, + }, } testConfig(t, tests, dataDir) diff --git a/agent/connect/ca/provider_vault.go b/agent/connect/ca/provider_vault.go index e9c1bf7dacd1..c9c0076debc9 100644 --- a/agent/connect/ca/provider_vault.go +++ b/agent/connect/ca/provider_vault.go @@ -28,6 +28,17 @@ type VaultProvider struct { clusterId string } +func vaultTLSConfig(config *structs.VaultCAProviderConfig) *vaultapi.TLSConfig { + return &vaultapi.TLSConfig{ + CACert: config.CAFile, + CAPath: config.CAPath, + ClientCert: config.CertFile, + ClientKey: config.KeyFile, + Insecure: config.TLSSkipVerify, + TLSServerName: config.TLSServerName, + } +} + // Configure sets up the provider using the given configuration. func (v *VaultProvider) Configure(clusterId string, isRoot bool, rawConfig map[string]interface{}) error { config, err := ParseVaultCAConfig(rawConfig) @@ -38,14 +49,7 @@ func (v *VaultProvider) Configure(clusterId string, isRoot bool, rawConfig map[s clientConf := &vaultapi.Config{ Address: config.Address, } - err = clientConf.ConfigureTLS(&vaultapi.TLSConfig{ - CACert: config.CAFile, - CAPath: config.CAPath, - ClientCert: config.CertFile, - ClientKey: config.KeyFile, - Insecure: config.TLSSkipVerify, - TLSServerName: config.TLSServerName, - }) + err = clientConf.ConfigureTLS(vaultTLSConfig(config)) if err != nil { return err } diff --git a/agent/connect/ca/provider_vault_test.go b/agent/connect/ca/provider_vault_test.go index 7409ae7c6117..d236b7287305 100644 --- a/agent/connect/ca/provider_vault_test.go +++ b/agent/connect/ca/provider_vault_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/hashicorp/consul/agent/connect" + "github.com/hashicorp/consul/agent/structs" vaultapi "github.com/hashicorp/vault/api" "github.com/hashicorp/vault/builtin/logical/pki" vaulthttp "github.com/hashicorp/vault/http" @@ -51,6 +52,25 @@ func testVaultClusterWithConfig(t *testing.T, isRoot bool, rawConf map[string]in return provider, core, ln } +func TestVaultCAProvider_VaultTLSConfig(t *testing.T) { + config := &structs.VaultCAProviderConfig{ + CAFile: "/capath/ca.pem", + CAPath: "/capath/", + CertFile: "/certpath/cert.pem", + KeyFile: "/certpath/key.pem", + TLSServerName: "server.name", + TLSSkipVerify: true, + } + tlsConfig := vaultTLSConfig(config) + require := require.New(t) + require.Equal(config.CAFile, tlsConfig.CACert) + require.Equal(config.CAPath, tlsConfig.CAPath) + require.Equal(config.CertFile, tlsConfig.ClientCert) + require.Equal(config.KeyFile, tlsConfig.ClientKey) + require.Equal(config.TLSServerName, tlsConfig.TLSServerName) + require.Equal(config.TLSSkipVerify, tlsConfig.Insecure) +} + func TestVaultCAProvider_Bootstrap(t *testing.T) { t.Parallel()