mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Access Control: Refactor scope resolvers with support to resolve into several scopes (#48202)
* Refactor Scope resolver to support resolving into several scopes * Change permission evaluator to match at least one of passed scopes
This commit is contained in:
@@ -68,8 +68,8 @@ func ProvideService(
|
||||
ac: ac,
|
||||
}
|
||||
|
||||
ac.RegisterAttributeScopeResolver(NewNameScopeResolver(store))
|
||||
ac.RegisterAttributeScopeResolver(NewIDScopeResolver(store))
|
||||
ac.RegisterScopeAttributeResolver(NewNameScopeResolver(store))
|
||||
ac.RegisterScopeAttributeResolver(NewIDScopeResolver(store))
|
||||
|
||||
return s
|
||||
}
|
||||
@@ -82,55 +82,55 @@ type DataSourceRetriever interface {
|
||||
|
||||
const secretType = "datasource"
|
||||
|
||||
// NewNameScopeResolver provides an AttributeScopeResolver able to
|
||||
// NewNameScopeResolver provides an ScopeAttributeResolver able to
|
||||
// translate a scope prefixed with "datasources:name:" into an uid based scope.
|
||||
func NewNameScopeResolver(db DataSourceRetriever) (string, accesscontrol.AttributeScopeResolveFunc) {
|
||||
func NewNameScopeResolver(db DataSourceRetriever) (string, accesscontrol.ScopeAttributeResolver) {
|
||||
prefix := datasources.ScopeProvider.GetResourceScopeName("")
|
||||
return prefix, func(ctx context.Context, orgID int64, initialScope string) (string, error) {
|
||||
return prefix, accesscontrol.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, initialScope string) ([]string, error) {
|
||||
if !strings.HasPrefix(initialScope, prefix) {
|
||||
return "", accesscontrol.ErrInvalidScope
|
||||
return nil, accesscontrol.ErrInvalidScope
|
||||
}
|
||||
|
||||
dsName := initialScope[len(prefix):]
|
||||
if dsName == "" {
|
||||
return "", accesscontrol.ErrInvalidScope
|
||||
return nil, accesscontrol.ErrInvalidScope
|
||||
}
|
||||
|
||||
query := models.GetDataSourceQuery{Name: dsName, OrgId: orgID}
|
||||
if err := db.GetDataSource(ctx, &query); err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return datasources.ScopeProvider.GetResourceScopeUID(query.Result.Uid), nil
|
||||
}
|
||||
return []string{datasources.ScopeProvider.GetResourceScopeUID(query.Result.Uid)}, nil
|
||||
})
|
||||
}
|
||||
|
||||
// NewIDScopeResolver provides an AttributeScopeResolver able to
|
||||
// NewIDScopeResolver provides an ScopeAttributeResolver able to
|
||||
// translate a scope prefixed with "datasources:id:" into an uid based scope.
|
||||
func NewIDScopeResolver(db DataSourceRetriever) (string, accesscontrol.AttributeScopeResolveFunc) {
|
||||
func NewIDScopeResolver(db DataSourceRetriever) (string, accesscontrol.ScopeAttributeResolver) {
|
||||
prefix := datasources.ScopeProvider.GetResourceScope("")
|
||||
return prefix, func(ctx context.Context, orgID int64, initialScope string) (string, error) {
|
||||
return prefix, accesscontrol.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, initialScope string) ([]string, error) {
|
||||
if !strings.HasPrefix(initialScope, prefix) {
|
||||
return "", accesscontrol.ErrInvalidScope
|
||||
return nil, accesscontrol.ErrInvalidScope
|
||||
}
|
||||
|
||||
id := initialScope[len(prefix):]
|
||||
if id == "" {
|
||||
return "", accesscontrol.ErrInvalidScope
|
||||
return nil, accesscontrol.ErrInvalidScope
|
||||
}
|
||||
|
||||
dsID, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
return "", accesscontrol.ErrInvalidScope
|
||||
return nil, accesscontrol.ErrInvalidScope
|
||||
}
|
||||
|
||||
query := models.GetDataSourceQuery{Id: dsID, OrgId: orgID}
|
||||
if err := db.GetDataSource(ctx, &query); err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return datasources.ScopeProvider.GetResourceScopeUID(query.Result.Uid), nil
|
||||
}
|
||||
return []string{datasources.ScopeProvider.GetResourceScopeUID(query.Result.Uid)}, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
|
||||
@@ -109,13 +109,14 @@ func TestService_NameScopeResolver(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
resolved, err := resolver(context.Background(), 1, tc.given)
|
||||
resolved, err := resolver.Resolve(context.Background(), 1, tc.given)
|
||||
if tc.wantErr != nil {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, tc.wantErr, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.want, resolved)
|
||||
require.Len(t, resolved, 1)
|
||||
require.Equal(t, tc.want, resolved[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -164,13 +165,14 @@ func TestService_IDScopeResolver(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
resolved, err := resolver(context.Background(), 1, tc.given)
|
||||
resolved, err := resolver.Resolve(context.Background(), 1, tc.given)
|
||||
if tc.wantErr != nil {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, tc.wantErr, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.want, resolved)
|
||||
require.Len(t, resolved, 1)
|
||||
require.Equal(t, tc.want, resolved[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user