diff --git a/.changelog/16316.txt b/.changelog/16316.txt new file mode 100644 index 000000000..cd297f5b0 --- /dev/null +++ b/.changelog/16316.txt @@ -0,0 +1,3 @@ +```release-note:bug +service: Fixed a bug where attaching a policy to a job would prevent workload identities for the job from reading the service registration API +``` diff --git a/nomad/service_registration_endpoint.go b/nomad/service_registration_endpoint.go index df8014216..23570f26a 100644 --- a/nomad/service_registration_endpoint.go +++ b/nomad/service_registration_endpoint.go @@ -217,7 +217,8 @@ func (s *ServiceRegistration) List( if err != nil { return structs.ErrPermissionDenied } - if !aclObj.AllowNsOp(args.RequestNamespace(), acl.NamespaceCapabilityReadJob) { + if args.GetIdentity().Claims == nil && + !aclObj.AllowNsOp(args.RequestNamespace(), acl.NamespaceCapabilityReadJob) { return structs.ErrPermissionDenied } @@ -381,7 +382,8 @@ func (s *ServiceRegistration) GetService( if err != nil { return structs.ErrPermissionDenied } - if !aclObj.AllowNsOp(args.RequestNamespace(), acl.NamespaceCapabilityReadJob) { + if args.GetIdentity().Claims == nil && + !aclObj.AllowNsOp(args.RequestNamespace(), acl.NamespaceCapabilityReadJob) { return structs.ErrPermissionDenied } diff --git a/nomad/service_registration_endpoint_test.go b/nomad/service_registration_endpoint_test.go index 9d198e0cb..448e68377 100644 --- a/nomad/service_registration_endpoint_test.go +++ b/nomad/service_registration_endpoint_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/hashicorp/go-memdb" - "github.com/hashicorp/net-rpc-msgpackrpc" + msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc" "github.com/hashicorp/nomad/acl" "github.com/hashicorp/nomad/ci" "github.com/hashicorp/nomad/nomad/mock" @@ -882,12 +882,28 @@ func TestServiceRegistration_List(t *testing.T) { // Generate an allocation with a signed identity allocs := []*structs.Allocation{mock.Alloc()} job := allocs[0].Job + job.Namespace = "platform" + allocs[0].Namespace = "platform" require.NoError(t, s.State().UpsertJob(structs.MsgTypeTestSetup, 10, job)) s.signAllocIdentities(job, allocs) require.NoError(t, s.State().UpsertAllocs(structs.MsgTypeTestSetup, 15, allocs)) signedToken := allocs[0].SignedIdentities["web"] + // Associate an unrelated policy with the identity's job to + // ensure it doesn't conflict. + policy := &structs.ACLPolicy{ + Name: "policy-for-identity", + Rules: mock.NodePolicy("read"), + JobACL: &structs.JobACL{ + Namespace: "platform", + JobID: job.ID, + }, + } + policy.SetHash() + must.NoError(t, s.State().UpsertACLPolicies(structs.MsgTypeTestSetup, 16, + []*structs.ACLPolicy{policy})) + // Generate and upsert some service registrations. services := mock.ServiceRegistrations() require.NoError(t, s.State().UpsertServiceRegistrations(