Skip to content

Commit cda7f39

Browse files
committed
task env: add NOMAD_UNIX_ADDR var
for easier task setup when using workload identity and nomad CLI
1 parent 95520ac commit cda7f39

File tree

7 files changed

+71
-4
lines changed

7 files changed

+71
-4
lines changed

.changelog/25598.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:improvement
2+
task environment: add NOMAD_UNIX_ADDR env var when using workload identity
3+
```

client/taskenv/env.go

+6
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ const (
9898

9999
HostAddrPrefix = "NOMAD_HOST_ADDR_"
100100

101+
// UnixAddr is the task api unix socket, in the appropriate format
102+
// for use in a NOMAD_ADDR (i.e. prefixed with "unix:")
103+
UnixAddr = "NOMAD_UNIX_ADDR"
104+
101105
// IpPrefix is the prefix for passing the host IP of a port allocation
102106
// to a task.
103107
IpPrefix = "NOMAD_IP_"
@@ -620,10 +624,12 @@ func (b *Builder) buildEnv(allocDir, localDir, secretsDir string,
620624
// Build the Nomad Workload Token
621625
if b.workloadTokenDefault != "" {
622626
envMap[WorkloadToken] = b.workloadTokenDefault
627+
envMap[UnixAddr] = "unix:" + filepath.Join(secretsDir, "api.sock")
623628
}
624629

625630
for name, token := range b.workloadTokens {
626631
envMap[WorkloadToken+"_"+name] = token
632+
envMap[UnixAddr] = "unix:" + filepath.Join(secretsDir, "api.sock")
627633
}
628634

629635
// Copy and interpolate task meta

client/taskenv/env_test.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ func TestEnvironment_AsList(t *testing.T) {
214214
}
215215
env := NewBuilder(n, a, task, "global").SetDriverNetwork(
216216
&drivers.DriverNetwork{PortMap: map[string]int{"https": 443}},
217-
)
217+
).SetDefaultWorkloadToken("test-wi-token")
218218

219219
act := env.Build().List()
220220
exp := []string{
@@ -263,6 +263,8 @@ func TestEnvironment_AsList(t *testing.T) {
263263
fmt.Sprintf("NOMAD_ALLOC_ID=%s", a.ID),
264264
fmt.Sprintf("NOMAD_SHORT_ALLOC_ID=%s", a.ID[:8]),
265265
"NOMAD_ALLOC_INDEX=0",
266+
"NOMAD_TOKEN=test-wi-token",
267+
"NOMAD_UNIX_ADDR=unix:api.sock",
266268
}
267269
sort.Strings(act)
268270
sort.Strings(exp)
@@ -342,7 +344,7 @@ func TestEnvironment_AllValues(t *testing.T) {
342344
}
343345
env := NewBuilder(n, a, task, "global").SetDriverNetwork(
344346
&drivers.DriverNetwork{PortMap: map[string]int{"https": 443}},
345-
)
347+
).SetDefaultWorkloadToken("test-wi-token")
346348

347349
// Setting the network status ensures we trigger the addNomadAllocNetwork
348350
// for the test.
@@ -453,6 +455,8 @@ func TestEnvironment_AllValues(t *testing.T) {
453455
"NOMAD_ALLOC_INTERFACE_admin": "eth0",
454456
"NOMAD_ALLOC_IP_admin": "172.26.64.19",
455457
"NOMAD_ALLOC_ADDR_admin": "172.26.64.19:9000",
458+
"NOMAD_TOKEN": "test-wi-token",
459+
"NOMAD_UNIX_ADDR": "unix:api.sock",
456460

457461
// Env vars from the host.
458462
"LC_CTYPE": "C.UTF-8",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright (c) HashiCorp, Inc.
2+
# SPDX-License-Identifier: BUSL-1.1
3+
4+
job "task-api-nomad-cli" {
5+
type = "batch"
6+
7+
group "grp" {
8+
restart { attempts = 0 }
9+
reschedule { attempts = 0 }
10+
constraint {
11+
attribute = "${attr.kernel.name}"
12+
value = "linux"
13+
}
14+
15+
task "tsk" {
16+
driver = "raw_exec"
17+
config {
18+
command = "bash"
19+
// "|| true" because failure to get a var makes nomad cli exit 1,
20+
// but for this test, "Variable not found" actually indicates successful
21+
// API connection.
22+
args = ["-xc", "echo $NOMAD_ADDR; nomad var get nothing || true"]
23+
}
24+
env {
25+
NOMAD_ADDR = "${NOMAD_UNIX_ADDR}"
26+
}
27+
identity { # creates unix addr
28+
env = true # provides NOMAD_TOKEN
29+
}
30+
}
31+
}
32+
}

e2e/workload_id/taskapi_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"testing"
1212

1313
"github.com/hashicorp/nomad/e2e/e2eutil"
14+
"github.com/hashicorp/nomad/e2e/v3/cluster3"
15+
"github.com/hashicorp/nomad/e2e/v3/jobs3"
1416
"github.com/hashicorp/nomad/helper/uuid"
1517
"github.com/shoenig/test"
1618
"github.com/shoenig/test/must"
@@ -26,6 +28,7 @@ func TestTaskAPI(t *testing.T) {
2628

2729
t.Run("testTaskAPI_Auth", testTaskAPIAuth)
2830
t.Run("testTaskAPI_Windows", testTaskAPIWindows)
31+
t.Run("testTaskAPI_NomadCLI", testTaskAPINomadCLI)
2932
}
3033

3134
func testTaskAPIAuth(t *testing.T) {
@@ -129,3 +132,17 @@ func testTaskAPIWindows(t *testing.T) {
129132

130133
must.StrHasSuffix(t, `"ok":true}}`, logs)
131134
}
135+
136+
func testTaskAPINomadCLI(t *testing.T) {
137+
cluster3.Establish(t,
138+
cluster3.LinuxClients(1),
139+
)
140+
sub, _ := jobs3.Submit(t,
141+
"./input/api-nomad-cli.nomad.hcl",
142+
jobs3.WaitComplete("grp"),
143+
)
144+
logs := sub.TaskLogs("grp", "tsk")
145+
test.StrContains(t, logs.Stdout, "unix:/") // from `echo $NOMAD_ADDR`
146+
test.StrContains(t, logs.Stdout, "secrets/api.sock")
147+
test.StrContains(t, logs.Stderr, "Variable not found") // api success
148+
}

website/content/docs/commands/index.mdx

+5-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ $ nomad -autocomplete-uninstall
3535
Nomad's CLI commands have implied contexts in their naming convention. Because
3636
the CLI is most commonly used to manipulate or query jobs, you can assume that
3737
any given command is working in that context unless the command name implies
38-
otherwise. For example, the `nomad job run` command runs a new job and the `nomad status` command queries information about existing jobs. Conversely,
38+
otherwise. For example, the `nomad job run` command runs a new job and the
39+
`nomad status` command queries information about existing jobs. Conversely,
3940
commands with a prefix in their name likely operate in a different context.
4041
Examples include the `nomad agent-info` or `nomad node drain` commands,
4142
which operate in the agent or node contexts respectively.
@@ -64,7 +65,8 @@ may override these environment variables with individual flags.
6465
#### Connection environment variables
6566

6667
- `NOMAD_ADDR` - The address of the Nomad server. Defaults to
67-
`http://127.0.0.1:4646`.
68+
`http://127.0.0.1:4646`. For unix sockets, as with the [task API][],
69+
the format is `unix:/path/to/api.sock`.
6870

