Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds vault role to JWT claims if specified in jobspec #19535

Merged
merged 1 commit into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/19535.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
identity: Added vault_role to JWT workload identity claims if specified in jobspec
```
4 changes: 3 additions & 1 deletion nomad/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -11317,6 +11317,7 @@ type IdentityClaims struct {

ConsulNamespace string `json:"consul_namespace,omitempty"`
VaultNamespace string `json:"vault_namespace,omitempty"`
VaultRole string `json:"vault_role,omitempty"`

jwt.Claims
}
Expand All @@ -11327,7 +11328,6 @@ type IdentityClaims struct {
// ID claim is random (nondeterministic) so multiple calls with the same values
// will not return equal claims by design. JWT IDs should never collide.
func NewIdentityClaims(job *Job, alloc *Allocation, wihandle *WIHandle, wid *WorkloadIdentity, now time.Time) *IdentityClaims {

tg := job.LookupTaskGroup(alloc.TaskGroup)
if tg == nil {
return nil
Expand Down Expand Up @@ -11399,7 +11399,9 @@ func NewIdentityClaims(job *Job, alloc *Allocation, wihandle *WIHandle, wid *Wor

if wid.IsVault() && task.Vault != nil {
claims.VaultNamespace = task.Vault.Namespace
claims.VaultRole = task.Vault.Role
}

} else if wid.IsConsul() && tg.Consul != nil {
claims.ConsulNamespace = tg.Consul.Namespace
}
Expand Down
7 changes: 7 additions & 0 deletions nomad/structs/structs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8014,6 +8014,7 @@ func TestNewIdentityClaims(t *testing.T) {
},
Vault: &Vault{
Namespace: "vault-namespace",
Role: "role-from-spec-group",
},
Identity: &WorkloadIdentity{
Name: "default-identity",
Expand Down Expand Up @@ -8087,6 +8088,7 @@ func TestNewIdentityClaims(t *testing.T) {
},
Vault: &Vault{
Namespace: "vault-namespace",
Role: "role-from-spec-consul-group",
},
Identity: &WorkloadIdentity{
Name: "default-identity",
Expand Down Expand Up @@ -8166,6 +8168,7 @@ func TestNewIdentityClaims(t *testing.T) {
Namespace: "default",
JobID: "job",
TaskName: "task",
VaultRole: "", // not specified in jobspec
Claims: jwt.Claims{
Subject: "global:default:job:group:task:vault_default",
Audience: jwt.Audience{"vault.io"},
Expand Down Expand Up @@ -8208,6 +8211,7 @@ func TestNewIdentityClaims(t *testing.T) {
Namespace: "default",
JobID: "job",
TaskName: "consul-vault-task",
VaultRole: "role-from-spec-group",
Claims: jwt.Claims{
Subject: "global:default:job:group:consul-vault-task:vault_default",
Audience: jwt.Audience{"vault.io"},
Expand Down Expand Up @@ -8272,6 +8276,7 @@ func TestNewIdentityClaims(t *testing.T) {
Namespace: "default",
JobID: "job",
TaskName: "task",
VaultRole: "", // not specified in jobspec
Claims: jwt.Claims{
Subject: "global:default:job:consul-group:task:vault_default",
Audience: jwt.Audience{"vault.io"},
Expand Down Expand Up @@ -8316,6 +8321,7 @@ func TestNewIdentityClaims(t *testing.T) {
Namespace: "default",
JobID: "job",
TaskName: "consul-vault-task",
VaultRole: "role-from-spec-consul-group",
Claims: jwt.Claims{
Subject: "global:default:job:consul-group:consul-vault-task:vault_default",
Audience: jwt.Audience{"vault.io"},
Expand Down Expand Up @@ -8365,6 +8371,7 @@ func TestNewIdentityClaims(t *testing.T) {

for _, s := range tg.Services {
path := path + "/services/" + s.Name

testCases = append(testCases, testCase{
name: path,
group: tg.Name,
Expand Down
22 changes: 21 additions & 1 deletion website/content/docs/concepts/workload-identity.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,23 @@ instead of the task name.
}
```

Workload identities for tasks that use Vault have an additional claim for
[`vault.role`][jobspec_vault_role] if a role is specified in the job.

-> **Note:** This claim will *not* be added if the role is inherited from
the [agent configuration][vault_role_agent_config] and is not present
in the Nomad job specification.

```json
{
"nomad_namespace": "default",
"nomad_job_id": "example",
"nomad_allocation_id": "8623ac7a-28ba-20c3-24a6-e615a39bbbf3",
"nomad_service": "example-cache-redis"
"vault_role": "nomad-jwt-login"
}
```

### Nomad Enterprise <EnterpriseAlert inline />

In Nomad Enterprise, tasks and services with a [`consul`][jobspec_consul] block
Expand All @@ -54,7 +71,7 @@ block that does it, have an additional claim called `consul_namespace`.
}
```

Similarly, tasks with a [`vault.namespace`][] value have the additional claim
Similarly, tasks with a [`vault.namespace`][jobspec_vault_ns] value have the additional claim
`vault_namespace`.

```json
Expand Down Expand Up @@ -159,6 +176,9 @@ integration pages for more information.
[identity-block]: /nomad/docs/job-specification/identity
[jobspec_consul]: /nomad/docs/job-specification/consul
[jobspec_consul_ns]: /nomad/docs/job-specification/consul#namespace
[jobspec_vault_ns]: /nomad/docs/job-specification/vault#namespace
[jobspec_vault_role]: /nomad/docs/job-specification/vault#role
[vault_role_agent_config]: /nomad/docs/configuration/vault#create_from_role
[plan applier]: /nomad/docs/concepts/scheduling/scheduling
[JSON Web Token (JWT)]: https://datatracker.ietf.org/doc/html/rfc7519
[Task Access to Variables]: /nomad/docs/concepts/variables#task-access-to-variables
Expand Down