Skip to content

Commit

Permalink
consul/connect: automatically set consul tls sni name for connect nat…
Browse files Browse the repository at this point in the history
…ive 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
  • Loading branch information
shoenig committed Jun 23, 2021
1 parent 6d2b704 commit fb830a5
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 21 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
14 changes: 11 additions & 3 deletions client/allocrunner/taskrunner/connect_native_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
46 changes: 35 additions & 11 deletions client/allocrunner/taskrunner/connect_native_hook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
}

Expand Down
37 changes: 30 additions & 7 deletions website/content/partials/envvars.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -277,32 +277,39 @@
<code>CONSUL_HTTP_ADDR</code>
</td>
<td>
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.
</td>
</tr>
<tr>
<td>
<code>CONSUL_HTTP_TOKEN</code>
</td>
<td>
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.
</td>
</tr>
<tr>
<td>
<code>CONSUL_HTTP_SSL</code>
</td>
<td>
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.
</td>
</tr>
<tr>
<td>
<code>CONSUL_HTTP_SSL_VERIFY</code>
</td>
<td>
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.
</td>
</tr>
<tr>
Expand All @@ -311,22 +318,38 @@
</td>
<td>
Specifies the path to the CA certificate used for Consul communication.
Will be automatically set if Nomad is configured with the <code>consul.share_ssl</code>
option.
</td>
</tr>
<tr>
<td>
<code>CONSUL_CLIENT_CERT</code>
</td>
<td>
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 <code>consul.share_ssl</code>
option.
</td>
</tr>
<tr>
<td>
<code>CONSUL_CLIENT_KEY</code>
</td>
<td>
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 <code>consul.share_ssl</code>
option.
</td>
</tr>
<tr>
<td>
<code>CONSUL_TLS_SERVER_NAME</code>
</td>
<td>
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.
</td>
</tr>
</tbody>
Expand Down

0 comments on commit fb830a5

Please sign in to comment.