From ab51794bdb868d4ef33601289df506e39e925457 Mon Sep 17 00:00:00 2001 From: Michael Mandrus <41969079+mmandrus@users.noreply.github.com> Date: Tue, 15 Jul 2025 14:39:20 -0400 Subject: [PATCH] SecretsManager: Unify KMS across OSS and Enterprise (#108085) * everything is compiling * tests passing * remove used object * write a test for secret key upgrades * misc cleanup * clean up some wording * lint issues * fix a typo * import hashicorp dependency explicitly * simplify oss kmsprovider package structure * consolidate current provider and available providers * add a new manager configuration test * fix hashivault import * fix import issue * fix unit tests * Update go.mod Co-authored-by: Matheus Macabu --------- Co-authored-by: Matheus Macabu --- conf/defaults.ini | 10 +- go.mod | 7 + go.sum | 11 + go.work.sum | 3 +- pkg/extensions/enterprise_imports.go | 1 + .../encryption/cipher/service/service.go | 28 +- .../encryption/cipher/service/service_test.go | 13 +- .../{defaultprovider => }/grafana_provider.go | 12 +- .../encryption/kmsproviders/kmsproviders.go | 33 ++- .../apis/secret/encryption/manager/manager.go | 96 ++----- .../secret/encryption/manager/manager_test.go | 258 +++++++++++++++--- .../secret/encryption/manager/test_helpers.go | 17 +- .../apis/secret/encryption/secrets.go | 18 +- .../secret/secretkeeper/secretkeeper_test.go | 14 +- .../apis/secret/testutils/testutils.go | 17 +- pkg/server/wire.go | 4 +- pkg/server/wire_gen.go | 123 +++++---- pkg/server/wireexts_oss.go | 2 + pkg/setting/setting_secrets_manager.go | 33 ++- pkg/setting/setting_secrets_manager_test.go | 173 ++++++++++++ 20 files changed, 631 insertions(+), 242 deletions(-) rename pkg/registry/apis/secret/encryption/kmsproviders/{defaultprovider => }/grafana_provider.go (51%) create mode 100644 pkg/setting/setting_secrets_manager_test.go diff --git a/conf/defaults.ini b/conf/defaults.ini index 3634bf235a0..fb4e547cf18 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -2147,12 +2147,12 @@ alert_rules_state = "paused" ###################################### Secrets Manager ###################################### [secrets_manager] -# Used for signing +# Current key provider used for envelope encryption +encryption_provider = secret_key.v1 + +[secrets_manager.encryption.secret_key.v1] +# Used to encrypt data keys secret_key = SW2YcwTIb9zpOOhoPsMm -# Current key provider used for envelope encryption, default to static value specified by secret_key -encryption_provider = secretKey.v1 -# List of configured key providers, space separated (Enterprise only): e.g., awskms.v1 azurekv.v1 -available_encryption_providers = ################################## Frontend development configuration ################################### # Warning! Any settings placed in this section will be available on `process.env.frontend_dev_{foo}` within frontend code diff --git a/go.mod b/go.mod index a46003d9444..7de0ab6300c 100644 --- a/go.mod +++ b/go.mod @@ -194,6 +194,7 @@ require ( go.uber.org/goleak v1.3.0 // @grafana/grafana-search-and-storage go.uber.org/zap v1.27.0 // @grafana/identity-access-team gocloud.dev v0.42.0 // @grafana/grafana-app-platform-squad + gocloud.dev/secrets/hashivault v0.42.0 // @grafana/grafana-operator-experience-squad golang.org/x/crypto v0.39.0 // @grafana/grafana-backend-group golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // @grafana/alerting-backend golang.org/x/mod v0.25.0 // indirect; @grafana/grafana-backend-group @@ -407,12 +408,17 @@ require ( github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-metrics v0.5.4 // indirect github.com/hashicorp/go-msgpack/v2 v2.1.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect + github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.7 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/memberlist v0.5.2 // indirect github.com/hashicorp/serf v0.10.2 // indirect + github.com/hashicorp/vault/api v1.16.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/invopop/jsonschema v0.13.0 // indirect @@ -501,6 +507,7 @@ require ( github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/segmentio/asm v1.2.0 // indirect diff --git a/go.sum b/go.sum index 5158881d6d9..fa234616138 100644 --- a/go.sum +++ b/go.sum @@ -1719,6 +1719,10 @@ github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= @@ -1740,6 +1744,7 @@ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iP github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.17.0 h1:z1XvSUyXd1HP10U4lrLg5e0JMVz6CPaJvAgxM0KNZVY= github.com/hashicorp/hcl/v2 v2.17.0/go.mod h1:gJyW2PTShkJqQBKpAmPO3yxMxIuoXkOF2TpqXzrQyx4= @@ -1760,6 +1765,8 @@ github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpT github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/serf v0.10.2 h1:m5IORhuNSjaxeljg5DeQVDlQyVkhRIjJDimbkCa8aAc= github.com/hashicorp/serf v0.10.2/go.mod h1:T1CmSGfSeGfnfNy/w0odXQUR1rfECGd2Qdsp84DjOiY= +github.com/hashicorp/vault/api v1.16.0 h1:nbEYGJiAPGzT9U4oWgaaB0g+Rj8E59QuHKyA5LhwQN4= +github.com/hashicorp/vault/api v1.16.0/go.mod h1:KhuUhzOD8lDSk29AtzNjgAu2kxRA9jL9NAbkFlqvkBA= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hetznercloud/hcloud-go/v2 v2.19.1 h1:UU/7h3uc/rdgspM8xkQF7wokmwZXePWDXcLqrQRRzzY= @@ -2295,6 +2302,8 @@ github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfF github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= @@ -2634,6 +2643,8 @@ go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fR go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= gocloud.dev v0.42.0 h1:qzG+9ItUL3RPB62/Amugws28n+4vGZXEoJEAMfjutzw= gocloud.dev v0.42.0/go.mod h1:zkaYAapZfQisXOA4bzhsbA4ckiStGQ3Psvs9/OQ5dPM= +gocloud.dev/secrets/hashivault v0.42.0 h1:kPWIIu1AP6ApHf7HwUrzGrwyRJEfTd46JNUNgnbpsFA= +gocloud.dev/secrets/hashivault v0.42.0/go.mod h1:LXprr1XLEAT7BVZ+Y66dJEHQMzDsowIExj5Ktr9HLvM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/go.work.sum b/go.work.sum index b260888a846..45af5346b64 100644 --- a/go.work.sum +++ b/go.work.sum @@ -982,7 +982,6 @@ github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6 github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/mdns v1.0.5 h1:1M5hW1cunYeoXOqHwEb/GBDDHAFo0Yqb/uz/beC6LbE= github.com/hashicorp/mdns v1.0.5/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= @@ -1123,6 +1122,8 @@ github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt github.com/mostynb/go-grpc-compression v1.2.3 h1:42/BKWMy0KEJGSdWvzqIyOZ95YcR9mLPqKctH7Uo//I= github.com/mostynb/go-grpc-compression v1.2.3/go.mod h1:AghIxF3P57umzqM9yz795+y1Vjs47Km/Y2FE6ouQ7Lg= github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8 h1:P48LjvUQpTReR3TQRbxSeSBsMXzfK0uol7eRcr7VBYQ= +github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= +github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4 h1:dnMxwus89s86tI8rcGVp2HwZzlz7c5o92VOy7dSckBQ= github.com/ncw/swift v1.0.53 h1:luHjjTNtekIEvHg5KdAFIBaH7bWfNkefwFnpDffSIks= github.com/ncw/swift v1.0.53/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= diff --git a/pkg/extensions/enterprise_imports.go b/pkg/extensions/enterprise_imports.go index de5a2e46eba..111b2b8c04c 100644 --- a/pkg/extensions/enterprise_imports.go +++ b/pkg/extensions/enterprise_imports.go @@ -28,6 +28,7 @@ import ( _ "github.com/russellhaering/goxmldsig" _ "github.com/spf13/cobra" // used by the standalone apiserver cli _ "github.com/stretchr/testify/require" + _ "gocloud.dev/secrets/hashivault" _ "golang.org/x/time/rate" _ "k8s.io/api" _ "k8s.io/apimachinery/pkg/util/httpstream/spdy" diff --git a/pkg/registry/apis/secret/encryption/cipher/service/service.go b/pkg/registry/apis/secret/encryption/cipher/service/service.go index 83d140da1a9..48ebef7e3a5 100644 --- a/pkg/registry/apis/secret/encryption/cipher/service/service.go +++ b/pkg/registry/apis/secret/encryption/cipher/service/service.go @@ -14,20 +14,16 @@ import ( "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/provider" - "github.com/grafana/grafana/pkg/setting" ) const ( encryptionAlgorithmDelimiter = '*' ) -// Service must not be used for cipher. -// Use secrets.Service implementing envelope encryption instead. -type Service struct { +type cipherService struct { tracer trace.Tracer log log.Logger - cfg *setting.Cfg usageMetrics usagestats.Service cipher cipher.Encrypter @@ -35,16 +31,13 @@ type Service struct { algorithm string } -func NewEncryptionService( +// ProvideAESGCMCipherService provides an AES-GCM cipher for encryption and decryption. +// It should not be used to encrypt payloads directly, as it is intended to encrypt data keys for envelope encryption. +func ProvideAESGCMCipherService( tracer trace.Tracer, usageMetrics usagestats.Service, - cfg *setting.Cfg, -) (*Service, error) { - if cfg.SecretsManagement.SecretKey == "" { - return nil, fmt.Errorf("`[secrets_manager]secret_key` is not set") - } - - s := &Service{ +) (cipher.Cipher, error) { + s := &cipherService{ tracer: tracer, log: log.New("encryption"), @@ -55,7 +48,6 @@ func NewEncryptionService( algorithm: provider.AesGcm, usageMetrics: usageMetrics, - cfg: cfg, } s.registerUsageMetrics() @@ -63,7 +55,7 @@ func NewEncryptionService( return s, nil } -func (s *Service) registerUsageMetrics() { +func (s *cipherService) registerUsageMetrics() { s.usageMetrics.RegisterMetricsFunc(func(context.Context) (map[string]any, error) { return map[string]any{ fmt.Sprintf("stats.%s.encryption.cipher.%s.count", encryption.UsageInsightsPrefix, s.algorithm): 1, @@ -71,7 +63,7 @@ func (s *Service) registerUsageMetrics() { }) } -func (s *Service) Decrypt(ctx context.Context, payload []byte, secret string) ([]byte, error) { +func (s *cipherService) Decrypt(ctx context.Context, payload []byte, secret string) ([]byte, error) { ctx, span := s.tracer.Start(ctx, "CipherService.Decrypt") defer span.End() @@ -99,7 +91,7 @@ func (s *Service) Decrypt(ctx context.Context, payload []byte, secret string) ([ return decrypted, err } -func (s *Service) deriveEncryptionAlgorithm(payload []byte) (string, []byte, error) { +func (s *cipherService) deriveEncryptionAlgorithm(payload []byte) (string, []byte, error) { if len(payload) == 0 { return "", nil, fmt.Errorf("unable to derive encryption algorithm") } @@ -120,7 +112,7 @@ func (s *Service) deriveEncryptionAlgorithm(payload []byte) (string, []byte, err return string(algorithm), payload, nil } -func (s *Service) Encrypt(ctx context.Context, payload []byte, secret string) ([]byte, error) { +func (s *cipherService) Encrypt(ctx context.Context, payload []byte, secret string) ([]byte, error) { ctx, span := s.tracer.Start(ctx, "CipherService.Encrypt") defer span.End() diff --git a/pkg/registry/apis/secret/encryption/cipher/service/service_test.go b/pkg/registry/apis/secret/encryption/cipher/service/service_test.go index 62a65ea0dbc..dd24e7927c6 100644 --- a/pkg/registry/apis/secret/encryption/cipher/service/service_test.go +++ b/pkg/registry/apis/secret/encryption/cipher/service/service_test.go @@ -8,21 +8,14 @@ import ( "go.opentelemetry.io/otel/trace/noop" "github.com/grafana/grafana/pkg/infra/usagestats" - "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher" ) -func newGcmService(t *testing.T) *Service { +func newGcmService(t *testing.T) cipher.Cipher { t.Helper() usageStats := &usagestats.UsageStatsMock{} - settings := &setting.Cfg{ - SecretsManagement: setting.SecretsManagerSettings{ - SecretKey: "SdlklWklckeLS", - EncryptionProvider: "secretKey.v1", - }, - } - - svc, err := NewEncryptionService(noop.NewTracerProvider().Tracer("test"), usageStats, settings) + svc, err := ProvideAESGCMCipherService(noop.NewTracerProvider().Tracer("test"), usageStats) require.NoError(t, err, "failed to set up encryption service") return svc } diff --git a/pkg/registry/apis/secret/encryption/kmsproviders/defaultprovider/grafana_provider.go b/pkg/registry/apis/secret/encryption/kmsproviders/grafana_provider.go similarity index 51% rename from pkg/registry/apis/secret/encryption/kmsproviders/defaultprovider/grafana_provider.go rename to pkg/registry/apis/secret/encryption/kmsproviders/grafana_provider.go index 067d455bfb6..e27fed9da07 100644 --- a/pkg/registry/apis/secret/encryption/kmsproviders/defaultprovider/grafana_provider.go +++ b/pkg/registry/apis/secret/encryption/kmsproviders/grafana_provider.go @@ -1,4 +1,4 @@ -package defaultprovider +package kmsproviders import ( "context" @@ -7,22 +7,22 @@ import ( "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher" ) -type grafanaProvider struct { +type secretKeyProvider struct { sk string encryption cipher.Cipher } -func New(sk string, encryption cipher.Cipher) encryption.Provider { - return grafanaProvider{ +func newSecretKeyProvider(sk string, encryption cipher.Cipher) encryption.Provider { + return secretKeyProvider{ sk: sk, encryption: encryption, } } -func (p grafanaProvider) Encrypt(ctx context.Context, blob []byte) ([]byte, error) { +func (p secretKeyProvider) Encrypt(ctx context.Context, blob []byte) ([]byte, error) { return p.encryption.Encrypt(ctx, blob, p.sk) } -func (p grafanaProvider) Decrypt(ctx context.Context, blob []byte) ([]byte, error) { +func (p secretKeyProvider) Decrypt(ctx context.Context, blob []byte) ([]byte, error) { return p.encryption.Decrypt(ctx, blob, p.sk) } diff --git a/pkg/registry/apis/secret/encryption/kmsproviders/kmsproviders.go b/pkg/registry/apis/secret/encryption/kmsproviders/kmsproviders.go index 0797d784c8e..d88fd353ab6 100644 --- a/pkg/registry/apis/secret/encryption/kmsproviders/kmsproviders.go +++ b/pkg/registry/apis/secret/encryption/kmsproviders/kmsproviders.go @@ -1,19 +1,40 @@ package kmsproviders import ( + "fmt" + "strings" + "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher" - "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/kmsproviders/defaultprovider" "github.com/grafana/grafana/pkg/setting" ) const ( - // Default is the identifier of the default kms provider which fallbacks to the configured secret_key - Default = "secretKey.v1" + // OSSProviderType is the identifier of the default kms provider which fallbacks to the configured secret_key + OSSProviderType = "secret_key" + // SecretKeyKey is the key in the section that contains the secret key + SecretKeyKey = "secret_key" ) -func GetOSSKMSProviders(cfg *setting.Cfg, enc cipher.Cipher) encryption.ProviderMap { - return encryption.ProviderMap{ - Default: defaultprovider.New(cfg.SecretsManagement.SecretKey, enc), +// ProvideOSSKMSProviders provides the ProviderConfig expected by the encryption manager in the OSS wire configuration. +// It looks for all configured 'secret_key' sections and creates a separate provider for each, each with its own secret key, allowing users to upgrade their secret key without breaking existing secrets. +func ProvideOSSKMSProviders(cfg *setting.Cfg, cipher cipher.Cipher) (encryption.ProviderConfig, error) { + pCfg := encryption.ProviderConfig{ + CurrentProvider: encryption.ProviderID(cfg.SecretsManagement.CurrentEncryptionProvider), + AvailableProviders: make(encryption.ProviderMap), + } + + // Look through the available secret_key providers and add them to the map + for providerName, properties := range cfg.SecretsManagement.ConfiguredKMSProviders { + if strings.HasPrefix(providerName, OSSProviderType) { + secretKey := properties[SecretKeyKey] + if secretKey != "" { + pCfg.AvailableProviders[encryption.ProviderID(providerName)] = newSecretKeyProvider(secretKey, cipher) + } else { + return pCfg, fmt.Errorf("missing secret_key for provider %s", providerName) + } + } } + + return pCfg, nil } diff --git a/pkg/registry/apis/secret/encryption/manager/manager.go b/pkg/registry/apis/secret/encryption/manager/manager.go index 1c596a3c70f..f48b350c1bd 100644 --- a/pkg/registry/apis/secret/encryption/manager/manager.go +++ b/pkg/registry/apis/secret/encryption/manager/manager.go @@ -20,9 +20,6 @@ import ( "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher" - "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/service" - "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/kmsproviders" - "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" ) @@ -33,16 +30,14 @@ const ( type EncryptionManager struct { tracer trace.Tracer store contracts.DataKeyStorage - enc cipher.Cipher - cfg *setting.Cfg usageStats usagestats.Service mtx sync.Mutex - pOnce sync.Once - providers encryption.ProviderMap - - currentProviderID encryption.ProviderID + // The cipher is used to encrypt and decrypt payloads with a data key. + cipher cipher.Cipher + // The providerConfig are used to encrypt and decrypt the data keys. + providerConfig encryption.ProviderConfig log log.Logger } @@ -51,33 +46,22 @@ type EncryptionManager struct { func ProvideEncryptionManager( tracer trace.Tracer, store contracts.DataKeyStorage, - cfg *setting.Cfg, usageStats usagestats.Service, - thirdPartyKMS encryption.ProviderMap, + enc cipher.Cipher, + providerConfig encryption.ProviderConfig, ) (contracts.EncryptionManager, error) { - currentProviderID := encryption.ProviderID(cfg.SecretsManagement.EncryptionProvider) - - enc, err := service.NewEncryptionService(tracer, usageStats, cfg) - if err != nil { - return nil, fmt.Errorf("failed to create encryption service: %w", err) + currentProviderID := providerConfig.CurrentProvider + if _, ok := providerConfig.AvailableProviders[currentProviderID]; !ok { + return nil, fmt.Errorf("missing configuration for current encryption provider %s", currentProviderID) } s := &EncryptionManager{ - tracer: tracer, - store: store, - cfg: cfg, - usageStats: usageStats, - enc: enc, - currentProviderID: currentProviderID, - log: log.New("encryption"), - } - - if err := s.InitProviders(thirdPartyKMS); err != nil { - return nil, err - } - - if _, ok := s.providers[currentProviderID]; !ok { - return nil, fmt.Errorf("missing configuration for current encryption provider %s", currentProviderID) + tracer: tracer, + store: store, + usageStats: usageStats, + cipher: enc, + log: log.New("encryption"), + providerConfig: providerConfig, } s.registerUsageMetrics() @@ -85,44 +69,20 @@ func ProvideEncryptionManager( return s, nil } -func (s *EncryptionManager) InitProviders(extraProviders encryption.ProviderMap) (err error) { - done := false - s.pOnce.Do(func() { - providers := kmsproviders.GetOSSKMSProviders(s.cfg, s.enc) - - for id, p := range extraProviders { - if _, exists := s.providers[id]; exists { - err = fmt.Errorf("provider %s already registered", id) - return - } - providers[id] = p - } - - s.providers = providers - done = true - }) - - if !done && err == nil { - err = fmt.Errorf("providers were already initialized, no action taken") - } - - return -} - func (s *EncryptionManager) registerUsageMetrics() { s.usageStats.RegisterMetricsFunc(func(ctx context.Context) (map[string]any, error) { usageMetrics := make(map[string]any) // Current provider - kind, err := s.currentProviderID.Kind() + kind, err := s.providerConfig.CurrentProvider.Kind() if err != nil { return nil, fmt.Errorf("encryptionManager.registerUsageMetrics: %w", err) } usageMetrics[fmt.Sprintf("stats.%s.encryption.current_provider.%s.count", encryption.UsageInsightsPrefix, kind)] = 1 // Count by kind - countByKind := make(map[string]int, len(s.providers)) - for id := range s.providers { + countByKind := make(map[string]int, len(s.providerConfig.AvailableProviders)) + for id := range s.providerConfig.AvailableProviders { kind, err := id.Kind() if err != nil { return nil, fmt.Errorf("encryptionManager.registerUsageMetrics: %w", err) @@ -161,7 +121,7 @@ func (s *EncryptionManager) Encrypt(ctx context.Context, namespace string, paylo } }() - label := encryption.KeyLabel(s.currentProviderID) + label := encryption.KeyLabel(s.providerConfig.CurrentProvider) var id string var dataKey []byte @@ -172,7 +132,7 @@ func (s *EncryptionManager) Encrypt(ctx context.Context, namespace string, paylo } var encrypted []byte - encrypted, err = s.enc.Encrypt(ctx, payload, string(dataKey)) + encrypted, err = s.cipher.Encrypt(ctx, payload, string(dataKey)) if err != nil { s.log.Error("Failed to encrypt secret", "error", err) return nil, err @@ -235,7 +195,7 @@ func (s *EncryptionManager) dataKeyByLabel(ctx context.Context, namespace, label } // 2.1 Find the encryption provider. - provider, exists := s.providers[dataKey.Provider] + provider, exists := s.providerConfig.AvailableProviders[dataKey.Provider] if !exists { return "", nil, fmt.Errorf("could not find encryption provider '%s'", dataKey.Provider) } @@ -264,9 +224,9 @@ func (s *EncryptionManager) newDataKey(ctx context.Context, namespace string, la } // 2.1 Find the encryption provider. - provider, exists := s.providers[s.currentProviderID] + provider, exists := s.providerConfig.AvailableProviders[s.providerConfig.CurrentProvider] if !exists { - return "", nil, fmt.Errorf("could not find encryption provider '%s'", s.currentProviderID) + return "", nil, fmt.Errorf("could not find encryption provider '%s'", s.providerConfig.CurrentProvider) } // 2.2 Encrypt the data key. @@ -282,7 +242,7 @@ func (s *EncryptionManager) newDataKey(ctx context.Context, namespace string, la Active: true, UID: id, Namespace: namespace, - Provider: s.currentProviderID, + Provider: s.providerConfig.CurrentProvider, EncryptedData: encrypted, Label: label, } @@ -351,7 +311,7 @@ func (s *EncryptionManager) Decrypt(ctx context.Context, namespace string, paylo } var decrypted []byte - decrypted, err = s.enc.Decrypt(ctx, payload, string(dataKey)) + decrypted, err = s.cipher.Decrypt(ctx, payload, string(dataKey)) return decrypted, err } @@ -384,7 +344,7 @@ func (s *EncryptionManager) dataKeyById(ctx context.Context, namespace, id strin } // 2.1. Find the encryption provider. - provider, exists := s.providers[dataKey.Provider] + provider, exists := s.providerConfig.AvailableProviders[dataKey.Provider] if !exists { return nil, fmt.Errorf("could not find encryption provider '%s'", dataKey.Provider) } @@ -398,6 +358,6 @@ func (s *EncryptionManager) dataKeyById(ctx context.Context, namespace, id strin return decrypted, nil } -func (s *EncryptionManager) GetProviders() encryption.ProviderMap { - return s.providers +func (s *EncryptionManager) GetProviders() encryption.ProviderConfig { + return s.providerConfig } diff --git a/pkg/registry/apis/secret/encryption/manager/manager_test.go b/pkg/registry/apis/secret/encryption/manager/manager_test.go index 75eeab5e8d2..b627bc5b187 100644 --- a/pkg/registry/apis/secret/encryption/manager/manager_test.go +++ b/pkg/registry/apis/secret/encryption/manager/manager_test.go @@ -5,6 +5,7 @@ import ( "errors" "testing" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" @@ -14,6 +15,8 @@ import ( "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" + "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/service" + osskmsproviders "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/kmsproviders" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" @@ -67,8 +70,8 @@ func TestEncryptionService_EnvelopeEncryption(t *testing.T) { reports, err := svc.usageStats.GetUsageReport(context.Background()) require.NoError(t, err) - assert.Equal(t, 1, reports.Metrics["stats.secrets_manager.encryption.current_provider.secretKey.count"]) - assert.Equal(t, 1, reports.Metrics["stats.secrets_manager.encryption.providers.secretKey.count"]) + assert.Equal(t, 1, reports.Metrics["stats.secrets_manager.encryption.current_provider.secret_key.count"]) + assert.Equal(t, 1, reports.Metrics["stats.secrets_manager.encryption.providers.secret_key.count"]) }) } @@ -161,7 +164,7 @@ func TestEncryptionService_DataKeys(t *testing.T) { func TestEncryptionService_UseCurrentProvider(t *testing.T) { t.Run("When encryption_provider is not specified explicitly, should use 'secretKey' as a current provider", func(t *testing.T) { svc := setupTestService(t) - assert.Equal(t, encryption.ProviderID("secretKey.v1"), svc.currentProviderID) + assert.Equal(t, encryption.ProviderID("secret_key.v1"), svc.providerConfig.CurrentProvider) }) t.Run("Should use encrypt/decrypt methods of the current encryption provider", func(t *testing.T) { @@ -175,8 +178,8 @@ func TestEncryptionService_UseCurrentProvider(t *testing.T) { cfg := &setting.Cfg{ Raw: raw, SecretsManagement: setting.SecretsManagerSettings{ - SecretKey: "sdDkslslld", - EncryptionProvider: "secretKey.v1", + CurrentEncryptionProvider: "secret_key.v1", + ConfiguredKMSProviders: map[string]map[string]string{"secret_key.v1": {"secret_key": "SW2YcwTIb9zpOOhoPsMm"}}, }, } @@ -186,12 +189,19 @@ func TestEncryptionService_UseCurrentProvider(t *testing.T) { encryptionStore, err := encryptionstorage.ProvideDataKeyStorage(database.ProvideDatabase(testDB, tracer), tracer, features, nil) require.NoError(t, err) + usageStats := &usagestats.UsageStatsMock{T: t} + enc, err := service.ProvideAESGCMCipherService(tracer, usageStats) + require.NoError(t, err) + + ossProviders, err := osskmsproviders.ProvideOSSKMSProviders(cfg, enc) + require.NoError(t, err) + encMgr, err := ProvideEncryptionManager( tracer, encryptionStore, - cfg, - &usagestats.UsageStatsMock{T: t}, - encryption.ProvideThirdPartyProviderMap(), + usageStats, + enc, + ossProviders, ) require.NoError(t, err) @@ -199,8 +209,10 @@ func TestEncryptionService_UseCurrentProvider(t *testing.T) { //override default provider with fake, and register the fake separately fake := &fakeProvider{} - encryptionManager.providers[encryption.ProviderID("fakeProvider.v1")] = fake - encryptionManager.currentProviderID = "fakeProvider.v1" + encryptionManager.providerConfig.AvailableProviders = encryption.ProviderMap{ + encryption.ProviderID("fakeProvider.v1"): fake, + } + encryptionManager.providerConfig.CurrentProvider = encryption.ProviderID("fakeProvider.v1") namespace := "test-namespace" encrypted, _ := encryptionManager.Encrypt(context.Background(), namespace, []byte{}) @@ -212,21 +224,185 @@ func TestEncryptionService_UseCurrentProvider(t *testing.T) { svcDecryptMgr, err := ProvideEncryptionManager( tracer, encryptionStore, - cfg, - &usagestats.UsageStatsMock{T: t}, - encryption.ProvideThirdPartyProviderMap(), + usageStats, + enc, + ossProviders, ) require.NoError(t, err) svcDecrypt := svcDecryptMgr.(*EncryptionManager) - svcDecrypt.providers[encryption.ProviderID("fakeProvider.v1")] = fake - svcDecrypt.currentProviderID = "fakeProvider.v1" + svcDecrypt.providerConfig.AvailableProviders = encryption.ProviderMap{ + encryption.ProviderID("fakeProvider.v1"): fake, + } + svcDecrypt.providerConfig.CurrentProvider = encryption.ProviderID("fakeProvider.v1") _, _ = svcDecrypt.Decrypt(context.Background(), namespace, encrypted) assert.True(t, fake.decryptCalled, "fake provider's decrypt should be called") }) } +func TestEncryptionService_SecretKeyVersionUpgrade(t *testing.T) { + ctx := context.Background() + namespace := "test-namespace" + + // Generate random keys for testing + oldKey := util.GenerateShortUID() + util.GenerateShortUID() // 32 chars + newKey := util.GenerateShortUID() + util.GenerateShortUID() // 32 chars + + t.Run("should encrypt with v1, upgrade to v2, encrypt with v2, and decrypt both", func(t *testing.T) { + // Step 1: Set up v1 configuration + cfgV1 := &setting.Cfg{ + SecretsManagement: setting.SecretsManagerSettings{ + CurrentEncryptionProvider: "secret_key.v1", + ConfiguredKMSProviders: map[string]map[string]string{"secret_key.v1": {"secret_key": oldKey}}, + }, + } + + testDB := sqlstore.NewTestStore(t, sqlstore.WithMigrator(migrator.New())) + features := featuremgmt.WithFeatures(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, featuremgmt.FlagSecretsManagementAppPlatform) + tracer := noop.NewTracerProvider().Tracer("test") + encryptionStore, err := encryptionstorage.ProvideDataKeyStorage(database.ProvideDatabase(testDB, tracer), tracer, features, nil) + require.NoError(t, err) + + usageStats := &usagestats.UsageStatsMock{T: t} + enc, err := service.ProvideAESGCMCipherService(tracer, usageStats) + require.NoError(t, err) + + ossProviders, err := osskmsproviders.ProvideOSSKMSProviders(cfgV1, enc) + require.NoError(t, err) + + svcV1, err := ProvideEncryptionManager( + tracer, + encryptionStore, + usageStats, + enc, + ossProviders, + ) + require.NoError(t, err) + + // Step 2: Encrypt something with v1 + plaintext := []byte("secret data from v1") + encryptedV1, err := svcV1.Encrypt(ctx, namespace, plaintext) + require.NoError(t, err) + + // Verify v1 can decrypt its own data + decryptedV1, err := svcV1.Decrypt(ctx, namespace, encryptedV1) + require.NoError(t, err) + assert.Equal(t, plaintext, decryptedV1) + + // Verify current provider is v1 + encMgrV1 := svcV1.(*EncryptionManager) + assert.Equal(t, encryption.ProviderID("secret_key.v1"), encMgrV1.providerConfig.CurrentProvider) + + // Step 3: Create new configuration with v2 as current provider + cfgV2 := &setting.Cfg{ + SecretsManagement: setting.SecretsManagerSettings{ + CurrentEncryptionProvider: "secret_key.v2", + ConfiguredKMSProviders: map[string]map[string]string{ + "secret_key.v1": {"secret_key": oldKey}, + "secret_key.v2": {"secret_key": newKey}, + }, + }, + } + + // Reinitialize service with v2 configuration (reuse same store) + ossProvidersV2, err := osskmsproviders.ProvideOSSKMSProviders(cfgV2, enc) + require.NoError(t, err) + + svcV2, err := ProvideEncryptionManager( + tracer, + encryptionStore, + usageStats, + enc, + ossProvidersV2, + ) + require.NoError(t, err) + + // Step 4: Ensure we can encrypt and decrypt with the new key (v2) + newPlaintext := []byte("secret data from v2") + encryptedV2, err := svcV2.Encrypt(ctx, namespace, newPlaintext) + require.NoError(t, err) + + decryptedV2, err := svcV2.Decrypt(ctx, namespace, encryptedV2) + require.NoError(t, err) + assert.Equal(t, newPlaintext, decryptedV2) + + // Verify current provider is v2 + encMgrV2 := svcV2.(*EncryptionManager) + assert.Equal(t, encryption.ProviderID("secret_key.v2"), encMgrV2.providerConfig.CurrentProvider) + + // Step 5: Ensure we can decrypt the old value encrypted with v1 + decryptedOldWithV2, err := svcV2.Decrypt(ctx, namespace, encryptedV1) + require.NoError(t, err) + assert.Equal(t, plaintext, decryptedOldWithV2) + + // Verify both providers are available + assert.Contains(t, encMgrV2.providerConfig.AvailableProviders, encryption.ProviderID("secret_key.v1")) + assert.Contains(t, encMgrV2.providerConfig.AvailableProviders, encryption.ProviderID("secret_key.v2")) + assert.Equal(t, 2, len(encMgrV2.providerConfig.AvailableProviders)) + }) + + t.Run("encrypting with v1 then removing the v1 config should cause decryption to fail", func(t *testing.T) { + tracer := noop.NewTracerProvider().Tracer("test") + testDB := sqlstore.NewTestStore(t, sqlstore.WithMigrator(migrator.New())) + features := featuremgmt.WithFeatures(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, featuremgmt.FlagSecretsManagementAppPlatform) + encryptionStore, err := encryptionstorage.ProvideDataKeyStorage(database.ProvideDatabase(testDB, tracer), tracer, features, nil) + require.NoError(t, err) + + usageStats := &usagestats.UsageStatsMock{T: t} + enc, err := service.ProvideAESGCMCipherService(tracer, usageStats) + require.NoError(t, err) + + cfgV1 := &setting.Cfg{ + SecretsManagement: setting.SecretsManagerSettings{ + CurrentEncryptionProvider: "secret_key.v1", + ConfiguredKMSProviders: map[string]map[string]string{ + "secret_key.v1": {"secret_key": uuid.New().String()}, + }, + }, + } + + ossProviders, err := osskmsproviders.ProvideOSSKMSProviders(cfgV1, enc) + require.NoError(t, err) + + svcV1, err := ProvideEncryptionManager( + tracer, + encryptionStore, + usageStats, + enc, + ossProviders, + ) + require.NoError(t, err) + + rsp, err := svcV1.Encrypt(ctx, namespace, []byte("test")) + require.NoError(t, err) + + cfgV2 := &setting.Cfg{ + SecretsManagement: setting.SecretsManagerSettings{ + CurrentEncryptionProvider: "secret_key.v2", + ConfiguredKMSProviders: map[string]map[string]string{ + "secret_key.v2": {"secret_key": uuid.New().String()}, + }, + }, + } + + ossProvidersV2, err := osskmsproviders.ProvideOSSKMSProviders(cfgV2, enc) + require.NoError(t, err) + + svcV2, err := ProvideEncryptionManager( + tracer, + encryptionStore, + usageStats, + enc, + ossProvidersV2, + ) + require.NoError(t, err) + + _, err = svcV2.Decrypt(ctx, namespace, rsp) + require.Error(t, err) + }) +} + type fakeProvider struct { encryptCalled bool decryptCalled bool @@ -364,14 +540,12 @@ func TestIntegration_SecretsService(t *testing.T) { t.Run(name, func(t *testing.T) { testDB := sqlstore.NewTestStore(t, sqlstore.WithMigrator(migrator.New())) tracer := noop.NewTracerProvider().Tracer("test") - features := featuremgmt.WithFeatures(featuremgmt.FlagSecretsManagementAppPlatform) - defaultKey := "SdlklWklckeLS" cfg := &setting.Cfg{ SecretsManagement: setting.SecretsManagerSettings{ - SecretKey: defaultKey, - EncryptionProvider: "secretKey.v1", + CurrentEncryptionProvider: "secret_key.v1", + ConfiguredKMSProviders: map[string]map[string]string{"secret_key.v1": {"secret_key": "SW2YcwTIb9zpOOhoPsMm"}}, }, } store, err := encryptionstorage.ProvideDataKeyStorage(database.ProvideDatabase(testDB, tracer), tracer, features, nil) @@ -379,12 +553,18 @@ func TestIntegration_SecretsService(t *testing.T) { usageStats := &usagestats.UsageStatsMock{T: t} + enc, err := service.ProvideAESGCMCipherService(tracer, usageStats) + require.NoError(t, err) + + ossProviders, err := osskmsproviders.ProvideOSSKMSProviders(cfg, enc) + require.NoError(t, err) + svc, err := ProvideEncryptionManager( tracer, store, - cfg, usageStats, - encryption.ProvideThirdPartyProviderMap(), + enc, + ossProviders, ) require.NoError(t, err) @@ -415,34 +595,28 @@ func TestIntegration_SecretsService(t *testing.T) { } } -func TestEncryptionService_ReInitReturnsError(t *testing.T) { - svc := setupTestService(t) - err := svc.InitProviders(encryption.ProviderMap{ - "fakeProvider.v1": &fakeProvider{}, - }) - require.Error(t, err) -} - func TestEncryptionService_ThirdPartyProviders(t *testing.T) { - cfg := &setting.Cfg{ - SecretsManagement: setting.SecretsManagerSettings{ - SecretKey: "SdlklWklckeLS", - EncryptionProvider: "secretKey.v1", - }, - } + tracer := noop.NewTracerProvider().Tracer("test") + usageStats := &usagestats.UsageStatsMock{T: t} + + enc, err := service.ProvideAESGCMCipherService(tracer, usageStats) + require.NoError(t, err) svc, err := ProvideEncryptionManager( + tracer, nil, - nil, - cfg, - &usagestats.UsageStatsMock{}, - encryption.ProviderMap{ - "fakeProvider.v1": &fakeProvider{}, + usageStats, + enc, + encryption.ProviderConfig{ + CurrentProvider: encryption.ProviderID("fakeProvider.v1"), + AvailableProviders: encryption.ProviderMap{ + encryption.ProviderID("fakeProvider.v1"): &fakeProvider{}, + }, }, ) require.NoError(t, err) encMgr := svc.(*EncryptionManager) - require.Len(t, encMgr.providers, 2) - require.Contains(t, encMgr.providers, encryption.ProviderID("fakeProvider.v1")) + require.Len(t, encMgr.providerConfig.AvailableProviders, 1) + require.Contains(t, encMgr.providerConfig.AvailableProviders, encryption.ProviderID("fakeProvider.v1")) } diff --git a/pkg/registry/apis/secret/encryption/manager/test_helpers.go b/pkg/registry/apis/secret/encryption/manager/test_helpers.go index 535db771f5d..220e4289852 100644 --- a/pkg/registry/apis/secret/encryption/manager/test_helpers.go +++ b/pkg/registry/apis/secret/encryption/manager/test_helpers.go @@ -7,7 +7,8 @@ import ( "go.opentelemetry.io/otel/trace/noop" "github.com/grafana/grafana/pkg/infra/usagestats" - "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" + "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/service" + osskmsproviders "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/kmsproviders" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" @@ -27,8 +28,8 @@ func setupTestService(tb testing.TB) *EncryptionManager { defaultKey := "SdlklWklckeLS" cfg := &setting.Cfg{ SecretsManagement: setting.SecretsManagerSettings{ - SecretKey: defaultKey, - EncryptionProvider: "secretKey.v1", + CurrentEncryptionProvider: "secret_key.v1", + ConfiguredKMSProviders: map[string]map[string]string{"secret_key.v1": {"secret_key": defaultKey}}, }, } store, err := encryptionstorage.ProvideDataKeyStorage(database, tracer, features, nil) @@ -36,12 +37,18 @@ func setupTestService(tb testing.TB) *EncryptionManager { usageStats := &usagestats.UsageStatsMock{T: tb} + enc, err := service.ProvideAESGCMCipherService(tracer, usageStats) + require.NoError(tb, err) + + ossProviders, err := osskmsproviders.ProvideOSSKMSProviders(cfg, enc) + require.NoError(tb, err) + encMgr, err := ProvideEncryptionManager( tracer, store, - cfg, usageStats, - encryption.ProvideThirdPartyProviderMap(), + enc, + ossProviders, ) require.NoError(tb, err) diff --git a/pkg/registry/apis/secret/encryption/secrets.go b/pkg/registry/apis/secret/encryption/secrets.go index 55a6d36c6cd..36beed76c37 100644 --- a/pkg/registry/apis/secret/encryption/secrets.go +++ b/pkg/registry/apis/secret/encryption/secrets.go @@ -9,7 +9,14 @@ import ( const UsageInsightsPrefix = "secrets_manager" -// Provider is a key encryption key provider for envelope encryption +type ProviderConfig struct { + CurrentProvider ProviderID + AvailableProviders ProviderMap +} + +type ProviderMap map[ProviderID]Provider + +// Provider is a fully configured key encryption key provider used for to encrypt and decrypt data keys for envelope encryption type Provider interface { Encrypt(ctx context.Context, blob []byte) ([]byte, error) Decrypt(ctx context.Context, blob []byte) ([]byte, error) @@ -17,6 +24,7 @@ type Provider interface { type ProviderID string +// Kind returns the kind of the provider, e.g. "secret_key", "aws_kms", "azure_keyvault", "google_kms", "hashicorp_vault" func (id ProviderID) Kind() (string, error) { idStr := string(id) @@ -28,17 +36,11 @@ func (id ProviderID) Kind() (string, error) { return parts[0], nil } +// KeyLabel returns a label for the data key that is unique to the current provider and today's date. func KeyLabel(providerID ProviderID) string { return fmt.Sprintf("%s@%s", time.Now().Format("2006-01-02"), providerID) } -type ProviderMap map[ProviderID]Provider - -// ProvideThirdPartyProviderMap fulfills the wire dependency needed by the encryption manager in OSS -func ProvideThirdPartyProviderMap() ProviderMap { - return ProviderMap{} -} - // BackgroundProvider should be implemented for a provider that has a task that needs to be run in the background. type BackgroundProvider interface { Run(ctx context.Context) error diff --git a/pkg/registry/apis/secret/secretkeeper/secretkeeper_test.go b/pkg/registry/apis/secret/secretkeeper/secretkeeper_test.go index a0d3a739523..e3e288cf2f6 100644 --- a/pkg/registry/apis/secret/secretkeeper/secretkeeper_test.go +++ b/pkg/registry/apis/secret/secretkeeper/secretkeeper_test.go @@ -8,6 +8,8 @@ import ( "go.opentelemetry.io/otel/trace/noop" "github.com/grafana/grafana/pkg/infra/usagestats" + "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/service" + osskmsproviders "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/kmsproviders" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" "github.com/grafana/grafana/pkg/registry/apis/secret/secretkeeper/sqlkeeper" "github.com/grafana/grafana/pkg/services/featuremgmt" @@ -26,8 +28,8 @@ func TestMain(m *testing.M) { func Test_OSSKeeperService(t *testing.T) { cfg := &setting.Cfg{ SecretsManagement: setting.SecretsManagerSettings{ - SecretKey: "sdDkslslld", - EncryptionProvider: "secretKey.v1", + CurrentEncryptionProvider: "secret_key.v1", + ConfiguredKMSProviders: map[string]map[string]string{"secret_key.v1": {"secret_key": "SW2YcwTIb9zpOOhoPsMm"}}, }, } keeperService, err := setupTestService(t, cfg) @@ -55,7 +57,13 @@ func setupTestService(t *testing.T, cfg *setting.Cfg) (*OSSKeeperService, error) encValueStore, err := encryptionstorage.ProvideEncryptedValueStorage(database, tracer, features) require.NoError(t, err) - encryptionManager, err := manager.ProvideEncryptionManager(tracer, dataKeyStore, cfg, &usagestats.UsageStatsMock{T: t}, nil) + usageStats := &usagestats.UsageStatsMock{T: t} + enc, err := service.ProvideAESGCMCipherService(tracer, usageStats) + require.NoError(t, err) + + ossProviders, err := osskmsproviders.ProvideOSSKMSProviders(cfg, enc) + require.NoError(t, err) + encryptionManager, err := manager.ProvideEncryptionManager(tracer, dataKeyStore, usageStats, enc, ossProviders) require.NoError(t, err) // Initialize the keeper service diff --git a/pkg/registry/apis/secret/testutils/testutils.go b/pkg/registry/apis/secret/testutils/testutils.go index bc2309231a4..b60e550ee53 100644 --- a/pkg/registry/apis/secret/testutils/testutils.go +++ b/pkg/registry/apis/secret/testutils/testutils.go @@ -16,7 +16,8 @@ import ( "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/decrypt" - "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" + cipher "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/service" + osskmsproviders "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/kmsproviders" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" "github.com/grafana/grafana/pkg/registry/apis/secret/secretkeeper/sqlkeeper" "github.com/grafana/grafana/pkg/registry/apis/secret/service" @@ -82,8 +83,8 @@ func Setup(t *testing.T, opts ...func(*SetupConfig)) Sut { defaultKey := "SdlklWklckeLS" cfg := &setting.Cfg{ SecretsManagement: setting.SecretsManagerSettings{ - SecretKey: defaultKey, - EncryptionProvider: "secretKey.v1", + CurrentEncryptionProvider: "secret_key.v1", + ConfiguredKMSProviders: map[string]map[string]string{"secret_key.v1": {"secret_key": defaultKey}}, }, } store, err := encryptionstorage.ProvideDataKeyStorage(database, tracer, features, nil) @@ -91,12 +92,18 @@ func Setup(t *testing.T, opts ...func(*SetupConfig)) Sut { usageStats := &usagestats.UsageStatsMock{T: t} + enc, err := cipher.ProvideAESGCMCipherService(tracer, usageStats) + require.NoError(t, err) + + ossProviders, err := osskmsproviders.ProvideOSSKMSProviders(cfg, enc) + require.NoError(t, err) + encryptionManager, err := manager.ProvideEncryptionManager( tracer, store, - cfg, usageStats, - encryption.ProvideThirdPartyProviderMap(), + enc, + ossProviders, ) require.NoError(t, err) diff --git a/pkg/server/wire.go b/pkg/server/wire.go index a828453388c..6b9d84eade8 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -43,7 +43,7 @@ import ( "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository/github" secretcontracts "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" secretdecrypt "github.com/grafana/grafana/pkg/registry/apis/secret/decrypt" - gsmEncryption "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" + cipher "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/service" encryptionManager "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" secretsecurevalueservice "github.com/grafana/grafana/pkg/registry/apis/secret/service" secretvalidator "github.com/grafana/grafana/pkg/registry/apis/secret/validator" @@ -437,7 +437,7 @@ var wireBasicSet = wire.NewSet( secretdatabase.ProvideDatabase, wire.Bind(new(secretcontracts.Database), new(*secretdatabase.Database)), encryptionManager.ProvideEncryptionManager, - gsmEncryption.ProvideThirdPartyProviderMap, + cipher.ProvideAESGCMCipherService, // Unified storage resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, diff --git a/pkg/server/wire_gen.go b/pkg/server/wire_gen.go index f7134904ba3..0550f5a1a5a 100644 --- a/pkg/server/wire_gen.go +++ b/pkg/server/wire_gen.go @@ -62,10 +62,11 @@ import ( "github.com/grafana/grafana/pkg/registry/apis/secret" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/decrypt" - encryption2 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" + service11 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/service" + "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/kmsproviders" manager4 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" "github.com/grafana/grafana/pkg/registry/apis/secret/secretkeeper" - service11 "github.com/grafana/grafana/pkg/registry/apis/secret/service" + service12 "github.com/grafana/grafana/pkg/registry/apis/secret/service" validator3 "github.com/grafana/grafana/pkg/registry/apis/secret/validator" "github.com/grafana/grafana/pkg/registry/apis/userstorage" "github.com/grafana/grafana/pkg/registry/apps" @@ -115,7 +116,7 @@ import ( "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources/guardian" service7 "github.com/grafana/grafana/pkg/services/datasources/service" - encryption3 "github.com/grafana/grafana/pkg/services/encryption" + encryption2 "github.com/grafana/grafana/pkg/services/encryption" "github.com/grafana/grafana/pkg/services/encryption/provider" service2 "github.com/grafana/grafana/pkg/services/encryption/service" "github.com/grafana/grafana/pkg/services/extsvcauth" @@ -473,8 +474,8 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser } extSvcAccountsService := extsvcaccounts.ProvideExtSvcAccountsService(acimplService, cfg, inProcBus, sqlStore, featureToggles, registerer, serviceAccountsService, secretsService, tracingService) registryRegistry := registry2.ProvideExtSvcRegistry(cfg, extSvcAccountsService, serverLockService, featureToggles) - service12 := service4.ProvideService(sqlStore, secretsService) - serviceregistrationService := serviceregistration.ProvideService(cfg, featureToggles, registryRegistry, service12) + service13 := service4.ProvideService(sqlStore, secretsService) + serviceregistrationService := serviceregistration.ProvideService(cfg, featureToggles, registryRegistry, service13) initialize := pipeline.ProvideInitializationStage(pluginManagementCfg, inMemory, providerService, processService, serviceregistrationService, acimplService, actionSetService, envVarsProvider, tracingService) terminate, err := pipeline.ProvideTerminationStage(pluginManagementCfg, inMemory, processService) if err != nil { @@ -497,7 +498,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser return nil, err } pluginService := service5.ProvideDashboardPluginService(featureToggles, dashboardServiceImpl) - service13 := service6.ProvideService(fileStoreManager, pluginService) + service14 := service6.ProvideService(fileStoreManager, pluginService) orgRoleMapper := connectors.ProvideOrgRoleMapper(cfg, orgService) ssosettingsimplService := ssosettingsimpl.ProvideService(cfg, sqlStore, accessControl, routeRegisterImpl, featureToggles, secretsService, usageStats, registerer, ossImpl, ossLicensingService) socialService := socialimpl.ProvideService(cfg, featureToggles, usageStats, bundleregistryService, remoteCache, orgRoleMapper, ssosettingsimplService) @@ -542,11 +543,11 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser datasourcePermissionsService := ossaccesscontrol.ProvideDatasourcePermissionsService(cfg, featureToggles, sqlStore) requestConfigProvider := pluginconfig.NewRequestConfigProvider(pluginInstanceCfg) baseProvider := plugincontext.ProvideBaseService(cfg, requestConfigProvider) - service14, err := service7.ProvideService(sqlStore, secretsService, secretsKVStore, cfg, featureToggles, accessControl, datasourcePermissionsService, quotaService, pluginstoreService, middlewareHandler, baseProvider) + service15, err := service7.ProvideService(sqlStore, secretsService, secretsKVStore, cfg, featureToggles, accessControl, datasourcePermissionsService, quotaService, pluginstoreService, middlewareHandler, baseProvider) if err != nil { return nil, err } - correlationsService, err := correlations.ProvideService(sqlStore, routeRegisterImpl, service14, accessControl, inProcBus, quotaService, cfg) + correlationsService, err := correlations.ProvideService(sqlStore, routeRegisterImpl, service15, accessControl, inProcBus, quotaService, cfg) if err != nil { return nil, err } @@ -563,14 +564,14 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser if err != nil { return nil, err } - provisioningServiceImpl, err := provisioning.ProvideService(accessControl, cfg, sqlStore, pluginstoreService, dBstore, serviceService, notificationService, dashboardProvisioningService, service14, correlationsService, dashboardService, folderimplService, service12, searchService, quotaService, secretsService, orgService, receiverPermissionsService, tracingService, dualwriteService) + provisioningServiceImpl, err := provisioning.ProvideService(accessControl, cfg, sqlStore, pluginstoreService, dBstore, serviceService, notificationService, dashboardProvisioningService, service15, correlationsService, dashboardService, folderimplService, service13, searchService, quotaService, secretsService, orgService, receiverPermissionsService, tracingService, dualwriteService) if err != nil { return nil, err } - dataSourceProxyService := datasourceproxy.ProvideService(cacheServiceImpl, ossDataSourceRequestValidator, pluginstoreService, cfg, httpclientProvider, oauthtokenService, service14, tracingService, secretsService, featureToggles) + dataSourceProxyService := datasourceproxy.ProvideService(cacheServiceImpl, ossDataSourceRequestValidator, pluginstoreService, cfg, httpclientProvider, oauthtokenService, service15, tracingService, secretsService, featureToggles) starService := starimpl.ProvideService(sqlStore) searchSearchService := search2.ProvideService(cfg, sqlStore, starService, dashboardService, folderimplService, featureToggles, sortService) - plugincontextProvider := plugincontext.ProvideService(cfg, cacheService, pluginstoreService, cacheServiceImpl, service14, service12, requestConfigProvider) + plugincontextProvider := plugincontext.ProvideService(cfg, cacheService, pluginstoreService, cacheServiceImpl, service15, service13, requestConfigProvider) exprService := expr.ProvideService(cfg, middlewareHandler, plugincontextProvider, featureToggles, registerer, tracingService) queryServiceImpl := query.ProvideService(cfg, cacheServiceImpl, exprService, ossDataSourceRequestValidator, middlewareHandler, plugincontextProvider) repositoryImpl := annotationsimpl.ProvideService(sqlStore, cfg, featureToggles, tagimplService, tracingService, dBstore, dashboardService, registerer) @@ -584,7 +585,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser contexthandlerContextHandler := contexthandler.ProvideService(cfg, authnAuthenticator, featureToggles) logger := loggermw.Provide(cfg, featureToggles) ngAlert := metrics2.ProvideService() - alertNG, err := ngalert.ProvideService(cfg, featureToggles, cacheServiceImpl, service14, routeRegisterImpl, sqlStore, kvStore, exprService, dataSourceProxyService, quotaService, secretsService, notificationService, ngAlert, folderimplService, accessControl, dashboardService, renderingService, inProcBus, acimplService, repositoryImpl, pluginstoreService, tracingService, dBstore, httpclientProvider, plugincontextProvider, receiverPermissionsService, userService) + alertNG, err := ngalert.ProvideService(cfg, featureToggles, cacheServiceImpl, service15, routeRegisterImpl, sqlStore, kvStore, exprService, dataSourceProxyService, quotaService, secretsService, notificationService, ngAlert, folderimplService, accessControl, dashboardService, renderingService, inProcBus, acimplService, repositoryImpl, pluginstoreService, tracingService, dBstore, httpclientProvider, plugincontextProvider, receiverPermissionsService, userService) if err != nil { return nil, err } @@ -621,7 +622,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser csrfCSRF := csrf.ProvideCSRFFilter(cfg) playlistService := playlistimpl.ProvideService(sqlStore, tracingService) secretsMigrator := migrator.ProvideSecretsMigrator(serviceService, secretsService, sqlStore, ossImpl, featureToggles) - dataSourceSecretMigrationService := migrations2.ProvideDataSourceMigrationService(service14, kvStore, featureToggles) + dataSourceSecretMigrationService := migrations2.ProvideDataSourceMigrationService(service15, kvStore, featureToggles) secretMigrationProviderImpl := migrations2.ProvideSecretMigrationProvider(serverLockService, dataSourceSecretMigrationService) publicDashboardServiceImpl := service3.ProvideService(cfg, featureToggles, publicDashboardStoreImpl, queryServiceImpl, repositoryImpl, accessControl, publicDashboardServiceWrapperImpl, dashboardService, ossLicensingService) middleware := api2.ProvideMiddleware() @@ -632,7 +633,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser return nil, err } authnService := authnimpl.ProvideAuthnService(authnimplService) - navtreeService := navtreeimpl.ProvideService(cfg, accessControl, pluginstoreService, service12, starService, featureToggles, dashboardService, acimplService, kvStore, apikeyService, ossLicensingService, authnService) + navtreeService := navtreeimpl.ProvideService(cfg, accessControl, pluginstoreService, service13, starService, featureToggles, dashboardService, acimplService, kvStore, apikeyService, ossLicensingService, authnService) searchHTTPService := searchV2.ProvideSearchHTTPService(searchService) statsService := statsimpl.ProvideService(cfg, sqlStore, dashboardService, folderimplService, orgService, featureToggles) gatherer := metrics.ProvideGatherer() @@ -649,7 +650,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser } idimplService := idimpl.ProvideService(cfg, localSigner, remoteCache, authnService, registerer, tracer) verifier := userimpl.ProvideVerifier(cfg, userService, tempuserService, notificationService, idimplService) - httpServer, err := api.ProvideHTTPServer(apiOpts, cfg, routeRegisterImpl, inProcBus, renderingService, ossLicensingService, hooksService, cacheService, sqlStore, ossDataSourceRequestValidator, pluginstoreService, service13, pluginstoreService, middlewareHandler, pluginerrsStore, pluginInstaller, ossImpl, cacheServiceImpl, userAuthTokenService, cleanUpService, shortURLService, queryHistoryService, correlationsService, remoteCache, provisioningServiceImpl, accessControl, dataSourceProxyService, searchSearchService, grafanaLive, gateway, plugincontextProvider, contexthandlerContextHandler, logger, featureToggles, alertNG, libraryPanelService, libraryElementService, quotaService, socialService, tracingService, serviceService, grafanaService, pluginsService, ossService, service14, queryServiceImpl, filestoreService, serviceAccountsProxy, pluginassetsService, authinfoimplService, storageService, notificationService, dashboardService, dashboardProvisioningService, folderimplService, ossProvider, serviceImpl, service12, avatarCacheServer, prefService, folderPermissionsService, dashboardPermissionsService, dashverService, starService, csrfCSRF, noop, playlistService, apikeyService, kvStore, secretsMigrator, secretsService, secretMigrationProviderImpl, secretsKVStore, apiApi, userService, tempuserService, loginattemptimplService, orgService, deletionService, teamService, acimplService, navtreeService, repositoryImpl, tagimplService, searchHTTPService, oauthtokenService, statsService, authnService, pluginscdnService, gatherer, apiAPI, registerer, eventualRestConfigProvider, anonDeviceService, verifier, preinstallImpl) + httpServer, err := api.ProvideHTTPServer(apiOpts, cfg, routeRegisterImpl, inProcBus, renderingService, ossLicensingService, hooksService, cacheService, sqlStore, ossDataSourceRequestValidator, pluginstoreService, service14, pluginstoreService, middlewareHandler, pluginerrsStore, pluginInstaller, ossImpl, cacheServiceImpl, userAuthTokenService, cleanUpService, shortURLService, queryHistoryService, correlationsService, remoteCache, provisioningServiceImpl, accessControl, dataSourceProxyService, searchSearchService, grafanaLive, gateway, plugincontextProvider, contexthandlerContextHandler, logger, featureToggles, alertNG, libraryPanelService, libraryElementService, quotaService, socialService, tracingService, serviceService, grafanaService, pluginsService, ossService, service15, queryServiceImpl, filestoreService, serviceAccountsProxy, pluginassetsService, authinfoimplService, storageService, notificationService, dashboardService, dashboardProvisioningService, folderimplService, ossProvider, serviceImpl, service13, avatarCacheServer, prefService, folderPermissionsService, dashboardPermissionsService, dashverService, starService, csrfCSRF, noop, playlistService, apikeyService, kvStore, secretsMigrator, secretsService, secretMigrationProviderImpl, secretsKVStore, apiApi, userService, tempuserService, loginattemptimplService, orgService, deletionService, teamService, acimplService, navtreeService, repositoryImpl, tagimplService, searchHTTPService, oauthtokenService, statsService, authnService, pluginscdnService, gatherer, apiAPI, registerer, eventualRestConfigProvider, anonDeviceService, verifier, preinstallImpl) if err != nil { return nil, err } @@ -662,12 +663,12 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser if err != nil { return nil, err } - statscollectorService := statscollector.ProvideService(usageStats, validatorService, statsService, cfg, sqlStore, socialService, pluginstoreService, featureManager, service14, httpclientProvider, sandboxService, advisorService) + statscollectorService := statscollector.ProvideService(usageStats, validatorService, statsService, cfg, sqlStore, socialService, pluginstoreService, featureManager, service15, httpclientProvider, sandboxService, advisorService) internalMetricsService, err := metrics.ProvideService(cfg, registerer, gatherer) if err != nil { return nil, err } - supportbundlesimplService, err := supportbundlesimpl.ProvideService(accessControl, acimplService, bundleregistryService, cfg, featureToggles, httpServer, kvStore, service12, pluginstoreService, routeRegisterImpl, ossImpl, sqlStore, usageStats, tracingService) + supportbundlesimplService, err := supportbundlesimpl.ProvideService(accessControl, acimplService, bundleregistryService, cfg, featureToggles, httpServer, kvStore, service13, pluginstoreService, routeRegisterImpl, ossImpl, sqlStore, usageStats, tracingService) if err != nil { return nil, err } @@ -675,7 +676,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser if err != nil { return nil, err } - scopedPluginDatasourceProvider := datasource.ProvideDefaultPluginConfigs(service14, cacheServiceImpl, plugincontextProvider) + scopedPluginDatasourceProvider := datasource.ProvideDefaultPluginConfigs(service15, cacheServiceImpl, plugincontextProvider) v := builder.ProvideDefaultBuildHandlerChainFuncFromBuilders() aggregatorRunner := aggregatorrunner.ProvideNoopAggregatorConfigurator() apiserverService, err := apiserver.ProvideService(cfg, featureToggles, routeRegisterImpl, tracingService, serverLockService, sqlStore, kvStore, middlewareHandler, scopedPluginDatasourceProvider, plugincontextProvider, pluginstoreService, dualwriteService, resourceClient, eventualRestConfigProvider, v, eventualRestConfigProvider, registerer, aggregatorRunner) @@ -693,15 +694,15 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser zanzanaReconciler := dualwrite2.ProvideZanzanaReconciler(cfg, featureToggles, client, sqlStore, serverLockService, folderimplService) playlistAppProvider := playlist.RegisterApp(playlistService, cfg, featureToggles) investigationsAppProvider := investigations.RegisterApp(cfg) - checkregistryService := checkregistry.ProvideService(service14, pluginstoreService, plugincontextProvider, middlewareHandler, plugincheckerService, repoManager, preinstallImpl, noop, provisionedpluginsNoop, ssosettingsimplService, cfg, pluginerrsStore) + checkregistryService := checkregistry.ProvideService(service15, pluginstoreService, plugincontextProvider, middlewareHandler, plugincheckerService, repoManager, preinstallImpl, noop, provisionedpluginsNoop, ssosettingsimplService, cfg, pluginerrsStore) advisorAppProvider := advisor2.RegisterApp(checkregistryService, cfg) alertingNotificationsAppProvider := notifications2.RegisterApp(cfg, alertNG) appregistryService, err := appregistry.ProvideRegistryServiceSink(apiserverService, eventualRestConfigProvider, featureToggles, playlistAppProvider, investigationsAppProvider, advisorAppProvider, alertingNotificationsAppProvider, cfg) if err != nil { return nil, err } - importDashboardService := service9.ProvideService(routeRegisterImpl, quotaService, service13, pluginstoreService, libraryPanelService, dashboardService, accessControl, folderimplService, featureToggles) - dashboardUpdater := service6.ProvideDashboardUpdater(inProcBus, pluginstoreService, service13, importDashboardService, service12, pluginService, dashboardService) + importDashboardService := service9.ProvideService(routeRegisterImpl, quotaService, service14, pluginstoreService, libraryPanelService, dashboardService, accessControl, folderimplService, featureToggles) + dashboardUpdater := service6.ProvideDashboardUpdater(inProcBus, pluginstoreService, service14, importDashboardService, service13, pluginService, dashboardService) sanitizerProvider := sanitizer.ProvideService(renderingService) healthService, err := grpcserver.ProvideHealthService(cfg, grpcserverProvider) if err != nil { @@ -715,7 +716,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser identitySynchronizer := authnimpl.ProvideIdentitySynchronizer(authnimplService) ldapImpl := service10.ProvideService(cfg, featureToggles, ssosettingsimplService) apiService := api4.ProvideService(cfg, routeRegisterImpl, accessControl, userService, authinfoimplService, ossGroups, identitySynchronizer, orgService, ldapImpl, userAuthTokenService, bundleregistryService) - dashboardsAPIBuilder := dashboard.RegisterAPIService(cfg, featureToggles, apiserverService, dashboardService, dashboardProvisioningService, service14, dashboardServiceImpl, accessControl, accessClient, provisioningServiceImpl, dashboardsStore, registerer, sqlStore, tracingService, resourceClient, dualwriteService, sortService, quotaService, dashboardFolderStoreImpl, libraryPanelService, eventualRestConfigProvider, userService) + dashboardsAPIBuilder := dashboard.RegisterAPIService(cfg, featureToggles, apiserverService, dashboardService, dashboardProvisioningService, service15, dashboardServiceImpl, accessControl, accessClient, provisioningServiceImpl, dashboardsStore, registerer, sqlStore, tracingService, resourceClient, dualwriteService, sortService, quotaService, dashboardFolderStoreImpl, libraryPanelService, eventualRestConfigProvider, userService) snapshotsAPIBuilder := dashboardsnapshot.RegisterAPIService(serviceImpl, apiserverService, cfg, featureToggles, sqlStore, registerer) featureFlagAPIBuilder := featuretoggle.RegisterAPIService(featureManager, accessControl, apiserverService, cfg, registerer) dataSourceAPIBuilder, err := datasource.RegisterAPIService(featureToggles, apiserverService, middlewareHandler, scopedPluginDatasourceProvider, plugincontextProvider, pluginstoreService, accessControl, registerer) @@ -728,8 +729,8 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser if err != nil { return nil, err } - legacyDataSourceLookup := service7.ProvideLegacyDataSourceLookup(service14) - queryAPIBuilder, err := query2.RegisterAPIService(featureToggles, apiserverService, service14, pluginstoreService, accessControl, middlewareHandler, plugincontextProvider, registerer, tracingService, legacyDataSourceLookup) + legacyDataSourceLookup := service7.ProvideLegacyDataSourceLookup(service15) + queryAPIBuilder, err := query2.RegisterAPIService(featureToggles, apiserverService, service15, pluginstoreService, accessControl, middlewareHandler, plugincontextProvider, registerer, tracingService, legacyDataSourceLookup) if err != nil { return nil, err } @@ -753,8 +754,15 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser if err != nil { return nil, err } - providerMap := encryption2.ProvideThirdPartyProviderMap() - encryptionManager, err := manager4.ProvideEncryptionManager(tracer, dataKeyStorage, cfg, usageStats, providerMap) + cipher, err := service11.ProvideAESGCMCipherService(tracer, usageStats) + if err != nil { + return nil, err + } + providerConfig, err := kmsproviders.ProvideOSSKMSProviders(cfg, cipher) + if err != nil { + return nil, err + } + encryptionManager, err := manager4.ProvideEncryptionManager(tracer, dataKeyStorage, usageStats, cipher, providerConfig) if err != nil { return nil, err } @@ -762,7 +770,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser if err != nil { return nil, err } - secureValueService := service11.ProvideSecureValueService(tracer, accessClient, databaseDatabase, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService) + secureValueService := service12.ProvideSecureValueService(tracer, accessClient, databaseDatabase, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService) decryptAllowList := decrypt.ProvideDecryptAllowList() decryptAuthorizer := decrypt.ProvideDecryptAuthorizer(tracer, decryptAllowList) decryptStorage, err := metadata.ProvideDecryptStorage(featureToggles, tracer, ossKeeperService, keeperMetadataStorage, secureValueMetadataStorage, decryptAuthorizer, registerer) @@ -792,7 +800,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser return nil, err } teamAPI := teamapi.ProvideTeamAPI(routeRegisterImpl, teamService, acimplService, accessControl, teamPermissionsService, userService, ossLicensingService, cfg, prefService, dashboardService, featureToggles) - cloudmigrationService, err := cloudmigrationimpl.ProvideService(cfg, httpclientProvider, featureToggles, sqlStore, service14, secretsKVStore, secretsService, routeRegisterImpl, registerer, tracingService, dashboardService, folderimplService, pluginstoreService, service12, accessControl, acimplService, kvStore, libraryElementService, alertNG) + cloudmigrationService, err := cloudmigrationimpl.ProvideService(cfg, httpclientProvider, featureToggles, sqlStore, service15, secretsKVStore, secretsService, routeRegisterImpl, registerer, tracingService, dashboardService, folderimplService, pluginstoreService, service13, accessControl, acimplService, kvStore, libraryElementService, alertNG) if err != nil { return nil, err } @@ -1014,8 +1022,8 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { } extSvcAccountsService := extsvcaccounts.ProvideExtSvcAccountsService(acimplService, cfg, inProcBus, sqlStore, featureToggles, registerer, serviceAccountsService, secretsService, tracingService) registryRegistry := registry2.ProvideExtSvcRegistry(cfg, extSvcAccountsService, serverLockService, featureToggles) - service12 := service4.ProvideService(sqlStore, secretsService) - serviceregistrationService := serviceregistration.ProvideService(cfg, featureToggles, registryRegistry, service12) + service13 := service4.ProvideService(sqlStore, secretsService) + serviceregistrationService := serviceregistration.ProvideService(cfg, featureToggles, registryRegistry, service13) initialize := pipeline.ProvideInitializationStage(pluginManagementCfg, inMemory, providerService, processService, serviceregistrationService, acimplService, actionSetService, envVarsProvider, tracingService) terminate, err := pipeline.ProvideTerminationStage(pluginManagementCfg, inMemory, processService) if err != nil { @@ -1038,7 +1046,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { return nil, err } pluginService := service5.ProvideDashboardPluginService(featureToggles, dashboardServiceImpl) - service13 := service6.ProvideService(fileStoreManager, pluginService) + service14 := service6.ProvideService(fileStoreManager, pluginService) oauthtokentestService := oauthtokentest.ProvideService() ossCachingService := caching.ProvideCachingService() middlewareHandler, err := pluginsintegration.ProvideClientWithMiddlewares(cfg, inMemory, oauthtokentestService, tracingService, ossCachingService, featureToggles, registerer) @@ -1078,11 +1086,11 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { datasourcePermissionsService := ossaccesscontrol.ProvideDatasourcePermissionsService(cfg, featureToggles, sqlStore) requestConfigProvider := pluginconfig.NewRequestConfigProvider(pluginInstanceCfg) baseProvider := plugincontext.ProvideBaseService(cfg, requestConfigProvider) - service14, err := service7.ProvideService(sqlStore, secretsService, secretsKVStore, cfg, featureToggles, accessControl, datasourcePermissionsService, quotaService, pluginstoreService, middlewareHandler, baseProvider) + service15, err := service7.ProvideService(sqlStore, secretsService, secretsKVStore, cfg, featureToggles, accessControl, datasourcePermissionsService, quotaService, pluginstoreService, middlewareHandler, baseProvider) if err != nil { return nil, err } - correlationsService, err := correlations.ProvideService(sqlStore, routeRegisterImpl, service14, accessControl, inProcBus, quotaService, cfg) + correlationsService, err := correlations.ProvideService(sqlStore, routeRegisterImpl, service15, accessControl, inProcBus, quotaService, cfg) if err != nil { return nil, err } @@ -1099,7 +1107,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { if err != nil { return nil, err } - provisioningServiceImpl, err := provisioning.ProvideService(accessControl, cfg, sqlStore, pluginstoreService, dBstore, serviceService, notificationService, dashboardProvisioningService, service14, correlationsService, dashboardService, folderimplService, service12, searchService, quotaService, secretsService, orgService, receiverPermissionsService, tracingService, dualwriteService) + provisioningServiceImpl, err := provisioning.ProvideService(accessControl, cfg, sqlStore, pluginstoreService, dBstore, serviceService, notificationService, dashboardProvisioningService, service15, correlationsService, dashboardService, folderimplService, service13, searchService, quotaService, secretsService, orgService, receiverPermissionsService, tracingService, dualwriteService) if err != nil { return nil, err } @@ -1109,10 +1117,10 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { loginStore := authinfoimpl.ProvideStore(sqlStore, secretsService) authinfoimplService := authinfoimpl.ProvideService(loginStore, remoteCache, secretsService) oauthtokenService := oauthtoken.ProvideService(socialService, authinfoimplService, cfg, registerer, serverLockService, tracingService, userAuthTokenService, featureToggles) - dataSourceProxyService := datasourceproxy.ProvideService(cacheServiceImpl, ossDataSourceRequestValidator, pluginstoreService, cfg, httpclientProvider, oauthtokenService, service14, tracingService, secretsService, featureToggles) + dataSourceProxyService := datasourceproxy.ProvideService(cacheServiceImpl, ossDataSourceRequestValidator, pluginstoreService, cfg, httpclientProvider, oauthtokenService, service15, tracingService, secretsService, featureToggles) starService := starimpl.ProvideService(sqlStore) searchSearchService := search2.ProvideService(cfg, sqlStore, starService, dashboardService, folderimplService, featureToggles, sortService) - plugincontextProvider := plugincontext.ProvideService(cfg, cacheService, pluginstoreService, cacheServiceImpl, service14, service12, requestConfigProvider) + plugincontextProvider := plugincontext.ProvideService(cfg, cacheService, pluginstoreService, cacheServiceImpl, service15, service13, requestConfigProvider) exprService := expr.ProvideService(cfg, middlewareHandler, plugincontextProvider, featureToggles, registerer, tracingService) queryServiceImpl := query.ProvideService(cfg, cacheServiceImpl, exprService, ossDataSourceRequestValidator, middlewareHandler, plugincontextProvider) repositoryImpl := annotationsimpl.ProvideService(sqlStore, cfg, featureToggles, tagimplService, tracingService, dBstore, dashboardService, registerer) @@ -1127,7 +1135,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { logger := loggermw.Provide(cfg, featureToggles) notificationServiceMock := notifications.MockNotificationService() ngAlert := metrics2.ProvideServiceForTest() - alertNG, err := ngalert.ProvideService(cfg, featureToggles, cacheServiceImpl, service14, routeRegisterImpl, sqlStore, kvStore, exprService, dataSourceProxyService, quotaService, secretsService, notificationServiceMock, ngAlert, folderimplService, accessControl, dashboardService, renderingService, inProcBus, acimplService, repositoryImpl, pluginstoreService, tracingService, dBstore, httpclientProvider, plugincontextProvider, receiverPermissionsService, userService) + alertNG, err := ngalert.ProvideService(cfg, featureToggles, cacheServiceImpl, service15, routeRegisterImpl, sqlStore, kvStore, exprService, dataSourceProxyService, quotaService, secretsService, notificationServiceMock, ngAlert, folderimplService, accessControl, dashboardService, renderingService, inProcBus, acimplService, repositoryImpl, pluginstoreService, tracingService, dBstore, httpclientProvider, plugincontextProvider, receiverPermissionsService, userService) if err != nil { return nil, err } @@ -1164,7 +1172,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { csrfCSRF := csrf.ProvideCSRFFilter(cfg) playlistService := playlistimpl.ProvideService(sqlStore, tracingService) secretsMigrator := migrator.ProvideSecretsMigrator(serviceService, secretsService, sqlStore, ossImpl, featureToggles) - dataSourceSecretMigrationService := migrations2.ProvideDataSourceMigrationService(service14, kvStore, featureToggles) + dataSourceSecretMigrationService := migrations2.ProvideDataSourceMigrationService(service15, kvStore, featureToggles) secretMigrationProviderImpl := migrations2.ProvideSecretMigrationProvider(serverLockService, dataSourceSecretMigrationService) publicDashboardServiceImpl := service3.ProvideService(cfg, featureToggles, publicDashboardStoreImpl, queryServiceImpl, repositoryImpl, accessControl, publicDashboardServiceWrapperImpl, dashboardService, ossLicensingService) middleware := api2.ProvideMiddleware() @@ -1175,7 +1183,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { return nil, err } authnService := authnimpl.ProvideAuthnService(authnimplService) - navtreeService := navtreeimpl.ProvideService(cfg, accessControl, pluginstoreService, service12, starService, featureToggles, dashboardService, acimplService, kvStore, apikeyService, ossLicensingService, authnService) + navtreeService := navtreeimpl.ProvideService(cfg, accessControl, pluginstoreService, service13, starService, featureToggles, dashboardService, acimplService, kvStore, apikeyService, ossLicensingService, authnService) searchHTTPService := searchV2.ProvideSearchHTTPService(searchService) statsService := statsimpl.ProvideService(cfg, sqlStore, dashboardService, folderimplService, orgService, featureToggles) gatherer := metrics.ProvideGathererForTest(registerer) @@ -1192,7 +1200,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { } idimplService := idimpl.ProvideService(cfg, localSigner, remoteCache, authnService, registerer, tracer) verifier := userimpl.ProvideVerifier(cfg, userService, tempuserService, notificationServiceMock, idimplService) - httpServer, err := api.ProvideHTTPServer(apiOpts, cfg, routeRegisterImpl, inProcBus, renderingService, ossLicensingService, hooksService, cacheService, sqlStore, ossDataSourceRequestValidator, pluginstoreService, service13, pluginstoreService, middlewareHandler, pluginerrsStore, pluginInstaller, ossImpl, cacheServiceImpl, userAuthTokenService, cleanUpService, shortURLService, queryHistoryService, correlationsService, remoteCache, provisioningServiceImpl, accessControl, dataSourceProxyService, searchSearchService, grafanaLive, gateway, plugincontextProvider, contexthandlerContextHandler, logger, featureToggles, alertNG, libraryPanelService, libraryElementService, quotaService, socialService, tracingService, serviceService, grafanaService, pluginsService, ossService, service14, queryServiceImpl, filestoreService, serviceAccountsProxy, pluginassetsService, authinfoimplService, storageService, notificationServiceMock, dashboardService, dashboardProvisioningService, folderimplService, ossProvider, serviceImpl, service12, avatarCacheServer, prefService, folderPermissionsService, dashboardPermissionsService, dashverService, starService, csrfCSRF, noop, playlistService, apikeyService, kvStore, secretsMigrator, secretsService, secretMigrationProviderImpl, secretsKVStore, apiApi, userService, tempuserService, loginattemptimplService, orgService, deletionService, teamService, acimplService, navtreeService, repositoryImpl, tagimplService, searchHTTPService, oauthtokentestService, statsService, authnService, pluginscdnService, gatherer, apiAPI, registerer, eventualRestConfigProvider, anonDeviceService, verifier, preinstallImpl) + httpServer, err := api.ProvideHTTPServer(apiOpts, cfg, routeRegisterImpl, inProcBus, renderingService, ossLicensingService, hooksService, cacheService, sqlStore, ossDataSourceRequestValidator, pluginstoreService, service14, pluginstoreService, middlewareHandler, pluginerrsStore, pluginInstaller, ossImpl, cacheServiceImpl, userAuthTokenService, cleanUpService, shortURLService, queryHistoryService, correlationsService, remoteCache, provisioningServiceImpl, accessControl, dataSourceProxyService, searchSearchService, grafanaLive, gateway, plugincontextProvider, contexthandlerContextHandler, logger, featureToggles, alertNG, libraryPanelService, libraryElementService, quotaService, socialService, tracingService, serviceService, grafanaService, pluginsService, ossService, service15, queryServiceImpl, filestoreService, serviceAccountsProxy, pluginassetsService, authinfoimplService, storageService, notificationServiceMock, dashboardService, dashboardProvisioningService, folderimplService, ossProvider, serviceImpl, service13, avatarCacheServer, prefService, folderPermissionsService, dashboardPermissionsService, dashverService, starService, csrfCSRF, noop, playlistService, apikeyService, kvStore, secretsMigrator, secretsService, secretMigrationProviderImpl, secretsKVStore, apiApi, userService, tempuserService, loginattemptimplService, orgService, deletionService, teamService, acimplService, navtreeService, repositoryImpl, tagimplService, searchHTTPService, oauthtokentestService, statsService, authnService, pluginscdnService, gatherer, apiAPI, registerer, eventualRestConfigProvider, anonDeviceService, verifier, preinstallImpl) if err != nil { return nil, err } @@ -1205,12 +1213,12 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { if err != nil { return nil, err } - statscollectorService := statscollector.ProvideService(usageStats, validatorService, statsService, cfg, sqlStore, socialService, pluginstoreService, featureManager, service14, httpclientProvider, sandboxService, advisorService) + statscollectorService := statscollector.ProvideService(usageStats, validatorService, statsService, cfg, sqlStore, socialService, pluginstoreService, featureManager, service15, httpclientProvider, sandboxService, advisorService) internalMetricsService, err := metrics.ProvideService(cfg, registerer, gatherer) if err != nil { return nil, err } - supportbundlesimplService, err := supportbundlesimpl.ProvideService(accessControl, acimplService, bundleregistryService, cfg, featureToggles, httpServer, kvStore, service12, pluginstoreService, routeRegisterImpl, ossImpl, sqlStore, usageStats, tracingService) + supportbundlesimplService, err := supportbundlesimpl.ProvideService(accessControl, acimplService, bundleregistryService, cfg, featureToggles, httpServer, kvStore, service13, pluginstoreService, routeRegisterImpl, ossImpl, sqlStore, usageStats, tracingService) if err != nil { return nil, err } @@ -1218,7 +1226,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { if err != nil { return nil, err } - scopedPluginDatasourceProvider := datasource.ProvideDefaultPluginConfigs(service14, cacheServiceImpl, plugincontextProvider) + scopedPluginDatasourceProvider := datasource.ProvideDefaultPluginConfigs(service15, cacheServiceImpl, plugincontextProvider) v := builder.ProvideDefaultBuildHandlerChainFuncFromBuilders() aggregatorRunner := aggregatorrunner.ProvideNoopAggregatorConfigurator() apiserverService, err := apiserver.ProvideService(cfg, featureToggles, routeRegisterImpl, tracingService, serverLockService, sqlStore, kvStore, middlewareHandler, scopedPluginDatasourceProvider, plugincontextProvider, pluginstoreService, dualwriteService, resourceClient, eventualRestConfigProvider, v, eventualRestConfigProvider, registerer, aggregatorRunner) @@ -1236,15 +1244,15 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { zanzanaReconciler := dualwrite2.ProvideZanzanaReconciler(cfg, featureToggles, client, sqlStore, serverLockService, folderimplService) playlistAppProvider := playlist.RegisterApp(playlistService, cfg, featureToggles) investigationsAppProvider := investigations.RegisterApp(cfg) - checkregistryService := checkregistry.ProvideService(service14, pluginstoreService, plugincontextProvider, middlewareHandler, plugincheckerService, repoManager, preinstallImpl, noop, provisionedpluginsNoop, ssosettingsimplService, cfg, pluginerrsStore) + checkregistryService := checkregistry.ProvideService(service15, pluginstoreService, plugincontextProvider, middlewareHandler, plugincheckerService, repoManager, preinstallImpl, noop, provisionedpluginsNoop, ssosettingsimplService, cfg, pluginerrsStore) advisorAppProvider := advisor2.RegisterApp(checkregistryService, cfg) alertingNotificationsAppProvider := notifications2.RegisterApp(cfg, alertNG) appregistryService, err := appregistry.ProvideRegistryServiceSink(apiserverService, eventualRestConfigProvider, featureToggles, playlistAppProvider, investigationsAppProvider, advisorAppProvider, alertingNotificationsAppProvider, cfg) if err != nil { return nil, err } - importDashboardService := service9.ProvideService(routeRegisterImpl, quotaService, service13, pluginstoreService, libraryPanelService, dashboardService, accessControl, folderimplService, featureToggles) - dashboardUpdater := service6.ProvideDashboardUpdater(inProcBus, pluginstoreService, service13, importDashboardService, service12, pluginService, dashboardService) + importDashboardService := service9.ProvideService(routeRegisterImpl, quotaService, service14, pluginstoreService, libraryPanelService, dashboardService, accessControl, folderimplService, featureToggles) + dashboardUpdater := service6.ProvideDashboardUpdater(inProcBus, pluginstoreService, service14, importDashboardService, service13, pluginService, dashboardService) sanitizerProvider := sanitizer.ProvideService(renderingService) healthService, err := grpcserver.ProvideHealthService(cfg, grpcserverProvider) if err != nil { @@ -1258,7 +1266,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { identitySynchronizer := authnimpl.ProvideIdentitySynchronizer(authnimplService) ldapImpl := service10.ProvideService(cfg, featureToggles, ssosettingsimplService) apiService := api4.ProvideService(cfg, routeRegisterImpl, accessControl, userService, authinfoimplService, ossGroups, identitySynchronizer, orgService, ldapImpl, userAuthTokenService, bundleregistryService) - dashboardsAPIBuilder := dashboard.RegisterAPIService(cfg, featureToggles, apiserverService, dashboardService, dashboardProvisioningService, service14, dashboardServiceImpl, accessControl, accessClient, provisioningServiceImpl, dashboardsStore, registerer, sqlStore, tracingService, resourceClient, dualwriteService, sortService, quotaService, dashboardFolderStoreImpl, libraryPanelService, eventualRestConfigProvider, userService) + dashboardsAPIBuilder := dashboard.RegisterAPIService(cfg, featureToggles, apiserverService, dashboardService, dashboardProvisioningService, service15, dashboardServiceImpl, accessControl, accessClient, provisioningServiceImpl, dashboardsStore, registerer, sqlStore, tracingService, resourceClient, dualwriteService, sortService, quotaService, dashboardFolderStoreImpl, libraryPanelService, eventualRestConfigProvider, userService) snapshotsAPIBuilder := dashboardsnapshot.RegisterAPIService(serviceImpl, apiserverService, cfg, featureToggles, sqlStore, registerer) featureFlagAPIBuilder := featuretoggle.RegisterAPIService(featureManager, accessControl, apiserverService, cfg, registerer) dataSourceAPIBuilder, err := datasource.RegisterAPIService(featureToggles, apiserverService, middlewareHandler, scopedPluginDatasourceProvider, plugincontextProvider, pluginstoreService, accessControl, registerer) @@ -1271,8 +1279,8 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { if err != nil { return nil, err } - legacyDataSourceLookup := service7.ProvideLegacyDataSourceLookup(service14) - queryAPIBuilder, err := query2.RegisterAPIService(featureToggles, apiserverService, service14, pluginstoreService, accessControl, middlewareHandler, plugincontextProvider, registerer, tracingService, legacyDataSourceLookup) + legacyDataSourceLookup := service7.ProvideLegacyDataSourceLookup(service15) + queryAPIBuilder, err := query2.RegisterAPIService(featureToggles, apiserverService, service15, pluginstoreService, accessControl, middlewareHandler, plugincontextProvider, registerer, tracingService, legacyDataSourceLookup) if err != nil { return nil, err } @@ -1296,8 +1304,15 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { if err != nil { return nil, err } - providerMap := encryption2.ProvideThirdPartyProviderMap() - encryptionManager, err := manager4.ProvideEncryptionManager(tracer, dataKeyStorage, cfg, usageStats, providerMap) + cipher, err := service11.ProvideAESGCMCipherService(tracer, usageStats) + if err != nil { + return nil, err + } + providerConfig, err := kmsproviders.ProvideOSSKMSProviders(cfg, cipher) + if err != nil { + return nil, err + } + encryptionManager, err := manager4.ProvideEncryptionManager(tracer, dataKeyStorage, usageStats, cipher, providerConfig) if err != nil { return nil, err } @@ -1305,7 +1320,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { if err != nil { return nil, err } - secureValueService := service11.ProvideSecureValueService(tracer, accessClient, databaseDatabase, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService) + secureValueService := service12.ProvideSecureValueService(tracer, accessClient, databaseDatabase, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService) decryptAllowList := decrypt.ProvideDecryptAllowList() decryptAuthorizer := decrypt.ProvideDecryptAuthorizer(tracer, decryptAllowList) decryptStorage, err := metadata.ProvideDecryptStorage(featureToggles, tracer, ossKeeperService, keeperMetadataStorage, secureValueMetadataStorage, decryptAuthorizer, registerer) @@ -1335,7 +1350,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { return nil, err } teamAPI := teamapi.ProvideTeamAPI(routeRegisterImpl, teamService, acimplService, accessControl, teamPermissionsService, userService, ossLicensingService, cfg, prefService, dashboardService, featureToggles) - cloudmigrationService, err := cloudmigrationimpl.ProvideService(cfg, httpclientProvider, featureToggles, sqlStore, service14, secretsKVStore, secretsService, routeRegisterImpl, registerer, tracingService, dashboardService, folderimplService, pluginstoreService, service12, accessControl, acimplService, kvStore, libraryElementService, alertNG) + cloudmigrationService, err := cloudmigrationimpl.ProvideService(cfg, httpclientProvider, featureToggles, sqlStore, service15, secretsKVStore, secretsService, routeRegisterImpl, registerer, tracingService, dashboardService, folderimplService, pluginstoreService, service13, accessControl, acimplService, kvStore, libraryElementService, alertNG) if err != nil { return nil, err } @@ -1500,7 +1515,7 @@ var withOTelSet = wire.NewSet( otelTracer, grpcserver.ProvideService, interceptors.ProvideAuthenticator, ) -var wireBasicSet = wire.NewSet(annotationsimpl.ProvideService, wire.Bind(new(annotations.Repository), new(*annotationsimpl.RepositoryImpl)), New, api.ProvideHTTPServer, query.ProvideService, wire.Bind(new(query.Service), new(*query.ServiceImpl)), bus.ProvideBus, wire.Bind(new(bus.Bus), new(*bus.InProcBus)), rendering.ProvideService, wire.Bind(new(rendering.Service), new(*rendering.RenderingService)), routing.ProvideRegister, wire.Bind(new(routing.RouteRegister), new(*routing.RouteRegisterImpl)), hooks.ProvideService, kvstore.ProvideService, localcache.ProvideService, bundleregistry.ProvideService, wire.Bind(new(supportbundles.Service), new(*bundleregistry.Service)), updatemanager.ProvideGrafanaService, updatemanager.ProvidePluginsService, service.ProvideService, wire.Bind(new(usagestats.Service), new(*service.UsageStats)), validator2.ProvideService, legacy.ProvideLegacyMigrator, pluginsintegration.WireSet, dashboards.ProvideFileStoreManager, wire.Bind(new(dashboards.FileStore), new(*dashboards.FileStoreManager)), cloudwatch.ProvideService, cloudmonitoring.ProvideService, azuremonitor.ProvideService, postgres.ProvideService, mysql.ProvideService, mssql.ProvideService, store.ProvideEntityEventsService, dualwrite.ProvideService, httpclientprovider.New, wire.Bind(new(httpclient.Provider), new(*httpclient2.Provider)), serverlock.ProvideService, annotationsimpl.ProvideCleanupService, wire.Bind(new(annotations.Cleaner), new(*annotationsimpl.CleanupServiceImpl)), cleanup.ProvideService, shorturlimpl.ProvideService, wire.Bind(new(shorturls.Service), new(*shorturlimpl.ShortURLService)), queryhistory.ProvideService, wire.Bind(new(queryhistory.Service), new(*queryhistory.QueryHistoryService)), correlations.ProvideService, wire.Bind(new(correlations.Service), new(*correlations.CorrelationsService)), quotaimpl.ProvideService, remotecache.ProvideService, wire.Bind(new(remotecache.CacheStorage), new(*remotecache.RemoteCache)), authinfoimpl.ProvideService, wire.Bind(new(login.AuthInfoService), new(*authinfoimpl.Service)), authinfoimpl.ProvideStore, datasourceproxy.ProvideService, sort.ProvideService, search2.ProvideService, searchV2.ProvideService, searchV2.ProvideSearchHTTPService, store.ProvideService, store.ProvideSystemUsersService, live.ProvideService, pushhttp.ProvideService, contexthandler.ProvideService, service10.ProvideService, wire.Bind(new(service10.LDAP), new(*service10.LDAPImpl)), jwt.ProvideService, wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), store2.ProvideDBStore, image.ProvideDeleteExpiredService, ngalert.ProvideService, librarypanels.ProvideService, wire.Bind(new(librarypanels.Service), new(*librarypanels.LibraryPanelService)), libraryelements.ProvideService, wire.Bind(new(libraryelements.Service), new(*libraryelements.LibraryElementService)), notifications.ProvideService, notifications.ProvideSmtpService, github.ProvideFactory, tracing.ProvideService, tracing.ProvideTracingConfig, wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)), withOTelSet, testdatasource.ProvideService, api4.ProvideService, opentsdb.ProvideService, socialimpl.ProvideService, influxdb.ProvideService, wire.Bind(new(social.Service), new(*socialimpl.SocialService)), tempo.ProvideService, loki.ProvideService, graphite.ProvideService, prometheus.ProvideService, elasticsearch.ProvideService, pyroscope.ProvideService, parca.ProvideService, zipkin.ProvideService, jaeger.ProvideService, service7.ProvideCacheService, wire.Bind(new(datasources.CacheService), new(*service7.CacheServiceImpl)), service2.ProvideEncryptionService, wire.Bind(new(encryption3.Internal), new(*service2.Service)), manager.ProvideSecretsService, wire.Bind(new(secrets2.Service), new(*manager.SecretsService)), database.ProvideSecretsStore, wire.Bind(new(secrets2.Store), new(*database.SecretsStoreImpl)), grafanads.ProvideService, wire.Bind(new(dashboardsnapshots.Store), new(*database4.DashboardSnapshotStore)), database4.ProvideStore, wire.Bind(new(dashboardsnapshots.Service), new(*service8.ServiceImpl)), service8.ProvideService, service7.ProvideService, wire.Bind(new(datasources.DataSourceService), new(*service7.Service)), service7.ProvideLegacyDataSourceLookup, retriever.ProvideService, wire.Bind(new(serviceaccounts.ServiceAccountRetriever), new(*retriever.Service)), ossaccesscontrol.ProvideServiceAccountPermissions, wire.Bind(new(accesscontrol.ServiceAccountPermissionsService), new(*ossaccesscontrol.ServiceAccountPermissionsService)), manager2.ProvideServiceAccountsService, proxy.ProvideServiceAccountsProxy, wire.Bind(new(serviceaccounts.Service), new(*proxy.ServiceAccountsProxy)), expr.ProvideService, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, service5.ProvideDashboardServiceImpl, wire.Bind(new(dashboards2.PermissionsRegistrationService), new(*service5.DashboardServiceImpl)), service5.ProvideDashboardService, service5.ProvideDashboardProvisioningService, service5.ProvideDashboardPluginService, database2.ProvideDashboardStore, folderimpl.ProvideService, wire.Bind(new(folder.Service), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), folderimpl.ProvideDashboardFolderStore, wire.Bind(new(folder.FolderStore), new(*folderimpl.DashboardFolderStoreImpl)), service9.ProvideService, wire.Bind(new(dashboardimport.Service), new(*service9.ImportDashboardService)), service6.ProvideService, wire.Bind(new(plugindashboards.Service), new(*service6.Service)), service6.ProvideDashboardUpdater, sanitizer.ProvideService, kvstore2.ProvideService, avatar.ProvideAvatarCacheServer, statscollector.ProvideService, csrf.ProvideCSRFFilter, wire.Bind(new(csrf.Service), new(*csrf.CSRF)), ossaccesscontrol.ProvideTeamPermissions, wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)), ossaccesscontrol.ProvideFolderPermissions, wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)), ossaccesscontrol.ProvideDashboardPermissions, wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)), ossaccesscontrol.ProvideReceiverPermissionsService, wire.Bind(new(accesscontrol.ReceiverPermissionsService), new(*ossaccesscontrol.ReceiverPermissionsService)), starimpl.ProvideService, playlistimpl.ProvideService, apikeyimpl.ProvideService, dashverimpl.ProvideService, service3.ProvideService, wire.Bind(new(publicdashboards.Service), new(*service3.PublicDashboardServiceImpl)), database3.ProvideStore, wire.Bind(new(publicdashboards.Store), new(*database3.PublicDashboardStoreImpl)), metric.ProvideService, api2.ProvideApi, api3.ProvideApi, userimpl.ProvideService, orgimpl.ProvideService, orgimpl.ProvideDeletionService, statsimpl.ProvideService, grpccontext.ProvideContextHandler, grpcserver.ProvideHealthService, grpcserver.ProvideReflectionService, resolver.ProvideEntityReferenceResolver, teamimpl.ProvideService, teamapi.ProvideTeamAPI, tempuserimpl.ProvideService, loginattemptimpl.ProvideService, wire.Bind(new(loginattempt.Service), new(*loginattemptimpl.Service)), migrations2.ProvideDataSourceMigrationService, migrations2.ProvideSecretMigrationProvider, wire.Bind(new(migrations2.SecretMigrationProvider), new(*migrations2.SecretMigrationProviderImpl)), resourcepermissions.NewActionSetService, wire.Bind(new(accesscontrol.ActionResolver), new(resourcepermissions.ActionSetService)), wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)), permreg.ProvidePermissionRegistry, acimpl.ProvideAccessControl, dualwrite2.ProvideZanzanaReconciler, navtreeimpl.ProvideService, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), wire.Bind(new(notifications.TempUserStore), new(tempuser.Service)), tagimpl.ProvideService, wire.Bind(new(tag.Service), new(*tagimpl.Service)), authnimpl.ProvideService, authnimpl.ProvideIdentitySynchronizer, authnimpl.ProvideAuthnService, authnimpl.ProvideAuthnServiceAuthenticateOnly, authnimpl.ProvideRegistration, supportbundlesimpl.ProvideService, extsvcaccounts.ProvideExtSvcAccountsService, wire.Bind(new(serviceaccounts.ExtSvcAccountsService), new(*extsvcaccounts.ExtSvcAccountsService)), registry2.ProvideExtSvcRegistry, wire.Bind(new(extsvcauth.ExternalServiceRegistry), new(*registry2.Registry)), anonstore.ProvideAnonDBStore, wire.Bind(new(anonstore.AnonStore), new(*anonstore.AnonDBStore)), loggermw.Provide, slogadapter.Provide, signingkeysimpl.ProvideEmbeddedSigningKeysService, wire.Bind(new(signingkeys.Service), new(*signingkeysimpl.Service)), ssosettingsimpl.ProvideService, wire.Bind(new(ssosettings.Service), new(*ssosettingsimpl.Service)), idimpl.ProvideService, wire.Bind(new(auth.IDService), new(*idimpl.Service)), cloudmigrationimpl.ProvideService, userimpl.ProvideVerifier, connectors.ProvideOrgRoleMapper, wire.Bind(new(user.Verifier), new(*userimpl.Verifier)), authz.WireSet, metadata.ProvideSecureValueMetadataStorage, metadata.ProvideKeeperMetadataStorage, metadata.ProvideDecryptStorage, decrypt.ProvideDecryptAuthorizer, decrypt.ProvideDecryptAllowList, decrypt.ProvideDecryptService, encryption.ProvideDataKeyStorage, encryption.ProvideEncryptedValueStorage, service11.ProvideSecureValueService, validator3.ProvideKeeperValidator, validator3.ProvideSecureValueValidator, migrator2.NewWithEngine, database5.ProvideDatabase, wire.Bind(new(contracts.Database), new(*database5.Database)), manager4.ProvideEncryptionManager, encryption2.ProvideThirdPartyProviderMap, resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, apiserver.WireSet, apiregistry.WireSet, appregistry.WireSet) +var wireBasicSet = wire.NewSet(annotationsimpl.ProvideService, wire.Bind(new(annotations.Repository), new(*annotationsimpl.RepositoryImpl)), New, api.ProvideHTTPServer, query.ProvideService, wire.Bind(new(query.Service), new(*query.ServiceImpl)), bus.ProvideBus, wire.Bind(new(bus.Bus), new(*bus.InProcBus)), rendering.ProvideService, wire.Bind(new(rendering.Service), new(*rendering.RenderingService)), routing.ProvideRegister, wire.Bind(new(routing.RouteRegister), new(*routing.RouteRegisterImpl)), hooks.ProvideService, kvstore.ProvideService, localcache.ProvideService, bundleregistry.ProvideService, wire.Bind(new(supportbundles.Service), new(*bundleregistry.Service)), updatemanager.ProvideGrafanaService, updatemanager.ProvidePluginsService, service.ProvideService, wire.Bind(new(usagestats.Service), new(*service.UsageStats)), validator2.ProvideService, legacy.ProvideLegacyMigrator, pluginsintegration.WireSet, dashboards.ProvideFileStoreManager, wire.Bind(new(dashboards.FileStore), new(*dashboards.FileStoreManager)), cloudwatch.ProvideService, cloudmonitoring.ProvideService, azuremonitor.ProvideService, postgres.ProvideService, mysql.ProvideService, mssql.ProvideService, store.ProvideEntityEventsService, dualwrite.ProvideService, httpclientprovider.New, wire.Bind(new(httpclient.Provider), new(*httpclient2.Provider)), serverlock.ProvideService, annotationsimpl.ProvideCleanupService, wire.Bind(new(annotations.Cleaner), new(*annotationsimpl.CleanupServiceImpl)), cleanup.ProvideService, shorturlimpl.ProvideService, wire.Bind(new(shorturls.Service), new(*shorturlimpl.ShortURLService)), queryhistory.ProvideService, wire.Bind(new(queryhistory.Service), new(*queryhistory.QueryHistoryService)), correlations.ProvideService, wire.Bind(new(correlations.Service), new(*correlations.CorrelationsService)), quotaimpl.ProvideService, remotecache.ProvideService, wire.Bind(new(remotecache.CacheStorage), new(*remotecache.RemoteCache)), authinfoimpl.ProvideService, wire.Bind(new(login.AuthInfoService), new(*authinfoimpl.Service)), authinfoimpl.ProvideStore, datasourceproxy.ProvideService, sort.ProvideService, search2.ProvideService, searchV2.ProvideService, searchV2.ProvideSearchHTTPService, store.ProvideService, store.ProvideSystemUsersService, live.ProvideService, pushhttp.ProvideService, contexthandler.ProvideService, service10.ProvideService, wire.Bind(new(service10.LDAP), new(*service10.LDAPImpl)), jwt.ProvideService, wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), store2.ProvideDBStore, image.ProvideDeleteExpiredService, ngalert.ProvideService, librarypanels.ProvideService, wire.Bind(new(librarypanels.Service), new(*librarypanels.LibraryPanelService)), libraryelements.ProvideService, wire.Bind(new(libraryelements.Service), new(*libraryelements.LibraryElementService)), notifications.ProvideService, notifications.ProvideSmtpService, github.ProvideFactory, tracing.ProvideService, tracing.ProvideTracingConfig, wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)), withOTelSet, testdatasource.ProvideService, api4.ProvideService, opentsdb.ProvideService, socialimpl.ProvideService, influxdb.ProvideService, wire.Bind(new(social.Service), new(*socialimpl.SocialService)), tempo.ProvideService, loki.ProvideService, graphite.ProvideService, prometheus.ProvideService, elasticsearch.ProvideService, pyroscope.ProvideService, parca.ProvideService, zipkin.ProvideService, jaeger.ProvideService, service7.ProvideCacheService, wire.Bind(new(datasources.CacheService), new(*service7.CacheServiceImpl)), service2.ProvideEncryptionService, wire.Bind(new(encryption2.Internal), new(*service2.Service)), manager.ProvideSecretsService, wire.Bind(new(secrets2.Service), new(*manager.SecretsService)), database.ProvideSecretsStore, wire.Bind(new(secrets2.Store), new(*database.SecretsStoreImpl)), grafanads.ProvideService, wire.Bind(new(dashboardsnapshots.Store), new(*database4.DashboardSnapshotStore)), database4.ProvideStore, wire.Bind(new(dashboardsnapshots.Service), new(*service8.ServiceImpl)), service8.ProvideService, service7.ProvideService, wire.Bind(new(datasources.DataSourceService), new(*service7.Service)), service7.ProvideLegacyDataSourceLookup, retriever.ProvideService, wire.Bind(new(serviceaccounts.ServiceAccountRetriever), new(*retriever.Service)), ossaccesscontrol.ProvideServiceAccountPermissions, wire.Bind(new(accesscontrol.ServiceAccountPermissionsService), new(*ossaccesscontrol.ServiceAccountPermissionsService)), manager2.ProvideServiceAccountsService, proxy.ProvideServiceAccountsProxy, wire.Bind(new(serviceaccounts.Service), new(*proxy.ServiceAccountsProxy)), expr.ProvideService, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, service5.ProvideDashboardServiceImpl, wire.Bind(new(dashboards2.PermissionsRegistrationService), new(*service5.DashboardServiceImpl)), service5.ProvideDashboardService, service5.ProvideDashboardProvisioningService, service5.ProvideDashboardPluginService, database2.ProvideDashboardStore, folderimpl.ProvideService, wire.Bind(new(folder.Service), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), folderimpl.ProvideDashboardFolderStore, wire.Bind(new(folder.FolderStore), new(*folderimpl.DashboardFolderStoreImpl)), service9.ProvideService, wire.Bind(new(dashboardimport.Service), new(*service9.ImportDashboardService)), service6.ProvideService, wire.Bind(new(plugindashboards.Service), new(*service6.Service)), service6.ProvideDashboardUpdater, sanitizer.ProvideService, kvstore2.ProvideService, avatar.ProvideAvatarCacheServer, statscollector.ProvideService, csrf.ProvideCSRFFilter, wire.Bind(new(csrf.Service), new(*csrf.CSRF)), ossaccesscontrol.ProvideTeamPermissions, wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)), ossaccesscontrol.ProvideFolderPermissions, wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)), ossaccesscontrol.ProvideDashboardPermissions, wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)), ossaccesscontrol.ProvideReceiverPermissionsService, wire.Bind(new(accesscontrol.ReceiverPermissionsService), new(*ossaccesscontrol.ReceiverPermissionsService)), starimpl.ProvideService, playlistimpl.ProvideService, apikeyimpl.ProvideService, dashverimpl.ProvideService, service3.ProvideService, wire.Bind(new(publicdashboards.Service), new(*service3.PublicDashboardServiceImpl)), database3.ProvideStore, wire.Bind(new(publicdashboards.Store), new(*database3.PublicDashboardStoreImpl)), metric.ProvideService, api2.ProvideApi, api3.ProvideApi, userimpl.ProvideService, orgimpl.ProvideService, orgimpl.ProvideDeletionService, statsimpl.ProvideService, grpccontext.ProvideContextHandler, grpcserver.ProvideHealthService, grpcserver.ProvideReflectionService, resolver.ProvideEntityReferenceResolver, teamimpl.ProvideService, teamapi.ProvideTeamAPI, tempuserimpl.ProvideService, loginattemptimpl.ProvideService, wire.Bind(new(loginattempt.Service), new(*loginattemptimpl.Service)), migrations2.ProvideDataSourceMigrationService, migrations2.ProvideSecretMigrationProvider, wire.Bind(new(migrations2.SecretMigrationProvider), new(*migrations2.SecretMigrationProviderImpl)), resourcepermissions.NewActionSetService, wire.Bind(new(accesscontrol.ActionResolver), new(resourcepermissions.ActionSetService)), wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)), permreg.ProvidePermissionRegistry, acimpl.ProvideAccessControl, dualwrite2.ProvideZanzanaReconciler, navtreeimpl.ProvideService, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), wire.Bind(new(notifications.TempUserStore), new(tempuser.Service)), tagimpl.ProvideService, wire.Bind(new(tag.Service), new(*tagimpl.Service)), authnimpl.ProvideService, authnimpl.ProvideIdentitySynchronizer, authnimpl.ProvideAuthnService, authnimpl.ProvideAuthnServiceAuthenticateOnly, authnimpl.ProvideRegistration, supportbundlesimpl.ProvideService, extsvcaccounts.ProvideExtSvcAccountsService, wire.Bind(new(serviceaccounts.ExtSvcAccountsService), new(*extsvcaccounts.ExtSvcAccountsService)), registry2.ProvideExtSvcRegistry, wire.Bind(new(extsvcauth.ExternalServiceRegistry), new(*registry2.Registry)), anonstore.ProvideAnonDBStore, wire.Bind(new(anonstore.AnonStore), new(*anonstore.AnonDBStore)), loggermw.Provide, slogadapter.Provide, signingkeysimpl.ProvideEmbeddedSigningKeysService, wire.Bind(new(signingkeys.Service), new(*signingkeysimpl.Service)), ssosettingsimpl.ProvideService, wire.Bind(new(ssosettings.Service), new(*ssosettingsimpl.Service)), idimpl.ProvideService, wire.Bind(new(auth.IDService), new(*idimpl.Service)), cloudmigrationimpl.ProvideService, userimpl.ProvideVerifier, connectors.ProvideOrgRoleMapper, wire.Bind(new(user.Verifier), new(*userimpl.Verifier)), authz.WireSet, metadata.ProvideSecureValueMetadataStorage, metadata.ProvideKeeperMetadataStorage, metadata.ProvideDecryptStorage, decrypt.ProvideDecryptAuthorizer, decrypt.ProvideDecryptAllowList, decrypt.ProvideDecryptService, encryption.ProvideDataKeyStorage, encryption.ProvideEncryptedValueStorage, service12.ProvideSecureValueService, validator3.ProvideKeeperValidator, validator3.ProvideSecureValueValidator, migrator2.NewWithEngine, database5.ProvideDatabase, wire.Bind(new(contracts.Database), new(*database5.Database)), manager4.ProvideEncryptionManager, service11.ProvideAESGCMCipherService, resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, apiserver.WireSet, apiregistry.WireSet, appregistry.WireSet) var wireSet = wire.NewSet( wireBasicSet, metrics.WireSet, sqlstore.ProvideService, metrics2.ProvideService, wire.Bind(new(notifications.Service), new(*notifications.NotificationService)), wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationService)), wire.Bind(new(notifications.EmailSender), new(*notifications.NotificationService)), wire.Bind(new(db.DB), new(*sqlstore.SQLStore)), prefimpl.ProvideService, oauthtoken.ProvideService, wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)), wire.Bind(new(cleanup.AlertRuleService), new(*store2.DBstore)), diff --git a/pkg/server/wireexts_oss.go b/pkg/server/wireexts_oss.go index 3361fb7c8db..8f083ace438 100644 --- a/pkg/server/wireexts_oss.go +++ b/pkg/server/wireexts_oss.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana/pkg/registry" apisregistry "github.com/grafana/grafana/pkg/registry/apis" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" + gsmKMSProviders "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/kmsproviders" "github.com/grafana/grafana/pkg/registry/apis/secret/secretkeeper" "github.com/grafana/grafana/pkg/registry/backgroundsvcs" "github.com/grafana/grafana/pkg/registry/usagestatssvcs" @@ -130,6 +131,7 @@ var wireExtsBasicSet = wire.NewSet( builder.ProvideDefaultBuildHandlerChainFuncFromBuilders, aggregatorrunner.ProvideNoopAggregatorConfigurator, apisregistry.WireSetExts, + gsmKMSProviders.ProvideOSSKMSProviders, ) var wireExtsSet = wire.NewSet( diff --git a/pkg/setting/setting_secrets_manager.go b/pkg/setting/setting_secrets_manager.go index f8a3b186e53..b855307635f 100644 --- a/pkg/setting/setting_secrets_manager.go +++ b/pkg/setting/setting_secrets_manager.go @@ -1,22 +1,37 @@ package setting import ( - "regexp" + "strings" +) - "github.com/grafana/grafana/pkg/services/kmsproviders" +const ( + ProviderPrefix = "secrets_manager.encryption." + MisconfiguredProvider = "misconfigured" ) type SecretsManagerSettings struct { - SecretKey string - EncryptionProvider string - AvailableProviders []string + CurrentEncryptionProvider string + + // ConfiguredKMSProviders is a map of KMS providers found in the config file. The keys are in the format of ., and the values are a map of the properties in that section + // In OSS, the provider type can only be "secret_key". In Enterprise, it can additionally be one of: "aws_kms", "azure_keyvault", "google_kms", "hashicorp_vault" + ConfiguredKMSProviders map[string]map[string]string } func (cfg *Cfg) readSecretsManagerSettings() { secretsMgmt := cfg.Raw.Section("secrets_manager") - cfg.SecretsManagement.EncryptionProvider = secretsMgmt.Key("encryption_provider").MustString(kmsproviders.Default) + cfg.SecretsManagement.CurrentEncryptionProvider = secretsMgmt.Key("encryption_provider").MustString(MisconfiguredProvider) - // TODO: These are not used yet by the secrets manager because we need to distentagle the dependencies with OSS. - cfg.SecretsManagement.SecretKey = secretsMgmt.Key("secret_key").MustString("") - cfg.SecretsManagement.AvailableProviders = regexp.MustCompile(`\s*,\s*`).Split(secretsMgmt.Key("available_encryption_providers").MustString(""), -1) // parse comma separated list + // Extract available KMS providers from configuration sections + providers := make(map[string]map[string]string) + for _, section := range cfg.Raw.Sections() { + sectionName := section.Name() + if strings.HasPrefix(sectionName, ProviderPrefix) { + // Extract the provider name (everything after the prefix) + providerName := strings.TrimPrefix(sectionName, ProviderPrefix) + if providerName != "" { + providers[providerName] = section.KeysHash() + } + } + } + cfg.SecretsManagement.ConfiguredKMSProviders = providers } diff --git a/pkg/setting/setting_secrets_manager_test.go b/pkg/setting/setting_secrets_manager_test.go new file mode 100644 index 00000000000..324acbe27ad --- /dev/null +++ b/pkg/setting/setting_secrets_manager_test.go @@ -0,0 +1,173 @@ +package setting + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestReadSecretsManagerSettings(t *testing.T) { + t.Run("should parse basic encryption provider", func(t *testing.T) { + iniContent := ` +[secrets_manager] +encryption_provider = aws_kms +` + cfg, err := NewCfgFromBytes([]byte(iniContent)) + require.NoError(t, err) + + assert.Equal(t, "aws_kms", cfg.SecretsManagement.CurrentEncryptionProvider) + assert.Empty(t, cfg.SecretsManagement.ConfiguredKMSProviders) + }) + + t.Run("should parse single KMS provider configuration", func(t *testing.T) { + iniContent := ` +[secrets_manager] +encryption_provider = aws_kms.v1 + +[secrets_manager.encryption.aws_kms.v1] +region = us-east-1 +key_id = arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012 +` + cfg, err := NewCfgFromBytes([]byte(iniContent)) + require.NoError(t, err) + + assert.Equal(t, "aws_kms.v1", cfg.SecretsManagement.CurrentEncryptionProvider) + assert.Len(t, cfg.SecretsManagement.ConfiguredKMSProviders, 1) + + awsProvider := cfg.SecretsManagement.ConfiguredKMSProviders["aws_kms.v1"] + assert.Equal(t, "us-east-1", awsProvider["region"]) + assert.Equal(t, "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", awsProvider["key_id"]) + }) + + t.Run("should parse multiple KMS providers", func(t *testing.T) { + iniContent := ` +[secrets_manager] +encryption_provider = aws_kms.v1 + +[secrets_manager.encryption.aws_kms.v1] +region = us-east-1 +key_id = arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012 + +[secrets_manager.encryption.azure_kv.v1] +vault_url = https://myvault.vault.azure.net/ +key_name = mykey +tenant_id = 12345678-1234-1234-1234-123456789012 + +[secrets_manager.encryption.secret_key.v1] +key = my-secret-key +` + cfg, err := NewCfgFromBytes([]byte(iniContent)) + require.NoError(t, err) + + assert.Equal(t, "aws_kms.v1", cfg.SecretsManagement.CurrentEncryptionProvider) + assert.Len(t, cfg.SecretsManagement.ConfiguredKMSProviders, 3) + + // Check AWS KMS provider + awsProvider := cfg.SecretsManagement.ConfiguredKMSProviders["aws_kms.v1"] + assert.Equal(t, "us-east-1", awsProvider["region"]) + assert.Equal(t, "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", awsProvider["key_id"]) + + // Check Azure Key Vault provider + azureProvider := cfg.SecretsManagement.ConfiguredKMSProviders["azure_kv.v1"] + assert.Equal(t, "https://myvault.vault.azure.net/", azureProvider["vault_url"]) + assert.Equal(t, "mykey", azureProvider["key_name"]) + assert.Equal(t, "12345678-1234-1234-1234-123456789012", azureProvider["tenant_id"]) + + // Check secret key provider + secretProvider := cfg.SecretsManagement.ConfiguredKMSProviders["secret_key.v1"] + assert.Equal(t, "my-secret-key", secretProvider["key"]) + }) + + t.Run("should default to misconfigured provider when no encryption_provider is set", func(t *testing.T) { + iniContent := ` +[secrets_manager] +# no encryption_provider setting +` + cfg, err := NewCfgFromBytes([]byte(iniContent)) + require.NoError(t, err) + + assert.Equal(t, MisconfiguredProvider, cfg.SecretsManagement.CurrentEncryptionProvider) + }) + + t.Run("should handle empty sections gracefully", func(t *testing.T) { + iniContent := ` +[secrets_manager] +encryption_provider = empty_provider + +[secrets_manager.encryption.empty_provider] +# empty section +` + cfg, err := NewCfgFromBytes([]byte(iniContent)) + require.NoError(t, err) + + assert.Equal(t, "empty_provider", cfg.SecretsManagement.CurrentEncryptionProvider) + assert.Len(t, cfg.SecretsManagement.ConfiguredKMSProviders, 1) + + emptyProvider := cfg.SecretsManagement.ConfiguredKMSProviders["empty_provider"] + assert.NotNil(t, emptyProvider) + assert.Empty(t, emptyProvider) + }) + + t.Run("should ignore sections that don't match provider prefix", func(t *testing.T) { + iniContent := ` +[secrets_manager] +encryption_provider = aws_kms.v1 + +[secrets_manager.encryption.valid_provider] +key = value + +[secrets_manager.other_section] +setting = value + +[completely_different_section] +some_setting = some_value +` + cfg, err := NewCfgFromBytes([]byte(iniContent)) + require.NoError(t, err) + + assert.Equal(t, "aws_kms.v1", cfg.SecretsManagement.CurrentEncryptionProvider) + assert.Len(t, cfg.SecretsManagement.ConfiguredKMSProviders, 1) + + validProvider := cfg.SecretsManagement.ConfiguredKMSProviders["valid_provider"] + assert.Equal(t, "value", validProvider["key"]) + }) + + t.Run("should handle provider names with special characters", func(t *testing.T) { + iniContent := ` +[secrets_manager] +encryption_provider = aws_kms.v1 + +[secrets_manager.encryption.aws_kms.v1] +region = us-west-2 +key_id = test-key + +[secrets_manager.encryption.azure_kv.v1] +vault_url = https://test.vault.azure.net/ +` + cfg, err := NewCfgFromBytes([]byte(iniContent)) + require.NoError(t, err) + + assert.Equal(t, "aws_kms.v1", cfg.SecretsManagement.CurrentEncryptionProvider) + assert.Len(t, cfg.SecretsManagement.ConfiguredKMSProviders, 2) + + awsProvider := cfg.SecretsManagement.ConfiguredKMSProviders["aws_kms.v1"] + assert.Equal(t, "us-west-2", awsProvider["region"]) + assert.Equal(t, "test-key", awsProvider["key_id"]) + + azureProvider := cfg.SecretsManagement.ConfiguredKMSProviders["azure_kv.v1"] + assert.Equal(t, "https://test.vault.azure.net/", azureProvider["vault_url"]) + }) + + t.Run("should handle configuration with no secrets_manager section", func(t *testing.T) { + iniContent := ` +[server] +domain = example.com +` + cfg, err := NewCfgFromBytes([]byte(iniContent)) + require.NoError(t, err) + + assert.Equal(t, MisconfiguredProvider, cfg.SecretsManagement.CurrentEncryptionProvider) + assert.Empty(t, cfg.SecretsManagement.ConfiguredKMSProviders) + }) +}