grafana-iam: Add role apis to the standalone app (#114897)

This commit is contained in:
Gabriel MABILLE
2025-12-08 09:22:28 +01:00
committed by GitHub
parent 78b1ae4f27
commit d0977b5245
2 changed files with 33 additions and 10 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ func newIAMAuthorizer(accessClient authlib.AccessClient, legacyAccessClient auth
authorizer := gfauthorizer.NewResourceAuthorizer(accessClient)
resourceAuthorizer[iamv0.CoreRoleInfo.GetName()] = iamauthorizer.NewCoreRoleAuthorizer(accessClient)
resourceAuthorizer[iamv0.RoleInfo.GetName()] = authorizer
resourceAuthorizer[iamv0.ResourcePermissionInfo.GetName()] = allowAuthorizer // Handled at storage layer
resourceAuthorizer[iamv0.ResourcePermissionInfo.GetName()] = allowAuthorizer // Handled by the backend wrapper
resourceAuthorizer[iamv0.RoleBindingInfo.GetName()] = authorizer
resourceAuthorizer[iamv0.ServiceAccountResourceInfo.GetName()] = authorizer
resourceAuthorizer[iamv0.UserResourceInfo.GetName()] = authorizer
+32 -9
View File
@@ -7,6 +7,7 @@ import (
"strings"
"github.com/prometheus/client_golang/prometheus"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -23,7 +24,6 @@ import (
"github.com/grafana/authlib/types"
iamv0 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
legacyiamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic"
@@ -32,6 +32,7 @@ import (
iamauthorizer "github.com/grafana/grafana/pkg/registry/apis/iam/authorizer"
"github.com/grafana/grafana/pkg/registry/apis/iam/externalgroupmapping"
"github.com/grafana/grafana/pkg/registry/apis/iam/legacy"
"github.com/grafana/grafana/pkg/registry/apis/iam/noopstorage"
"github.com/grafana/grafana/pkg/registry/apis/iam/resourcepermission"
"github.com/grafana/grafana/pkg/registry/apis/iam/serviceaccount"
"github.com/grafana/grafana/pkg/registry/apis/iam/sso"
@@ -39,6 +40,7 @@ import (
"github.com/grafana/grafana/pkg/registry/apis/iam/teambinding"
"github.com/grafana/grafana/pkg/registry/apis/iam/user"
"github.com/grafana/grafana/pkg/services/accesscontrol"
gfauthorizer "github.com/grafana/grafana/pkg/services/apiserver/auth/authorizer"
"github.com/grafana/grafana/pkg/services/apiserver/auth/authorizer/storewrapper"
"github.com/grafana/grafana/pkg/services/apiserver/builder"
"github.com/grafana/grafana/pkg/services/authz/zanzana"
@@ -116,6 +118,8 @@ func RegisterAPIService(
func NewAPIService(
accessClient types.AccessClient,
dbProvider legacysql.LegacyDatabaseProvider,
coreRoleStorage CoreRoleStorageBackend,
roleStorage RoleStorageBackend,
features featuremgmt.FeatureToggles,
zClient zanzana.Client,
reg prometheus.Registerer,
@@ -123,10 +127,17 @@ func NewAPIService(
store := legacy.NewLegacySQLStores(dbProvider)
resourcePermissionsStorage := resourcepermission.ProvideStorageBackend(dbProvider)
registerMetrics(reg)
resourceAuthorizer := gfauthorizer.NewResourceAuthorizer(accessClient)
coreRoleAuthorizer := iamauthorizer.NewCoreRoleAuthorizer(accessClient)
return &IdentityAccessManagementAPIBuilder{
store: store,
display: user.NewLegacyDisplayREST(store),
resourcePermissionsStorage: resourcePermissionsStorage,
rolesStorage: roleStorage,
coreRolesStorage: coreRoleStorage,
roleBindingsStorage: noopstorage.ProvideStorageBackend(), // TODO: add a proper storage backend
logger: log.New("iam.apis"),
features: features,
accessClient: accessClient,
@@ -135,20 +146,32 @@ func NewAPIService(
reg: reg,
authorizer: authorizer.AuthorizerFunc(
func(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
user, ok := types.AuthInfoFrom(ctx)
if !ok {
return authorizer.DecisionDeny, "no identity found", apierrors.NewUnauthorized("no identity found in context")
}
if a.GetResource() == "coreroles" {
if user.GetIdentityType() != types.TypeAccessPolicy {
return authorizer.DecisionDeny, "only access policy identities have access for now", nil
}
return coreRoleAuthorizer.Authorize(ctx, a)
}
// For now only authorize resourcepermissions resource
if a.GetResource() == "resourcepermissions" {
// Authorization is handled at the storage layer
// Authorization is handled by the backend wrapper
return authorizer.DecisionAllow, "", nil
}
user, err := identity.GetRequester(ctx)
if err != nil {
return authorizer.DecisionDeny, "no identity found", err
if a.GetResource() == "roles" {
if user.GetIdentityType() != types.TypeAccessPolicy {
return authorizer.DecisionDeny, "only access policy identities have access for now", nil
}
return resourceAuthorizer.Authorize(ctx, a)
}
if user.GetIsGrafanaAdmin() {
return authorizer.DecisionAllow, "", nil
}
return authorizer.DecisionDeny, "only grafana admins have access for now", nil
return authorizer.DecisionDeny, "access denied", nil
}),
}
}