mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
committed by
GitHub
parent
a71b4f13e4
commit
9abe9fa702
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user