From f587868439bdf37db69233195bb1621987ead87f Mon Sep 17 00:00:00 2001 From: Luiz Aoqui Date: Wed, 6 Jul 2022 16:17:16 -0400 Subject: [PATCH] api: apply new ACL check for wildcard namespace (#13608) api: apply new ACL check for wildcard namespace In #13606 the ACL check was refactored to better support the all namespaces wildcard (`*`). This commit applies the changes to the jobs and alloc list endpoints. --- .changelog/13608.txt | 3 +++ nomad/alloc_endpoint.go | 23 +++++------------------ nomad/alloc_endpoint_test.go | 3 ++- nomad/job_endpoint.go | 25 ++++++------------------- 4 files changed, 16 insertions(+), 38 deletions(-) create mode 100644 .changelog/13608.txt diff --git a/.changelog/13608.txt b/.changelog/13608.txt new file mode 100644 index 000000000..431009715 --- /dev/null +++ b/.changelog/13608.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api: refactor ACL check when using the all namespaces wildcard in the job and alloc list endpoints +``` diff --git a/nomad/alloc_endpoint.go b/nomad/alloc_endpoint.go index cf678bbd1..30957db09 100644 --- a/nomad/alloc_endpoint.go +++ b/nomad/alloc_endpoint.go @@ -35,29 +35,16 @@ func (a *Alloc) List(args *structs.AllocListRequest, reply *structs.AllocListRes defer metrics.MeasureSince([]string{"nomad", "alloc", "list"}, time.Now()) namespace := args.RequestNamespace() - var allow func(string) bool // Check namespace read-job permissions aclObj, err := a.srv.ResolveToken(args.AuthToken) - - switch { - case err != nil: + if err != nil { return err - case aclObj == nil: - allow = func(string) bool { - return true - } - case namespace == structs.AllNamespacesSentinel: - allow = func(ns string) bool { - return aclObj.AllowNsOp(ns, acl.NamespaceCapabilityReadJob) - } - case !aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityReadJob): - return structs.ErrPermissionDenied - default: - allow = func(string) bool { - return true - } } + if !aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityReadJob) { + return structs.ErrPermissionDenied + } + allow := aclObj.AllowNsOpFunc(acl.NamespaceCapabilityReadJob) // Setup the blocking query sort := state.SortOption(args.Reverse) diff --git a/nomad/alloc_endpoint_test.go b/nomad/alloc_endpoint_test.go index b15fae6e3..63a43774d 100644 --- a/nomad/alloc_endpoint_test.go +++ b/nomad/alloc_endpoint_test.go @@ -1284,8 +1284,9 @@ func TestAllocEndpoint_List_AllNamespaces_ACL_OSS(t *testing.T) { { Label: "all namespaces with insufficient token", Namespace: "*", - Allocs: []*structs.Allocation{}, Token: ns1tokenInsufficient.SecretID, + Error: true, + Message: structs.ErrPermissionDenied.Error(), }, { Label: "ns1 with ns1 token", diff --git a/nomad/job_endpoint.go b/nomad/job_endpoint.go index f9a4b2497..5c1e62a62 100644 --- a/nomad/job_endpoint.go +++ b/nomad/job_endpoint.go @@ -1297,29 +1297,16 @@ func (j *Job) List(args *structs.JobListRequest, reply *structs.JobListResponse) defer metrics.MeasureSince([]string{"nomad", "job", "list"}, time.Now()) namespace := args.RequestNamespace() - var allow func(string) bool // Check for list-job permissions aclObj, err := j.srv.ResolveToken(args.AuthToken) - - switch { - case err != nil: + if err != nil { return err - case aclObj == nil: - allow = func(string) bool { - return true - } - case namespace == structs.AllNamespacesSentinel: - allow = func(ns string) bool { - return aclObj.AllowNsOp(ns, acl.NamespaceCapabilityListJobs) - } - case !aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityListJobs): - return structs.ErrPermissionDenied - default: - allow = func(string) bool { - return true - } } + if !aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityListJobs) { + return structs.ErrPermissionDenied + } + allow := aclObj.AllowNsOpFunc(acl.NamespaceCapabilityListJobs) // Setup the blocking query opts := blockingOptions{ @@ -1330,7 +1317,7 @@ func (j *Job) List(args *structs.JobListRequest, reply *structs.JobListResponse) var err error var iter memdb.ResultIterator - // check if user has permission to all namespaces + // Get the namespaces the user is allowed to access. allowableNamespaces, err := allowedNSes(aclObj, state, allow) if err == structs.ErrPermissionDenied { // return empty jobs if token isn't authorized for any