Auth: Extended JWT client for OBO and Service Authentication (#83814)
* reenable ext-jwt-client * fixup settings struct * add user and service auth * lint up * add user auth to grafana ext * fixes * Populate token permissions Co-authored-by: jguer <joao.guerreiro@grafana.com> * fix tests * fix lint * small prealloc * small prealloc * use special namespace for access policies * fix access policy auth * fix tests * fix uncalled settings expander * add feature toggle * small feedback fixes * rename entitlements to permissions * add authlibn * allow viewing the signed in user info for non user namespace * fix invalid namespacedID * use authlib as verifier for tokens * Update pkg/services/authn/clients/ext_jwt.go Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> * Update pkg/services/authn/clients/ext_jwt_test.go Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> * fix parameter names * change asserts to normal package * add rule for assert * fix ownerships * Local diff * test and lint * Fix test * Fix ac test * Fix pluginproxy test * Revert testdata changes * Force revert on test data --------- Co-authored-by: gamab <gabriel.mabille@grafana.com> Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
This commit is contained in:
co-authored by
Gabriel MABILLE
gamab
parent
ac6e51c94a
commit
5340a6e548
@@ -24,6 +24,8 @@ type AccessControl interface {
|
||||
|
||||
type Service interface {
|
||||
registry.ProvidesUsageStats
|
||||
// GetRoleByName returns a role by name
|
||||
GetRoleByName(ctx context.Context, orgID int64, roleName string) (*RoleDTO, error)
|
||||
// GetUserPermissions returns user permissions with only action and scope fields set.
|
||||
GetUserPermissions(ctx context.Context, user identity.Requester, options Options) ([]Permission, error)
|
||||
// GetUserPermissionsInOrg return user permission in a specific organization
|
||||
|
||||
@@ -504,3 +504,26 @@ func (s *Service) DeleteExternalServiceRole(ctx context.Context, externalService
|
||||
func (*Service) SyncUserRoles(ctx context.Context, orgID int64, cmd accesscontrol.SyncUserRolesCommand) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) GetRoleByName(ctx context.Context, orgID int64, roleName string) (*accesscontrol.RoleDTO, error) {
|
||||
err := accesscontrol.ErrRoleNotFound
|
||||
if _, ok := s.roles[roleName]; ok {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var role *accesscontrol.RoleDTO
|
||||
s.registrations.Range(func(registration accesscontrol.RoleRegistration) bool {
|
||||
if registration.Role.Name == roleName {
|
||||
role = &accesscontrol.RoleDTO{
|
||||
Name: registration.Role.Name,
|
||||
Permissions: registration.Role.Permissions,
|
||||
DisplayName: registration.Role.DisplayName,
|
||||
Description: registration.Role.Description,
|
||||
}
|
||||
err = nil
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return role, err
|
||||
}
|
||||
|
||||
@@ -754,8 +754,9 @@ func TestPermissionCacheKey(t *testing.T) {
|
||||
{
|
||||
name: "should return correct key for user",
|
||||
signedInUser: &user.SignedInUser{
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
NamespacedID: "user:1",
|
||||
},
|
||||
expected: "rbac-permissions-1-user-1",
|
||||
},
|
||||
@@ -765,6 +766,7 @@ func TestPermissionCacheKey(t *testing.T) {
|
||||
OrgID: 1,
|
||||
ApiKeyID: 1,
|
||||
IsServiceAccount: false,
|
||||
NamespacedID: "user:1",
|
||||
},
|
||||
expected: "rbac-permissions-1-api-key-1",
|
||||
},
|
||||
@@ -774,6 +776,7 @@ func TestPermissionCacheKey(t *testing.T) {
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
IsServiceAccount: true,
|
||||
NamespacedID: "serviceaccount:1",
|
||||
},
|
||||
expected: "rbac-permissions-1-service-account-1",
|
||||
},
|
||||
@@ -783,14 +786,16 @@ func TestPermissionCacheKey(t *testing.T) {
|
||||
OrgID: 1,
|
||||
UserID: -1,
|
||||
IsServiceAccount: true,
|
||||
NamespacedID: "serviceaccount:-1",
|
||||
},
|
||||
expected: "rbac-permissions-1-service-account--1",
|
||||
},
|
||||
{
|
||||
name: "should use org role if no unique id",
|
||||
signedInUser: &user.SignedInUser{
|
||||
OrgID: 1,
|
||||
OrgRole: org.RoleNone,
|
||||
OrgID: 1,
|
||||
OrgRole: org.RoleNone,
|
||||
NamespacedID: "user:1",
|
||||
},
|
||||
expected: "rbac-permissions-1-user-None",
|
||||
},
|
||||
|
||||
@@ -20,6 +20,7 @@ type fullAccessControl interface {
|
||||
|
||||
type Calls struct {
|
||||
Evaluate []interface{}
|
||||
GetRoleByName []interface{}
|
||||
GetUserPermissions []interface{}
|
||||
GetUserPermissionsInOrg []interface{}
|
||||
ClearUserPermissionCache []interface{}
|
||||
@@ -47,6 +48,7 @@ type Mock struct {
|
||||
|
||||
// Override functions
|
||||
EvaluateFunc func(context.Context, identity.Requester, accesscontrol.Evaluator) (bool, error)
|
||||
GetRoleByNameFunc func(context.Context, int64, string) (*accesscontrol.RoleDTO, error)
|
||||
GetUserPermissionsFunc func(context.Context, identity.Requester, accesscontrol.Options) ([]accesscontrol.Permission, error)
|
||||
GetUserPermissionsInOrgFunc func(context.Context, identity.Requester, int64) ([]accesscontrol.Permission, error)
|
||||
ClearUserPermissionCacheFunc func(identity.Requester)
|
||||
@@ -81,6 +83,14 @@ func New() *Mock {
|
||||
return mock
|
||||
}
|
||||
|
||||
func (m *Mock) GetRoleByName(ctx context.Context, orgID int64, roleName string) (*accesscontrol.RoleDTO, error) {
|
||||
m.Calls.GetRoleByName = append(m.Calls.GetRoleByName, []interface{}{ctx, orgID, roleName})
|
||||
if m.GetRoleByNameFunc != nil {
|
||||
return m.GetRoleByNameFunc(ctx, orgID, roleName)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *Mock) GetUsageStats(ctx context.Context) map[string]interface{} {
|
||||
return make(map[string]interface{})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user