diff --git a/pkg/registry/apis/secret/contracts/decrypt.go b/pkg/registry/apis/secret/contracts/decrypt.go index 83e6fc72185..d42b1c7c958 100644 --- a/pkg/registry/apis/secret/contracts/decrypt.go +++ b/pkg/registry/apis/secret/contracts/decrypt.go @@ -24,7 +24,7 @@ type DecryptStorage interface { // DecryptAuthorizer is the interface for authorizing decryption requests. type DecryptAuthorizer interface { - Authorize(ctx context.Context, secureValueName string, secureValueDecrypters []string) (identity string, allowed bool) + Authorize(ctx context.Context, namespace xkube.Namespace, secureValueName string, secureValueDecrypters []string) (identity string, allowed bool) } // DecryptService is the interface for the decrypt service. diff --git a/pkg/registry/apis/secret/decrypt/authorizer.go b/pkg/registry/apis/secret/decrypt/authorizer.go index 042ec12e0ab..ca112302e63 100644 --- a/pkg/registry/apis/secret/decrypt/authorizer.go +++ b/pkg/registry/apis/secret/decrypt/authorizer.go @@ -11,6 +11,7 @@ import ( secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" + "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" ) // decryptAuthorizer is the authorizer implementation for decrypt operations. @@ -25,7 +26,7 @@ func ProvideDecryptAuthorizer(tracer trace.Tracer) contracts.DecryptAuthorizer { } // authorize checks whether the auth info token has the right permissions to decrypt the secure value. -func (a *decryptAuthorizer) Authorize(ctx context.Context, secureValueName string, secureValueDecrypters []string) (id string, isAllowed bool) { +func (a *decryptAuthorizer) Authorize(ctx context.Context, ns xkube.Namespace, secureValueName string, secureValueDecrypters []string) (id string, isAllowed bool) { ctx, span := a.tracer.Start(ctx, "DecryptAuthorizer.Authorize", trace.WithAttributes( attribute.String("name", secureValueName), attribute.StringSlice("decrypters", secureValueDecrypters), @@ -44,6 +45,10 @@ func (a *decryptAuthorizer) Authorize(ctx context.Context, secureValueName strin return "", false } + if !claims.NamespaceMatches(authInfo.GetNamespace(), ns.String()) { + return "", false + } + serviceIdentityList, ok := authInfo.GetExtra()[authn.ServiceIdentityKey] if !ok { return "", false diff --git a/pkg/registry/apis/secret/decrypt/authorizer_test.go b/pkg/registry/apis/secret/decrypt/authorizer_test.go index 131ec33fb8b..61008b9faf8 100644 --- a/pkg/registry/apis/secret/decrypt/authorizer_test.go +++ b/pkg/registry/apis/secret/decrypt/authorizer_test.go @@ -10,43 +10,45 @@ import ( "go.opentelemetry.io/otel/trace/noop" "github.com/grafana/grafana/pkg/apimachinery/identity" + "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" ) func TestDecryptAuthorizer(t *testing.T) { tracer := noop.NewTracerProvider().Tracer("test") + defaultNs := xkube.Namespace("default") t.Run("when no auth info is present, it returns false", func(t *testing.T) { ctx := context.Background() authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", nil) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", nil) require.Empty(t, identity) require.False(t, allowed) }) t.Run("when token permissions are empty, it returns false", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "identity", []string{}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", nil) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", nil) require.NotEmpty(t, identity) require.False(t, allowed) }) t.Run("when service identity is empty, it returns false", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "", []string{}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "", []string{}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", nil) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", nil) require.Empty(t, identity) require.False(t, allowed) }) t.Run("when service identity is empty string, it returns false", func(t *testing.T) { - ctx := createAuthContext(context.Background(), " ", []string{}) + ctx := createAuthContext(context.Background(), defaultNs.String(), " ", []string{}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", nil) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", nil) require.Empty(t, identity) require.False(t, allowed) }) @@ -55,14 +57,14 @@ func TestDecryptAuthorizer(t *testing.T) { authorizer := ProvideDecryptAuthorizer(tracer) // nameless - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues"}) - identity, allowed := authorizer.Authorize(ctx, "", nil) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", nil) require.NotEmpty(t, identity) require.False(t, allowed) // named - ctx = createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues/name"}) - identity, allowed = authorizer.Authorize(ctx, "", nil) + ctx = createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues/name"}) + identity, allowed = authorizer.Authorize(ctx, defaultNs, "", nil) require.NotEmpty(t, identity) require.False(t, allowed) }) @@ -71,32 +73,32 @@ func TestDecryptAuthorizer(t *testing.T) { authorizer := ProvideDecryptAuthorizer(tracer) // nameless - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues:*"}) - identity, allowed := authorizer.Authorize(ctx, "", nil) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues:*"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", nil) require.NotEmpty(t, identity) require.False(t, allowed) // named - ctx = createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues/name:something"}) - identity, allowed = authorizer.Authorize(ctx, "", nil) + ctx = createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues/name:something"}) + identity, allowed = authorizer.Authorize(ctx, defaultNs, "", nil) require.NotEmpty(t, identity) require.False(t, allowed) }) t.Run("when permission does not have 2 or 3 parts, it returns false", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app:decrypt"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app:decrypt"}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", nil) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", nil) require.NotEmpty(t, identity) require.False(t, allowed) }) t.Run("when permission has group that is not `secret.grafana.app`, it returns false", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "identity", []string{"wrong.group/securevalues/invalid:decrypt"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"wrong.group/securevalues/invalid:decrypt"}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", nil) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", nil) require.NotEmpty(t, identity) require.False(t, allowed) }) @@ -105,23 +107,23 @@ func TestDecryptAuthorizer(t *testing.T) { authorizer := ProvideDecryptAuthorizer(tracer) // nameless - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/invalid-resource:decrypt"}) - identity, allowed := authorizer.Authorize(ctx, "", nil) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/invalid-resource:decrypt"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", nil) require.NotEmpty(t, identity) require.False(t, allowed) // named - ctx = createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/invalid-resource/name:decrypt"}) - identity, allowed = authorizer.Authorize(ctx, "", nil) + ctx = createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/invalid-resource/name:decrypt"}) + identity, allowed = authorizer.Authorize(ctx, defaultNs, "", nil) require.NotEmpty(t, identity) require.False(t, allowed) }) t.Run("when the allow list is empty, it allows all identities", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues:decrypt"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues:decrypt"}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", []string{"identity"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", []string{"identity"}) require.NotEmpty(t, identity) require.True(t, allowed) }) @@ -130,14 +132,14 @@ func TestDecryptAuthorizer(t *testing.T) { authorizer := ProvideDecryptAuthorizer(tracer) // nameless - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues:decrypt"}) - identity, allowed := authorizer.Authorize(ctx, "", []string{"group2"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues:decrypt"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", []string{"group2"}) require.NotEmpty(t, identity) require.False(t, allowed) // named - ctx = createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues/name:decrypt"}) - identity, allowed = authorizer.Authorize(ctx, "", []string{"group2"}) + ctx = createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues/name:decrypt"}) + identity, allowed = authorizer.Authorize(ctx, defaultNs, "", []string{"group2"}) require.NotEmpty(t, identity) require.False(t, allowed) }) @@ -146,20 +148,20 @@ func TestDecryptAuthorizer(t *testing.T) { authorizer := ProvideDecryptAuthorizer(tracer) // nameless - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues:decrypt"}) - identity, allowed := authorizer.Authorize(ctx, "", []string{"identity"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues:decrypt"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", []string{"identity"}) require.True(t, allowed) require.Equal(t, "identity", identity) // named - ctx = createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues/name:decrypt"}) - identity, allowed = authorizer.Authorize(ctx, "name", []string{"identity"}) + ctx = createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues/name:decrypt"}) + identity, allowed = authorizer.Authorize(ctx, defaultNs, "name", []string{"identity"}) require.True(t, allowed) require.Equal(t, "identity", identity) }) t.Run("when there are multiple permissions, some invalid, only valid ones are considered", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "identity", []string{ + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{ "secret.grafana.app/securevalues/name1:decrypt", "secret.grafana.app/securevalues/name2:decrypt", "secret.grafana.app/securevalues/invalid:read", @@ -168,47 +170,47 @@ func TestDecryptAuthorizer(t *testing.T) { }) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "name1", []string{"identity"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "name1", []string{"identity"}) require.True(t, allowed) require.Equal(t, "identity", identity) - identity, allowed = authorizer.Authorize(ctx, "name2", []string{"identity"}) + identity, allowed = authorizer.Authorize(ctx, defaultNs, "name2", []string{"identity"}) require.True(t, allowed) require.Equal(t, "identity", identity) }) t.Run("when empty secure value name with specific permission, it returns false", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues/name:decrypt"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues/name:decrypt"}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", []string{"identity"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", []string{"identity"}) require.Equal(t, "identity", identity) require.False(t, allowed) }) t.Run("when permission has an extra / but no name, it returns false", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues/:decrypt"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues/:decrypt"}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", []string{"identity"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", []string{"identity"}) require.Equal(t, "identity", identity) require.False(t, allowed) }) t.Run("when the decrypters list is empty, meaning nothing can decrypt the secure value, it returns false", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues:decrypt"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues:decrypt"}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "name", []string{}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "name", []string{}) require.Equal(t, "identity", identity) require.False(t, allowed) }) t.Run("when one of decrypters matches the identity, it returns true", func(t *testing.T) { - ctx := createAuthContext(context.Background(), "identity1", []string{"secret.grafana.app/securevalues:decrypt"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity1", []string{"secret.grafana.app/securevalues:decrypt"}) authorizer := ProvideDecryptAuthorizer(tracer) - identity, allowed := authorizer.Authorize(ctx, "", []string{"identity1", "identity2", "identity3"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", []string{"identity1", "identity2", "identity3"}) require.Equal(t, "identity1", identity) require.True(t, allowed) }) @@ -216,25 +218,35 @@ func TestDecryptAuthorizer(t *testing.T) { t.Run("permissions must be case-sensitive and return false", func(t *testing.T) { authorizer := ProvideDecryptAuthorizer(tracer) - ctx := createAuthContext(context.Background(), "identity", []string{"SECRET.grafana.app/securevalues:decrypt"}) - identity, allowed := authorizer.Authorize(ctx, "", []string{"identity"}) + ctx := createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"SECRET.grafana.app/securevalues:decrypt"}) + identity, allowed := authorizer.Authorize(ctx, defaultNs, "", []string{"identity"}) require.Equal(t, "identity", identity) require.False(t, allowed) - ctx = createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/SECUREVALUES:decrypt"}) - identity, allowed = authorizer.Authorize(ctx, "", []string{"identity"}) + ctx = createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/SECUREVALUES:decrypt"}) + identity, allowed = authorizer.Authorize(ctx, defaultNs, "", []string{"identity"}) require.Equal(t, "identity", identity) require.False(t, allowed) - ctx = createAuthContext(context.Background(), "identity", []string{"secret.grafana.app/securevalues:DECRYPT"}) - identity, allowed = authorizer.Authorize(ctx, "", []string{"identity"}) + ctx = createAuthContext(context.Background(), defaultNs.String(), "identity", []string{"secret.grafana.app/securevalues:DECRYPT"}) + identity, allowed = authorizer.Authorize(ctx, defaultNs, "", []string{"identity"}) require.Equal(t, "identity", identity) require.False(t, allowed) }) + + t.Run("when namespace doesn't match the token's, it returns false", func(t *testing.T) { + authorizer := ProvideDecryptAuthorizer(tracer) + + ctx := createAuthContext(context.Background(), "namespace1", "identity", []string{"secret.grafana.app/securevalues:decrypt"}) + identity, allowed := authorizer.Authorize(ctx, "namespace2", "", []string{"identity"}) + require.Empty(t, identity) + require.False(t, allowed) + }) } -func createAuthContext(ctx context.Context, serviceIdentity string, permissions []string) context.Context { +func createAuthContext(ctx context.Context, namespace string, serviceIdentity string, permissions []string) context.Context { requester := &identity.StaticRequester{ + Namespace: namespace, AccessTokenClaims: &authn.Claims[authn.AccessTokenClaims]{ Rest: authn.AccessTokenClaims{ Permissions: permissions, diff --git a/pkg/registry/apis/secret/decrypt/noop_authorizer.go b/pkg/registry/apis/secret/decrypt/noop_authorizer.go index 079d49b67ab..f2fe29cbc48 100644 --- a/pkg/registry/apis/secret/decrypt/noop_authorizer.go +++ b/pkg/registry/apis/secret/decrypt/noop_authorizer.go @@ -4,6 +4,7 @@ import ( "context" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" + "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" ) // NoopAlwaysAllowedAuthorizer is a no-op implementation of the DecryptAuthorizer which always returns `allowed=true`. @@ -11,6 +12,6 @@ type NoopAlwaysAllowedAuthorizer struct{} var _ contracts.DecryptAuthorizer = &NoopAlwaysAllowedAuthorizer{} -func (a *NoopAlwaysAllowedAuthorizer) Authorize(ctx context.Context, secureValueName string, secureValueDecrypters []string) (identity string, allowed bool) { +func (a *NoopAlwaysAllowedAuthorizer) Authorize(context.Context, xkube.Namespace, string, []string) (string, bool) { return "", true } diff --git a/pkg/registry/apis/secret/secure_value_client.go b/pkg/registry/apis/secret/secure_value_client.go index e34f31abd42..faf1eea4ef1 100644 --- a/pkg/registry/apis/secret/secure_value_client.go +++ b/pkg/registry/apis/secret/secure_value_client.go @@ -265,8 +265,17 @@ func (c *secureValueClient) mapError(err error, name string) error { } func (c *secureValueClient) checkAccess(ctx context.Context, name, verb string) error { + authInfo, ok := claims.AuthInfoFrom(ctx) + if !ok { + return apierrors.NewUnauthorized("missing auth info in context") + } + gr := secretv1beta1.SecureValuesResourceInfo.GroupResource() + if !claims.NamespaceMatches(authInfo.GetNamespace(), c.namespace) { + return apierrors.NewForbidden(gr, name, fmt.Errorf("namespace mismatch: %s != %s", authInfo.GetNamespace(), c.namespace)) + } + decision, reason, err := c.access.Authorize(ctx, authorizer.AttributesRecord{ Verb: verb, Namespace: c.namespace, diff --git a/pkg/registry/apis/secret/secure_value_client_test.go b/pkg/registry/apis/secret/secure_value_client_test.go index 44e8349c101..480b8c5062f 100644 --- a/pkg/registry/apis/secret/secure_value_client_test.go +++ b/pkg/registry/apis/secret/secure_value_client_test.go @@ -1,6 +1,7 @@ package secret import ( + "context" "testing" "github.com/stretchr/testify/require" @@ -118,61 +119,75 @@ func TestIntegration_SecureValueClient_CRUD(t *testing.T) { } func Test_SecureValueClient_CRUD_NoPermissions(t *testing.T) { - setup := testutils.Setup(t) - - validator := validator.ProvideSecureValueValidator() - - client := ProvideSecureValueClient( - setup.SecureValueService, - validator, - setup.AccessClient, - ) - ns := "stacks-1234" - ctx := testutils.CreateUserAuthContext(t.Context(), ns, nil) - nsClient, err := client.Client(ctx, ns) - require.NoError(t, err) - require.NotNil(t, nsClient) - - sv := &secretv1beta1.SecureValue{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-sv", - Namespace: ns, - }, + testcases := []struct { + name string + ctx context.Context + errorReason metav1.StatusReason + }{ + {"no auth context", context.Background(), metav1.StatusReasonUnauthorized}, + {"no permissions", testutils.CreateUserAuthContext(t.Context(), ns, nil), metav1.StatusReasonForbidden}, + {"mismatching namespace", testutils.CreateUserAuthContext(t.Context(), "other-ns", nil), metav1.StatusReasonForbidden}, } - unstructured, err := toUnstructured(sv) - require.NoError(t, err) + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + setup := testutils.Setup(t) - // Create - created, err := nsClient.Create(ctx, unstructured, metav1.CreateOptions{}) - var apiErr *apierrors.StatusError - require.ErrorAs(t, err, &apiErr) - require.Equal(t, apiErr.ErrStatus.Reason, metav1.StatusReasonForbidden) - require.Nil(t, created) + validator := validator.ProvideSecureValueValidator() - // Read - read, err := nsClient.Get(ctx, sv.Name, metav1.GetOptions{}) - require.ErrorAs(t, err, &apiErr) - require.Equal(t, apiErr.ErrStatus.Reason, metav1.StatusReasonForbidden) - require.Nil(t, created) + client := ProvideSecureValueClient( + setup.SecureValueService, + validator, + setup.AccessClient, + ) - // Update - updated, err := nsClient.Update(ctx, unstructured, metav1.UpdateOptions{}) - require.ErrorAs(t, err, &apiErr) - require.Equal(t, apiErr.ErrStatus.Reason, metav1.StatusReasonForbidden) - require.Nil(t, updated) + ctx := tc.ctx - // List - list, err := nsClient.List(ctx, metav1.ListOptions{}) - require.ErrorAs(t, err, &apiErr) - require.Equal(t, apiErr.ErrStatus.Reason, metav1.StatusReasonForbidden) - require.Nil(t, list) + nsClient, err := client.Client(ctx, ns) + require.NoError(t, err) + require.NotNil(t, nsClient) - // Delete - err = nsClient.Delete(ctx, sv.Name, metav1.DeleteOptions{}) - require.ErrorAs(t, err, &apiErr) - require.Equal(t, apiErr.ErrStatus.Reason, metav1.StatusReasonForbidden) - require.Nil(t, read) + sv := &secretv1beta1.SecureValue{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sv", + Namespace: ns, + }, + } + + unstructured, err := toUnstructured(sv) + require.NoError(t, err) + + // Create + created, err := nsClient.Create(ctx, unstructured, metav1.CreateOptions{}) + var apiErr *apierrors.StatusError + require.ErrorAs(t, err, &apiErr) + require.Equal(t, apiErr.ErrStatus.Reason, tc.errorReason) + require.Nil(t, created) + + // Read + read, err := nsClient.Get(ctx, sv.Name, metav1.GetOptions{}) + require.ErrorAs(t, err, &apiErr) + require.Equal(t, apiErr.ErrStatus.Reason, tc.errorReason) + require.Nil(t, read) + + // Update + updated, err := nsClient.Update(ctx, unstructured, metav1.UpdateOptions{}) + require.ErrorAs(t, err, &apiErr) + require.Equal(t, apiErr.ErrStatus.Reason, tc.errorReason) + require.Nil(t, updated) + + // List + list, err := nsClient.List(ctx, metav1.ListOptions{}) + require.ErrorAs(t, err, &apiErr) + require.Equal(t, apiErr.ErrStatus.Reason, tc.errorReason) + require.Nil(t, list) + + // Delete + err = nsClient.Delete(ctx, sv.Name, metav1.DeleteOptions{}) + require.ErrorAs(t, err, &apiErr) + require.Equal(t, apiErr.ErrStatus.Reason, tc.errorReason) + }) + } } diff --git a/pkg/storage/secret/metadata/decrypt_store.go b/pkg/storage/secret/metadata/decrypt_store.go index cd959883824..1a827b32d00 100644 --- a/pkg/storage/secret/metadata/decrypt_store.go +++ b/pkg/storage/secret/metadata/decrypt_store.go @@ -110,7 +110,7 @@ func (s *decryptStorage) Decrypt(ctx context.Context, namespace xkube.Namespace, return "", contracts.ErrDecryptNotFound } - decrypterIdentity, authorized := s.decryptAuthorizer.Authorize(ctx, name, sv.Spec.Decrypters) + decrypterIdentity, authorized := s.decryptAuthorizer.Authorize(ctx, namespace, name, sv.Spec.Decrypters) if !authorized { return "", contracts.ErrDecryptNotAuthorized }