Encryption: Cleanup and add logging (#42084)

* Encryption: Add more logs

* Add logging and checks

* Removed unused methods from secrets service

* Refactor and update tests

* Address review feedback
pull/42204/head^2
Tania B 4 years ago committed by GitHub
parent 06e474dfd5
commit 4014891971
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      pkg/expr/service_test.go
  2. 6
      pkg/services/secrets/database/database.go
  3. 24
      pkg/services/secrets/manager/manager.go
  4. 82
      pkg/services/secrets/manager/manager_test.go

@ -13,10 +13,8 @@ import (
"github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
"github.com/grafana/grafana/pkg/services/kmsproviders/osskmsproviders"
"github.com/grafana/grafana/pkg/services/secrets/fakes" "github.com/grafana/grafana/pkg/services/secrets/fakes"
"github.com/grafana/grafana/pkg/services/secrets/manager" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -31,16 +29,8 @@ func TestService(t *testing.T) {
} }
cfg := setting.NewCfg() cfg := setting.NewCfg()
encr := ossencryption.ProvideService()
settings := setting.ProvideProvider(cfg) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
secretsService, err := manager.ProvideSecretsService(
fakes.NewFakeSecretsStore(),
osskmsproviders.ProvideService(encr, settings),
encr,
settings,
)
require.NoError(t, err)
s := Service{ s := Service{
cfg: cfg, cfg: cfg,

@ -13,15 +13,15 @@ import (
const dataKeysTable = "data_keys" const dataKeysTable = "data_keys"
var logger = log.New("secrets-store")
type SecretsStoreImpl struct { type SecretsStoreImpl struct {
sqlStore *sqlstore.SQLStore sqlStore *sqlstore.SQLStore
log log.Logger
} }
func ProvideSecretsStore(sqlStore *sqlstore.SQLStore) *SecretsStoreImpl { func ProvideSecretsStore(sqlStore *sqlstore.SQLStore) *SecretsStoreImpl {
return &SecretsStoreImpl{ return &SecretsStoreImpl{
sqlStore: sqlStore, sqlStore: sqlStore,
log: log.New("secrets.store"),
} }
} }
@ -42,7 +42,7 @@ func (ss *SecretsStoreImpl) GetDataKey(ctx context.Context, name string) (*secre
} }
if err != nil { if err != nil {
logger.Error("Failed getting data key", "err", err, "name", name) ss.log.Error("Failed to get data key", "err", err, "name", name)
return nil, fmt.Errorf("failed getting data key: %w", err) return nil, fmt.Errorf("failed getting data key: %w", err)
} }

@ -9,6 +9,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/encryption" "github.com/grafana/grafana/pkg/services/encryption"
"github.com/grafana/grafana/pkg/services/kmsproviders" "github.com/grafana/grafana/pkg/services/kmsproviders"
"github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/services/secrets"
@ -24,6 +25,7 @@ type SecretsService struct {
currentProvider string currentProvider string
providers map[string]secrets.Provider providers map[string]secrets.Provider
dataKeyCache map[string]dataKeyCacheItem dataKeyCache map[string]dataKeyCacheItem
log log.Logger
} }
func ProvideSecretsService( func ProvideSecretsService(
@ -37,8 +39,20 @@ func ProvideSecretsService(
return nil, err return nil, err
} }
logger := log.New("secrets")
enabled := settings.IsFeatureToggleEnabled(secrets.EnvelopeEncryptionFeatureToggle)
currentProvider := settings.KeyValue("security", "encryption_provider").MustString(kmsproviders.Default) currentProvider := settings.KeyValue("security", "encryption_provider").MustString(kmsproviders.Default)
if _, ok := providers[currentProvider]; enabled && !ok {
return nil, fmt.Errorf("missing configuration for current encryption provider %s", currentProvider)
}
if !enabled && currentProvider != kmsproviders.Default {
logger.Warn("Changing encryption provider requires enabling envelope encryption feature")
}
logger.Debug("Envelope encryption state", "enabled", enabled, "current provider", currentProvider)
s := &SecretsService{ s := &SecretsService{
store: store, store: store,
enc: enc, enc: enc,
@ -46,6 +60,7 @@ func ProvideSecretsService(
providers: providers, providers: providers,
currentProvider: currentProvider, currentProvider: currentProvider,
dataKeyCache: make(map[string]dataKeyCacheItem), dataKeyCache: make(map[string]dataKeyCacheItem),
log: logger,
} }
return s, nil return s, nil
@ -133,6 +148,7 @@ func (s *SecretsService) Decrypt(ctx context.Context, payload []byte) ([]byte, e
dataKey, err = s.dataKey(ctx, string(key)) dataKey, err = s.dataKey(ctx, string(key))
if err != nil { if err != nil {
s.log.Error("Failed to lookup data key", "name", string(key), "error", err)
return nil, err return nil, err
} }
} }
@ -274,14 +290,6 @@ func (s *SecretsService) dataKey(ctx context.Context, name string) ([]byte, erro
return decrypted, nil return decrypted, nil
} }
func (s *SecretsService) RegisterProvider(providerID string, provider secrets.Provider) {
s.providers[providerID] = provider
}
func (s *SecretsService) CurrentProviderID() string {
return s.currentProvider
}
func (s *SecretsService) GetProviders() map[string]secrets.Provider { func (s *SecretsService) GetProviders() map[string]secrets.Provider {
return s.providers return s.providers
} }

@ -152,76 +152,56 @@ func TestSecretsService_UseCurrentProvider(t *testing.T) {
assert.Equal(t, "secretKey", svc.currentProvider) assert.Equal(t, "secretKey", svc.currentProvider)
}) })
t.Run("When encryption_provider value is set, should use it as a current provider", func(t *testing.T) { t.Run("Should use encrypt/decrypt methods of the current encryption provider", func(t *testing.T) {
rawCfg := `[security]
secret_key = sdDkslslld
encryption_provider = awskms.second_key`
raw, err := ini.Load([]byte(rawCfg))
require.NoError(t, err)
cfg := &setting.Cfg{Raw: raw, FeatureToggles: map[string]bool{secrets.EnvelopeEncryptionFeatureToggle: true}}
settings := &setting.OSSImpl{Cfg: cfg}
encr := ossencryption.ProvideService()
svc, err := ProvideSecretsService(
database.ProvideSecretsStore(sqlstore.InitTestDB(t)),
osskmsproviders.ProvideService(encr, settings),
encr,
settings,
)
require.NoError(t, err)
assert.Equal(t, "awskms.second_key", svc.currentProvider)
})
t.Run("Should use encrypt/decrypt methods of the current provider", func(t *testing.T) {
rawCfg := ` rawCfg := `
[security] [security]
secret_key = sdDkslslld secret_key = sdDkslslld
encryption_provider = fake-provider.some-key encryption_provider = fakeProvider.v1
available_encryption_providers = fakeProvider.v1
[security.encryption.fake-provider.some-key] [security.encryption.fakeProvider.v1]
` `
raw, err := ini.Load([]byte(rawCfg)) raw, err := ini.Load([]byte(rawCfg))
require.NoError(t, err) require.NoError(t, err)
cfg := &setting.Cfg{Raw: raw, FeatureToggles: map[string]bool{secrets.EnvelopeEncryptionFeatureToggle: true}} providerID := "fakeProvider.v1"
settings := &setting.OSSImpl{Cfg: cfg} settings := &setting.OSSImpl{
Cfg: &setting.Cfg{
Raw: raw,
FeatureToggles: map[string]bool{secrets.EnvelopeEncryptionFeatureToggle: true},
},
}
encr := ossencryption.ProvideService()
kms := newFakeKMS(osskmsproviders.ProvideService(encr, settings))
secretStore := database.ProvideSecretsStore(sqlstore.InitTestDB(t)) secretStore := database.ProvideSecretsStore(sqlstore.InitTestDB(t))
fake := fakeProvider{}
providerID := "fake-provider.some-key"
encr := ossencryption.ProvideService()
svcEncrypt, err := ProvideSecretsService( svcEncrypt, err := ProvideSecretsService(
secretStore, secretStore,
osskmsproviders.ProvideService(encr, settings), &kms,
encr, encr,
settings, settings,
) )
require.NoError(t, err) require.NoError(t, err)
svcEncrypt.RegisterProvider(providerID, &fake) assert.Equal(t, providerID, svcEncrypt.currentProvider)
require.NoError(t, err)
assert.Equal(t, providerID, svcEncrypt.CurrentProviderID())
assert.Equal(t, 2, len(svcEncrypt.GetProviders())) assert.Equal(t, 2, len(svcEncrypt.GetProviders()))
encrypted, _ := svcEncrypt.Encrypt(context.Background(), []byte{}, secrets.WithoutScope()) encrypted, _ := svcEncrypt.Encrypt(context.Background(), []byte{}, secrets.WithoutScope())
assert.True(t, fake.encryptCalled) assert.True(t, kms.fake.encryptCalled)
// secret service tries to find a DEK in a cache first before calling provider's decrypt // secret service tries to find a DEK in a cache first before calling provider's decrypt
// to bypass the cache, we set up one more secrets service to test decrypting // to bypass the cache, we set up one more secrets service to test decrypting
svcDecrypt, err := ProvideSecretsService( svcDecrypt, err := ProvideSecretsService(
secretStore, secretStore,
osskmsproviders.ProvideService(encr, settings), &kms,
encr, encr,
settings, settings,
) )
require.NoError(t, err) require.NoError(t, err)
svcDecrypt.RegisterProvider(providerID, &fake)
_, _ = svcDecrypt.Decrypt(context.Background(), encrypted) _, _ = svcDecrypt.Decrypt(context.Background(), encrypted)
assert.True(t, fake.decryptCalled, "fake provider's decrypt should be called") assert.True(t, kms.fake.decryptCalled, "fake provider's decrypt should be called")
}) })
} }
@ -239,3 +219,25 @@ func (p *fakeProvider) Decrypt(_ context.Context, _ []byte) ([]byte, error) {
p.decryptCalled = true p.decryptCalled = true
return []byte{}, nil return []byte{}, nil
} }
type fakeKMS struct {
kms osskmsproviders.Service
fake *fakeProvider
}
func newFakeKMS(kms osskmsproviders.Service) fakeKMS {
return fakeKMS{
kms: kms,
fake: &fakeProvider{},
}
}
func (f *fakeKMS) Provide() (map[string]secrets.Provider, error) {
providers, err := f.kms.Provide()
if err != nil {
return providers, err
}
providers["fakeProvider.v1"] = f.fake
return providers, nil
}

Loading…
Cancel
Save