ext jwt client: map k8s-style to rbac permissions (#106279)
* initial commit * Proposal Co-Authored-By: mohammad-hamid <mohammad.hamid@grafana.com> * extend k8s-style mapper - add tests * address comments * cleanup * address comments --------- Co-authored-by: Gabriel Mabille <gabriel.mabille@grafana.com>
This commit is contained in:
co-authored by
Gabriel Mabille
parent
67f50478d9
commit
936dd05eac
@@ -17,6 +17,7 @@ import (
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
permreg "github.com/grafana/grafana/pkg/services/accesscontrol/permreg/test"
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
rbac "github.com/grafana/grafana/pkg/services/authz/rbac"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
)
|
||||
@@ -421,6 +422,135 @@ func TestRBACSync_ClearUserPermissionCacheHook(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRBACSync_translateK8sPermissions(t *testing.T) {
|
||||
type testCase struct {
|
||||
name string
|
||||
k8sPerms []string
|
||||
expectedPerms []accesscontrol.Permission
|
||||
expectedError error
|
||||
}
|
||||
|
||||
tests := []testCase{
|
||||
{
|
||||
name: "should translate folder.grafana.app/folders:get to folders:read",
|
||||
k8sPerms: []string{
|
||||
"folder.grafana.app/folders:get",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{
|
||||
{Action: "folders:read", Scope: "folders:uid:*"},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should translate resource with wildcard verb",
|
||||
k8sPerms: []string{
|
||||
"folder.grafana.app/folders:*",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{
|
||||
{Action: "folders:read", Scope: "folders:uid:*"},
|
||||
{Action: "folders:write", Scope: "folders:uid:*"},
|
||||
{Action: "folders:delete", Scope: "folders:uid:*"},
|
||||
{Action: "folders:create", Scope: "folders:uid:*"},
|
||||
{Action: "folders.permissions:read", Scope: "folders:uid:*"},
|
||||
{Action: "folders.permissions:write", Scope: "folders:uid:*"},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should handle invalid permission format",
|
||||
k8sPerms: []string{
|
||||
"invalid-format",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should handle unknown resource",
|
||||
k8sPerms: []string{
|
||||
"folder.grafana.app/unknown:get",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should handle unknown verb",
|
||||
k8sPerms: []string{
|
||||
"folder.grafana.app/folders:unknown",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should handle group:verb format",
|
||||
k8sPerms: []string{
|
||||
"folder.grafana.app:get",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{
|
||||
{Action: "folders:read", Scope: "folders:uid:*"},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should handle group:* format",
|
||||
k8sPerms: []string{
|
||||
"folder.grafana.app:*",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{
|
||||
{Action: "folders:read", Scope: "folders:uid:*"},
|
||||
{Action: "folders:write", Scope: "folders:uid:*"},
|
||||
{Action: "folders:delete", Scope: "folders:uid:*"},
|
||||
{Action: "folders:create", Scope: "folders:uid:*"},
|
||||
{Action: "folders.permissions:read", Scope: "folders:uid:*"},
|
||||
{Action: "folders.permissions:write", Scope: "folders:uid:*"},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should handle unknown group in group:verb format",
|
||||
k8sPerms: []string{
|
||||
"unknown.grafana.app:get",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should handle unknown verb in group:verb format",
|
||||
k8sPerms: []string{
|
||||
"folder.grafana.app:unknownverb",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should handle multiple group:verb permissions",
|
||||
k8sPerms: []string{
|
||||
"folder.grafana.app:get",
|
||||
"folder.grafana.app:create",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{
|
||||
{Action: "folders:read", Scope: "folders:uid:*"},
|
||||
{Action: "folders:create", Scope: "folders:uid:*"},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "should skip invalid permissions group/resource/additional/part:verb",
|
||||
k8sPerms: []string{
|
||||
"folder.grafana.app/folder/fold1/subresource:get",
|
||||
},
|
||||
expectedPerms: []accesscontrol.Permission{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := setupTestEnv(t)
|
||||
perms := s.translateK8sPermissions(context.Background(), tt.k8sPerms)
|
||||
assert.ElementsMatch(t, tt.expectedPerms, perms)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func setupTestEnv(t *testing.T) *RBACSync {
|
||||
acMock := &acmock.Mock{
|
||||
GetUserPermissionsFunc: func(ctx context.Context, siu identity.Requester, o accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
@@ -446,11 +576,19 @@ func setupTestEnv(t *testing.T) *RBACSync {
|
||||
},
|
||||
}
|
||||
permRegistry := permreg.ProvidePermissionRegistry(t)
|
||||
|
||||
require.NoError(t, permRegistry.RegisterPermission("folders:write", "folders:uid:"))
|
||||
require.NoError(t, permRegistry.RegisterPermission("folders:create", "folders:uid:"))
|
||||
require.NoError(t, permRegistry.RegisterPermission("folders:delete", "folders:uid:"))
|
||||
require.NoError(t, permRegistry.RegisterPermission("folders.permissions:read", "folders:uid:"))
|
||||
require.NoError(t, permRegistry.RegisterPermission("folders.permissions:write", "folders:uid:"))
|
||||
|
||||
s := &RBACSync{
|
||||
ac: acMock,
|
||||
log: log.NewNopLogger(),
|
||||
tracer: tracing.InitializeTracerForTest(),
|
||||
permRegistry: permRegistry,
|
||||
mapper: rbac.NewMapperRegistry(),
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user