6971
- `NOMAD_REGION` - The region of the Nomad server to forward commands to.
7072
Defaults to the Agent's local region
@@ -118,4 +120,5 @@ may override these environment variables with individual flags.
118120
- `NOMAD_LICENSE` - The Nomad Enterprise license file contents as a string.
119121

120122

123+
[task API]: /nomad/api-docs/task-api
121124
[`tls` block in agent configuration]: /nomad/docs/configuration/tls

website/content/partials/envvars.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
| `NOMAD_PARENT_CGROUP` | The parent cgroup used to contain task cgroups (Linux only) |
2323
| `NOMAD_NAMESPACE` | Namespace in which the allocation is running |
2424
| `NOMAD_REGION` | Region in which the allocation is running |
25+
| `NOMAD_UNIX_ADDR` | Use this value as your `NOMAD_ADDR` to use `nomad` CLI with the [task API][]'s unix socket. The value is equivalent to `"unix:${NOMAD_SECRETS_DIR}/api.sock"`
2526
| `NOMAD_META_<key>` | The metadata value given by `key` on the task's metadata. Any character in a key other than `[A-Za-z0-9_.]` will be converted to `_`. <br/> **Note:** this is different from [`${meta.<key>}`](/nomad/docs/runtime/interpolation#node-variables-) which are keys in the node's metadata. |
2627
| `CONSUL_HTTP_TOKEN` | The tasks' Consul token. See [Consul Integration][consul] documentation for more details. |
2728
| `CONSUL_TOKEN` | The tasks' Consul token. See [Consul Integration][consul] documentation for more details. This variable is deprecated and exists only for backwards compatibility. |
@@ -68,6 +69,7 @@ names such as `NOMAD_ADDR_<task>_<label>`
6869
| `CONSUL_CLIENT_KEY` | 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. |
6970
| `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. |
7071

72+
[task API]: /nomad/api-docs/task-api
7173
[upstream]: /nomad/docs/job-specification/upstreams
7274
[taskdirs]: /nomad/docs/runtime/environment#task-directories
7375
[network-block]: /nomad/docs/job-specification/network

0 commit comments

Comments
 (0)