Secrets: Bump API version to v1beta1 (#108026)

This commit is contained in:
Matheus Macabu
2025-07-11 19:14:05 +02:00
committed by GitHub
parent 9786389ae8
commit 9c1b2fb792
25 changed files with 290 additions and 276 deletions
+3 -2
View File
@@ -136,6 +136,7 @@ require (
github.com/matttproud/golang_protobuf_extensions v1.0.4 // @grafana/alerting-backend
github.com/microsoft/go-mssqldb v1.8.0 // @grafana/partner-datasources
github.com/migueleliasweb/go-github-mock v1.1.0 // @grafana/grafana-app-platform-squad
github.com/mitchellh/copystructure v1.2.0 // @grafana/grafana-operator-experience-squad
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c //@grafana/identity-access-team
github.com/mocktools/go-smtp-mock/v2 v2.3.1 // @grafana/grafana-backend-group
github.com/modern-go/reflect2 v1.0.2 // @grafana/alerting-backend
@@ -233,8 +234,9 @@ require (
github.com/grafana/grafana/apps/iam v0.0.0-20250627191313-2f1a6ae1712b // @grafana/identity-access-team
github.com/grafana/grafana/apps/investigations v0.0.0-20250627191313-2f1a6ae1712b // @fcjack @matryer
github.com/grafana/grafana/apps/playlist v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad
github.com/grafana/grafana/apps/secret v0.0.0-20250711114246-c9b2126c4ad5 // @grafana/grafana-operator-experience-squad
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250711114246-c9b2126c4ad5 // @grafana/grafana-app-platform-squad
github.com/grafana/grafana/pkg/apis/secret v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-operator-experience-squad
github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad
@@ -455,7 +457,6 @@ require (
github.com/miekg/dns v1.1.63 // indirect
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 // indirect
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
+4 -2
View File
@@ -1621,10 +1621,12 @@ github.com/grafana/grafana/apps/investigations v0.0.0-20250627191313-2f1a6ae1712
github.com/grafana/grafana/apps/investigations v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:8RlQ4U9lccPEBD/QxV4zyIMh9+lzjS/7xGpiqn3cHLY=
github.com/grafana/grafana/apps/playlist v0.0.0-20250627191313-2f1a6ae1712b h1:elfpvk06igCjE0yL+/urc69UDOt1B/sPfdNg9X9kUMc=
github.com/grafana/grafana/apps/playlist v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:fPtx6dwGm0PweQRVbgtthMapJMvXobBcORbndb7Dgd4=
github.com/grafana/grafana/apps/secret v0.0.0-20250711114246-c9b2126c4ad5 h1:+fMhUoqwGdY8ntH0GL2icJa3uk+bTiIMicawDG2r9Uc=
github.com/grafana/grafana/apps/secret v0.0.0-20250711114246-c9b2126c4ad5/go.mod h1:TIrKvhgo2j6lvVeOZ3TUmXbI4I48d6v7QcadL/f6SKQ=
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b h1:ei01IFqmnXkOrrVvsT3CYe+i5xYra3SCX7Wsu3PMsDU=
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:+H4Va9jDJlGQJjAN+OFD/hLx2I/yEzDRMQLaKecvgAc=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250627191313-2f1a6ae1712b h1:e0dG1tPpuv4NHCAPP235Gip/MBQB8fQ2XW2bwHqoWh4=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:u0+k7KLCvGi6zHWsc2B7r+tmGcYjN/qR+gn51pl104E=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250711114246-c9b2126c4ad5 h1:f4fopIH6eQRoZ/E7bstn69UtDAHleIdQ6DrdzEs++Ug=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250711114246-c9b2126c4ad5/go.mod h1:eAlOam2uWhrsEZlOoAr7XZ9hbBP7SyYGYn31/aQAPs8=
github.com/grafana/grafana/pkg/apis/secret v0.0.0-20250627191313-2f1a6ae1712b h1:rkQO7exsDLdr4KGA7kgEnkQnbJGePbDIP1SUQptLRs8=
github.com/grafana/grafana/pkg/apis/secret v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:9YjiHZzii2DZfocRDJbqSeC8M3GWenU5yexeHHxsZ4Y=
github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b h1:QyJLJn3xwFTIXu9KPZujsrIUN0X8DdiR9b2h75L0AfI=
+1 -2
View File
@@ -718,7 +718,7 @@ github.com/grafana/grafana/apps/dashboard v0.0.0-20250616145019-8d27f12428cb/go.
github.com/grafana/grafana/apps/investigation v0.0.0-20250121113133-e747350fee2d/go.mod h1:HQprw3MmiYj5OUV9CZnkwA1FKDZBmYACuAB3oDvUOmI=
github.com/grafana/grafana/apps/playlist v0.0.0-20250121113133-e747350fee2d/go.mod h1:DjJe5osrW/BKrzN9hAAOSElNWutj1bcriExa7iDP7kA=
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250121113133-e747350fee2d/go.mod h1:1sq0guad+G4SUTlBgx7SXfhnzy7D86K/LcVOtiQCiMA=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250710134100-1f3dc0533caf/go.mod h1:eAlOam2uWhrsEZlOoAr7XZ9hbBP7SyYGYn31/aQAPs8=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250711114246-c9b2126c4ad5/go.mod h1:eAlOam2uWhrsEZlOoAr7XZ9hbBP7SyYGYn31/aQAPs8=
github.com/grafana/grafana/pkg/semconv v0.0.0-20250121113133-e747350fee2d/go.mod h1:tfLnBpPYgwrBMRz4EXqPCZJyCjEG4Ev37FSlXnocJ2c=
github.com/grafana/grafana/pkg/storage/unified/apistore v0.0.0-20250121113133-e747350fee2d/go.mod h1:CXpwZ3Mkw6xVlGKc0SqUxqXCP3Uv182q6qAQnLaLxRg=
github.com/grafana/grafana/pkg/storage/unified/apistore v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:xrKQcxQxz+IUF90ybtfENFeEXtlj9nAsX/3Fw0KEIeQ=
@@ -1424,7 +1424,6 @@ k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1
k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kms v0.33.2/go.mod h1:C1I8mjFFBNzfUZXYt9FZVJ8MJl7ynFbGgZFbBzkBJ3E=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
modernc.org/cc/v3 v3.36.3 h1:uISP3F66UlixxWEcKuIWERa4TwrZENHSL8tWxZz8bHg=
modernc.org/ccgo/v3 v3.16.9 h1:AXquSwg7GuMk11pIdw7fmO1Y/ybgazVkMhsZWCV0mHM=
@@ -4,7 +4,7 @@ import (
"context"
"errors"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
)
@@ -16,7 +16,7 @@ var (
// DecryptStorage is the interface for wiring and dependency injection.
type DecryptStorage interface {
Decrypt(ctx context.Context, namespace xkube.Namespace, name string) (secretv0alpha1.ExposedSecureValue, error)
Decrypt(ctx context.Context, namespace xkube.Namespace, name string) (secretv1beta1.ExposedSecureValue, error)
}
// DecryptAuthorizer is the interface for authorizing decryption requests.
+11 -11
View File
@@ -4,7 +4,7 @@ import (
"context"
"errors"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
"k8s.io/apimachinery/pkg/util/validation/field"
)
@@ -15,12 +15,12 @@ var (
// KeeperMetadataStorage is the interface for wiring and dependency injection.
type KeeperMetadataStorage interface {
Create(ctx context.Context, keeper *secretv0alpha1.Keeper, actorUID string) (*secretv0alpha1.Keeper, error)
Read(ctx context.Context, namespace xkube.Namespace, name string, opts ReadOpts) (*secretv0alpha1.Keeper, error)
Update(ctx context.Context, keeper *secretv0alpha1.Keeper, actorUID string) (*secretv0alpha1.Keeper, error)
Create(ctx context.Context, keeper *secretv1beta1.Keeper, actorUID string) (*secretv1beta1.Keeper, error)
Read(ctx context.Context, namespace xkube.Namespace, name string, opts ReadOpts) (*secretv1beta1.Keeper, error)
Update(ctx context.Context, keeper *secretv1beta1.Keeper, actorUID string) (*secretv1beta1.Keeper, error)
Delete(ctx context.Context, namespace xkube.Namespace, name string) error
List(ctx context.Context, namespace xkube.Namespace) ([]secretv0alpha1.Keeper, error)
GetKeeperConfig(ctx context.Context, namespace string, name *string, opts ReadOpts) (secretv0alpha1.KeeperConfig, error)
List(ctx context.Context, namespace xkube.Namespace) ([]secretv1beta1.Keeper, error)
GetKeeperConfig(ctx context.Context, namespace string, name *string, opts ReadOpts) (secretv1beta1.KeeperConfig, error)
}
// ErrKeeperInvalidSecureValues is returned when a Keeper references SecureValues that do not exist.
@@ -95,14 +95,14 @@ func (s ExternalID) String() string {
// Keeper is the interface for secret keepers.
type Keeper interface {
Store(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, exposedValueOrRef string) (ExternalID, error)
Update(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, externalID ExternalID, exposedValueOrRef string) error
Expose(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, externalID ExternalID) (secretv0alpha1.ExposedSecureValue, error)
Delete(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, externalID ExternalID) error
Store(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, exposedValueOrRef string) (ExternalID, error)
Update(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, externalID ExternalID, exposedValueOrRef string) error
Expose(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, externalID ExternalID) (secretv1beta1.ExposedSecureValue, error)
Delete(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, externalID ExternalID) error
}
// Service is the interface for secret keeper services.
// This exists because OSS and Enterprise have different amounts of keepers available.
type KeeperService interface {
KeeperForConfig(secretv0alpha1.KeeperConfig) (Keeper, error)
KeeperForConfig(secretv1beta1.KeeperConfig) (Keeper, error)
}
@@ -4,7 +4,7 @@ import (
"context"
"errors"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
)
@@ -30,9 +30,9 @@ type ReadOpts struct {
// SecureValueMetadataStorage is the interface for wiring and dependency injection.
type SecureValueMetadataStorage interface {
Create(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error)
Read(ctx context.Context, namespace xkube.Namespace, name string, opts ReadOpts) (*secretv0alpha1.SecureValue, error)
List(ctx context.Context, namespace xkube.Namespace) ([]secretv0alpha1.SecureValue, error)
Create(ctx context.Context, sv *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, error)
Read(ctx context.Context, namespace xkube.Namespace, name string, opts ReadOpts) (*secretv1beta1.SecureValue, error)
List(ctx context.Context, namespace xkube.Namespace) ([]secretv1beta1.SecureValue, error)
SetVersionToActive(ctx context.Context, namespace xkube.Namespace, name string, version int64) error
SetVersionToInactive(ctx context.Context, namespace xkube.Namespace, name string, version int64) error
SetExternalID(ctx context.Context, namespace xkube.Namespace, name string, version int64, externalID ExternalID) error
@@ -9,7 +9,7 @@ import (
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
)
@@ -88,8 +88,8 @@ func (a *decryptAuthorizer) Authorize(ctx context.Context, secureValueName strin
// Changes: 1) we don't support `*` for verbs; 2) we support specific names in the permission.
func hasPermissionInToken(tokenPermissions []string, name string) bool {
var (
group = secretv0alpha1.GROUP
resource = secretv0alpha1.SecureValuesResourceInfo.GetName()
group = secretv1beta1.APIGroup
resource = secretv1beta1.SecureValuesResourceInfo.GetName()
verb = "decrypt"
)
@@ -5,7 +5,7 @@ import (
"errors"
"testing"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/registry/apis/secret/service"
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
"github.com/stretchr/testify/mock"
@@ -22,7 +22,7 @@ func TestDecryptService(t *testing.T) {
mockErr := errors.New("mock error")
mockStorage := &MockDecryptStorage{}
mockStorage.On("Decrypt", mock.Anything, mock.Anything, mock.Anything).Return(secretv0alpha1.ExposedSecureValue(""), mockErr)
mockStorage.On("Decrypt", mock.Anything, mock.Anything, mock.Anything).Return(secretv1beta1.ExposedSecureValue(""), mockErr)
decryptedValuesResp := map[string]service.DecryptResult{
"secure-value-1": service.NewDecryptResultErr(mockErr),
}
@@ -42,8 +42,8 @@ func TestDecryptService(t *testing.T) {
mockStorage := &MockDecryptStorage{}
// Set up the mock to return a different value for each name in the test
exposedSecureValue1 := secretv0alpha1.NewExposedSecureValue("value1")
exposedSecureValue2 := secretv0alpha1.NewExposedSecureValue("value2")
exposedSecureValue1 := secretv1beta1.NewExposedSecureValue("value1")
exposedSecureValue2 := secretv1beta1.NewExposedSecureValue("value2")
mockStorage.On("Decrypt", mock.Anything, xkube.Namespace("default"), "secure-value-1").
Return(exposedSecureValue1, nil)
mockStorage.On("Decrypt", mock.Anything, xkube.Namespace("default"), "secure-value-2").
@@ -69,11 +69,11 @@ func TestDecryptService(t *testing.T) {
mockErr := errors.New("mock error")
mockStorage := &MockDecryptStorage{}
exposedSecureValue := secretv0alpha1.NewExposedSecureValue("value")
exposedSecureValue := secretv1beta1.NewExposedSecureValue("value")
mockStorage.On("Decrypt", mock.Anything, xkube.Namespace("default"), "secure-value-1").
Return(exposedSecureValue, nil)
mockStorage.On("Decrypt", mock.Anything, xkube.Namespace("default"), "secure-value-2").
Return(secretv0alpha1.ExposedSecureValue(""), mockErr)
Return(secretv1beta1.ExposedSecureValue(""), mockErr)
decryptedValuesResp := map[string]service.DecryptResult{
"secure-value-1": service.NewDecryptResultValue(&exposedSecureValue),
@@ -95,7 +95,7 @@ type MockDecryptStorage struct {
mock.Mock
}
func (m *MockDecryptStorage) Decrypt(ctx context.Context, namespace xkube.Namespace, name string) (secretv0alpha1.ExposedSecureValue, error) {
func (m *MockDecryptStorage) Decrypt(ctx context.Context, namespace xkube.Namespace, name string) (secretv1beta1.ExposedSecureValue, error) {
args := m.Called(ctx, namespace, name)
return args.Get(0).(secretv0alpha1.ExposedSecureValue), args.Error(1)
return args.Get(0).(secretv1beta1.ExposedSecureValue), args.Error(1)
}
@@ -6,7 +6,7 @@ import (
"github.com/google/uuid"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
)
@@ -24,7 +24,7 @@ func NewFakeKeeper() *FakeKeeper {
}
}
func (s *FakeKeeper) Store(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, exposedValueOrRef string) (contracts.ExternalID, error) {
func (s *FakeKeeper) Store(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, exposedValueOrRef string) (contracts.ExternalID, error) {
ns, ok := s.values[namespace]
if !ok {
ns = make(map[string]string)
@@ -36,7 +36,7 @@ func (s *FakeKeeper) Store(ctx context.Context, cfg secretv0alpha1.KeeperConfig,
return contracts.ExternalID(uid), nil
}
func (s *FakeKeeper) Expose(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, externalID contracts.ExternalID) (secretv0alpha1.ExposedSecureValue, error) {
func (s *FakeKeeper) Expose(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, externalID contracts.ExternalID) (secretv1beta1.ExposedSecureValue, error) {
ns, ok := s.values[namespace]
if !ok {
return "", ErrSecretNotFound
@@ -46,14 +46,14 @@ func (s *FakeKeeper) Expose(ctx context.Context, cfg secretv0alpha1.KeeperConfig
return "", ErrSecretNotFound
}
return secretv0alpha1.NewExposedSecureValue(exposedVal), nil
return secretv1beta1.NewExposedSecureValue(exposedVal), nil
}
func (s *FakeKeeper) Delete(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, externalID contracts.ExternalID) error {
func (s *FakeKeeper) Delete(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, externalID contracts.ExternalID) error {
return nil
}
func (s *FakeKeeper) Update(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, externalID contracts.ExternalID, exposedValueOrRef string) error {
func (s *FakeKeeper) Update(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, externalID contracts.ExternalID, exposedValueOrRef string) error {
ns, ok := s.values[namespace]
if !ok {
return ErrSecretNotFound
@@ -3,7 +3,7 @@ package secretkeeper
import (
"go.opentelemetry.io/otel/trace"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
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/secretkeeper/sqlkeeper"
"github.com/prometheus/client_golang/prometheus"
@@ -30,6 +30,6 @@ func ProvideService(
// Ignore the config, but we could use it to get the keeper type and then return the correct keeper.
// Instantiation only happens on ProvideService ONCE.
func (k *OSSKeeperService) KeeperForConfig(secretv0alpha1.KeeperConfig) (contracts.Keeper, error) {
func (k *OSSKeeperService) KeeperForConfig(secretv1beta1.KeeperConfig) (contracts.Keeper, error) {
return k.systemKeeper, nil
}
@@ -5,7 +5,7 @@ import (
"fmt"
"time"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
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/secretkeeper/metrics"
"github.com/prometheus/client_golang/prometheus"
@@ -36,7 +36,7 @@ func NewSQLKeeper(
}
}
func (s *SQLKeeper) Store(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, exposedValueOrRef string) (contracts.ExternalID, error) {
func (s *SQLKeeper) Store(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, exposedValueOrRef string) (contracts.ExternalID, error) {
ctx, span := s.tracer.Start(ctx, "SQLKeeper.Store", trace.WithAttributes(attribute.String("namespace", namespace)))
defer span.End()
@@ -58,7 +58,7 @@ func (s *SQLKeeper) Store(ctx context.Context, cfg secretv0alpha1.KeeperConfig,
return externalID, nil
}
func (s *SQLKeeper) Expose(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, externalID contracts.ExternalID) (secretv0alpha1.ExposedSecureValue, error) {
func (s *SQLKeeper) Expose(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, externalID contracts.ExternalID) (secretv1beta1.ExposedSecureValue, error) {
ctx, span := s.tracer.Start(ctx, "SQLKeeper.Expose", trace.WithAttributes(
attribute.String("namespace", namespace),
attribute.String("externalID", externalID.String()),
@@ -76,13 +76,13 @@ func (s *SQLKeeper) Expose(ctx context.Context, cfg secretv0alpha1.KeeperConfig,
return "", fmt.Errorf("unable to decrypt value: %w", err)
}
exposedValue := secretv0alpha1.NewExposedSecureValue(string(exposedBytes))
exposedValue := secretv1beta1.NewExposedSecureValue(string(exposedBytes))
s.metrics.ExposeDuration.WithLabelValues(string(cfg.Type())).Observe(time.Since(start).Seconds())
return exposedValue, nil
}
func (s *SQLKeeper) Delete(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, externalID contracts.ExternalID) error {
func (s *SQLKeeper) Delete(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, externalID contracts.ExternalID) error {
ctx, span := s.tracer.Start(ctx, "SQLKeeper.Delete", trace.WithAttributes(
attribute.String("namespace", namespace),
attribute.String("externalID", externalID.String()),
@@ -100,7 +100,7 @@ func (s *SQLKeeper) Delete(ctx context.Context, cfg secretv0alpha1.KeeperConfig,
return nil
}
func (s *SQLKeeper) Update(ctx context.Context, cfg secretv0alpha1.KeeperConfig, namespace string, externalID contracts.ExternalID, exposedValueOrRef string) error {
func (s *SQLKeeper) Update(ctx context.Context, cfg secretv1beta1.KeeperConfig, namespace string, externalID contracts.ExternalID, exposedValueOrRef string) error {
ctx, span := s.tracer.Start(ctx, "SQLKeeper.Update", trace.WithAttributes(
attribute.String("namespace", namespace),
attribute.String("externalID", externalID.String()),
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/trace/noop"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/infra/usagestats"
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
encryptionmanager "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager"
@@ -44,7 +44,7 @@ func Test_SQLKeeperSetup(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, sqlKeeper)
keeperCfg := &secretv0alpha1.SystemKeeperConfig{}
keeperCfg := &secretv1beta1.SystemKeeperConfig{}
t.Run("storing an encrypted value returns no error", func(t *testing.T) {
externalId1, err := sqlKeeper.Store(ctx, keeperCfg, namespace1, plaintext1)
+4 -4
View File
@@ -3,14 +3,14 @@ package service
import (
"context"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
)
// DecryptResult is the (union) result of a decryption operation.
// It contains the decrypted `value` when the decryption succeeds, and the `err` when it fails.
// It is not possible to construct a `DecryptResult` where both `value` and `err` are set from another package.
type DecryptResult struct {
value *secretv0alpha1.ExposedSecureValue
value *secretv1beta1.ExposedSecureValue
err error
}
@@ -18,7 +18,7 @@ func (d DecryptResult) Error() error {
return d.err
}
func (d DecryptResult) Value() *secretv0alpha1.ExposedSecureValue {
func (d DecryptResult) Value() *secretv1beta1.ExposedSecureValue {
return d.value
}
@@ -26,7 +26,7 @@ func NewDecryptResultErr(err error) DecryptResult {
return DecryptResult{err: err}
}
func NewDecryptResultValue(value *secretv0alpha1.ExposedSecureValue) DecryptResult {
func NewDecryptResultValue(value *secretv1beta1.ExposedSecureValue) DecryptResult {
return DecryptResult{value: value}
}
@@ -6,8 +6,8 @@ import (
claims "github.com/grafana/authlib/types"
"github.com/grafana/grafana-app-sdk/logging"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
"go.opentelemetry.io/otel/attribute"
@@ -41,7 +41,7 @@ func ProvideSecureValueService(
}
}
func (s *SecureValueService) Create(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error) {
func (s *SecureValueService) Create(ctx context.Context, sv *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, error) {
ctx, span := s.tracer.Start(ctx, "SecureValueService.Create", trace.WithAttributes(
attribute.String("name", sv.GetName()),
attribute.String("namespace", sv.GetNamespace()),
@@ -51,7 +51,7 @@ func (s *SecureValueService) Create(ctx context.Context, sv *secretv0alpha1.Secu
return s.createNewVersion(ctx, sv, actorUID)
}
func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, bool, error) {
func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, bool, error) {
ctx, span := s.tracer.Start(ctx, "SecureValueService.Update", trace.WithAttributes(
attribute.String("name", newSecureValue.GetName()),
attribute.String("namespace", newSecureValue.GetNamespace()),
@@ -59,7 +59,7 @@ func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv
))
defer span.End()
if newSecureValue.Spec.Value == "" {
if newSecureValue.Spec.Value == nil {
decrypted, err := s.secureValueMetadataStorage.ReadForDecrypt(ctx, xkube.Namespace(newSecureValue.Namespace), newSecureValue.Name)
if err != nil {
return nil, false, fmt.Errorf("reading secure value secret: %+w", err)
@@ -82,7 +82,7 @@ func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv
return nil, false, fmt.Errorf("reading secret value from keeper: %w", err)
}
newSecureValue.Spec.Value = secret
newSecureValue.Spec.Value = &secret
}
const updateIsSync = true
@@ -90,12 +90,12 @@ func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv
return createdSv, updateIsSync, err
}
func (s *SecureValueService) createNewVersion(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error) {
func (s *SecureValueService) createNewVersion(ctx context.Context, sv *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, error) {
createdSv, err := s.secureValueMetadataStorage.Create(ctx, sv, actorUID)
if err != nil {
return nil, fmt.Errorf("creating secure value: %w", err)
}
createdSv.Status = secretv0alpha1.SecureValueStatus{
createdSv.Status = secretv1beta1.SecureValueStatus{
Version: createdSv.Status.Version,
}
@@ -135,7 +135,7 @@ func (s *SecureValueService) createNewVersion(ctx context.Context, sv *secretv0a
return createdSv, nil
}
func (s *SecureValueService) Read(ctx context.Context, namespace xkube.Namespace, name string) (*secretv0alpha1.SecureValue, error) {
func (s *SecureValueService) Read(ctx context.Context, namespace xkube.Namespace, name string) (*secretv1beta1.SecureValue, error) {
ctx, span := s.tracer.Start(ctx, "SecureValueService.Read", trace.WithAttributes(
attribute.String("name", name),
attribute.String("namespace", namespace.String()),
@@ -145,7 +145,7 @@ func (s *SecureValueService) Read(ctx context.Context, namespace xkube.Namespace
return s.secureValueMetadataStorage.Read(ctx, namespace, name, contracts.ReadOpts{ForUpdate: false})
}
func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace) (*secretv0alpha1.SecureValueList, error) {
func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace) (*secretv1beta1.SecureValueList, error) {
ctx, span := s.tracer.Start(ctx, "SecureValueService.List", trace.WithAttributes(
attribute.String("namespace", namespace.String()),
))
@@ -157,8 +157,8 @@ func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace
}
hasPermissionFor, err := s.accessClient.Compile(ctx, user, claims.ListRequest{
Group: secretv0alpha1.GROUP,
Resource: secretv0alpha1.SecureValuesResourceInfo.GetName(),
Group: secretv1beta1.APIGroup,
Resource: secretv1beta1.SecureValuesResourceInfo.GetName(),
Namespace: namespace.String(),
Verb: utils.VerbGet, // Why not VerbList?
})
@@ -171,7 +171,7 @@ func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace
return nil, fmt.Errorf("fetching secure values from storage: %+w", err)
}
out := make([]secretv0alpha1.SecureValue, 0)
out := make([]secretv1beta1.SecureValue, 0)
for _, metadata := range secureValuesMetadata {
// Check whether the user has permission to access this specific SecureValue in the namespace.
@@ -182,12 +182,12 @@ func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace
out = append(out, metadata)
}
return &secretv0alpha1.SecureValueList{
return &secretv1beta1.SecureValueList{
Items: out,
}, nil
}
func (s *SecureValueService) Delete(ctx context.Context, namespace xkube.Namespace, name string) (*secretv0alpha1.SecureValue, error) {
func (s *SecureValueService) Delete(ctx context.Context, namespace xkube.Namespace, name string) (*secretv1beta1.SecureValue, error) {
ctx, span := s.tracer.Start(ctx, "SecureValueService.Delete", trace.WithAttributes(
attribute.String("name", name),
attribute.String("namespace", namespace.String()),
@@ -3,11 +3,12 @@ package service_test
import (
"testing"
"github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
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/testutils"
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
"github.com/stretchr/testify/require"
"k8s.io/utils/ptr"
)
func TestCrud(t *testing.T) {
@@ -23,7 +24,7 @@ func TestCrud(t *testing.T) {
// Create the same secure value twice
input := sv1.DeepCopy()
input.Spec.Description = "d2"
input.Spec.Value = v0alpha1.NewExposedSecureValue("v2")
input.Spec.Value = ptr.To(secretv1beta1.NewExposedSecureValue("v2"))
sv2, err := sut.CreateSv(t.Context(), testutils.CreateSvWithSv(input))
require.NoError(t, err)
@@ -55,6 +56,7 @@ func TestCrud(t *testing.T) {
// Update the secure value
input := sv1.DeepCopy()
input.Spec.Description = "d2"
input.Spec.Value = ptr.To(secretv1beta1.NewExposedSecureValue("v3"))
sv2, err := sut.UpdateSv(t.Context(), input)
require.NoError(t, err)
+12 -11
View File
@@ -6,11 +6,12 @@ import (
"github.com/grafana/authlib/authn"
"github.com/grafana/authlib/types"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
encryptionstorage "github.com/grafana/grafana/pkg/storage/secret/encryption"
"go.opentelemetry.io/otel/trace/noop"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"github.com/grafana/grafana/pkg/infra/usagestats"
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
@@ -138,28 +139,28 @@ type Sut struct {
}
type CreateSvConfig struct {
Sv *secretv0alpha1.SecureValue
Sv *secretv1beta1.SecureValue
}
func CreateSvWithSv(sv *secretv0alpha1.SecureValue) func(*CreateSvConfig) {
func CreateSvWithSv(sv *secretv1beta1.SecureValue) func(*CreateSvConfig) {
return func(cfg *CreateSvConfig) {
cfg.Sv = sv
}
}
func (s *Sut) CreateSv(ctx context.Context, opts ...func(*CreateSvConfig)) (*secretv0alpha1.SecureValue, error) {
func (s *Sut) CreateSv(ctx context.Context, opts ...func(*CreateSvConfig)) (*secretv1beta1.SecureValue, error) {
cfg := CreateSvConfig{
Sv: &secretv0alpha1.SecureValue{
Sv: &secretv1beta1.SecureValue{
ObjectMeta: metav1.ObjectMeta{
Name: "sv1",
Namespace: "ns1",
},
Spec: secretv0alpha1.SecureValueSpec{
Spec: secretv1beta1.SecureValueSpec{
Description: "desc1",
Value: secretv0alpha1.NewExposedSecureValue("v1"),
Value: ptr.To(secretv1beta1.NewExposedSecureValue("v1")),
Decrypters: []string{"decrypter1"},
},
Status: secretv0alpha1.SecureValueStatus{},
Status: secretv1beta1.SecureValueStatus{},
},
}
for _, opt := range opts {
@@ -173,12 +174,12 @@ func (s *Sut) CreateSv(ctx context.Context, opts ...func(*CreateSvConfig)) (*sec
return createdSv, nil
}
func (s *Sut) UpdateSv(ctx context.Context, sv *secretv0alpha1.SecureValue) (*secretv0alpha1.SecureValue, error) {
func (s *Sut) UpdateSv(ctx context.Context, sv *secretv1beta1.SecureValue) (*secretv1beta1.SecureValue, error) {
newSv, _, err := s.SecureValueService.Update(ctx, sv, "actor-uid")
return newSv, err
}
func (s *Sut) DeleteSv(ctx context.Context, namespace, name string) (*secretv0alpha1.SecureValue, error) {
func (s *Sut) DeleteSv(ctx context.Context, namespace, name string) (*secretv1beta1.SecureValue, error) {
sv, err := s.SecureValueService.Delete(ctx, xkube.Namespace(namespace), name)
return sv, err
}
@@ -191,7 +192,7 @@ func newKeeperServiceWrapper(keeper contracts.Keeper) *keeperServiceWrapper {
return &keeperServiceWrapper{keeper: keeper}
}
func (wrapper *keeperServiceWrapper) KeeperForConfig(cfg secretv0alpha1.KeeperConfig) (contracts.Keeper, error) {
func (wrapper *keeperServiceWrapper) KeeperForConfig(cfg secretv1beta1.KeeperConfig) (contracts.Keeper, error) {
return wrapper.keeper, nil
}
+2 -2
View File
@@ -13,7 +13,7 @@ import (
"go.opentelemetry.io/otel/trace"
"github.com/grafana/grafana-app-sdk/logging"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
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"
"github.com/grafana/grafana/pkg/services/featuremgmt"
@@ -60,7 +60,7 @@ type decryptStorage struct {
}
// Decrypt decrypts a secure value from the keeper.
func (s *decryptStorage) Decrypt(ctx context.Context, namespace xkube.Namespace, name string) (_ secretv0alpha1.ExposedSecureValue, decryptErr error) {
func (s *decryptStorage) Decrypt(ctx context.Context, namespace xkube.Namespace, name string) (_ secretv1beta1.ExposedSecureValue, decryptErr error) {
ctx, span := s.tracer.Start(ctx, "DecryptStorage.Decrypt", trace.WithAttributes(
attribute.String("namespace", namespace.String()),
attribute.String("name", name),
@@ -7,9 +7,10 @@ import (
"github.com/grafana/authlib/authn"
"github.com/grafana/authlib/types"
"github.com/stretchr/testify/require"
"k8s.io/utils/ptr"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
"github.com/grafana/grafana/pkg/registry/apis/secret/testutils"
)
@@ -73,12 +74,12 @@ func TestIntegrationDecrypt(t *testing.T) {
}))
// Create a secure value that is not in the allowlist
spec := secretv0alpha1.SecureValueSpec{
spec := secretv1beta1.SecureValueSpec{
Description: "description",
Decrypters: []string{svcIdentity},
Value: secretv0alpha1.NewExposedSecureValue("value"),
Value: ptr.To(secretv1beta1.NewExposedSecureValue("value")),
}
sv := &secretv0alpha1.SecureValue{Spec: spec}
sv := &secretv1beta1.SecureValue{Spec: spec}
sv.Name = svName
sv.Namespace = "default"
@@ -110,12 +111,12 @@ func TestIntegrationDecrypt(t *testing.T) {
}))
// Create a secure value that is in the allowlist
spec := secretv0alpha1.SecureValueSpec{
spec := secretv1beta1.SecureValueSpec{
Description: "description",
Decrypters: []string{svcIdentity},
Value: secretv0alpha1.NewExposedSecureValue("value"),
Value: ptr.To(secretv1beta1.NewExposedSecureValue("value")),
}
sv := &secretv0alpha1.SecureValue{Spec: spec}
sv := &secretv1beta1.SecureValue{Spec: spec}
sv.Name = "sv-test"
sv.Namespace = "default"
@@ -149,12 +150,12 @@ func TestIntegrationDecrypt(t *testing.T) {
}))
// Create a secure value that is in the allowlist
spec := secretv0alpha1.SecureValueSpec{
spec := secretv1beta1.SecureValueSpec{
Description: "description",
Decrypters: []string{svcIdentity},
Value: secretv0alpha1.NewExposedSecureValue("value"),
Value: ptr.To(secretv1beta1.NewExposedSecureValue("value")),
}
sv := &secretv0alpha1.SecureValue{Spec: spec}
sv := &secretv1beta1.SecureValue{Spec: spec}
sv.Name = svName
sv.Namespace = "default"
@@ -181,12 +182,12 @@ func TestIntegrationDecrypt(t *testing.T) {
sut := testutils.Setup(t)
// Create a secure value
spec := secretv0alpha1.SecureValueSpec{
spec := secretv1beta1.SecureValueSpec{
Description: "description",
Decrypters: []string{svcIdentity},
Value: secretv0alpha1.NewExposedSecureValue("value"),
Value: ptr.To(secretv1beta1.NewExposedSecureValue("value")),
}
sv := &secretv0alpha1.SecureValue{Spec: spec}
sv := &secretv1beta1.SecureValue{Spec: spec}
sv.Name = "sv-test"
sv.Namespace = "default"
@@ -214,12 +215,12 @@ func TestIntegrationDecrypt(t *testing.T) {
sut := testutils.Setup(t)
// Create a secure value
spec := secretv0alpha1.SecureValueSpec{
spec := secretv1beta1.SecureValueSpec{
Description: "description",
Decrypters: []string{svcIdentity},
Value: secretv0alpha1.NewExposedSecureValue("value"),
Value: ptr.To(secretv1beta1.NewExposedSecureValue("value")),
}
sv := &secretv0alpha1.SecureValue{Spec: spec}
sv := &secretv1beta1.SecureValue{Spec: spec}
sv.Name = svName
sv.Namespace = "default"
@@ -246,12 +247,12 @@ func TestIntegrationDecrypt(t *testing.T) {
sut := testutils.Setup(t)
// Create a secure value
spec := secretv0alpha1.SecureValueSpec{
spec := secretv1beta1.SecureValueSpec{
Description: "description",
Decrypters: []string{svcIdentity},
Value: secretv0alpha1.NewExposedSecureValue("value"),
Value: ptr.To(secretv1beta1.NewExposedSecureValue("value")),
}
sv := &secretv0alpha1.SecureValue{Spec: spec}
sv := &secretv1beta1.SecureValue{Spec: spec}
sv.Name = "sv-test"
sv.Namespace = "default"
@@ -279,12 +280,12 @@ func TestIntegrationDecrypt(t *testing.T) {
sut := testutils.Setup(t)
// Create a secure value
spec := secretv0alpha1.SecureValueSpec{
spec := secretv1beta1.SecureValueSpec{
Description: "description",
Decrypters: []string{svcIdentity},
Value: secretv0alpha1.NewExposedSecureValue("value"),
Value: ptr.To(secretv1beta1.NewExposedSecureValue("value")),
}
sv := &secretv0alpha1.SecureValue{Spec: spec}
sv := &secretv1beta1.SecureValue{Spec: spec}
sv.Name = svName
sv.Namespace = "default"
+45 -45
View File
@@ -6,8 +6,8 @@ import (
"time"
"github.com/google/uuid"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
"github.com/grafana/grafana/pkg/storage/secret/migrator"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -37,7 +37,7 @@ func (*keeperDB) TableName() string {
}
// toKubernetes maps a DB row into a Kubernetes resource (metadata + spec).
func (kp *keeperDB) toKubernetes() (*secretv0alpha1.Keeper, error) {
func (kp *keeperDB) toKubernetes() (*secretv1beta1.Keeper, error) {
annotations := make(map[string]string, 0)
if kp.Annotations != "" {
if err := json.Unmarshal([]byte(kp.Annotations), &annotations); err != nil {
@@ -52,23 +52,23 @@ func (kp *keeperDB) toKubernetes() (*secretv0alpha1.Keeper, error) {
}
}
resource := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
resource := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: kp.Description,
},
}
// Obtain provider configs
provider := toProvider(secretv0alpha1.KeeperType(kp.Type), kp.Payload)
provider := toProvider(secretv1beta1.KeeperType(kp.Type), kp.Payload)
switch v := provider.(type) {
case *secretv0alpha1.AWSKeeperConfig:
resource.Spec.AWS = v
case *secretv0alpha1.AzureKeeperConfig:
case *secretv1beta1.KeeperAWSConfig:
resource.Spec.Aws = v
case *secretv1beta1.KeeperAzureConfig:
resource.Spec.Azure = v
case *secretv0alpha1.GCPKeeperConfig:
resource.Spec.GCP = v
case *secretv0alpha1.HashiCorpKeeperConfig:
resource.Spec.HashiCorp = v
case *secretv1beta1.KeeperGCPConfig:
resource.Spec.Gcp = v
case *secretv1beta1.KeeperHashiCorpConfig:
resource.Spec.HashiCorpVault = v
}
// Set all meta fields here for consistency.
@@ -94,7 +94,7 @@ func (kp *keeperDB) toKubernetes() (*secretv0alpha1.Keeper, error) {
}
// toKeeperCreateRow maps a Kubernetes resource into a DB row for new resources being created/inserted.
func toKeeperCreateRow(kp *secretv0alpha1.Keeper, actorUID string) (*keeperDB, error) {
func toKeeperCreateRow(kp *secretv1beta1.Keeper, actorUID string) (*keeperDB, error) {
row, err := toKeeperRow(kp)
if err != nil {
return nil, fmt.Errorf("failed to map to row: %w", err)
@@ -112,7 +112,7 @@ func toKeeperCreateRow(kp *secretv0alpha1.Keeper, actorUID string) (*keeperDB, e
}
// toKeeperUpdateRow maps a Kubernetes resource into a DB row for existing resources being updated.
func toKeeperUpdateRow(currentRow *keeperDB, newKeeper *secretv0alpha1.Keeper, actorUID string) (*keeperDB, error) {
func toKeeperUpdateRow(currentRow *keeperDB, newKeeper *secretv1beta1.Keeper, actorUID string) (*keeperDB, error) {
row, err := toKeeperRow(newKeeper)
if err != nil {
return nil, fmt.Errorf("failed to map to row: %w", err)
@@ -130,7 +130,7 @@ func toKeeperUpdateRow(currentRow *keeperDB, newKeeper *secretv0alpha1.Keeper, a
}
// toKeeperRow maps a Kubernetes Keeper resource into a Keeper DB row.
func toKeeperRow(kp *secretv0alpha1.Keeper) (*keeperDB, error) {
func toKeeperRow(kp *secretv1beta1.Keeper) (*keeperDB, error) {
var annotations string
if len(kp.Annotations) > 0 {
cleanedAnnotations := xkube.CleanAnnotations(kp.Annotations)
@@ -196,19 +196,19 @@ func toKeeperRow(kp *secretv0alpha1.Keeper) (*keeperDB, error) {
// toTypeAndPayload obtain keeper type and payload from a Kubernetes Keeper resource.
// TODO: Move as method of KeeperSpec
func toTypeAndPayload(kp *secretv0alpha1.Keeper) (secretv0alpha1.KeeperType, string, error) {
if kp.Spec.AWS != nil {
payload, err := json.Marshal(kp.Spec.AWS.AWSCredentials)
return secretv0alpha1.AWSKeeperType, string(payload), err
func toTypeAndPayload(kp *secretv1beta1.Keeper) (secretv1beta1.KeeperType, string, error) {
if kp.Spec.Aws != nil {
payload, err := json.Marshal(kp.Spec.Aws)
return secretv1beta1.AWSKeeperType, string(payload), err
} else if kp.Spec.Azure != nil {
payload, err := json.Marshal(kp.Spec.Azure)
return secretv0alpha1.AzureKeeperType, string(payload), err
} else if kp.Spec.GCP != nil {
payload, err := json.Marshal(kp.Spec.GCP)
return secretv0alpha1.GCPKeeperType, string(payload), err
} else if kp.Spec.HashiCorp != nil {
payload, err := json.Marshal(kp.Spec.HashiCorp)
return secretv0alpha1.HashiCorpKeeperType, string(payload), err
return secretv1beta1.AzureKeeperType, string(payload), err
} else if kp.Spec.Gcp != nil {
payload, err := json.Marshal(kp.Spec.Gcp)
return secretv1beta1.GCPKeeperType, string(payload), err
} else if kp.Spec.HashiCorpVault != nil {
payload, err := json.Marshal(kp.Spec.HashiCorpVault)
return secretv1beta1.HashiCorpKeeperType, string(payload), err
}
return "", "", fmt.Errorf("no keeper type found")
@@ -216,28 +216,28 @@ func toTypeAndPayload(kp *secretv0alpha1.Keeper) (secretv0alpha1.KeeperType, str
// toProvider maps a KeeperType and payload into a provider config struct.
// TODO: Move as method of KeeperType
func toProvider(keeperType secretv0alpha1.KeeperType, payload string) secretv0alpha1.KeeperConfig {
func toProvider(keeperType secretv1beta1.KeeperType, payload string) secretv1beta1.KeeperConfig {
switch keeperType {
case secretv0alpha1.AWSKeeperType:
aws := &secretv0alpha1.AWSKeeperConfig{}
case secretv1beta1.AWSKeeperType:
aws := &secretv1beta1.KeeperAWSConfig{}
if err := json.Unmarshal([]byte(payload), aws); err != nil {
return nil
}
return aws
case secretv0alpha1.AzureKeeperType:
azure := &secretv0alpha1.AzureKeeperConfig{}
case secretv1beta1.AzureKeeperType:
azure := &secretv1beta1.KeeperAzureConfig{}
if err := json.Unmarshal([]byte(payload), azure); err != nil {
return nil
}
return azure
case secretv0alpha1.GCPKeeperType:
gcp := &secretv0alpha1.GCPKeeperConfig{}
case secretv1beta1.GCPKeeperType:
gcp := &secretv1beta1.KeeperGCPConfig{}
if err := json.Unmarshal([]byte(payload), gcp); err != nil {
return nil
}
return gcp
case secretv0alpha1.HashiCorpKeeperType:
hashicorp := &secretv0alpha1.HashiCorpKeeperConfig{}
case secretv1beta1.HashiCorpKeeperType:
hashicorp := &secretv1beta1.KeeperHashiCorpConfig{}
if err := json.Unmarshal([]byte(payload), hashicorp); err != nil {
return nil
}
@@ -248,17 +248,17 @@ func toProvider(keeperType secretv0alpha1.KeeperType, payload string) secretv0al
}
// extractSecureValues extracts unique securevalues referenced by the keeper, if any.
func extractSecureValues(kp *secretv0alpha1.Keeper) map[string]struct{} {
func extractSecureValues(kp *secretv1beta1.Keeper) map[string]struct{} {
switch {
case kp.Spec.AWS != nil:
case kp.Spec.Aws != nil:
secureValues := make(map[string]struct{}, 0)
if kp.Spec.AWS.AccessKeyID.SecureValueName != "" {
secureValues[kp.Spec.AWS.AccessKeyID.SecureValueName] = struct{}{}
if kp.Spec.Aws.AccessKeyID.SecureValueName != "" {
secureValues[kp.Spec.Aws.AccessKeyID.SecureValueName] = struct{}{}
}
if kp.Spec.AWS.SecretAccessKey.SecureValueName != "" {
secureValues[kp.Spec.AWS.SecretAccessKey.SecureValueName] = struct{}{}
if kp.Spec.Aws.SecretAccessKey.SecureValueName != "" {
secureValues[kp.Spec.Aws.SecretAccessKey.SecureValueName] = struct{}{}
}
return secureValues
@@ -269,12 +269,12 @@ func extractSecureValues(kp *secretv0alpha1.Keeper) map[string]struct{} {
}
// GCP does not reference secureValues.
case kp.Spec.GCP != nil:
case kp.Spec.Gcp != nil:
return nil
case kp.Spec.HashiCorp != nil:
if kp.Spec.HashiCorp.Token.SecureValueName != "" {
return map[string]struct{}{kp.Spec.HashiCorp.Token.SecureValueName: {}}
case kp.Spec.HashiCorpVault != nil:
if kp.Spec.HashiCorpVault.Token.SecureValueName != "" {
return map[string]struct{}{kp.Spec.HashiCorpVault.Token.SecureValueName: {}}
}
}
+10 -10
View File
@@ -5,7 +5,7 @@ import (
"fmt"
"time"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
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"
"github.com/grafana/grafana/pkg/services/featuremgmt"
@@ -46,7 +46,7 @@ func ProvideKeeperMetadataStorage(
}, nil
}
func (s *keeperMetadataStorage) Create(ctx context.Context, keeper *secretv0alpha1.Keeper, actorUID string) (*secretv0alpha1.Keeper, error) {
func (s *keeperMetadataStorage) Create(ctx context.Context, keeper *secretv1beta1.Keeper, actorUID string) (*secretv1beta1.Keeper, error) {
start := time.Now()
ctx, span := s.tracer.Start(ctx, "KeeperMetadataStorage.Create", trace.WithAttributes(
attribute.String("name", keeper.GetName()),
@@ -111,7 +111,7 @@ func (s *keeperMetadataStorage) Create(ctx context.Context, keeper *secretv0alph
return createdKeeper, nil
}
func (s *keeperMetadataStorage) Read(ctx context.Context, namespace xkube.Namespace, name string, opts contracts.ReadOpts) (*secretv0alpha1.Keeper, error) {
func (s *keeperMetadataStorage) Read(ctx context.Context, namespace xkube.Namespace, name string, opts contracts.ReadOpts) (*secretv1beta1.Keeper, error) {
start := time.Now()
ctx, span := s.tracer.Start(ctx, "KeeperMetadataStorage.Read", trace.WithAttributes(
attribute.String("name", name),
@@ -174,7 +174,7 @@ func (s *keeperMetadataStorage) read(ctx context.Context, namespace, name string
return &keeper, nil
}
func (s *keeperMetadataStorage) Update(ctx context.Context, newKeeper *secretv0alpha1.Keeper, actorUID string) (*secretv0alpha1.Keeper, error) {
func (s *keeperMetadataStorage) Update(ctx context.Context, newKeeper *secretv1beta1.Keeper, actorUID string) (*secretv1beta1.Keeper, error) {
start := time.Now()
ctx, span := s.tracer.Start(ctx, "KeeperMetadataStorage.Update", trace.WithAttributes(
attribute.String("name", newKeeper.GetName()),
@@ -291,7 +291,7 @@ func (s *keeperMetadataStorage) Delete(ctx context.Context, namespace xkube.Name
return nil
}
func (s *keeperMetadataStorage) List(ctx context.Context, namespace xkube.Namespace) (keeperList []secretv0alpha1.Keeper, err error) {
func (s *keeperMetadataStorage) List(ctx context.Context, namespace xkube.Namespace) (keeperList []secretv1beta1.Keeper, err error) {
start := time.Now()
ctx, span := s.tracer.Start(ctx, "KeeperMetadataStorage.List", trace.WithAttributes(
attribute.String("namespace", namespace.String()),
@@ -318,7 +318,7 @@ func (s *keeperMetadataStorage) List(ctx context.Context, namespace xkube.Namesp
}
defer func() { _ = rows.Close() }()
keepers := make([]secretv0alpha1.Keeper, 0)
keepers := make([]secretv1beta1.Keeper, 0)
for rows.Next() {
var row keeperDB
@@ -350,7 +350,7 @@ func (s *keeperMetadataStorage) List(ctx context.Context, namespace xkube.Namesp
// validateSecureValueReferences checks that all secure values referenced by the keeper exist and are not referenced by other third-party keepers.
// It is used by other methods inside a transaction.
func (s *keeperMetadataStorage) validateSecureValueReferences(ctx context.Context, keeper *secretv0alpha1.Keeper) (err error) {
func (s *keeperMetadataStorage) validateSecureValueReferences(ctx context.Context, keeper *secretv1beta1.Keeper) (err error) {
ctx, span := s.tracer.Start(ctx, "KeeperMetadataStorage.ValidateSecureValueReferences", trace.WithAttributes(
attribute.String("name", keeper.GetName()),
attribute.String("namespace", keeper.GetNamespace()),
@@ -497,7 +497,7 @@ func (s *keeperMetadataStorage) validateSecureValueReferences(ctx context.Contex
return nil
}
func (s *keeperMetadataStorage) GetKeeperConfig(ctx context.Context, namespace string, name *string, opts contracts.ReadOpts) (secretv0alpha1.KeeperConfig, error) {
func (s *keeperMetadataStorage) GetKeeperConfig(ctx context.Context, namespace string, name *string, opts contracts.ReadOpts) (secretv1beta1.KeeperConfig, error) {
ctx, span := s.tracer.Start(ctx, "KeeperMetadataStorage.GetKeeperConfig", trace.WithAttributes(
attribute.String("namespace", namespace),
attribute.Bool("isForUpdate", opts.ForUpdate),
@@ -506,7 +506,7 @@ func (s *keeperMetadataStorage) GetKeeperConfig(ctx context.Context, namespace s
// Check if keeper is the systemwide one.
if name == nil {
return &secretv0alpha1.SystemKeeperConfig{}, nil
return &secretv1beta1.SystemKeeperConfig{}, nil
}
start := time.Now()
@@ -518,7 +518,7 @@ func (s *keeperMetadataStorage) GetKeeperConfig(ctx context.Context, namespace s
return nil, err
}
keeperConfig := toProvider(secretv0alpha1.KeeperType(kp.Type), kp.Payload)
keeperConfig := toProvider(secretv1beta1.KeeperType(kp.Type), kp.Payload)
s.metrics.KeeperMetadataGetKeeperConfigDuration.Observe(time.Since(start).Seconds())
@@ -4,7 +4,7 @@ import (
"context"
"testing"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
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"
"github.com/grafana/grafana/pkg/services/featuremgmt"
@@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/storage/secret/migrator"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/trace/noop"
"k8s.io/utils/ptr"
)
func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
@@ -22,10 +23,10 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
defaultKeeperName := "kp-test"
defaultKeeperNS := "default"
testKeeper := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
testKeeper := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: "description",
AWS: &secretv0alpha1.AWSKeeperConfig{},
Aws: &secretv1beta1.KeeperAWSConfig{},
},
}
@@ -41,7 +42,7 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
// get system keeper config
keeperConfig, err := keeperMetadataStorage.GetKeeperConfig(ctx, defaultKeeperNS, nil, contracts.ReadOpts{})
require.NoError(t, err)
require.IsType(t, &secretv0alpha1.SystemKeeperConfig{}, keeperConfig)
require.IsType(t, &secretv1beta1.SystemKeeperConfig{}, keeperConfig)
})
t.Run("get test keeper config", func(t *testing.T) {
@@ -90,10 +91,10 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
keeperTest := "kp-test2"
keeperNamespaceTest := "ns"
testKeeper := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
testKeeper := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: "another description",
AWS: &secretv0alpha1.AWSKeeperConfig{},
Aws: &secretv1beta1.KeeperAWSConfig{},
},
}
testKeeper.Name = keeperTest
@@ -128,10 +129,10 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
keeperNamespaceTest := "ns"
// Create initial keeper
initialKeeper := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
initialKeeper := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: "initial description",
AWS: &secretv0alpha1.AWSKeeperConfig{},
Aws: &secretv1beta1.KeeperAWSConfig{},
},
}
initialKeeper.Name = keeperTest
@@ -147,10 +148,10 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
require.Equal(t, "initial description", keeper.Spec.Description)
// Update the keeper with new values
updatedKeeper := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
updatedKeeper := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: "updated description",
AWS: &secretv0alpha1.AWSKeeperConfig{},
Aws: &secretv1beta1.KeeperAWSConfig{},
},
}
updatedKeeper.Name = keeperTest
@@ -182,19 +183,17 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
keeperNamespaceTest := "ns"
// Create initial keeper with first AWS config
initialKeeper := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
initialKeeper := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: "initial description",
AWS: &secretv0alpha1.AWSKeeperConfig{
AWSCredentials: secretv0alpha1.AWSCredentials{
AccessKeyID: secretv0alpha1.CredentialValue{
ValueFromEnv: "AWS_ACCESS_KEY_ID_1",
},
SecretAccessKey: secretv0alpha1.CredentialValue{
ValueFromEnv: "AWS_SECRET_ACCESS_KEY_1",
},
KMSKeyID: "kms-key-id-1",
Aws: &secretv1beta1.KeeperAWSConfig{
AccessKeyID: secretv1beta1.KeeperCredentialValue{
ValueFromEnv: "AWS_ACCESS_KEY_ID_1",
},
SecretAccessKey: secretv1beta1.KeeperCredentialValue{
ValueFromEnv: "AWS_SECRET_ACCESS_KEY_1",
},
KmsKeyID: ptr.To("kms-key-id-1"),
},
},
}
@@ -208,24 +207,22 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
// Verify initial AWS config
keeper, err := keeperMetadataStorage.Read(ctx, xkube.Namespace(keeperNamespaceTest), keeperTest, contracts.ReadOpts{})
require.NoError(t, err)
require.Equal(t, "AWS_ACCESS_KEY_ID_1", keeper.Spec.AWS.AccessKeyID.ValueFromEnv)
require.Equal(t, "AWS_SECRET_ACCESS_KEY_1", keeper.Spec.AWS.SecretAccessKey.ValueFromEnv)
require.Equal(t, "kms-key-id-1", keeper.Spec.AWS.KMSKeyID)
require.Equal(t, "AWS_ACCESS_KEY_ID_1", keeper.Spec.Aws.AccessKeyID.ValueFromEnv)
require.Equal(t, "AWS_SECRET_ACCESS_KEY_1", keeper.Spec.Aws.SecretAccessKey.ValueFromEnv)
require.Equal(t, "kms-key-id-1", *keeper.Spec.Aws.KmsKeyID)
// Update with new AWS config
updatedKeeper := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
updatedKeeper := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: "updated description",
AWS: &secretv0alpha1.AWSKeeperConfig{
AWSCredentials: secretv0alpha1.AWSCredentials{
AccessKeyID: secretv0alpha1.CredentialValue{
ValueFromEnv: "AWS_ACCESS_KEY_ID_2",
},
SecretAccessKey: secretv0alpha1.CredentialValue{
ValueFromEnv: "AWS_SECRET_ACCESS_KEY_2",
},
KMSKeyID: "kms-key-id-2",
Aws: &secretv1beta1.KeeperAWSConfig{
AccessKeyID: secretv1beta1.KeeperCredentialValue{
ValueFromEnv: "AWS_ACCESS_KEY_ID_2",
},
SecretAccessKey: secretv1beta1.KeeperCredentialValue{
ValueFromEnv: "AWS_SECRET_ACCESS_KEY_2",
},
KmsKeyID: ptr.To("kms-key-id-2"),
},
},
}
@@ -239,9 +236,9 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
// Verify updated AWS config
updatedKeeper, err = keeperMetadataStorage.Read(ctx, xkube.Namespace(keeperNamespaceTest), keeperTest, contracts.ReadOpts{})
require.NoError(t, err)
require.Equal(t, "AWS_ACCESS_KEY_ID_2", updatedKeeper.Spec.AWS.AccessKeyID.ValueFromEnv)
require.Equal(t, "AWS_SECRET_ACCESS_KEY_2", updatedKeeper.Spec.AWS.SecretAccessKey.ValueFromEnv)
require.Equal(t, "kms-key-id-2", updatedKeeper.Spec.AWS.KMSKeyID)
require.Equal(t, "AWS_ACCESS_KEY_ID_2", updatedKeeper.Spec.Aws.AccessKeyID.ValueFromEnv)
require.Equal(t, "AWS_SECRET_ACCESS_KEY_2", updatedKeeper.Spec.Aws.SecretAccessKey.ValueFromEnv)
require.Equal(t, "kms-key-id-2", *updatedKeeper.Spec.Aws.KmsKeyID)
})
t.Run("list keepers in empty namespace", func(t *testing.T) {
@@ -276,17 +273,15 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
keeperNamespaceTest := "ns1"
// Create initial keeper
initialKeeper := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
initialKeeper := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: "initial description",
AWS: &secretv0alpha1.AWSKeeperConfig{
AWSCredentials: secretv0alpha1.AWSCredentials{
AccessKeyID: secretv0alpha1.CredentialValue{
ValueFromEnv: "AWS_ACCESS_KEY_ID",
},
SecretAccessKey: secretv0alpha1.CredentialValue{
ValueFromEnv: "AWS_SECRET_ACCESS_KEY",
},
Aws: &secretv1beta1.KeeperAWSConfig{
AccessKeyID: secretv1beta1.KeeperCredentialValue{
ValueFromEnv: "AWS_ACCESS_KEY_ID",
},
SecretAccessKey: secretv1beta1.KeeperCredentialValue{
ValueFromEnv: "AWS_SECRET_ACCESS_KEY",
},
},
},
@@ -320,10 +315,10 @@ func Test_KeeperMetadataStorage_GetKeeperConfig(t *testing.T) {
ctx := context.Background()
keeperMetadataStorage := initStorage(t)
nonExistentKeeper := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
nonExistentKeeper := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: "some description",
AWS: &secretv0alpha1.AWSKeeperConfig{},
Aws: &secretv1beta1.KeeperAWSConfig{},
},
}
nonExistentKeeper.Name = "non-existent"
@@ -7,8 +7,8 @@ import (
"time"
"github.com/google/uuid"
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
"github.com/grafana/grafana/pkg/storage/secret/migrator"
@@ -45,7 +45,7 @@ func (*secureValueDB) TableName() string {
}
// toKubernetes maps a DB row into a Kubernetes resource (metadata + spec).
func (sv *secureValueDB) toKubernetes() (*secretv0alpha1.SecureValue, error) {
func (sv *secureValueDB) toKubernetes() (*secretv1beta1.SecureValue, error) {
annotations := make(map[string]string, 0)
if sv.Annotations != "" {
if err := json.Unmarshal([]byte(sv.Annotations), &annotations); err != nil {
@@ -68,12 +68,12 @@ func (sv *secureValueDB) toKubernetes() (*secretv0alpha1.SecureValue, error) {
}
}
resource := &secretv0alpha1.SecureValue{
Spec: secretv0alpha1.SecureValueSpec{
resource := &secretv1beta1.SecureValue{
Spec: secretv1beta1.SecureValueSpec{
Description: sv.Description,
Decrypters: decrypters,
},
Status: secretv0alpha1.SecureValueStatus{
Status: secretv1beta1.SecureValueStatus{
ExternalID: sv.ExternalID,
Version: sv.Version,
},
@@ -111,7 +111,7 @@ func (sv *secureValueDB) toKubernetes() (*secretv0alpha1.SecureValue, error) {
}
// toCreateRow maps a Kubernetes resource into a DB row for new resources being created/inserted.
func toCreateRow(sv *secretv0alpha1.SecureValue, actorUID string) (*secureValueDB, error) {
func toCreateRow(sv *secretv1beta1.SecureValue, actorUID string) (*secureValueDB, error) {
row, err := toRow(sv, "")
if err != nil {
return nil, fmt.Errorf("failed to convert SecureValue to secureValueDB: %w", err)
@@ -129,7 +129,7 @@ func toCreateRow(sv *secretv0alpha1.SecureValue, actorUID string) (*secureValueD
}
// toRow maps a Kubernetes resource into a DB row.
func toRow(sv *secretv0alpha1.SecureValue, externalID string) (*secureValueDB, error) {
func toRow(sv *secretv1beta1.SecureValue, externalID string) (*secureValueDB, error) {
var annotations string
if len(sv.Annotations) > 0 {
cleanedAnnotations := xkube.CleanAnnotations(sv.Annotations)
@@ -5,7 +5,7 @@ import (
"fmt"
"time"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
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"
"github.com/grafana/grafana/pkg/services/featuremgmt"
@@ -46,7 +46,7 @@ type secureValueMetadataStorage struct {
tracer trace.Tracer
}
func (s *secureValueMetadataStorage) Create(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error) {
func (s *secureValueMetadataStorage) Create(ctx context.Context, sv *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, error) {
start := time.Now()
ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.Create", trace.WithAttributes(
attribute.String("name", sv.GetName()),
@@ -289,7 +289,7 @@ func (s *secureValueMetadataStorage) readActiveVersion(ctx context.Context, name
return secureValue, nil
}
func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.Namespace, name string, opts contracts.ReadOpts) (*secretv0alpha1.SecureValue, error) {
func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.Namespace, name string, opts contracts.ReadOpts) (*secretv1beta1.SecureValue, error) {
start := time.Now()
ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.Read", trace.WithAttributes(
attribute.String("name", name),
@@ -314,7 +314,7 @@ func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.N
return secureValueKub, nil
}
func (s *secureValueMetadataStorage) List(ctx context.Context, namespace xkube.Namespace) (svList []secretv0alpha1.SecureValue, error error) {
func (s *secureValueMetadataStorage) List(ctx context.Context, namespace xkube.Namespace) (svList []secretv1beta1.SecureValue, error error) {
start := time.Now()
ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.List", trace.WithAttributes(
attribute.String("namespace", namespace.String()),
@@ -341,7 +341,7 @@ func (s *secureValueMetadataStorage) List(ctx context.Context, namespace xkube.N
}
defer func() { _ = rows.Close() }()
secureValues := make([]secretv0alpha1.SecureValue, 0)
secureValues := make([]secretv1beta1.SecureValue, 0)
for rows.Next() {
row := secureValueDB{}
@@ -4,7 +4,7 @@ import (
"context"
"testing"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
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"
"github.com/grafana/grafana/pkg/services/featuremgmt"
@@ -14,15 +14,16 @@ import (
"github.com/grafana/grafana/pkg/storage/secret/migrator"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/trace/noop"
"k8s.io/utils/ptr"
)
func createTestKeeper(t *testing.T, ctx context.Context, keeperStorage contracts.KeeperMetadataStorage, name, namespace string) string {
t.Helper()
testKeeper := &secretv0alpha1.Keeper{
Spec: secretv0alpha1.KeeperSpec{
testKeeper := &secretv1beta1.Keeper{
Spec: secretv1beta1.KeeperSpec{
Description: "test keeper description",
AWS: &secretv0alpha1.AWSKeeperConfig{},
Aws: &secretv1beta1.KeeperAWSConfig{},
},
}
testKeeper.Name = name
@@ -56,10 +57,10 @@ func Test_SecureValueMetadataStorage_CreateAndRead(t *testing.T) {
keeperName := createTestKeeper(t, ctx, keeperStorage, "test-keeper", "default")
// Create a test secure value
testSecureValue := &secretv0alpha1.SecureValue{
Spec: secretv0alpha1.SecureValueSpec{
testSecureValue := &secretv1beta1.SecureValue{
Spec: secretv1beta1.SecureValueSpec{
Description: "test description",
Value: "test-value",
Value: ptr.To(secretv1beta1.NewExposedSecureValue("test-value")),
Keeper: &keeperName,
},
}
@@ -110,10 +111,10 @@ func Test_SecureValueMetadataStorage_CreateAndRead(t *testing.T) {
keeperName := createTestKeeper(t, ctx, keeperStorage, "test-keeper-2", "default")
// Create a test secure value
testSecureValue := &secretv0alpha1.SecureValue{
Spec: secretv0alpha1.SecureValueSpec{
testSecureValue := &secretv1beta1.SecureValue{
Spec: secretv1beta1.SecureValueSpec{
Description: "test description 2",
Value: "test-value-2",
Value: ptr.To(secretv1beta1.NewExposedSecureValue("test-value-2")),
Keeper: &keeperName,
},
}
@@ -5,18 +5,20 @@ import (
"slices"
"testing"
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
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/service"
"github.com/grafana/grafana/pkg/registry/apis/secret/testutils"
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
"github.com/mitchellh/copystructure"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"pgregory.net/rapid"
)
type modelSecureValue struct {
*secretv0alpha1.SecureValue
*secretv1beta1.SecureValue
active bool
}
@@ -66,7 +68,7 @@ func (m *model) readActiveVersion(namespace, name string) *modelSecureValue {
return nil
}
func (m *model) create(sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error) {
func (m *model) create(sv *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, error) {
modelSv := &modelSecureValue{sv, false}
modelSv.Status.Version = m.getNewVersionNumber(modelSv.Namespace, modelSv.Name)
modelSv.Status.ExternalID = fmt.Sprintf("%d", modelSv.Status.Version)
@@ -75,9 +77,9 @@ func (m *model) create(sv *secretv0alpha1.SecureValue, actorUID string) (*secret
return modelSv.SecureValue, nil
}
func (m *model) update(newSecureValue *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, bool, error) {
func (m *model) update(newSecureValue *secretv1beta1.SecureValue, actorUID string) (*secretv1beta1.SecureValue, bool, error) {
// If the payload doesn't contain a value, get the value from current version
if newSecureValue.Spec.Value == "" {
if newSecureValue.Spec.Value == nil {
sv := m.readActiveVersion(newSecureValue.Namespace, newSecureValue.Name)
if sv == nil {
return nil, false, contracts.ErrSecureValueNotFound
@@ -88,7 +90,7 @@ func (m *model) update(newSecureValue *secretv0alpha1.SecureValue, actorUID stri
return createdSv, true, err
}
func (m *model) delete(namespace, name string) (*secretv0alpha1.SecureValue, error) {
func (m *model) delete(namespace, name string) (*secretv1beta1.SecureValue, error) {
modelSv := m.readActiveVersion(namespace, name)
if modelSv == nil {
return nil, contracts.ErrSecureValueNotFound
@@ -97,8 +99,8 @@ func (m *model) delete(namespace, name string) (*secretv0alpha1.SecureValue, err
return modelSv.SecureValue, nil
}
func (m *model) list(namespace string) (*secretv0alpha1.SecureValueList, error) {
out := make([]secretv0alpha1.SecureValue, 0)
func (m *model) list(namespace string) (*secretv1beta1.SecureValueList, error) {
out := make([]secretv1beta1.SecureValue, 0)
for _, v := range m.secureValues {
if v.Namespace == namespace && v.active {
@@ -106,7 +108,7 @@ func (m *model) list(namespace string) (*secretv0alpha1.SecureValueList, error)
}
}
return &secretv0alpha1.SecureValueList{Items: out}, nil
return &secretv1beta1.SecureValueList{Items: out}, nil
}
func (m *model) decrypt(decrypter, namespace, name string) (map[string]service.DecryptResult, error) {
@@ -116,7 +118,7 @@ func (m *model) decrypt(decrypter, namespace, name string) (map[string]service.D
v.active {
if slices.ContainsFunc(v.Spec.Decrypters, func(d string) bool { return d == decrypter }) {
return map[string]service.DecryptResult{
name: service.NewDecryptResultValue(&v.DeepCopy().Spec.Value),
name: service.NewDecryptResultValue(deepCopy(v).Spec.Value),
}, nil
}
@@ -130,7 +132,7 @@ func (m *model) decrypt(decrypter, namespace, name string) (map[string]service.D
}, nil
}
func (m *model) read(namespace, name string) (*secretv0alpha1.SecureValue, error) {
func (m *model) read(namespace, name string) (*secretv1beta1.SecureValue, error) {
modelSv := m.readActiveVersion(namespace, name)
if modelSv == nil {
return nil, contracts.ErrSecureValueNotFound
@@ -142,25 +144,25 @@ var (
decryptersGen = rapid.SampledFrom([]string{"svc1", "svc2", "svc3", "svc4", "svc5"})
nameGen = rapid.SampledFrom([]string{"n1", "n2", "n3", "n4", "n5"})
namespaceGen = rapid.SampledFrom([]string{"ns1", "ns2", "ns3", "ns4", "ns5"})
anySecureValueGen = rapid.Custom(func(t *rapid.T) *secretv0alpha1.SecureValue {
return &secretv0alpha1.SecureValue{
anySecureValueGen = rapid.Custom(func(t *rapid.T) *secretv1beta1.SecureValue {
return &secretv1beta1.SecureValue{
ObjectMeta: metav1.ObjectMeta{
Name: nameGen.Draw(t, "name"),
Namespace: namespaceGen.Draw(t, "ns"),
},
Spec: secretv0alpha1.SecureValueSpec{
Spec: secretv1beta1.SecureValueSpec{
Description: rapid.SampledFrom([]string{"d1", "d2", "d3", "d4", "d5"}).Draw(t, "description"),
Value: secretv0alpha1.NewExposedSecureValue(rapid.SampledFrom([]string{"v1", "v2", "v3", "v4", "v5"}).Draw(t, "value")),
Value: ptr.To(secretv1beta1.NewExposedSecureValue(rapid.SampledFrom([]string{"v1", "v2", "v3", "v4", "v5"}).Draw(t, "value"))),
Decrypters: rapid.SliceOfDistinct(decryptersGen, func(v string) string { return v }).Draw(t, "decrypters"),
},
Status: secretv0alpha1.SecureValueStatus{},
Status: secretv1beta1.SecureValueStatus{},
}
})
updateSecureValueGen = rapid.Custom(func(t *rapid.T) *secretv0alpha1.SecureValue {
updateSecureValueGen = rapid.Custom(func(t *rapid.T) *secretv1beta1.SecureValue {
sv := anySecureValueGen.Draw(t, "sv")
// Maybe update the secret value, maybe not
if !rapid.Bool().Draw(t, "should_update_value") {
sv.Spec.Value = ""
sv.Spec.Value = nil
}
return sv
})
@@ -184,17 +186,17 @@ type decryptInput struct {
func TestModel(t *testing.T) {
t.Parallel()
sv := &secretv0alpha1.SecureValue{
sv := &secretv1beta1.SecureValue{
ObjectMeta: metav1.ObjectMeta{
Name: "sv1",
Namespace: "ns1",
},
Spec: secretv0alpha1.SecureValueSpec{
Spec: secretv1beta1.SecureValueSpec{
Description: "desc1",
Value: secretv0alpha1.NewExposedSecureValue("v1"),
Value: ptr.To(secretv1beta1.NewExposedSecureValue("v1")),
Decrypters: []string{"decrypter1"},
},
Status: secretv0alpha1.SecureValueStatus{},
Status: secretv1beta1.SecureValueStatus{},
}
t.Run("creating secure values", func(t *testing.T) {
@@ -203,14 +205,14 @@ func TestModel(t *testing.T) {
m := newModel()
// Create a secure value
sv1, err := m.create(sv.DeepCopy(), "actor-uid")
sv1, err := m.create(deepCopy(sv), "actor-uid")
require.NoError(t, err)
require.Equal(t, sv.Namespace, sv1.Namespace)
require.Equal(t, sv.Name, sv1.Name)
require.EqualValues(t, 1, sv1.Status.Version)
// Create a new version of a secure value
sv2, err := m.create(sv.DeepCopy(), "actor-uid")
sv2, err := m.create(deepCopy(sv), "actor-uid")
require.NoError(t, err)
require.Equal(t, sv.Namespace, sv2.Namespace)
require.Equal(t, sv.Name, sv2.Name)
@@ -222,27 +224,27 @@ func TestModel(t *testing.T) {
m := newModel()
sv1, err := m.create(sv.DeepCopy(), "actor-uid")
sv1, err := m.create(deepCopy(sv), "actor-uid")
require.NoError(t, err)
// Create a new version of a secure value by updating it
sv2, _, err := m.update(sv1.DeepCopy(), "actor-uid")
sv2, _, err := m.update(deepCopy(sv1), "actor-uid")
require.NoError(t, err)
require.Equal(t, sv.Namespace, sv2.Namespace)
require.Equal(t, sv.Name, sv2.Name)
require.EqualValues(t, 2, sv2.Status.Version)
// Try updating a secure value that doesn't exist without specifying a value for it
sv3 := sv2.DeepCopy()
sv3 := deepCopy(sv2)
sv3.Name = "i_dont_exist"
sv3.Spec.Value = ""
sv3.Spec.Value = nil
_, _, err = m.update(sv3, "actor-uid")
require.ErrorIs(t, err, contracts.ErrSecureValueNotFound)
// Updating a value that doesn't exist creates a new version
sv4 := sv3.DeepCopy()
sv4 := deepCopy(sv3)
sv4.Name = "i_dont_exist"
sv4.Spec.Value = secretv0alpha1.NewExposedSecureValue("sv4")
sv4.Spec.Value = ptr.To(secretv1beta1.NewExposedSecureValue("sv4"))
sv4, _, err = m.update(sv4, "actor-uid")
require.NoError(t, err)
require.EqualValues(t, 1, sv4.Status.Version)
@@ -253,7 +255,7 @@ func TestModel(t *testing.T) {
m := newModel()
sv1, err := m.create(sv.DeepCopy(), "actor-uid")
sv1, err := m.create(deepCopy(sv), "actor-uid")
require.NoError(t, err)
// Deleting a secure value
@@ -279,7 +281,7 @@ func TestModel(t *testing.T) {
require.Equal(t, 0, len(list.Items))
// Create a secure value
sv1, err := m.create(sv.DeepCopy(), "actor-uid")
sv1, err := m.create(deepCopy(sv), "actor-uid")
require.NoError(t, err)
// 1 secure value exists and it should be returned
@@ -304,7 +306,8 @@ func TestModel(t *testing.T) {
require.ErrorIs(t, result["name"].Error(), contracts.ErrDecryptNotFound)
// Create a secure value
sv1, err := m.create(sv.DeepCopy(), "actor-uid")
secret := "v1"
sv1, err := m.create(deepCopy(sv), "actor-uid")
require.NoError(t, err)
// Decrypt the just created secure value
@@ -312,7 +315,7 @@ func TestModel(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 1, len(result))
require.Nil(t, result[sv1.Name].Error())
require.Equal(t, result[sv1.Name].Value().DangerouslyExposeAndConsumeValue(), sv.DeepCopy().Spec.Value.DangerouslyExposeAndConsumeValue())
require.Equal(t, secret, result[sv1.Name].Value().DangerouslyExposeAndConsumeValue())
})
}
@@ -328,9 +331,10 @@ func TestStateMachine(t *testing.T) {
t.Repeat(map[string]func(*rapid.T){
"create": func(t *rapid.T) {
sv := anySecureValueGen.Draw(t, "sv")
modelCreatedSv, modelErr := model.create(sv.DeepCopy(), "actor-uid")
createdSv, err := sut.CreateSv(t.Context(), testutils.CreateSvWithSv(sv.DeepCopy()))
modelCreatedSv, modelErr := model.create(deepCopy(sv), "actor-uid")
createdSv, err := sut.CreateSv(t.Context(), testutils.CreateSvWithSv(deepCopy(sv)))
if err != nil || modelErr != nil {
require.ErrorIs(t, err, modelErr)
return
@@ -341,8 +345,8 @@ func TestStateMachine(t *testing.T) {
},
"update": func(t *rapid.T) {
sv := updateSecureValueGen.Draw(t, "sv")
modelCreatedSv, _, modelErr := model.update(sv.DeepCopy(), "actor-uid")
createdSv, err := sut.UpdateSv(t.Context(), sv.DeepCopy())
modelCreatedSv, _, modelErr := model.update(deepCopy(sv), "actor-uid")
createdSv, err := sut.UpdateSv(t.Context(), deepCopy(sv))
if err != nil || modelErr != nil {
require.ErrorIs(t, err, modelErr)
return
@@ -379,7 +383,7 @@ func TestStateMachine(t *testing.T) {
// PERFORMANCE: The lists are always small
for _, v1 := range modelList.Items {
if !slices.ContainsFunc(list.Items, func(v2 secretv0alpha1.SecureValue) bool {
if !slices.ContainsFunc(list.Items, func(v2 secretv1beta1.SecureValue) bool {
return v2.Namespace == v1.Namespace && v2.Name == v1.Name && v2.Status.Version == v1.Status.Version
}) {
t.Fatalf("expected sut to return secure value ns=%+v name=%+v version=%+v in the result", v1.Namespace, v1.Name, v1.Status.Version)
@@ -417,3 +421,11 @@ func TestStateMachine(t *testing.T) {
})
})
}
func deepCopy[T any](sv T) T {
copied, err := copystructure.Copy(sv)
if err != nil {
panic(fmt.Sprintf("failed to copy secure value: %v", err))
}
return copied.(T)
}