SSO: Fix secrets migration for LDAP in SSO settings (#94252)

fix secrets migration for LDAP in SSO settings
This commit is contained in:
Mihai Doarna
2024-10-04 18:18:53 +03:00
committed by GitHub
parent 6eeef432de
commit 82a5913dfa
2 changed files with 83 additions and 41 deletions

View File

@ -7,6 +7,7 @@ import (
"fmt"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/services/encryption"
"github.com/grafana/grafana/pkg/services/ngalert/notifier"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/secrets/manager"
@ -308,26 +309,10 @@ func (s ssoSettingsSecret) ReEncrypt(ctx context.Context, secretsSrv *manager.Se
for _, result := range results {
err := sqlStore.InTransaction(ctx, func(ctx context.Context) error {
for field, value := range result.Settings {
if ssosettingsimpl.IsSecretField(field) {
decrypted, err := s.decryptValue(ctx, value, secretsSrv)
if err != nil {
logger.Warn("Could not decrypt SSO settings secret", "id", result.ID, "field", field, "error", err)
return err
}
if decrypted == nil {
continue
}
reencrypted, err := secretsSrv.Encrypt(ctx, decrypted, secrets.WithoutScope())
if err != nil {
logger.Warn("Could not re-encrypt SSO settings secret", "id", result.ID, "field", field, "error", err)
return err
}
result.Settings[field] = base64.RawStdEncoding.EncodeToString(reencrypted)
}
result.Settings, err = s.reEncryptSecretsInMap(ctx, result.Settings, secretsSrv, nil, "")
if err != nil {
logger.Warn("failed re-encrypting SSO settings secret", "id", result.ID, "error", err)
return err
}
err = sqlStore.WithDbSession(ctx, func(sess *db.Session) error {
@ -378,3 +363,77 @@ func (s ssoSettingsSecret) decryptValue(ctx context.Context, value any, secretsS
return decrypted, nil
}
func (s ssoSettingsSecret) reEncryptSecretsInMap(ctx context.Context, m map[string]any, secretsSrv *manager.SecretsService, encryptionSrv encryption.Internal, secretKey string) (map[string]any, error) {
var err error
result := make(map[string]any)
for k, v := range m {
switch v := v.(type) {
case string:
result[k] = v
if ssosettingsimpl.IsSecretField(k) {
decrypted, err := s.decryptValue(ctx, v, secretsSrv)
if err != nil {
logger.Warn("Could not decrypt SSO settings secret", "field", k, "error", err)
return nil, err
}
if decrypted == nil {
continue
}
var reencrypted []byte
if encryptionSrv == nil {
reencrypted, err = secretsSrv.Encrypt(ctx, decrypted, secrets.WithoutScope())
} else {
reencrypted, err = encryptionSrv.Encrypt(ctx, decrypted, secretKey)
}
if err != nil {
logger.Warn("Could not re-encrypt SSO settings secret", "id", "field", k, "error", err)
return nil, err
}
result[k] = base64.RawStdEncoding.EncodeToString(reencrypted)
}
case []any:
result[k], err = s.reEncryptSecretsInSlice(ctx, v, secretsSrv, encryptionSrv, secretKey)
if err != nil {
return nil, err
}
case map[string]any:
result[k], err = s.reEncryptSecretsInMap(ctx, v, secretsSrv, encryptionSrv, secretKey)
if err != nil {
return nil, err
}
default:
result[k] = v
}
}
return result, nil
}
func (s ssoSettingsSecret) reEncryptSecretsInSlice(ctx context.Context, a []any, secretsSrv *manager.SecretsService, encryptionSrv encryption.Internal, secretKey string) ([]any, error) {
result := make([]any, 0)
for _, v := range a {
switch v := v.(type) {
case []any:
inner, err := s.reEncryptSecretsInSlice(ctx, v, secretsSrv, encryptionSrv, secretKey)
if err != nil {
return nil, err
}
result = append(result, inner)
case map[string]any:
inner, err := s.reEncryptSecretsInMap(ctx, v, secretsSrv, encryptionSrv, secretKey)
if err != nil {
return nil, err
}
result = append(result, inner)
default:
result = append(result, v)
}
}
return result, nil
}

View File

@ -11,7 +11,6 @@ import (
"github.com/grafana/grafana/pkg/services/ngalert/notifier"
"github.com/grafana/grafana/pkg/services/secrets/manager"
"github.com/grafana/grafana/pkg/services/ssosettings/models"
"github.com/grafana/grafana/pkg/services/ssosettings/ssosettingsimpl"
)
func (s simpleSecret) Rollback(
@ -317,26 +316,10 @@ func (s ssoSettingsSecret) Rollback(
for _, result := range results {
err := sqlStore.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
for field, value := range result.Settings {
if ssosettingsimpl.IsSecretField(field) {
decrypted, err := s.decryptValue(ctx, value, secretsSrv)
if err != nil {
logger.Warn("Could not decrypt SSO settings secret", "id", result.ID, "field", field, "error", err)
return err
}
if decrypted == nil {
continue
}
reencrypted, err := encryptionSrv.Encrypt(ctx, decrypted, secretKey)
if err != nil {
logger.Warn("Could not re-encrypt SSO settings secret", "id", result.ID, "field", field, "error", err)
return err
}
result.Settings[field] = base64.RawStdEncoding.EncodeToString(reencrypted)
}
result.Settings, err = s.reEncryptSecretsInMap(ctx, result.Settings, secretsSrv, encryptionSrv, secretKey)
if err != nil {
logger.Warn("failed rolling back SSO settings secret", "id", result.ID, "error", err)
return err
}
err = sqlStore.WithDbSession(ctx, func(sess *db.Session) error {