Files
grafana/pkg/tests/apis/iam/resource_permissions_integration_test.go
Gabriel MABILLE 478ae15f0e grafana-iam: Use parent folder to authorize ResourcePermissions (#115008)
* `grafana-iam`: Fetch target parent folder

* WIP add different ParentProviders

* Add version

* Move code to a different file

* Instantiate resourceParentProvider

* same import name

* imports

* Add tests

* Remove unecessary test

* forgot wire

* WIP integration tests

* Add test to cover list

* Fix caching problem in integration tests

* comments

* Logger and comments

* Add lazy creation and caching

* Instantiate clients only once

* Rerun wire gen
2025-12-12 11:43:12 +01:00

626 lines
24 KiB
Go

package identity
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
iamv0 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tests/apis"
"github.com/grafana/grafana/pkg/tests/testinfra"
"github.com/grafana/grafana/pkg/util/testutil"
)
var gvrResourcePermissions = schema.GroupVersionResource{
Group: "iam.grafana.app",
Version: "v0alpha1",
Resource: "resourcepermissions",
}
var gvrFolders = schema.GroupVersionResource{
Group: "folder.grafana.app",
Version: "v1beta1",
Resource: "folders",
}
var gvrDashboards = schema.GroupVersionResource{
Group: "dashboard.grafana.app",
Version: "v1beta1",
Resource: "dashboards",
}
type permission struct {
kind string
name string
verb string
}
func newPermission(kind, name, verb string) permission {
return permission{
kind: kind,
name: name,
verb: verb,
}
}
func (p permission) ToMap() map[string]interface{} {
return map[string]interface{}{
"kind": p.kind,
"name": p.name,
"verb": p.verb,
}
}
func newPermissionMaps(permissions ...permission) []map[string]interface{} {
permissionsMaps := make([]map[string]interface{}, len(permissions))
for i, permission := range permissions {
permissionsMaps[i] = permission.ToMap()
}
return permissionsMaps
}
type k8sTestClients struct {
rpAdmin *apis.K8sResourceClient
rpEditor *apis.K8sResourceClient
rpViewer *apis.K8sResourceClient
}
func newk8sTestHelperClients(helper *apis.K8sTestHelper) *k8sTestClients {
return &k8sTestClients{
rpAdmin: helper.GetResourceClient(apis.ResourceClientArgs{
User: helper.Org1.Admin,
Namespace: helper.Namespacer(helper.Org1.OrgID),
GVR: gvrResourcePermissions,
}),
rpEditor: helper.GetResourceClient(apis.ResourceClientArgs{
User: helper.Org1.Editor,
Namespace: helper.Namespacer(helper.Org1.OrgID),
GVR: gvrResourcePermissions,
}),
rpViewer: helper.GetResourceClient(apis.ResourceClientArgs{
User: helper.Org1.Viewer,
Namespace: helper.Namespacer(helper.Org1.OrgID),
GVR: gvrResourcePermissions,
}),
}
}
func TestIntegrationResourcePermissions(t *testing.T) {
testutil.SkipIntegrationTestInShortMode(t)
modes := []rest.DualWriterMode{rest.Mode0, rest.Mode1, rest.Mode2, rest.Mode3}
for _, mode := range modes {
if mode >= rest.Mode3 {
t.Skip("Skipping ResourcePermission tests for Mode3+ because default permissions are not written through the new APIs")
continue
}
t.Run(fmt.Sprintf("ResourcePermission CRUD with dual writer mode %d", mode), func(t *testing.T) {
// Turn off authorization cache so permission changes apply right away in tests
t.Setenv("GF_AUTHORIZATION_CACHE_TTL", "0s")
helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{
AppModeProduction: false,
DisableAnonymous: true,
APIServerStorageType: "unified",
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
"resourcepermissions.iam.grafana.app": {
DualWriterMode: mode,
},
"folders.folder.grafana.app": {
DualWriterMode: mode,
},
"dashboards.dashboard.grafana.app": {
DualWriterMode: mode,
},
},
EnableFeatureToggles: []string{
featuremgmt.FlagKubernetesAuthzResourcePermissionApis,
// Prevents nested folders from having default permissions
featuremgmt.FlagKubernetesDashboards,
},
})
// Work around the default permissions applied on root folders
// so we can test the ResourcePermission APIs without the default permissions interfering
parentFolder := createRootFolderWithoutDefaultPermissions(t, helper)
parentUID := parentFolder.GetName()
clients := newk8sTestHelperClients(helper)
doResourcePermissionCRUDTests(t, helper, clients, parentUID)
doResourcePermissionAuthzTests(t, helper, clients, parentUID)
doResourcePermissionHierarchyTests(t, helper, clients, parentUID)
doResourcePermissionListFilteringTests(t, helper, clients, parentUID)
// TODO: Add tests for External JWT authentication
// doResourcePermissionAccessPolicyTests(t, helper)
})
}
}
func doResourcePermissionCRUDTests(t *testing.T, helper *apis.K8sTestHelper, clients *k8sTestClients, parentUID string) {
t.Run("should create/get/update/delete ResourcePermission using the new APIs", func(t *testing.T) {
ctx := context.Background()
// Create ResourcePermission for the folder
permission := newPermission("ServiceAccount", helper.Org1.ViewerServiceAccount.UID, "view")
toCreate := createResourcePermissionObject(parentUID, gvrFolders.Group, gvrFolders.Resource, permission)
created, err := clients.rpAdmin.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.NoError(t, err)
require.NotNil(t, created)
createdName := created.GetName()
require.NotEmpty(t, createdName)
// Verify spec
spec := created.Object["spec"].(map[string]interface{})
resource := spec["resource"].(map[string]interface{})
require.Equal(t, gvrFolders.Group, resource["apiGroup"])
require.Equal(t, gvrFolders.Resource, resource["resource"])
require.Equal(t, parentUID, resource["name"])
// Get the ResourcePermission
fetched, err := clients.rpAdmin.Resource.Get(ctx, createdName, metav1.GetOptions{})
require.NoError(t, err)
require.NotNil(t, fetched)
require.Equal(t, createdName, fetched.GetName())
// Update the ResourcePermission
fetched.Object["spec"].(map[string]interface{})["permissions"] = newPermissionMaps(
newPermission("User", helper.Org1.Viewer.Identity.GetIdentifier(), "edit"),
)
updated, err := clients.rpAdmin.Resource.Update(ctx, fetched, metav1.UpdateOptions{})
require.NoError(t, err)
require.NotNil(t, updated)
updatedSpec := updated.Object["spec"].(map[string]interface{})
permissions := updatedSpec["permissions"].([]interface{})
require.Len(t, permissions, 1)
perm := permissions[0].(map[string]interface{})
require.Equal(t, helper.Org1.Viewer.Identity.GetIdentifier(), perm["name"])
require.Equal(t, "edit", perm["verb"])
// Delete should work
err = clients.rpAdmin.Resource.Delete(ctx, createdName, metav1.DeleteOptions{})
require.NoError(t, err)
_, err = clients.rpAdmin.Resource.Get(ctx, createdName, metav1.GetOptions{})
require.Error(t, err)
var statusErr *errors.StatusError
require.ErrorAs(t, err, &statusErr)
require.Equal(t, int32(404), statusErr.ErrStatus.Code)
})
t.Run("should return 404 for non-existent ResourcePermission", func(t *testing.T) {
ctx := context.Background()
_, err := clients.rpAdmin.Resource.Get(ctx, "folder.grafana.app-folders-unknown", metav1.GetOptions{})
require.Error(t, err)
var statusErr *errors.StatusError
require.ErrorAs(t, err, &statusErr)
require.Equal(t, int32(404), statusErr.ErrStatus.Code)
})
}
func doResourcePermissionAuthzTests(t *testing.T, helper *apis.K8sTestHelper, clients *k8sTestClients, parentUID string) {
t.Run("admin can create/update/delete ResourcePermission", func(t *testing.T) {
ctx := context.Background()
folder := createTestFolder(t, helper, helper.Org1.Admin, "test-folder-admin", parentUID)
folderUID := folder.GetName()
permission := newPermission("User", helper.Org1.Admin.Identity.GetIdentifier(), "admin")
toCreate := createResourcePermissionObject(folderUID, gvrFolders.Group, gvrFolders.Resource, permission)
created, err := clients.rpAdmin.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.NoError(t, err)
require.NotNil(t, created)
createdName := created.GetName()
// Get the created object
fetched, err := clients.rpAdmin.Resource.Get(ctx, createdName, metav1.GetOptions{})
require.NoError(t, err)
require.NotNil(t, fetched)
// Update should work
permission = newPermission("Team", helper.Org1.Staff.UID, "edit")
fetched.Object["spec"].(map[string]interface{})["permissions"] = []interface{}{permission.ToMap()}
_, err = clients.rpAdmin.Resource.Update(ctx, fetched, metav1.UpdateOptions{})
require.NoError(t, err)
// Delete should work
err = clients.rpAdmin.Resource.Delete(ctx, createdName, metav1.DeleteOptions{})
require.NoError(t, err)
})
t.Run("editor cannot create ResourcePermission (insufficient permissions)", func(t *testing.T) {
ctx := context.Background()
folder := createTestFolder(t, helper, helper.Org1.Admin, "test-folder-editor-deny", parentUID)
folderUID := folder.GetName()
permission := newPermission("User", helper.Org1.Editor.Identity.GetIdentifier(), "admin")
toCreate := createResourcePermissionObject(folderUID, gvrFolders.Group, gvrFolders.Resource, permission)
_, err := clients.rpEditor.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.Error(t, err)
var statusErr *errors.StatusError
require.ErrorAs(t, err, &statusErr)
require.Equal(t, int32(403), statusErr.ErrStatus.Code)
})
t.Run("viewer cannot create ResourcePermission (insufficient permissions)", func(t *testing.T) {
ctx := context.Background()
folder := createTestFolder(t, helper, helper.Org1.Admin, "test-folder-viewer-deny", parentUID)
folderUID := folder.GetName()
permission := newPermission("User", helper.Org1.Viewer.Identity.GetIdentifier(), "admin")
toCreate := createResourcePermissionObject(folderUID, gvrFolders.Group, gvrFolders.Resource, permission)
_, err := clients.rpViewer.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.Error(t, err)
var statusErr *errors.StatusError
require.ErrorAs(t, err, &statusErr)
require.Equal(t, int32(403), statusErr.ErrStatus.Code)
})
t.Run("viewer can update ResourcePermission of folder they can admin", func(t *testing.T) {
ctx := context.Background()
folder := createTestFolder(t, helper, helper.Org1.Admin, "test-folder-viewer-admin", parentUID)
folderUID := folder.GetName()
// Grant admin permissions to the viewer
permission := newPermission("User", helper.Org1.Viewer.Identity.GetIdentifier(), "admin")
toCreate := createResourcePermissionObject(folderUID, gvrFolders.Group, gvrFolders.Resource, permission)
_, err := clients.rpAdmin.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.NoError(t, err)
// As a Viewer we should now be able to get and update the ResourcePermission of the folder
fetched, err := clients.rpViewer.Resource.Get(ctx, "folder.grafana.app-folders-"+folderUID, metav1.GetOptions{})
require.NoError(t, err)
require.NotNil(t, fetched)
// Update the ResourcePermission to grant editor permissions
fetched.Object["spec"].(map[string]interface{})["permissions"] = newPermissionMaps(
newPermission("BasicRole", "Editor", "edit"),
newPermission("User", helper.Org1.Viewer.Identity.GetIdentifier(), "admin"),
)
_, err = clients.rpViewer.Resource.Update(ctx, fetched, metav1.UpdateOptions{})
require.NoError(t, err)
})
}
func doResourcePermissionHierarchyTests(t *testing.T, helper *apis.K8sTestHelper, clients *k8sTestClients, parentUID string) {
permission := newPermission("BasicRole", "Editor", "admin")
t.Run("should respect folder hierarchy for folder permissions", func(t *testing.T) {
ctx := context.Background()
sub1 := createTestFolder(t, helper, helper.Org1.Admin, "sub1-folder-hierarchy", parentUID)
sub1UID := sub1.GetName()
sub2 := createTestFolder(t, helper, helper.Org1.Admin, "sub2-folder-hierarchy", sub1UID)
sub2UID := sub2.GetName()
toCreate := createResourcePermissionObject(sub2UID, gvrFolders.Group, gvrFolders.Resource, permission)
_, err := clients.rpAdmin.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.NoError(t, err)
t.Run("editor can update ResourcePermission of sub2", func(t *testing.T) {
fetched, err := clients.rpEditor.Resource.Get(ctx, "folder.grafana.app-folders-"+sub2UID, metav1.GetOptions{})
require.NoError(t, err)
fetched.Object["spec"].(map[string]interface{})["permissions"] = newPermissionMaps(
newPermission("BasicRole", "Editor", "admin"),
newPermission("User", helper.Org1.Viewer.Identity.GetIdentifier(), "edit"),
)
_, err = clients.rpEditor.Resource.Update(ctx, fetched, metav1.UpdateOptions{})
require.NoError(t, err)
})
t.Run("editor cannot create ResourcePermission of sub1", func(t *testing.T) {
toCreate := createResourcePermissionObject(sub1UID, gvrFolders.Group, gvrFolders.Resource, permission)
_, err := clients.rpEditor.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.Error(t, err)
var statusErr *errors.StatusError
require.ErrorAs(t, err, &statusErr)
require.Equal(t, int32(403), statusErr.ErrStatus.Code)
})
// Delete the ResourcePermission of sub2
err = clients.rpAdmin.Resource.Delete(ctx, "folder.grafana.app-folders-"+sub2UID, metav1.DeleteOptions{})
require.NoError(t, err)
// Create a new ResourcePermission for sub2
toCreate = createResourcePermissionObject(sub1UID, gvrFolders.Group, gvrFolders.Resource, permission)
_, err = clients.rpAdmin.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.NoError(t, err)
t.Run("editor can create ResourcePermission of sub2 with parent folder permission", func(t *testing.T) {
toCreate := createResourcePermissionObject(sub2UID, gvrFolders.Group, gvrFolders.Resource, permission)
_, err = clients.rpEditor.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.NoError(t, err)
fetched, err := clients.rpEditor.Resource.Get(ctx, "folder.grafana.app-folders-"+sub2UID, metav1.GetOptions{})
require.NoError(t, err)
require.NotNil(t, fetched)
permissions := fetched.Object["spec"].(map[string]interface{})["permissions"]
require.Len(t, permissions, 1)
})
})
t.Run("should respect folder hierarchy for dashboard permissions", func(t *testing.T) {
ctx := context.Background()
// Create folder and a nested dashboard
folder := createTestFolder(t, helper, helper.Org1.Admin, "sub1-dashboard-hierarchy", parentUID)
folderUID := folder.GetName()
dashboard := createTestDashboard(t, helper, helper.Org1.Admin, "sub2-dashboard", folderUID)
dashboardUID := dashboard.GetName()
// Verify dashboard has parent folder annotation
annotations := dashboard.GetAnnotations()
require.Equal(t, folderUID, annotations[utils.AnnoKeyFolder])
t.Run("editor cannot create ResourcePermission of dashboard without parent folder permission", func(t *testing.T) {
toCreate := createResourcePermissionObject(dashboardUID, gvrDashboards.Group, gvrDashboards.Resource, permission)
_, err := clients.rpEditor.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.Error(t, err)
var statusErr *errors.StatusError
require.ErrorAs(t, err, &statusErr)
require.Equal(t, int32(403), statusErr.ErrStatus.Code)
})
// Admin creates ResourcePermission for parent folder
toCreate := createResourcePermissionObject(folderUID, gvrFolders.Group, gvrFolders.Resource, permission)
created, err := clients.rpAdmin.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.NoError(t, err)
require.NotNil(t, created)
t.Run("editor can create ResourcePermission of dashboard with parent folder permission", func(t *testing.T) {
toCreate := createResourcePermissionObject(dashboardUID, gvrDashboards.Group, gvrDashboards.Resource, permission)
_, err := clients.rpEditor.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
require.NoError(t, err)
fetched, err := clients.rpEditor.Resource.Get(ctx, "dashboard.grafana.app-dashboards-"+dashboardUID, metav1.GetOptions{})
require.NoError(t, err)
require.NotNil(t, fetched)
permissions := fetched.Object["spec"].(map[string]interface{})["permissions"]
require.Len(t, permissions, 1)
})
})
}
func doResourcePermissionListFilteringTests(t *testing.T, helper *apis.K8sTestHelper, clients *k8sTestClients, parentUID string) {
viewerCanAdmin := newPermission("BasicRole", "Viewer", "admin")
viewerCanView := newPermission("BasicRole", "Viewer", "view")
editorCanAdmin := newPermission("BasicRole", "Editor", "admin")
ctx := context.Background()
// Create two folders
editorFolder := createTestFolder(t, helper, helper.Org1.Admin, "editor-only-folder", parentUID)
editorFolderUID := editorFolder.GetName()
viewerFolder := createTestFolder(t, helper, helper.Org1.Admin, "viewer-only-folder", parentUID)
viewerFolderUID := viewerFolder.GetName()
dashboardViewerCanAdmin := createTestDashboard(t, helper, helper.Org1.Admin, "dashboard-in-editor-folder-viewer-can-admin", editorFolderUID)
dashboardViewerCanAdminUID := dashboardViewerCanAdmin.GetName()
dashboardViewerCanView := createTestDashboard(t, helper, helper.Org1.Admin, "dashboard-in-editor-folder-viewer-can-view", editorFolderUID)
dashboardViewerCanViewUID := dashboardViewerCanView.GetName()
// Grant admin permissions to the viewer on folder2 and dashboard1
rp1 := createResourcePermissionObject(viewerFolderUID, gvrFolders.Group, gvrFolders.Resource, viewerCanAdmin)
_, err := clients.rpAdmin.Resource.Create(ctx, rp1, metav1.CreateOptions{})
require.NoError(t, err)
rp2 := createResourcePermissionObject(dashboardViewerCanAdminUID, gvrDashboards.Group, gvrDashboards.Resource, viewerCanAdmin)
_, err = clients.rpAdmin.Resource.Create(ctx, rp2, metav1.CreateOptions{})
require.NoError(t, err)
// Grant admin permissions to the editor on folder1
rp3 := createResourcePermissionObject(editorFolderUID, gvrFolders.Group, gvrFolders.Resource, editorCanAdmin)
_, err = clients.rpAdmin.Resource.Create(ctx, rp3, metav1.CreateOptions{})
require.NoError(t, err)
// Grant view permissions to the viewer on dashboard2
rp4 := createResourcePermissionObject(dashboardViewerCanViewUID, gvrDashboards.Group, gvrDashboards.Resource, viewerCanView)
_, err = clients.rpAdmin.Resource.Create(ctx, rp4, metav1.CreateOptions{})
require.NoError(t, err)
t.Run("Admin can list all ResourcePermissions", func(t *testing.T) {
// Admin can list all ResourcePermissions
list, err := clients.rpAdmin.Resource.List(ctx, metav1.ListOptions{})
require.NoError(t, err)
require.NotNil(t, list)
// Check that all expected items are present (there may be more from other tests)
itemNames := getNamesFromList(list)
require.Contains(t, itemNames, rp1.GetName(), "Admin should see viewer folder permission")
require.Contains(t, itemNames, rp2.GetName(), "Admin should see dashboard viewer can admin permission")
require.Contains(t, itemNames, rp3.GetName(), "Admin should see editor folder permission")
require.Contains(t, itemNames, rp4.GetName(), "Admin should see dashboard viewer can view permission")
})
t.Run("Viewer can list ResourcePermissions of folder2 and dashboard1", func(t *testing.T) {
list, err := clients.rpViewer.Resource.List(ctx, metav1.ListOptions{})
require.NoError(t, err)
require.NotNil(t, list)
itemNames := getNamesFromList(list)
// Viewer should see permissions for resources they can admin
require.Contains(t, itemNames, rp1.GetName(), "Viewer should see viewer folder permission")
require.Contains(t, itemNames, rp2.GetName(), "Viewer should see dashboard viewer can admin permission")
// Viewer should NOT see permissions for resources they cannot admin
require.NotContains(t, itemNames, rp3.GetName(), "Viewer should NOT see editor folder permission")
require.NotContains(t, itemNames, rp4.GetName(), "Viewer should NOT see dashboard viewer can view permission")
})
t.Run("Editor can list ResourcePermissions of folder1 and its nested dashboards", func(t *testing.T) {
list, err := clients.rpEditor.Resource.List(ctx, metav1.ListOptions{})
require.NoError(t, err)
require.NotNil(t, list)
itemNames := getNamesFromList(list)
// Editor has admin on editorFolder, so they should see:
// - rp3 (editorFolder permission)
// - rp2 (dashboard in editorFolder with admin permission)
// - rp4 (dashboard in editorFolder with view permission)
require.Contains(t, itemNames, rp2.GetName(), "Editor should see dashboard admin permission in their folder")
require.Contains(t, itemNames, rp3.GetName(), "Editor should see their folder permission")
require.Contains(t, itemNames, rp4.GetName(), "Editor should see dashboard view permission in their folder")
// Editor should NOT see permissions for viewerFolder
require.NotContains(t, itemNames, rp1.GetName(), "Editor should NOT see viewer-only folder permission")
})
}
// Helper functions
func createTestFolder(t *testing.T, helper *apis.K8sTestHelper, user apis.User, title string, parentUID string) *unstructured.Unstructured {
t.Helper()
ctx := context.Background()
folderClient := helper.GetResourceClient(apis.ResourceClientArgs{
User: user,
Namespace: helper.Namespacer(user.Identity.GetOrgID()),
GVR: gvrFolders,
})
metadata := map[string]interface{}{
"generateName": "test-folder-",
"namespace": helper.Namespacer(user.Identity.GetOrgID()),
}
if parentUID != "" {
metadata["annotations"] = map[string]interface{}{
utils.AnnoKeyFolder: parentUID,
}
}
folder := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "folder.grafana.app/v1beta1",
"kind": "Folder",
"metadata": metadata,
"spec": map[string]interface{}{
"title": title,
},
},
}
created, err := folderClient.Resource.Create(ctx, folder, metav1.CreateOptions{})
require.NoError(t, err)
require.NotNil(t, created)
return created
}
// Helper function to delete default permissions
func deleteDefaultPermissions(t *testing.T, client *apis.K8sResourceClient, resourceName string) {
ctx := context.Background()
// Delete the resource permission
err := client.Resource.Delete(ctx, resourceName, metav1.DeleteOptions{})
require.NoError(t, err)
// Check if the resource permission is deleted
_, err = client.Resource.Get(ctx, resourceName, metav1.GetOptions{})
require.Error(t, err)
var statusErr *errors.StatusError
require.ErrorAs(t, err, &statusErr)
require.Equal(t, int32(404), statusErr.ErrStatus.Code)
}
// Helper function to create a root folder without default permissions
func createRootFolderWithoutDefaultPermissions(t *testing.T, helper *apis.K8sTestHelper) *unstructured.Unstructured {
t.Helper()
// Create folder as admin
folder := createTestFolder(t, helper, helper.Org1.Admin, "root-without-permissions", "")
folderUID := folder.GetName()
// Delete default permissions
rpClient := helper.GetResourceClient(apis.ResourceClientArgs{
User: helper.Org1.Admin,
Namespace: helper.Namespacer(helper.Org1.OrgID),
GVR: gvrResourcePermissions,
})
// It would be better to create the folder without default permissions, but this is a workaround for the time being
deleteDefaultPermissions(t, rpClient, "folder.grafana.app-folders-"+folderUID)
return folder
}
func createTestDashboard(t *testing.T, helper *apis.K8sTestHelper, user apis.User, title, folderUID string) *unstructured.Unstructured {
t.Helper()
ctx := context.Background()
dashboardClient := helper.GetResourceClient(apis.ResourceClientArgs{
User: user,
Namespace: helper.Namespacer(user.Identity.GetOrgID()),
GVR: gvrDashboards,
})
dashboard := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "dashboard.grafana.app/v1beta1",
"kind": "Dashboard",
"metadata": map[string]interface{}{
"generateName": "test-dashboard-",
"namespace": helper.Namespacer(user.Identity.GetOrgID()),
"annotations": map[string]interface{}{
utils.AnnoKeyFolder: folderUID,
},
},
"spec": map[string]interface{}{
"title": title,
},
},
}
created, err := dashboardClient.Resource.Create(ctx, dashboard, metav1.CreateOptions{})
require.NoError(t, err)
require.NotNil(t, created)
return created
}
func createResourcePermissionObject(resourceName, apiGroup, resource string, permissions ...permission) *unstructured.Unstructured {
permissionMaps := newPermissionMaps(permissions...)
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": iamv0.GROUP + "/" + iamv0.VERSION,
"kind": "ResourcePermission",
"metadata": map[string]interface{}{
"name": apiGroup + "-" + resource + "-" + resourceName,
},
"spec": map[string]interface{}{
"resource": map[string]interface{}{
"apiGroup": apiGroup,
"resource": resource,
"name": resourceName,
},
"permissions": permissionMaps,
},
},
}
}
func getNamesFromList(list *unstructured.UnstructuredList) []string {
names := make([]string, len(list.Items))
for i, item := range list.Items {
names[i] = item.GetName()
}
return names
}