From 509244213b2ddcf4b03c970bfefe479e6b151d73 Mon Sep 17 00:00:00 2001 From: Roberto Jimenez Sanchez Date: Wed, 17 Dec 2025 18:07:29 +0100 Subject: [PATCH] provisioning: consolidate auth helpers into allowForAdminsOrAccessPolicy Simplifies authorization by: - Adding isAccessPolicy() helper for AccessPolicy identity check - Adding allowForAdminsOrAccessPolicy() that returns Decision directly - Consolidating stats/settings/jobs into single switch case - Using consistent pattern in files.go --- pkg/registry/apis/provisioning/files.go | 2 +- pkg/registry/apis/provisioning/register.go | 51 +++++----------------- 2 files changed, 12 insertions(+), 41 deletions(-) diff --git a/pkg/registry/apis/provisioning/files.go b/pkg/registry/apis/provisioning/files.go index be36d540c68..9a0502fefb2 100644 --- a/pkg/registry/apis/provisioning/files.go +++ b/pkg/registry/apis/provisioning/files.go @@ -243,7 +243,7 @@ func (c *filesConnector) listFolderFiles(ctx context.Context, filePath string, r // Check admin access - the frontend provisioning pages require admin access (controlled by navtree). // AccessPolicy identities (ST->MT flow) are trusted internal callers. - if !isAdminOrAccessPolicy(id) { + if !isAccessPolicy(id) && !id.GetOrgRole().Includes(identity.RoleAdmin) { return nil, apierrors.NewForbidden(resources.DashboardResource.GroupResource(), "", fmt.Errorf("admin role is required")) } diff --git a/pkg/registry/apis/provisioning/register.go b/pkg/registry/apis/provisioning/register.go index a955bd0bc85..11f38d409ba 100644 --- a/pkg/registry/apis/provisioning/register.go +++ b/pkg/registry/apis/provisioning/register.go @@ -358,12 +358,8 @@ func (b *APIBuilder) authorizeResource(ctx context.Context, a authorizer.Attribu switch a.GetResource() { case provisioning.RepositoryResourceInfo.GetName(): return b.authorizeRepositorySubresource(a, id) - case "stats": - return b.authorizeStats(id) - case "settings": - return b.authorizeSettings(id) - case provisioning.JobResourceInfo.GetName(), provisioning.HistoricJobResourceInfo.GetName(): - return b.authorizeJobs(id) + case "stats", "settings", provisioning.JobResourceInfo.GetName(), provisioning.HistoricJobResourceInfo.GetName(): + return allowForAdminsOrAccessPolicy(id) case provisioning.ConnectionResourceInfo.GetName(): return b.authorizeConnectionSubresource(a, id) default: @@ -422,42 +418,17 @@ func (b *APIBuilder) authorizeRepositorySubresource(a authorizer.Attributes, id } } -// isAdminOrAccessPolicy checks if the requester is either an admin user or an AccessPolicy identity. -// AccessPolicy identities are used in trusted internal flows (e.g., ST->MT) and don't have org roles, -// so we allow them through. Regular users must have admin role. -func isAdminOrAccessPolicy(id identity.Requester) bool { - // AccessPolicy identities are trusted internal callers (ST->MT flow) - if authlib.IsIdentityType(id.GetIdentityType(), authlib.TypeAccessPolicy) { - return true - } - // Regular users need admin role - return id.GetOrgRole().Includes(identity.RoleAdmin) +// isAccessPolicy checks if the requester is an AccessPolicy identity. +// AccessPolicy identities are used in trusted internal flows (e.g., ST->MT) and don't have org roles. +func isAccessPolicy(id identity.Requester) bool { + return authlib.IsIdentityType(id.GetIdentityType(), authlib.TypeAccessPolicy) } -// authorizeStats handles authorization for stats resource. -func (b *APIBuilder) authorizeStats(id identity.Requester) (authorizer.Decision, string, error) { - // Stats is a read-only endpoint that returns resource counts. - // The frontend provisioning pages require admin access (controlled by navtree). - if isAdminOrAccessPolicy(id) { - return authorizer.DecisionAllow, "", nil - } - return authorizer.DecisionDeny, "admin role is required", nil -} - -// authorizeSettings handles authorization for settings resource. -func (b *APIBuilder) authorizeSettings(id identity.Requester) (authorizer.Decision, string, error) { - // Settings is a read-only endpoint that returns available repository types and configuration. - // The frontend provisioning pages require admin access (controlled by navtree). - if isAdminOrAccessPolicy(id) { - return authorizer.DecisionAllow, "", nil - } - return authorizer.DecisionDeny, "admin role is required", nil -} - -// authorizeJobs handles authorization for job resources. -func (b *APIBuilder) authorizeJobs(id identity.Requester) (authorizer.Decision, string, error) { - // Jobs are shown on the configuration page. - if isAdminOrAccessPolicy(id) { +// allowForAdminsOrAccessPolicy allows access for admin users or AccessPolicy identities. +// The frontend provisioning pages require admin access (controlled by navtree in admin.go). +// AccessPolicy identities (ST->MT flow) are trusted internal callers without org roles. +func allowForAdminsOrAccessPolicy(id identity.Requester) (authorizer.Decision, string, error) { + if isAccessPolicy(id) || id.GetOrgRole().Includes(identity.RoleAdmin) { return authorizer.DecisionAllow, "", nil } return authorizer.DecisionDeny, "admin role is required", nil