diff --git a/.changelog/23763.txt b/.changelog/23763.txt new file mode 100644 index 000000000..e3089ee2d --- /dev/null +++ b/.changelog/23763.txt @@ -0,0 +1,3 @@ +```release-note:bug +identity: Fixed a bug where a missing default task identity could panic the leader +``` diff --git a/nomad/encrypter.go b/nomad/encrypter.go index 6b23bb9a7..0ab6c251a 100644 --- a/nomad/encrypter.go +++ b/nomad/encrypter.go @@ -242,6 +242,10 @@ const keyIDHeader = "kid" // SignClaims adds the Issuer claim prior to signing. func (e *Encrypter) SignClaims(claims *structs.IdentityClaims) (string, string, error) { + if claims == nil { + return "", "", errors.New("cannot sign empty claims") + } + // If a key is rotated immediately following a leader election, plans that // are in-flight may get signed before the new leader has the key. Allow for // a short timeout-and-retry to avoid rejecting plans diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 6879623a6..aad6b42a1 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -8055,9 +8055,10 @@ func (t *Task) Canonicalize(job *Job, tg *TaskGroup) { // If there was no default identity, always create one. if t.Identity == nil { - t.Identity = &WorkloadIdentity{} + t.Identity = DefaultWorkloadIdentity() + } else { + t.Identity.Canonicalize() } - t.Identity.Canonicalize() } func (t *Task) GoString() string { diff --git a/nomad/structs/workload_id.go b/nomad/structs/workload_id.go index 90a288508..c66c4bbb3 100644 --- a/nomad/structs/workload_id.go +++ b/nomad/structs/workload_id.go @@ -110,6 +110,9 @@ func NewIdentityClaimsBuilder(job *Job, alloc *Allocation, wihandle *WIHandle, w if tg == nil { return nil } + if wid == nil { + wid = DefaultWorkloadIdentity() + } return &IdentityClaimsBuilder{ alloc: alloc, @@ -318,9 +321,19 @@ type WorkloadIdentity struct { // escalate their privileges if they know what claim mappings to expect. } +func DefaultWorkloadIdentity() *WorkloadIdentity { + return &WorkloadIdentity{ + Name: WorkloadIdentityDefaultName, + Audience: []string{WorkloadIdentityDefaultAud}, + } +} + // IsConsul returns true if the identity name starts with the standard prefix // for Consul tasks and services. func (wi *WorkloadIdentity) IsConsul() bool { + if wi == nil { + return false + } return strings.HasPrefix(wi.Name, ConsulTaskIdentityNamePrefix) || strings.HasPrefix(wi.Name, ConsulServiceIdentityNamePrefix) } @@ -328,6 +341,9 @@ func (wi *WorkloadIdentity) IsConsul() bool { // IsVault returns true if the identity name starts with the standard prefix // for Vault tasks. func (wi *WorkloadIdentity) IsVault() bool { + if wi == nil { + return false + } return strings.HasPrefix(wi.Name, WorkloadIdentityVaultPrefix) }