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:
Karl Persson
2022-05-02 09:29:30 +02:00
committed by GitHub
parent 9622e7457e
commit de50f39c12
18 changed files with 453 additions and 434 deletions

View File

@@ -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 {

View File

@@ -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])
}
})
}