grafana-iam: Implement resourcepermission get (#110256)
* resource permissions get * address review feedback * address comments - read using rp name - narrow by scope and actionsets - update sql tests * align with verb simplification * keep original format to avoid conflicts * add sqltests * cleanup * Remove unecessary errors * Move query template to queries * Use splitN to make sure we have three parts * Revert user permission management for now. We don't need it * Revert error change * group permissions by resource * extract parse scope * Move sql_test * Move & test parseScope * Add tests to getResourcePermission * Linting * Use namespace * Add test to the backend * Ongoing tests * Remove pagination, fix query boolean, insert basic role binding * Linting * Straightened the created and updated times * error handling and uniformization with other backend * Restore comments to avoid later conflicts * Integration testing * switch to function, no need to make it a method * isServiceAccount should default to FALSE instead of TRUE :surprised: * PR feedback * Sort spec permissions * Shouldn't happen but double proofing --------- Co-authored-by: Gabriel Mabille <gabriel.mabille@grafana.com>
This commit is contained in:
co-authored by
Gabriel Mabille
parent
40bf167cb7
commit
abcdf20105
@@ -1,8 +1,98 @@
|
||||
package resourcepermission
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/authlib/types"
|
||||
v0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/storage/legacysql"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// List
|
||||
|
||||
// Get
|
||||
// getResourcePermissions queries resource permissions based on the provided ListResourcePermissionsQuery and groups them by resource (e.g. {folder.grafana.app, folders, fold1})
|
||||
func (s *ResourcePermSqlBackend) getResourcePermissions(ctx context.Context, sql *legacysql.LegacyDatabaseHelper, query *ListResourcePermissionsQuery) (map[groupResourceName][]flatResourcePermission, error) {
|
||||
rawQuery, args, err := buildListResourcePermissionsQueryFromTemplate(sql, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := sql.DB.GetSqlxSession().Query(ctx, rawQuery, args...)
|
||||
if err != nil {
|
||||
if rows != nil {
|
||||
_ = rows.Close()
|
||||
}
|
||||
return nil, fmt.Errorf("querying resource permissions: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = rows.Close()
|
||||
}()
|
||||
|
||||
permissions := make(map[groupResourceName][]flatResourcePermission)
|
||||
for rows.Next() {
|
||||
var perm flatResourcePermission
|
||||
if err := rows.Scan(
|
||||
&perm.ID, &perm.Action, &perm.Scope, &perm.Created, &perm.Updated, &perm.RoleName,
|
||||
&perm.SubjectUID, &perm.SubjectType, &perm.IsServiceAccount,
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("scanning resource permission: %w", err)
|
||||
}
|
||||
|
||||
key, err := s.parseScope(perm.Scope)
|
||||
if err != nil {
|
||||
s.logger.Warn("skipping", "scope", perm.Scope, "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
permissions[*key] = append(permissions[*key], perm)
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
// getResourcePermission retrieves a single ResourcePermission by its name in the format <group>-<resource>-<name> (e.g. dashboard.grafana.app-dashboards-ad5rwqs)
|
||||
func (s *ResourcePermSqlBackend) getResourcePermission(ctx context.Context, sql *legacysql.LegacyDatabaseHelper, ns types.NamespaceInfo, name string) (*v0alpha1.ResourcePermission, error) {
|
||||
// e.g. dashboard.grafana.app-dashboards-ad5rwqs
|
||||
parts := strings.SplitN(name, "-", 3)
|
||||
if len(parts) != 3 {
|
||||
return nil, fmt.Errorf("%w: %s", errInvalidName, name)
|
||||
}
|
||||
|
||||
group, resourceType, uid := parts[0], parts[1], parts[2]
|
||||
mapper, ok := s.mappers[schema.GroupResource{Group: group, Resource: resourceType}]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%w: %s/%s", errUnknownGroupResource, group, resourceType)
|
||||
}
|
||||
|
||||
resourceQuery := &ListResourcePermissionsQuery{
|
||||
Scope: mapper.Scope(uid),
|
||||
OrgID: ns.OrgID,
|
||||
ActionSets: mapper.ActionSets(),
|
||||
}
|
||||
|
||||
permsByResource, err := s.getResourcePermissions(ctx, sql, resourceQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(permsByResource) == 0 {
|
||||
return nil, fmt.Errorf("resource permission %q: %w", resourceQuery.Scope, errNotFound)
|
||||
}
|
||||
|
||||
resourcePermission, err := toV0ResourcePermissions(permsByResource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resourcePermission == nil {
|
||||
return nil, fmt.Errorf("resource permission %q: %w", resourceQuery.Scope, errNotFound)
|
||||
}
|
||||
|
||||
return &resourcePermission[0], nil
|
||||
}
|
||||
|
||||
// Create
|
||||
|
||||
|
||||
Reference in New Issue
Block a user