Secrets: Extract external facing decrypt types to apps (#110432)
This commit is contained in:
@@ -5,30 +5,10 @@ import (
|
||||
"fmt"
|
||||
|
||||
provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
||||
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
|
||||
"github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
)
|
||||
|
||||
// HACK: this interface and struct are used to avoid the dependency on the secret contracts
|
||||
// "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" which creates a circular dependency
|
||||
// between the apps/provisioning and root modules.
|
||||
type DecryptResult struct {
|
||||
Val *secretv1beta1.ExposedSecureValue
|
||||
Err error
|
||||
}
|
||||
|
||||
func (d DecryptResult) Error() error {
|
||||
return d.Err
|
||||
}
|
||||
|
||||
func (d DecryptResult) Value() *secretv1beta1.ExposedSecureValue {
|
||||
return d.Val
|
||||
}
|
||||
|
||||
type DecryptService interface {
|
||||
Decrypt(ctx context.Context, group, namespace string, names ...string) (map[string]DecryptResult, error)
|
||||
}
|
||||
|
||||
type Decrypter = func(r *provisioning.Repository) SecureValues
|
||||
|
||||
type SecureValues interface {
|
||||
@@ -37,7 +17,7 @@ type SecureValues interface {
|
||||
}
|
||||
|
||||
type secureValues struct {
|
||||
svc DecryptService
|
||||
svc decrypt.DecryptService
|
||||
names provisioning.SecureValues
|
||||
namespace string
|
||||
}
|
||||
@@ -72,7 +52,7 @@ func (s *secureValues) WebhookSecret(ctx context.Context) (common.RawSecureValue
|
||||
return s.get(ctx, s.names.WebhookSecret)
|
||||
}
|
||||
|
||||
func ProvideDecrypter(svc DecryptService) Decrypter {
|
||||
func ProvideDecrypter(svc decrypt.DecryptService) Decrypter {
|
||||
return func(r *provisioning.Repository) SecureValues {
|
||||
return &secureValues{svc: svc, names: r.Secure, namespace: r.Namespace}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
||||
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
|
||||
"github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
)
|
||||
|
||||
@@ -34,11 +35,11 @@ func TestRepositorySecureValues(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]DecryptResult, error) {
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]decrypt.DecryptResult, error) {
|
||||
require.Equal(t, []string{"secret"}, names)
|
||||
val := secretv1beta1.NewExposedSecureValue(names[0])
|
||||
return map[string]DecryptResult{
|
||||
names[0]: {Val: &val},
|
||||
return map[string]decrypt.DecryptResult{
|
||||
names[0]: decrypt.NewDecryptResultValue(&val),
|
||||
}, nil
|
||||
},
|
||||
token: expectedDecryptedResult{
|
||||
@@ -54,7 +55,7 @@ func TestRepositorySecureValues(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]DecryptResult, error) {
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]decrypt.DecryptResult, error) {
|
||||
t.Fatal("decrypt should not be called when Create is set")
|
||||
return nil, nil
|
||||
},
|
||||
@@ -67,7 +68,7 @@ func TestRepositorySecureValues(t *testing.T) {
|
||||
config: &provisioning.Repository{
|
||||
Secure: provisioning.SecureValues{},
|
||||
},
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]DecryptResult, error) {
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]decrypt.DecryptResult, error) {
|
||||
t.Fatal("decrypt should not be called when no values are configured")
|
||||
return nil, nil
|
||||
},
|
||||
@@ -81,10 +82,10 @@ func TestRepositorySecureValues(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]DecryptResult, error) {
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]decrypt.DecryptResult, error) {
|
||||
require.Equal(t, []string{"secret"}, names)
|
||||
return map[string]DecryptResult{
|
||||
names[0]: {Err: fmt.Errorf("error for name")},
|
||||
return map[string]decrypt.DecryptResult{
|
||||
names[0]: decrypt.NewDecryptResultErr(fmt.Errorf("error for name")),
|
||||
}, nil
|
||||
},
|
||||
webhook: expectedDecryptedResult{
|
||||
@@ -100,8 +101,8 @@ func TestRepositorySecureValues(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]DecryptResult, error) {
|
||||
return map[string]DecryptResult{}, nil
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]decrypt.DecryptResult, error) {
|
||||
return map[string]decrypt.DecryptResult{}, nil
|
||||
},
|
||||
token: expectedDecryptedResult{
|
||||
error: "not found", // it is not in the results above
|
||||
@@ -116,7 +117,7 @@ func TestRepositorySecureValues(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]DecryptResult, error) {
|
||||
decrypt: func(t *testing.T, names ...string) (map[string]decrypt.DecryptResult, error) {
|
||||
return nil, fmt.Errorf("explode")
|
||||
},
|
||||
webhook: expectedDecryptedResult{
|
||||
@@ -148,13 +149,13 @@ func TestRepositorySecureValues(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type decryptFn = func(t *testing.T, names ...string) (map[string]DecryptResult, error)
|
||||
type decryptFn = func(t *testing.T, names ...string) (map[string]decrypt.DecryptResult, error)
|
||||
|
||||
type dummyDecryptService struct {
|
||||
t *testing.T
|
||||
fn decryptFn
|
||||
}
|
||||
|
||||
func (d *dummyDecryptService) Decrypt(_ context.Context, _ string, _ string, names ...string) (map[string]DecryptResult, error) {
|
||||
func (d *dummyDecryptService) Decrypt(_ context.Context, _ string, _ string, names ...string) (map[string]decrypt.DecryptResult, error) {
|
||||
return d.fn(d.t, names...)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package decrypt
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
|
||||
)
|
||||
|
||||
// DecryptService is the interface for the decrypt service.
|
||||
type DecryptService interface {
|
||||
Decrypt(ctx context.Context, serviceName string, namespace string, names ...string) (map[string]DecryptResult, error)
|
||||
}
|
||||
|
||||
// DecryptResult is the (union) result of a decryption operation.
|
||||
// It contains the decrypted `value` when the decryption succeeds, and the `err` when it fails.
|
||||
// It is not possible to construct a `DecryptResult` where both `value` and `err` are set from another package.
|
||||
type DecryptResult struct {
|
||||
value *secretv1beta1.ExposedSecureValue
|
||||
err error
|
||||
}
|
||||
|
||||
func (d DecryptResult) Error() error {
|
||||
return d.err
|
||||
}
|
||||
|
||||
func (d DecryptResult) Value() *secretv1beta1.ExposedSecureValue {
|
||||
return d.value
|
||||
}
|
||||
|
||||
func NewDecryptResultErr(err error) DecryptResult {
|
||||
return DecryptResult{err: err}
|
||||
}
|
||||
|
||||
func NewDecryptResultValue(value *secretv1beta1.ExposedSecureValue) DecryptResult {
|
||||
return DecryptResult{value: value}
|
||||
}
|
||||
@@ -4,10 +4,9 @@ import (
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/repository"
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/repository/github"
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/repository/local"
|
||||
"github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/provisioning"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/provisioning/secure"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/provisioning/webhooks"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -20,21 +19,17 @@ func ProvideProvisioningOSSExtras(webhook *webhooks.WebhookExtraBuilder) []provi
|
||||
|
||||
func ProvideProvisioningOSSRepositoryExtras(
|
||||
cfg *setting.Cfg,
|
||||
decryptSvc secret.DecryptService,
|
||||
decryptSvc decrypt.DecryptService,
|
||||
ghFactory *github.Factory,
|
||||
webhooksBuilder *webhooks.WebhookExtraBuilder,
|
||||
) []repository.Extra {
|
||||
// HACK: this interface and struct are used to avoid the dependency on the secret contracts
|
||||
// "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" which creates a circular dependency
|
||||
// between the apps/provisioning and root modules.
|
||||
wrapper := secure.ProvideDecryptService(decryptSvc)
|
||||
return []repository.Extra{
|
||||
local.Extra(
|
||||
cfg.HomePath,
|
||||
cfg.PermittedProvisioningPaths,
|
||||
),
|
||||
github.Extra(
|
||||
repository.ProvideDecrypter(wrapper),
|
||||
repository.ProvideDecrypter(decryptSvc),
|
||||
ghFactory,
|
||||
webhooksBuilder,
|
||||
),
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package secure
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/repository"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
)
|
||||
|
||||
// HACK: this interface and struct are used to avoid the dependency on the secret contracts
|
||||
// "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" which creates a circular dependency
|
||||
// between the apps/provisioning and root modules.
|
||||
type wrapper struct {
|
||||
svc contracts.DecryptService
|
||||
}
|
||||
|
||||
func (w *wrapper) Decrypt(ctx context.Context, group, namespace string, names ...string) (map[string]repository.DecryptResult, error) {
|
||||
values, err := w.svc.Decrypt(ctx, group, namespace, names...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
results := make(map[string]repository.DecryptResult, len(values))
|
||||
for k, v := range values {
|
||||
results[k] = repository.DecryptResult{
|
||||
Val: v.Value(),
|
||||
Err: v.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func ProvideDecryptService(svc contracts.DecryptService) repository.DecryptService {
|
||||
return &wrapper{svc: svc}
|
||||
}
|
||||
@@ -26,32 +26,3 @@ type DecryptStorage interface {
|
||||
type DecryptAuthorizer interface {
|
||||
Authorize(ctx context.Context, namespace xkube.Namespace, secureValueName string, secureValueDecrypters []string) (identity string, allowed bool)
|
||||
}
|
||||
|
||||
// DecryptService is the interface for the decrypt service.
|
||||
type DecryptService interface {
|
||||
Decrypt(ctx context.Context, serviceName string, namespace string, names ...string) (map[string]DecryptResult, error)
|
||||
}
|
||||
|
||||
// DecryptResult is the (union) result of a decryption operation.
|
||||
// It contains the decrypted `value` when the decryption succeeds, and the `err` when it fails.
|
||||
// It is not possible to construct a `DecryptResult` where both `value` and `err` are set from another package.
|
||||
type DecryptResult struct {
|
||||
value *secretv1beta1.ExposedSecureValue
|
||||
err error
|
||||
}
|
||||
|
||||
func (d DecryptResult) Error() error {
|
||||
return d.err
|
||||
}
|
||||
|
||||
func (d DecryptResult) Value() *secretv1beta1.ExposedSecureValue {
|
||||
return d.value
|
||||
}
|
||||
|
||||
func NewDecryptResultErr(err error) DecryptResult {
|
||||
return DecryptResult{err: err}
|
||||
}
|
||||
|
||||
func NewDecryptResultValue(value *secretv1beta1.ExposedSecureValue) DecryptResult {
|
||||
return DecryptResult{value: value}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/grafana/authlib/types"
|
||||
decryptv1beta1 "github.com/grafana/grafana/apps/secret/decrypt/v1beta1"
|
||||
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
|
||||
"github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
)
|
||||
|
||||
@@ -30,7 +31,7 @@ type GRPCDecryptClient struct {
|
||||
tokenExchanger authnlib.TokenExchanger
|
||||
}
|
||||
|
||||
var _ contracts.DecryptService = &GRPCDecryptClient{}
|
||||
var _ decrypt.DecryptService = &GRPCDecryptClient{}
|
||||
|
||||
type TLSConfig struct {
|
||||
UseTLS bool
|
||||
@@ -101,7 +102,7 @@ func createTLSCredentials(config TLSConfig) (credentials.TransportCredentials, e
|
||||
}
|
||||
|
||||
// Decrypt a set of secure value names in a given namespace for a specific service name.
|
||||
func (g *GRPCDecryptClient) Decrypt(ctx context.Context, serviceName string, namespace string, names ...string) (map[string]contracts.DecryptResult, error) {
|
||||
func (g *GRPCDecryptClient) Decrypt(ctx context.Context, serviceName string, namespace string, names ...string) (map[string]decrypt.DecryptResult, error) {
|
||||
_, err := types.ParseNamespace(namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -114,7 +115,7 @@ func (g *GRPCDecryptClient) Decrypt(ctx context.Context, serviceName string, nam
|
||||
}
|
||||
}
|
||||
if len(unique) < 1 {
|
||||
return map[string]contracts.DecryptResult{}, nil
|
||||
return map[string]decrypt.DecryptResult{}, nil
|
||||
}
|
||||
|
||||
tokenExchangerInterceptor := authnlib.NewGrpcClientInterceptor(
|
||||
@@ -149,14 +150,14 @@ func (g *GRPCDecryptClient) Decrypt(ctx context.Context, serviceName string, nam
|
||||
return nil, fmt.Errorf("grpc decrypt failed: %w", err)
|
||||
}
|
||||
|
||||
results := make(map[string]contracts.DecryptResult, len(resp.GetDecryptedValues()))
|
||||
results := make(map[string]decrypt.DecryptResult, len(resp.GetDecryptedValues()))
|
||||
|
||||
for name, result := range resp.GetDecryptedValues() {
|
||||
if result.GetErrorMessage() != "" {
|
||||
results[name] = contracts.NewDecryptResultErr(errors.New(result.GetErrorMessage()))
|
||||
results[name] = decrypt.NewDecryptResultErr(errors.New(result.GetErrorMessage()))
|
||||
} else {
|
||||
exposedSecureValue := secretv1beta1.NewExposedSecureValue(result.GetValue())
|
||||
results[name] = contracts.NewDecryptResultValue(&exposedSecureValue)
|
||||
results[name] = decrypt.NewDecryptResultValue(&exposedSecureValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/authlib/types"
|
||||
"github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
||||
@@ -13,7 +14,7 @@ type LocalDecryptClient struct {
|
||||
decryptStorage contracts.DecryptStorage
|
||||
}
|
||||
|
||||
var _ contracts.DecryptService = &LocalDecryptClient{}
|
||||
var _ decrypt.DecryptService = &LocalDecryptClient{}
|
||||
|
||||
func NewLocalDecryptClient(decryptStorage contracts.DecryptStorage) (*LocalDecryptClient, error) {
|
||||
return &LocalDecryptClient{
|
||||
@@ -21,7 +22,7 @@ func NewLocalDecryptClient(decryptStorage contracts.DecryptStorage) (*LocalDecry
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *LocalDecryptClient) Decrypt(ctx context.Context, serviceName, namespace string, names ...string) (map[string]contracts.DecryptResult, error) {
|
||||
func (c *LocalDecryptClient) Decrypt(ctx context.Context, serviceName, namespace string, names ...string) (map[string]decrypt.DecryptResult, error) {
|
||||
ns, err := types.ParseNamespace(namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -29,7 +30,7 @@ func (c *LocalDecryptClient) Decrypt(ctx context.Context, serviceName, namespace
|
||||
|
||||
ctx = identity.WithServiceIdentityContext(ctx, ns.OrgID, identity.WithServiceIdentityName(serviceName))
|
||||
|
||||
results := make(map[string]contracts.DecryptResult, len(names))
|
||||
results := make(map[string]decrypt.DecryptResult, len(names))
|
||||
|
||||
for _, name := range names {
|
||||
_, found := results[name]
|
||||
@@ -38,9 +39,9 @@ func (c *LocalDecryptClient) Decrypt(ctx context.Context, serviceName, namespace
|
||||
}
|
||||
exposedSecureValue, err := c.decryptStorage.Decrypt(ctx, xkube.Namespace(namespace), name)
|
||||
if err != nil {
|
||||
results[name] = contracts.NewDecryptResultErr(err)
|
||||
results[name] = decrypt.NewDecryptResultErr(err)
|
||||
} else {
|
||||
results[name] = contracts.NewDecryptResultValue(&exposedSecureValue)
|
||||
results[name] = decrypt.NewDecryptResultValue(&exposedSecureValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,13 @@ import (
|
||||
authnlib "github.com/grafana/authlib/authn"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
"github.com/grafana/grafana/pkg/services/authn/grpcutils"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func ProvideDecryptService(cfg *setting.Cfg, tracer trace.Tracer, decryptStorage contracts.DecryptStorage) (contracts.DecryptService, error) {
|
||||
func ProvideDecryptService(cfg *setting.Cfg, tracer trace.Tracer, decryptStorage contracts.DecryptStorage) (decrypt.DecryptService, error) {
|
||||
if cfg.SecretsManagement.GrpcClientEnable {
|
||||
grpcClientConfig := grpcutils.ReadGrpcClientConfig(cfg)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
decryptv1beta1 "github.com/grafana/grafana/apps/secret/decrypt/v1beta1"
|
||||
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
|
||||
decryptcontracts "github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
"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/testutils"
|
||||
@@ -39,8 +40,8 @@ func TestDecryptService(t *testing.T) {
|
||||
mockErr := errors.New("mock error")
|
||||
mockStorage := &mockDecryptStorage{}
|
||||
mockStorage.On("Decrypt", mock.Anything, mock.Anything, mock.Anything).Return(secretv1beta1.ExposedSecureValue(""), mockErr)
|
||||
decryptedValuesResp := map[string]contracts.DecryptResult{
|
||||
"secure-value-1": contracts.NewDecryptResultErr(mockErr),
|
||||
decryptedValuesResp := map[string]decryptcontracts.DecryptResult{
|
||||
"secure-value-1": decryptcontracts.NewDecryptResultErr(mockErr),
|
||||
}
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
@@ -66,9 +67,9 @@ func TestDecryptService(t *testing.T) {
|
||||
mockStorage.On("Decrypt", mock.Anything, xkube.Namespace("default"), "secure-value-2").
|
||||
Return(exposedSecureValue2, nil)
|
||||
|
||||
decryptedValuesResp := map[string]contracts.DecryptResult{
|
||||
"secure-value-1": contracts.NewDecryptResultValue(&exposedSecureValue1),
|
||||
"secure-value-2": contracts.NewDecryptResultValue(&exposedSecureValue2),
|
||||
decryptedValuesResp := map[string]decryptcontracts.DecryptResult{
|
||||
"secure-value-1": decryptcontracts.NewDecryptResultValue(&exposedSecureValue1),
|
||||
"secure-value-2": decryptcontracts.NewDecryptResultValue(&exposedSecureValue2),
|
||||
}
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
@@ -93,9 +94,9 @@ func TestDecryptService(t *testing.T) {
|
||||
mockStorage.On("Decrypt", mock.Anything, xkube.Namespace("default"), "secure-value-2").
|
||||
Return(secretv1beta1.ExposedSecureValue(""), mockErr)
|
||||
|
||||
decryptedValuesResp := map[string]contracts.DecryptResult{
|
||||
"secure-value-1": contracts.NewDecryptResultValue(&exposedSecureValue),
|
||||
"secure-value-2": contracts.NewDecryptResultErr(mockErr),
|
||||
decryptedValuesResp := map[string]decryptcontracts.DecryptResult{
|
||||
"secure-value-1": decryptcontracts.NewDecryptResultValue(&exposedSecureValue),
|
||||
"secure-value-2": decryptcontracts.NewDecryptResultErr(mockErr),
|
||||
}
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package secret
|
||||
|
||||
import (
|
||||
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
)
|
||||
|
||||
// DecryptService is a decrypt client for secure value secrets.
|
||||
//
|
||||
//go:generate mockery --name DecryptService --structname MockDecryptService --inpackage --filename decrypt_client_mock.go --with-expecter
|
||||
type DecryptService = contracts.DecryptService
|
||||
|
||||
var (
|
||||
ErrDecryptNotFound = contracts.ErrDecryptNotFound
|
||||
ErrDecryptNotAuthorized = contracts.ErrDecryptNotAuthorized
|
||||
ErrDecryptFailed = contracts.ErrDecryptFailed
|
||||
)
|
||||
|
||||
type DecryptResult = contracts.DecryptResult
|
||||
|
||||
func NewDecryptResultErr(err error) DecryptResult {
|
||||
return contracts.NewDecryptResultErr(err)
|
||||
}
|
||||
|
||||
func NewDecryptResultValue(value *secretv1beta1.ExposedSecureValue) DecryptResult {
|
||||
return contracts.NewDecryptResultValue(value)
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package secret
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
contracts "github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
)
|
||||
|
||||
// MockDecryptService is an autogenerated mock type for the DecryptService type
|
||||
type MockDecryptService struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockDecryptService_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockDecryptService) EXPECT() *MockDecryptService_Expecter {
|
||||
return &MockDecryptService_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Decrypt provides a mock function with given fields: ctx, serviceName, namespace, names
|
||||
func (_m *MockDecryptService) Decrypt(ctx context.Context, serviceName string, namespace string, names ...string) (map[string]contracts.DecryptResult, error) {
|
||||
_va := make([]interface{}, len(names))
|
||||
for _i := range names {
|
||||
_va[_i] = names[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, serviceName, namespace)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Decrypt")
|
||||
}
|
||||
|
||||
var r0 map[string]contracts.DecryptResult
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, ...string) (map[string]contracts.DecryptResult, error)); ok {
|
||||
return rf(ctx, serviceName, namespace, names...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, ...string) map[string]contracts.DecryptResult); ok {
|
||||
r0 = rf(ctx, serviceName, namespace, names...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(map[string]contracts.DecryptResult)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, string, ...string) error); ok {
|
||||
r1 = rf(ctx, serviceName, namespace, names...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockDecryptService_Decrypt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Decrypt'
|
||||
type MockDecryptService_Decrypt_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Decrypt is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - serviceName string
|
||||
// - namespace string
|
||||
// - names ...string
|
||||
func (_e *MockDecryptService_Expecter) Decrypt(ctx interface{}, serviceName interface{}, namespace interface{}, names ...interface{}) *MockDecryptService_Decrypt_Call {
|
||||
return &MockDecryptService_Decrypt_Call{Call: _e.mock.On("Decrypt",
|
||||
append([]interface{}{ctx, serviceName, namespace}, names...)...)}
|
||||
}
|
||||
|
||||
func (_c *MockDecryptService_Decrypt_Call) Run(run func(ctx context.Context, serviceName string, namespace string, names ...string)) *MockDecryptService_Decrypt_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]string, len(args)-3)
|
||||
for i, a := range args[3:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(string)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockDecryptService_Decrypt_Call) Return(_a0 map[string]contracts.DecryptResult, _a1 error) *MockDecryptService_Decrypt_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockDecryptService_Decrypt_Call) RunAndReturn(run func(context.Context, string, string, ...string) (map[string]contracts.DecryptResult, error)) *MockDecryptService_Decrypt_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewMockDecryptService creates a new instance of MockDecryptService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewMockDecryptService(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *MockDecryptService {
|
||||
mock := &MockDecryptService{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
|
||||
decryptcontracts "github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
@@ -162,7 +163,7 @@ type Sut struct {
|
||||
SecureValueService contracts.SecureValueService
|
||||
SecureValueMetadataStorage contracts.SecureValueMetadataStorage
|
||||
DecryptStorage contracts.DecryptStorage
|
||||
DecryptService contracts.DecryptService
|
||||
DecryptService decryptcontracts.DecryptService
|
||||
EncryptedValueStorage contracts.EncryptedValueStorage
|
||||
GlobalEncryptedValueStorage contracts.GlobalEncryptedValueStorage
|
||||
SQLKeeper *sqlkeeper.SQLKeeper
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/repository/github"
|
||||
"github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver"
|
||||
@@ -35,7 +35,7 @@ func ProvideTestEnv(
|
||||
resourceClient resource.ResourceClient,
|
||||
idService auth.IDService,
|
||||
githubFactory *github.Factory,
|
||||
decryptService secret.DecryptService,
|
||||
decryptService decrypt.DecryptService,
|
||||
) (*TestEnv, error) {
|
||||
return &TestEnv{
|
||||
TestingT: testingT,
|
||||
@@ -73,5 +73,5 @@ type TestEnv struct {
|
||||
ResourceClient resource.ResourceClient
|
||||
IDService auth.IDService
|
||||
GitHubFactory *github.Factory
|
||||
DecryptService secret.DecryptService
|
||||
DecryptService decrypt.DecryptService
|
||||
}
|
||||
|
||||
@@ -812,13 +812,13 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v4, err := decrypt.ProvideDecryptService(cfg, tracer, decryptStorage)
|
||||
decryptService, err := decrypt.ProvideDecryptService(cfg, tracer, decryptStorage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
factory := github.ProvideFactory()
|
||||
v5 := extras.ProvideProvisioningOSSRepositoryExtras(cfg, v4, factory, webhookExtraBuilder)
|
||||
repositoryFactory, err := repository.ProvideFactory(v5)
|
||||
v4 := extras.ProvideProvisioningOSSRepositoryExtras(cfg, decryptService, factory, webhookExtraBuilder)
|
||||
repositoryFactory, err := repository.ProvideFactory(v4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1394,13 +1394,13 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v4, err := decrypt.ProvideDecryptService(cfg, tracer, decryptStorage)
|
||||
decryptService, err := decrypt.ProvideDecryptService(cfg, tracer, decryptStorage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
factory := github.ProvideFactory()
|
||||
v5 := extras.ProvideProvisioningOSSRepositoryExtras(cfg, v4, factory, webhookExtraBuilder)
|
||||
repositoryFactory, err := repository.ProvideFactory(v5)
|
||||
v4 := extras.ProvideProvisioningOSSRepositoryExtras(cfg, decryptService, factory, webhookExtraBuilder)
|
||||
repositoryFactory, err := repository.ProvideFactory(v4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1439,7 +1439,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
testEnv, err := ProvideTestEnv(testingT, server, sqlStore, cfg, notificationServiceMock, grpcserverProvider, inMemory, httpclientProvider, oauthtokentestService, featureToggles, resourceClient, idimplService, factory, v4)
|
||||
testEnv, err := ProvideTestEnv(testingT, server, sqlStore, cfg, notificationServiceMock, grpcserverProvider, inMemory, httpclientProvider, oauthtokentestService, featureToggles, resourceClient, idimplService, factory, decryptService)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"pgregory.net/rapid"
|
||||
|
||||
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
|
||||
"github.com/grafana/grafana/apps/secret/pkg/decrypt"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/testutils"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
||||
@@ -111,24 +112,24 @@ func (m *model) list(namespace string) (*secretv1beta1.SecureValueList, error) {
|
||||
return &secretv1beta1.SecureValueList{Items: out}, nil
|
||||
}
|
||||
|
||||
func (m *model) decrypt(decrypter, namespace, name string) (map[string]contracts.DecryptResult, error) {
|
||||
func (m *model) decrypt(decrypter, namespace, name string) (map[string]decrypt.DecryptResult, error) {
|
||||
for _, v := range m.secureValues {
|
||||
if v.Namespace == namespace &&
|
||||
v.Name == name &&
|
||||
v.active {
|
||||
if slices.ContainsFunc(v.Spec.Decrypters, func(d string) bool { return d == decrypter }) {
|
||||
return map[string]contracts.DecryptResult{
|
||||
name: contracts.NewDecryptResultValue(deepCopy(v).Spec.Value),
|
||||
return map[string]decrypt.DecryptResult{
|
||||
name: decrypt.NewDecryptResultValue(deepCopy(v).Spec.Value),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return map[string]contracts.DecryptResult{
|
||||
name: contracts.NewDecryptResultErr(contracts.ErrDecryptNotAuthorized),
|
||||
return map[string]decrypt.DecryptResult{
|
||||
name: decrypt.NewDecryptResultErr(contracts.ErrDecryptNotAuthorized),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
return map[string]contracts.DecryptResult{
|
||||
name: contracts.NewDecryptResultErr(contracts.ErrDecryptNotFound),
|
||||
return map[string]decrypt.DecryptResult{
|
||||
name: decrypt.NewDecryptResultErr(contracts.ErrDecryptNotFound),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user