From ceca07268fbd8d3f25ef709de97b175c40401446 Mon Sep 17 00:00:00 2001 From: Igor Fominykh Date: Wed, 15 Apr 2026 14:37:59 +0200 Subject: [PATCH 1/2] fix: use generated org cluster for provider auth models --- .../authorization_model_generation.go | 2 +- .../authorization_model_generation_test.go | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/internal/subroutine/authorization_model_generation.go b/internal/subroutine/authorization_model_generation.go index acfb1fec..98425525 100644 --- a/internal/subroutine/authorization_model_generation.go +++ b/internal/subroutine/authorization_model_generation.go @@ -283,7 +283,7 @@ func (a *AuthorizationModelGenerationSubroutine) Process(ctx context.Context, ob Model: buffer.String(), StoreRef: securityv1alpha1.WorkspaceStoreRef{ Name: accountInfo.Spec.Organization.Name, - Cluster: accountInfo.Spec.Organization.OriginClusterId, + Cluster: accountInfo.Spec.Organization.GeneratedClusterId, }, } return nil diff --git a/internal/subroutine/authorization_model_generation_test.go b/internal/subroutine/authorization_model_generation_test.go index 1df2fff4..df036b7b 100644 --- a/internal/subroutine/authorization_model_generation_test.go +++ b/internal/subroutine/authorization_model_generation_test.go @@ -5,6 +5,7 @@ import ( "testing" accountv1alpha1 "github.com/platform-mesh/account-operator/api/v1alpha1" + securityv1alpha1 "github.com/platform-mesh/security-operator/api/v1alpha1" "github.com/platform-mesh/security-operator/internal/subroutine" "github.com/platform-mesh/security-operator/internal/subroutine/mocks" "github.com/stretchr/testify/assert" @@ -42,9 +43,14 @@ func bindingWithApiExportCluster(name, path, exportCluster string) *kcpapisv1alp } func mockAccountInfo(cl *mocks.MockClient, orgName, originCluster string) { + mockAccountInfoWithClusters(cl, orgName, originCluster, originCluster) +} + +func mockAccountInfoWithClusters(cl *mocks.MockClient, orgName, generatedCluster, originCluster string) { cl.EXPECT().Get(mock.Anything, mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, nn types.NamespacedName, o client.Object, opts ...client.GetOption) error { if acc, ok := o.(*accountv1alpha1.AccountInfo); ok { acc.Spec.Organization.Name = orgName + acc.Spec.Organization.GeneratedClusterId = generatedCluster acc.Spec.Organization.OriginClusterId = originCluster } return nil @@ -304,6 +310,48 @@ func TestAuthorizationModelGeneration_Process(t *testing.T) { } } +func TestAuthorizationModelGeneration_Process_UsesGeneratedClusterForStoreRef(t *testing.T) { + manager := mocks.NewMockManager(t) + allClient := mocks.NewMockClient(t) + cluster := mocks.NewMockCluster(t) + kcpClient := mocks.NewMockClient(t) + + manager.EXPECT().ClusterFromContext(mock.Anything).Return(cluster, nil) + cluster.EXPECT().GetClient().Return(kcpClient) + mockAccountInfoWithClusters(kcpClient, "org", "generated-org-cluster", "origin-org-cluster") + manager.EXPECT().GetCluster(mock.Anything, mock.Anything).Return(cluster, nil) + kcpClient.EXPECT().Get(mock.Anything, mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, nn types.NamespacedName, o client.Object, opts ...client.GetOption) error { + if ae, ok := o.(*kcpapisv1alpha2.APIExport); ok { + ae.Spec.Resources = []kcpapisv1alpha2.ResourceSchema{{Schema: "schema1"}} + return nil + } + return nil + }).Once() + kcpClient.EXPECT().Get(mock.Anything, mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, nn types.NamespacedName, o client.Object, opts ...client.GetOption) error { + if rs, ok := o.(*kcpapisv1alpha1.APIResourceSchema); ok { + rs.Spec.Group = "operations.openkcm.io" + rs.Spec.Names.Plural = "servicekeys" + rs.Spec.Names.Singular = "servicekey" + rs.Spec.Scope = apiextensionsv1.NamespaceScoped + return nil + } + return nil + }).Once() + kcpClient.EXPECT().Get(mock.Anything, mock.Anything, mock.Anything).Return( + kerrors.NewNotFound(schema.GroupResource{Group: "core.platform-mesh.io", Resource: "authorizationmodels"}, "servicekeys-org"), + ).Once() + kcpClient.EXPECT().Create(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { + model := obj.(*securityv1alpha1.AuthorizationModel) + assert.Equal(t, "generated-org-cluster", model.Spec.StoreRef.Cluster) + assert.Equal(t, "org", model.Spec.StoreRef.Name) + return nil + }).Once() + + sub := subroutine.NewAuthorizationModelGenerationSubroutine(manager, allClient) + _, err := sub.Process(context.Background(), newApiBinding("operations.openkcm.io", "root:providers:openkcm-provider")) + assert.Nil(t, err) +} + func TestAuthorizationModelGeneration_Finalize(t *testing.T) { tests := []struct { name string From 0cdd690773eb1a63c3debce3587418521d70ee21 Mon Sep 17 00:00:00 2001 From: Igor Fominykh Date: Wed, 15 Apr 2026 16:37:48 +0200 Subject: [PATCH 2/2] test: drop provider-specific names in store-ref regression test The StoreRef-cluster fix is generic to every provider; the test should read that way. Swap OpenKCM-specific identifiers (operations.openkcm.io / servicekeys / openkcm-provider workspace) for the stand-in example.io / widgets / providers:example so the intent is 'any provider APIBinding generates an AuthorizationModel addressed at the org GeneratedClusterId', not 'OpenKCM happens to break on cc-d2'. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../subroutine/authorization_model_generation_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/subroutine/authorization_model_generation_test.go b/internal/subroutine/authorization_model_generation_test.go index df036b7b..9d866312 100644 --- a/internal/subroutine/authorization_model_generation_test.go +++ b/internal/subroutine/authorization_model_generation_test.go @@ -329,16 +329,16 @@ func TestAuthorizationModelGeneration_Process_UsesGeneratedClusterForStoreRef(t }).Once() kcpClient.EXPECT().Get(mock.Anything, mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, nn types.NamespacedName, o client.Object, opts ...client.GetOption) error { if rs, ok := o.(*kcpapisv1alpha1.APIResourceSchema); ok { - rs.Spec.Group = "operations.openkcm.io" - rs.Spec.Names.Plural = "servicekeys" - rs.Spec.Names.Singular = "servicekey" + rs.Spec.Group = "example.io" + rs.Spec.Names.Plural = "widgets" + rs.Spec.Names.Singular = "widget" rs.Spec.Scope = apiextensionsv1.NamespaceScoped return nil } return nil }).Once() kcpClient.EXPECT().Get(mock.Anything, mock.Anything, mock.Anything).Return( - kerrors.NewNotFound(schema.GroupResource{Group: "core.platform-mesh.io", Resource: "authorizationmodels"}, "servicekeys-org"), + kerrors.NewNotFound(schema.GroupResource{Group: "core.platform-mesh.io", Resource: "authorizationmodels"}, "widgets-org"), ).Once() kcpClient.EXPECT().Create(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { model := obj.(*securityv1alpha1.AuthorizationModel) @@ -348,7 +348,7 @@ func TestAuthorizationModelGeneration_Process_UsesGeneratedClusterForStoreRef(t }).Once() sub := subroutine.NewAuthorizationModelGenerationSubroutine(manager, allClient) - _, err := sub.Process(context.Background(), newApiBinding("operations.openkcm.io", "root:providers:openkcm-provider")) + _, err := sub.Process(context.Background(), newApiBinding("example.io", "root:providers:example")) assert.Nil(t, err) }