provisioning: add isAdminOrAccessPolicy helper for auth checks
Consolidates authorization logic for provisioning endpoints: - Adds isAdminOrAccessPolicy() helper that allows admin users OR AccessPolicy identities - AccessPolicy identities (ST->MT flow) are trusted internal callers without org roles - Regular users must have admin role (matching frontend navtree restriction) Used in: authorizeSettings, authorizeStats, authorizeJobs, listFolderFiles
This commit is contained in:
2 files changed
+37
-10
No files matched your search
@@ -15,6 +15,7 @@ import (
|
||||
provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/repository"
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/safepath"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/provisioning/resources"
|
||||
)
|
||||
|
||||
@@ -235,8 +236,17 @@ func (c *filesConnector) Connect(ctx context.Context, name string, opts runtime.
|
||||
|
||||
// listFolderFiles returns a list of files in a folder
|
||||
func (c *filesConnector) listFolderFiles(ctx context.Context, filePath string, ref string, readWriter repository.ReaderWriter) (*provisioning.FileList, error) {
|
||||
// Authorization is handled at the route level - any authenticated user who can access
|
||||
// the files endpoint can list files. The AccessClient controls per-file access.
|
||||
id, err := identity.GetRequester(ctx)
|
||||
if err != nil {
|
||||
return nil, apierrors.NewUnauthorized("missing auth info in context")
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return nil, apierrors.NewForbidden(resources.DashboardResource.GroupResource(), "",
|
||||
fmt.Errorf("admin role is required"))
|
||||
}
|
||||
|
||||
// TODO: Implement folder navigation
|
||||
if len(filePath) > 0 {
|
||||
|
||||
@@ -422,25 +422,42 @@ 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)
|
||||
}
|
||||
|
||||
// authorizeStats handles authorization for stats resource.
|
||||
func (b *APIBuilder) authorizeStats(_ identity.Requester) (authorizer.Decision, string, error) {
|
||||
func (b *APIBuilder) authorizeStats(id identity.Requester) (authorizer.Decision, string, error) {
|
||||
// Stats is a read-only endpoint that returns resource counts.
|
||||
// Any authenticated user can access it - authentication is verified before this point.
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
// 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(_ identity.Requester) (authorizer.Decision, string, error) {
|
||||
func (b *APIBuilder) authorizeSettings(id identity.Requester) (authorizer.Decision, string, error) {
|
||||
// Settings is a read-only endpoint that returns available repository types and configuration.
|
||||
// Any authenticated user can access it - authentication is verified before this point.
|
||||
// The frontend needs this to display the provisioning wizard.
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
// 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 id.GetOrgRole().Includes(identity.RoleAdmin) {
|
||||
if isAdminOrAccessPolicy(id) {
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
||||
return authorizer.DecisionDeny, "admin role is required", nil
|
||||
|
||||
Reference in new issue
Block a user