From 909b9b6bc1b21280b0d9a3cc0cf09a203da0f5c6 Mon Sep 17 00:00:00 2001 From: Roberto Jimenez Sanchez Date: Mon, 15 Dec 2025 17:07:30 +0100 Subject: [PATCH] Move tests --- .../apis/provisioning/authorization_test.go | 249 ------------------ pkg/tests/apis/provisioning/files_test.go | 239 +++++++++++++++++ 2 files changed, 239 insertions(+), 249 deletions(-) delete mode 100644 pkg/tests/apis/provisioning/authorization_test.go diff --git a/pkg/tests/apis/provisioning/authorization_test.go b/pkg/tests/apis/provisioning/authorization_test.go deleted file mode 100644 index 1ee79530aab..00000000000 --- a/pkg/tests/apis/provisioning/authorization_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package provisioning - -import ( - "context" - "encoding/json" - "testing" - - "github.com/stretchr/testify/require" - apierrors "k8s.io/apimachinery/pkg/api/errors" - - provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" -) - -// TestIntegrationProvisioning_FilesAuthorization verifies that authorization -// works correctly for file operations with the access checker -func TestIntegrationProvisioning_FilesAuthorization(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } - - helper := runGrafana(t) - ctx := context.Background() - - // Create a repository with a dashboard - const repo = "authz-test-repo" - helper.CreateRepo(t, TestRepo{ - Name: repo, - Path: helper.ProvisioningPath, - Target: "instance", - SkipResourceAssertions: true, // We validate authorization, not resource creation - Copies: map[string]string{ - "testdata/all-panels.json": "dashboard1.json", - }, - }) - - t.Run("GET file - Admin role should succeed", func(t *testing.T) { - result := helper.AdminREST.Get(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "dashboard1.json"). - Do(ctx) - - require.NoError(t, result.Error(), "admin should be able to read files") - - var wrapper provisioning.ResourceWrapper - require.NoError(t, result.Into(&wrapper)) - require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have resource data") - }) - - t.Run("GET file - Editor role should succeed", func(t *testing.T) { - result := helper.EditorREST.Get(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "dashboard1.json"). - Do(ctx) - - require.NoError(t, result.Error(), "editor should be able to read files") - - var wrapper provisioning.ResourceWrapper - require.NoError(t, result.Into(&wrapper)) - require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have resource data") - }) - - t.Run("GET file - Viewer role should succeed", func(t *testing.T) { - result := helper.ViewerREST.Get(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "dashboard1.json"). - Do(ctx) - - require.NoError(t, result.Error(), "viewer should be able to read files") - - var wrapper provisioning.ResourceWrapper - require.NoError(t, result.Into(&wrapper)) - require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have resource data") - }) - - t.Run("POST file (create) - Admin role should succeed", func(t *testing.T) { - dashboardContent := helper.LoadFile("testdata/timeline-demo.json") - - result := helper.AdminREST.Post(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "new-dashboard.json"). - Body(dashboardContent). - SetHeader("Content-Type", "application/json"). - Do(ctx) - - require.NoError(t, result.Error(), "admin should be able to create files") - - // Verify the dashboard was created - var wrapper provisioning.ResourceWrapper - require.NoError(t, result.Into(&wrapper)) - require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have created resource") - }) - - t.Run("POST file (create) - Editor role should succeed", func(t *testing.T) { - dashboardContent := helper.LoadFile("testdata/text-options.json") - - result := helper.EditorREST.Post(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "editor-dashboard.json"). - Body(dashboardContent). - SetHeader("Content-Type", "application/json"). - Do(ctx) - - require.NoError(t, result.Error(), "editor should be able to create files via access checker") - - // Verify the dashboard was created - var wrapper provisioning.ResourceWrapper - require.NoError(t, result.Into(&wrapper)) - require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have created resource") - }) - - t.Run("POST file (create) - Viewer role should fail", func(t *testing.T) { - dashboardContent := helper.LoadFile("testdata/text-options.json") - - result := helper.ViewerREST.Post(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "viewer-dashboard.json"). - Body(dashboardContent). - SetHeader("Content-Type", "application/json"). - Do(ctx) - - require.Error(t, result.Error(), "viewer should not be able to create files") - require.True(t, apierrors.IsForbidden(result.Error()), "should return Forbidden error") - }) - - t.Run("PUT file (update) - Admin role should succeed", func(t *testing.T) { - // Read the dashboard first - getDashboard := helper.AdminREST.Get(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "dashboard1.json"). - Do(ctx) - require.NoError(t, getDashboard.Error()) - - var wrapper provisioning.ResourceWrapper - require.NoError(t, getDashboard.Into(&wrapper)) - - // Modify the dashboard title - dashData, err := json.Marshal(wrapper.Resource.Upsert.Object) - require.NoError(t, err) - - result := helper.AdminREST.Put(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "dashboard1.json"). - Body(dashData). - SetHeader("Content-Type", "application/json"). - Do(ctx) - - require.NoError(t, result.Error(), "admin should be able to update files") - }) - - t.Run("PUT file (update) - Editor role should succeed", func(t *testing.T) { - // Read the dashboard first - getDashboard := helper.EditorREST.Get(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "new-dashboard.json"). - Do(ctx) - require.NoError(t, getDashboard.Error()) - - var wrapper provisioning.ResourceWrapper - require.NoError(t, getDashboard.Into(&wrapper)) - - // Modify the dashboard - dashData, err := json.Marshal(wrapper.Resource.Upsert.Object) - require.NoError(t, err) - - result := helper.EditorREST.Put(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "new-dashboard.json"). - Body(dashData). - SetHeader("Content-Type", "application/json"). - Do(ctx) - - require.NoError(t, result.Error(), "editor should be able to update files via access checker") - }) - - t.Run("PUT file (update) - Viewer role should fail", func(t *testing.T) { - // Try to update without reading first - dashboardContent := helper.LoadFile("testdata/all-panels.json") - - result := helper.ViewerREST.Put(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "dashboard1.json"). - Body(dashboardContent). - SetHeader("Content-Type", "application/json"). - Do(ctx) - - require.Error(t, result.Error(), "viewer should not be able to update files") - require.True(t, apierrors.IsForbidden(result.Error()), "should return Forbidden error") - }) - - t.Run("DELETE file on branch - Editor role should succeed", func(t *testing.T) { - // Create a test file - dashboardContent := helper.LoadFile("testdata/timeline-demo.json") - result := helper.AdminREST.Post(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "to-delete.json"). - Body(dashboardContent). - SetHeader("Content-Type", "application/json"). - Do(ctx) - require.NoError(t, result.Error()) - - // Delete on a branch (delete on configured branch is not allowed) - result = helper.EditorREST.Delete(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "to-delete.json"). - Param("ref", "test-delete-branch"). - Do(ctx) - - require.NoError(t, result.Error(), "editor should be able to delete files on branches via access checker") - }) - - t.Run("DELETE file on branch - Viewer role should fail", func(t *testing.T) { - result := helper.ViewerREST.Delete(). - Namespace("default"). - Resource("repositories"). - Name(repo). - SubResource("files", "dashboard1.json"). - Param("ref", "test-delete-branch"). - Do(ctx) - - require.Error(t, result.Error(), "viewer should not be able to delete files") - require.True(t, apierrors.IsForbidden(result.Error()), "should return Forbidden error") - }) -} diff --git a/pkg/tests/apis/provisioning/files_test.go b/pkg/tests/apis/provisioning/files_test.go index 823241aa6b0..38fff414075 100644 --- a/pkg/tests/apis/provisioning/files_test.go +++ b/pkg/tests/apis/provisioning/files_test.go @@ -2,6 +2,7 @@ package provisioning import ( "context" + "encoding/json" "errors" "fmt" "io" @@ -10,6 +11,7 @@ import ( "sync" "testing" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/util/testutil" "github.com/stretchr/testify/assert" @@ -590,3 +592,240 @@ func TestIntegrationProvisioning_FilesOwnershipProtection(t *testing.T) { require.Equal(t, repo2, dashboard2.GetAnnotations()[utils.AnnoKeyManagerIdentity], "repo2's dashboard should still be owned by repo2") }) } + +// TestIntegrationProvisioning_FilesAuthorization verifies that authorization +// works correctly for file operations with the access checker +func TestIntegrationProvisioning_FilesAuthorization(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + helper := runGrafana(t) + ctx := context.Background() + + // Create a repository with a dashboard + const repo = "authz-test-repo" + helper.CreateRepo(t, TestRepo{ + Name: repo, + Path: helper.ProvisioningPath, + Target: "instance", + SkipResourceAssertions: true, // We validate authorization, not resource creation + Copies: map[string]string{ + "testdata/all-panels.json": "dashboard1.json", + }, + }) + + t.Run("GET file - Admin role should succeed", func(t *testing.T) { + result := helper.AdminREST.Get(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "dashboard1.json"). + Do(ctx) + + require.NoError(t, result.Error(), "admin should be able to read files") + + var wrapper provisioning.ResourceWrapper + require.NoError(t, result.Into(&wrapper)) + require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have resource data") + }) + + t.Run("GET file - Editor role should succeed", func(t *testing.T) { + result := helper.EditorREST.Get(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "dashboard1.json"). + Do(ctx) + + require.NoError(t, result.Error(), "editor should be able to read files") + + var wrapper provisioning.ResourceWrapper + require.NoError(t, result.Into(&wrapper)) + require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have resource data") + }) + + t.Run("GET file - Viewer role should succeed", func(t *testing.T) { + result := helper.ViewerREST.Get(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "dashboard1.json"). + Do(ctx) + + require.NoError(t, result.Error(), "viewer should be able to read files") + + var wrapper provisioning.ResourceWrapper + require.NoError(t, result.Into(&wrapper)) + require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have resource data") + }) + + t.Run("POST file (create) - Admin role should succeed", func(t *testing.T) { + dashboardContent := helper.LoadFile("testdata/timeline-demo.json") + + result := helper.AdminREST.Post(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "new-dashboard.json"). + Body(dashboardContent). + SetHeader("Content-Type", "application/json"). + Do(ctx) + + require.NoError(t, result.Error(), "admin should be able to create files") + + // Verify the dashboard was created + var wrapper provisioning.ResourceWrapper + require.NoError(t, result.Into(&wrapper)) + require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have created resource") + }) + + t.Run("POST file (create) - Editor role should succeed", func(t *testing.T) { + dashboardContent := helper.LoadFile("testdata/text-options.json") + + result := helper.EditorREST.Post(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "editor-dashboard.json"). + Body(dashboardContent). + SetHeader("Content-Type", "application/json"). + Do(ctx) + + require.NoError(t, result.Error(), "editor should be able to create files via access checker") + + // Verify the dashboard was created + var wrapper provisioning.ResourceWrapper + require.NoError(t, result.Into(&wrapper)) + require.NotEmpty(t, wrapper.Resource.Upsert.Object, "should have created resource") + }) + + t.Run("POST file (create) - Viewer role should fail", func(t *testing.T) { + dashboardContent := helper.LoadFile("testdata/text-options.json") + + result := helper.ViewerREST.Post(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "viewer-dashboard.json"). + Body(dashboardContent). + SetHeader("Content-Type", "application/json"). + Do(ctx) + + require.Error(t, result.Error(), "viewer should not be able to create files") + require.True(t, apierrors.IsForbidden(result.Error()), "should return Forbidden error") + }) + + t.Run("PUT file (update) - Admin role should succeed", func(t *testing.T) { + // Read the dashboard first + getDashboard := helper.AdminREST.Get(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "dashboard1.json"). + Do(ctx) + require.NoError(t, getDashboard.Error()) + + var wrapper provisioning.ResourceWrapper + require.NoError(t, getDashboard.Into(&wrapper)) + + // Modify the dashboard title + dashData, err := json.Marshal(wrapper.Resource.Upsert.Object) + require.NoError(t, err) + + result := helper.AdminREST.Put(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "dashboard1.json"). + Body(dashData). + SetHeader("Content-Type", "application/json"). + Do(ctx) + + require.NoError(t, result.Error(), "admin should be able to update files") + }) + + t.Run("PUT file (update) - Editor role should succeed", func(t *testing.T) { + // Read the dashboard first + getDashboard := helper.EditorREST.Get(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "new-dashboard.json"). + Do(ctx) + require.NoError(t, getDashboard.Error()) + + var wrapper provisioning.ResourceWrapper + require.NoError(t, getDashboard.Into(&wrapper)) + + // Modify the dashboard + dashData, err := json.Marshal(wrapper.Resource.Upsert.Object) + require.NoError(t, err) + + result := helper.EditorREST.Put(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "new-dashboard.json"). + Body(dashData). + SetHeader("Content-Type", "application/json"). + Do(ctx) + + require.NoError(t, result.Error(), "editor should be able to update files via access checker") + }) + + t.Run("PUT file (update) - Viewer role should fail", func(t *testing.T) { + // Try to update without reading first + dashboardContent := helper.LoadFile("testdata/all-panels.json") + + result := helper.ViewerREST.Put(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "dashboard1.json"). + Body(dashboardContent). + SetHeader("Content-Type", "application/json"). + Do(ctx) + + require.Error(t, result.Error(), "viewer should not be able to update files") + require.True(t, apierrors.IsForbidden(result.Error()), "should return Forbidden error") + }) + + t.Run("DELETE file on branch - Editor role should succeed", func(t *testing.T) { + // Create a test file + dashboardContent := helper.LoadFile("testdata/timeline-demo.json") + result := helper.AdminREST.Post(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "to-delete.json"). + Body(dashboardContent). + SetHeader("Content-Type", "application/json"). + Do(ctx) + require.NoError(t, result.Error()) + + // Delete on a branch (delete on configured branch is not allowed) + result = helper.EditorREST.Delete(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "to-delete.json"). + Param("ref", "test-delete-branch"). + Do(ctx) + + require.NoError(t, result.Error(), "editor should be able to delete files on branches via access checker") + }) + + t.Run("DELETE file on branch - Viewer role should fail", func(t *testing.T) { + result := helper.ViewerREST.Delete(). + Namespace("default"). + Resource("repositories"). + Name(repo). + SubResource("files", "dashboard1.json"). + Param("ref", "test-delete-branch"). + Do(ctx) + + require.Error(t, result.Error(), "viewer should not be able to delete files") + require.True(t, apierrors.IsForbidden(result.Error()), "should return Forbidden error") + }) +}