Encryption: Expose secrets migrations through HTTP API (#51707)

* Encryption: Move secrets migrations into secrets.Migrator

* Encryption: Refactor secrets.Service initialization

* Encryption: Add support to run secrets migrations even when EE is disabled

* Encryption: Expose secrets migrations through HTTP API

* Update docs

* Fix docs links

* Some adjustments to makes errors explicit through HTTP response
This commit is contained in:
Joan López de la Franca Beltran
2022-07-18 08:57:58 +02:00
committed by GitHub
parent a71b4f13e4
commit 9abe9fa702
8 changed files with 168 additions and 45 deletions

View File

@@ -37,14 +37,14 @@ func ProvideSecretsMigrator(
}
}
func (m *SecretsMigrator) ReEncryptSecrets(ctx context.Context) error {
func (m *SecretsMigrator) ReEncryptSecrets(ctx context.Context) (bool, error) {
err := m.initProvidersIfNeeded()
if err != nil {
return err
return false, err
}
toReencrypt := []interface {
reencrypt(context.Context, *manager.SecretsService, *sqlstore.SQLStore)
reencrypt(context.Context, *manager.SecretsService, *sqlstore.SQLStore) bool
}{
simpleSecret{tableName: "dashboard_snapshot", columnName: "dashboard_encrypted"},
b64Secret{simpleSecret: simpleSecret{tableName: "user_auth", columnName: "o_auth_access_token"}, encoding: base64.StdEncoding},
@@ -56,30 +56,21 @@ func (m *SecretsMigrator) ReEncryptSecrets(ctx context.Context) error {
alertingSecret{},
}
var anyFailure bool
for _, r := range toReencrypt {
r.reencrypt(ctx, m.secretsSrv, m.sqlStore)
}
return nil
}
func (m *SecretsMigrator) initProvidersIfNeeded() error {
if m.features.IsEnabled(featuremgmt.FlagDisableEnvelopeEncryption) {
logger.Info("Envelope encryption is not enabled but trying to init providers anyway...")
if err := m.secretsSrv.InitProviders(); err != nil {
logger.Error("Envelope encryption providers initialization failed", "error", err)
return err
if success := r.reencrypt(ctx, m.secretsSrv, m.sqlStore); !success {
anyFailure = true
}
}
return nil
return !anyFailure, nil
}
func (m *SecretsMigrator) RollBackSecrets(ctx context.Context) error {
func (m *SecretsMigrator) RollBackSecrets(ctx context.Context) (bool, error) {
err := m.initProvidersIfNeeded()
if err != nil {
return err
return false, err
}
toRollback := []interface {
@@ -110,11 +101,26 @@ func (m *SecretsMigrator) RollBackSecrets(ctx context.Context) error {
if anyFailure {
logger.Warn("Some errors happened, not cleaning up data keys table...")
return nil
return false, nil
}
if _, sqlErr := m.sqlStore.NewSession(ctx).Exec("DELETE FROM data_keys"); sqlErr != nil {
_, sqlErr := m.sqlStore.NewSession(ctx).Exec("DELETE FROM data_keys")
if sqlErr != nil {
logger.Warn("Error while cleaning up data keys table...", "error", sqlErr)
return false, nil
}
return true, nil
}
func (m *SecretsMigrator) initProvidersIfNeeded() error {
if m.features.IsEnabled(featuremgmt.FlagDisableEnvelopeEncryption) {
logger.Info("Envelope encryption is not enabled but trying to init providers anyway...")
if err := m.secretsSrv.InitProviders(); err != nil {
logger.Error("Envelope encryption providers initialization failed", "error", err)
return err
}
}
return nil

View File

@@ -12,7 +12,7 @@ import (
"github.com/grafana/grafana/pkg/services/sqlstore"
)
func (s simpleSecret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsService, sqlStore *sqlstore.SQLStore) {
func (s simpleSecret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsService, sqlStore *sqlstore.SQLStore) bool {
var rows []struct {
Id int
Secret []byte
@@ -20,7 +20,7 @@ func (s simpleSecret) reencrypt(ctx context.Context, secretsSrv *manager.Secrets
if err := sqlStore.NewSession(ctx).Table(s.tableName).Select(fmt.Sprintf("id, %s as secret", s.columnName)).Find(&rows); err != nil {
logger.Warn("Could not find any secret to re-encrypt", "table", s.tableName)
return
return false
}
var anyFailure bool
@@ -62,9 +62,11 @@ func (s simpleSecret) reencrypt(ctx context.Context, secretsSrv *manager.Secrets
} else {
logger.Info(fmt.Sprintf("Column %s from %s has been re-encrypted successfully", s.columnName, s.tableName))
}
return !anyFailure
}
func (s b64Secret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsService, sqlStore *sqlstore.SQLStore) {
func (s b64Secret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsService, sqlStore *sqlstore.SQLStore) bool {
var rows []struct {
Id int
Secret string
@@ -72,7 +74,7 @@ func (s b64Secret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsSer
if err := sqlStore.NewSession(ctx).Table(s.tableName).Select(fmt.Sprintf("id, %s as secret", s.columnName)).Find(&rows); err != nil {
logger.Warn("Could not find any secret to re-encrypt", "table", s.tableName)
return
return false
}
var anyFailure bool
@@ -128,9 +130,11 @@ func (s b64Secret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsSer
} else {
logger.Info(fmt.Sprintf("Column %s from %s has been re-encrypted successfully", s.columnName, s.tableName))
}
return !anyFailure
}
func (s jsonSecret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsService, sqlStore *sqlstore.SQLStore) {
func (s jsonSecret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsService, sqlStore *sqlstore.SQLStore) bool {
var rows []struct {
Id int
SecureJsonData map[string][]byte
@@ -138,7 +142,7 @@ func (s jsonSecret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsSe
if err := sqlStore.NewSession(ctx).Table(s.tableName).Cols("id", "secure_json_data").Find(&rows); err != nil {
logger.Warn("Could not find any secret to re-encrypt", "table", s.tableName)
return
return false
}
var anyFailure bool
@@ -184,9 +188,11 @@ func (s jsonSecret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsSe
} else {
logger.Info(fmt.Sprintf("Secure json data secrets from %s have been re-encrypted successfully", s.tableName))
}
return !anyFailure
}
func (s alertingSecret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsService, sqlStore *sqlstore.SQLStore) {
func (s alertingSecret) reencrypt(ctx context.Context, secretsSrv *manager.SecretsService, sqlStore *sqlstore.SQLStore) bool {
var results []struct {
Id int
AlertmanagerConfiguration string
@@ -195,7 +201,7 @@ func (s alertingSecret) reencrypt(ctx context.Context, secretsSrv *manager.Secre
selectSQL := "SELECT id, alertmanager_configuration FROM alert_configuration"
if err := sqlStore.NewSession(ctx).SQL(selectSQL).Find(&results); err != nil {
logger.Warn("Could not find any alert_configuration secret to re-encrypt")
return
return false
}
var anyFailure bool
@@ -261,4 +267,6 @@ func (s alertingSecret) reencrypt(ctx context.Context, secretsSrv *manager.Secre
} else {
logger.Info("Alerting configuration secrets have been re-encrypted successfully")
}
return !anyFailure
}