From fb830a53e04e2ef24d0c4e43ce19cb1fbc4187e3 Mon Sep 17 00:00:00 2001 From: Seth Hoenig Date: Wed, 23 Jun 2021 14:04:10 -0500 Subject: [PATCH] consul/connect: automatically set consul tls sni name for connect native tasks This PR makes it so that Nomad will automatically set the CONSUL_TLS_SERVER_NAME environment variable for Connect native tasks running in bridge networking mode where Consul has TLS enabled. Because of the use of a unix domain socket for communicating with Consul when in bridge networking mode, the server name is a file name instead of something compatible with the mTLS certificate Consul will authenticate against. "localhost" is by default a compatible name, so Nomad will set the environment variable to that. Fixes #10804 --- CHANGELOG.md | 4 ++ .../taskrunner/connect_native_hook.go | 14 ++++-- .../taskrunner/connect_native_hook_test.go | 46 ++++++++++++++----- website/content/partials/envvars.mdx | 37 ++++++++++++--- 4 files changed, 80 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74eadb76f7b8..5997ddc8d1a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 1.1.3 (Unreleased) +IMPROVEMENTS: + +* consul/connect: automatically set CONSUL_TLS_SERVER_NAME for connect native tasks [[GH-10804](https://github.com/hashicorp/nomad/issues/10804)] + ## 1.1.2 (June 22, 2021) IMPROVEMENTS: diff --git a/client/allocrunner/taskrunner/connect_native_hook.go b/client/allocrunner/taskrunner/connect_native_hook.go index 23243809bab3..91fc98ec9a97 100644 --- a/client/allocrunner/taskrunner/connect_native_hook.go +++ b/client/allocrunner/taskrunner/connect_native_hook.go @@ -212,18 +212,26 @@ func (h *connectNativeHook) tlsEnv(env map[string]string) map[string]string { // if the task is running inside an alloc's network namespace (i.e. bridge mode). // // Sets CONSUL_HTTP_ADDR if not already set. +// Sets CONSUL_TLS_SERVER_NAME if not already set, and consul tls is enabled. func (h *connectNativeHook) bridgeEnv(env map[string]string) map[string]string { + if h.alloc.AllocatedResources.Shared.Networks[0].Mode != "bridge" { return nil } + result := make(map[string]string) + if _, exists := env["CONSUL_HTTP_ADDR"]; !exists { - return map[string]string{ - "CONSUL_HTTP_ADDR": "unix:///" + allocdir.AllocHTTPSocket, + result["CONSUL_HTTP_ADDR"] = "unix:///" + allocdir.AllocHTTPSocket + } + + if _, exists := env["CONSUL_TLS_SERVER_NAME"]; !exists { + if v := h.consulConfig.SSL; v != "" { + result["CONSUL_TLS_SERVER_NAME"] = "localhost" } } - return nil + return result } // hostEnv creates a set of additional environment variables to be used when launching diff --git a/client/allocrunner/taskrunner/connect_native_hook_test.go b/client/allocrunner/taskrunner/connect_native_hook_test.go index a1c368a42efc..b9a447fe3cc2 100644 --- a/client/allocrunner/taskrunner/connect_native_hook_test.go +++ b/client/allocrunner/taskrunner/connect_native_hook_test.go @@ -165,21 +165,45 @@ func TestConnectNativeHook_tlsEnv(t *testing.T) { func TestConnectNativeHook_bridgeEnv_bridge(t *testing.T) { t.Parallel() - hook := new(connectNativeHook) - hook.alloc = mock.ConnectNativeAlloc("bridge") + t.Run("without tls", func(t *testing.T) { + hook := new(connectNativeHook) + hook.alloc = mock.ConnectNativeAlloc("bridge") + + t.Run("consul address env not preconfigured", func(t *testing.T) { + result := hook.bridgeEnv(nil) + require.Equal(t, map[string]string{ + "CONSUL_HTTP_ADDR": "unix:///alloc/tmp/consul_http.sock", + }, result) + }) - t.Run("consul address env not preconfigured", func(t *testing.T) { - result := hook.bridgeEnv(nil) - require.Equal(t, map[string]string{ - "CONSUL_HTTP_ADDR": "unix:///alloc/tmp/consul_http.sock", - }, result) + t.Run("consul address env is preconfigured", func(t *testing.T) { + result := hook.bridgeEnv(map[string]string{ + "CONSUL_HTTP_ADDR": "10.1.1.1", + }) + require.Empty(t, result) + }) }) - t.Run("consul address env is preconfigured", func(t *testing.T) { - result := hook.bridgeEnv(map[string]string{ - "CONSUL_HTTP_ADDR": "10.1.1.1", + t.Run("with tls", func(t *testing.T) { + hook := new(connectNativeHook) + hook.alloc = mock.ConnectNativeAlloc("bridge") + hook.consulConfig.SSL = "true" + + t.Run("consul tls server name not preconfigured", func(t *testing.T) { + result := hook.bridgeEnv(nil) + require.Equal(t, map[string]string{ + "CONSUL_HTTP_ADDR": "unix:///alloc/tmp/consul_http.sock", + "CONSUL_TLS_SERVER_NAME": "localhost", + }, result) + }) + + t.Run("consul tls server name preconfigured", func(t *testing.T) { + result := hook.bridgeEnv(map[string]string{ + "CONSUL_HTTP_ADDR": "10.1.1.1", + "CONSUL_TLS_SERVER_NAME": "consul.local", + }) + require.Empty(t, result) }) - require.Empty(t, result) }) } diff --git a/website/content/partials/envvars.mdx b/website/content/partials/envvars.mdx index 93f74e8317ed..9ccb0cc555ea 100644 --- a/website/content/partials/envvars.mdx +++ b/website/content/partials/envvars.mdx @@ -277,8 +277,9 @@ CONSUL_HTTP_ADDR - Specifies the address to the local Consul agent, will be a unix domain - socket in bridge mode and a tcp address in host networking. + Specifies the address to the local Consul agent. Will be automatically + set to a unix domain socket in bridge networking mode, or a tcp address in + host networking mode. @@ -286,7 +287,9 @@ CONSUL_HTTP_TOKEN - The token to authenticate against consul. + Specifies the Consul ACL token used to authorize with Consul. Will be + automatically set to a generated Connect service identity token specific + to the service instance if Consul ACLs are enabled. @@ -294,7 +297,9 @@ CONSUL_HTTP_SSL - Specifies whether HTTPS should be used when communicating with consul. + Specifies whether HTTPS should be used when communicating with consul. Will + be automatically set to true if Nomad is configured to communicate with + Consul using TLS. @@ -302,7 +307,9 @@ CONSUL_HTTP_SSL_VERIFY - Specifies whether the HTTPS connection should be verified. + Specifies whether the HTTPS connection with Consul should be mutually + verified. Will be automatically set to true if Nomad is configured to + verify TLS certificates. @@ -311,6 +318,8 @@ Specifies the path to the CA certificate used for Consul communication. + Will be automatically set if Nomad is configured with the consul.share_ssl + option. @@ -318,7 +327,9 @@ CONSUL_CLIENT_CERT - The client certificate to use when communicating with Consul. + Specifies the path to the Client certificate used for Consul communication. + Will be automatically set if Nomad is configured with the consul.share_ssl + option. @@ -326,7 +337,19 @@ CONSUL_CLIENT_KEY - The client key to use when communicating with Consul. + Specifies the path to the CLient Key certificate used for Consul communication. + Will be automatically set if Nomad is configured with the consul.share_ssl + option. + + + + + CONSUL_TLS_SERVER_NAME + + + Specifies the server name to use as the SNI host for Consul communication. + Will be automatically set if Consul is configured to use TLS and the task + is in a group using bridge networking mode.