diff --git a/pkg/registry/apis/iam/authorizer.go b/pkg/registry/apis/iam/authorizer.go index 0ec018d86de..05c8da97c2e 100644 --- a/pkg/registry/apis/iam/authorizer.go +++ b/pkg/registry/apis/iam/authorizer.go @@ -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 diff --git a/pkg/registry/apis/iam/register.go b/pkg/registry/apis/iam/register.go index 786635fa19a..32e2c9fefef 100644 --- a/pkg/registry/apis/iam/register.go +++ b/pkg/registry/apis/iam/register.go @@ -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 }), } }