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
+10 -10
View File
@@ -401,20 +401,21 @@ func (hs *HTTPServer) GetAnnotationTags(c *models.ReqContext) response.Response
return response.JSON(http.StatusOK, annotations.GetAnnotationTagsResponse{Result: result})
}
// AnnotationTypeScopeResolver provides an AttributeScopeResolver able to
// AnnotationTypeScopeResolver provides an ScopeAttributeResolver able to
// resolve annotation types. Scope "annotations:id:<id>" will be translated to "annotations:type:<type>,
// where <type> is the type of annotation with id <id>.
func AnnotationTypeScopeResolver() (string, accesscontrol.AttributeScopeResolveFunc) {
annotationTypeResolver := func(ctx context.Context, orgID int64, initialScope string) (string, error) {
func AnnotationTypeScopeResolver() (string, accesscontrol.ScopeAttributeResolver) {
prefix := accesscontrol.ScopeAnnotationsProvider.GetResourceScope("")
return prefix, accesscontrol.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, initialScope string) ([]string, error) {
scopeParts := strings.Split(initialScope, ":")
if scopeParts[0] != accesscontrol.ScopeAnnotationsRoot || len(scopeParts) != 3 {
return "", accesscontrol.ErrInvalidScope
return nil, accesscontrol.ErrInvalidScope
}
annotationIdStr := scopeParts[2]
annotationId, err := strconv.Atoi(annotationIdStr)
if err != nil {
return "", accesscontrol.ErrInvalidScope
return nil, accesscontrol.ErrInvalidScope
}
// tempUser is used to resolve annotation type.
@@ -431,16 +432,15 @@ func AnnotationTypeScopeResolver() (string, accesscontrol.AttributeScopeResolveF
annotation, resp := findAnnotationByID(ctx, annotations.GetRepository(), int64(annotationId), tempUser)
if resp != nil {
return "", errors.New("could not resolve annotation type")
return nil, errors.New("could not resolve annotation type")
}
if annotation.GetType() == annotations.Organization {
return accesscontrol.ScopeAnnotationsTypeOrganization, nil
return []string{accesscontrol.ScopeAnnotationsTypeOrganization}, nil
} else {
return accesscontrol.ScopeAnnotationsTypeDashboard, nil
return []string{accesscontrol.ScopeAnnotationsTypeDashboard}, nil
}
}
return accesscontrol.ScopeAnnotationsProvider.GetResourceScope(""), annotationTypeResolver
})
}
func (hs *HTTPServer) canCreateAnnotation(c *models.ReqContext, dashboardId int64) (bool, error) {
+4 -3
View File
@@ -722,7 +722,7 @@ func TestAPI_Annotations_AccessControl(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
setUpRBACGuardian(t)
sc.acmock.
RegisterAttributeScopeResolver(AnnotationTypeScopeResolver())
RegisterScopeAttributeResolver(AnnotationTypeScopeResolver())
setAccessControlPermissions(sc.acmock, tt.args.permissions, sc.initCtx.OrgId)
r := callAPI(sc.server, tt.args.method, tt.args.url, tt.args.body, t)
@@ -780,13 +780,14 @@ func TestService_AnnotationTypeScopeResolver(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])
}
})
}
+1 -1
View File
@@ -265,7 +265,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
hs.registerRoutes()
// Register access control scope resolver for annotations
hs.AccessControl.RegisterAttributeScopeResolver(AnnotationTypeScopeResolver())
hs.AccessControl.RegisterScopeAttributeResolver(AnnotationTypeScopeResolver())
if err := hs.declareFixedRoles(); err != nil {
return nil, err