From d448b514e9c2c02dc88a5bafd3681ba53729b89d Mon Sep 17 00:00:00 2001 From: Austin Gebauer <34121980+austingebauer@users.noreply.github.com> Date: Thu, 6 Jul 2023 08:38:25 -0700 Subject: [PATCH] Backport v0.14.x: only run periodic func on active instance in primary cluster or local mount (#150) (#155) --- backend.go | 122 +++++++++++++++++++++++++++++------------------------ 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/backend.go b/backend.go index 919809dd..a41237c7 100644 --- a/backend.go +++ b/backend.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/vault-plugin-secrets-azure/api" "github.com/hashicorp/vault/sdk/framework" + "github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/helper/locksutil" "github.com/hashicorp/vault/sdk/logical" ) @@ -76,78 +77,87 @@ func backend() *azureSecretBackend { } func (b *azureSecretBackend) periodicFunc(ctx context.Context, sys *logical.Request) error { - b.Logger().Debug("starting periodic func") - if !b.updatePassword { - b.Logger().Debug("periodic func", "rotate-root", "no rotate-root update") - return nil - } + // Root rotation through the periodic func writes to storage. Only run this on the + // active instance in the primary cluster or local mounts. The periodic func doesn't + // run on perf standbys or DR secondaries, but we still protect against this here. + replicationState := b.System().ReplicationState() + if (b.System().LocalMount() || !replicationState.HasState(consts.ReplicationPerformanceSecondary)) && + !replicationState.HasState(consts.ReplicationDRSecondary) && + !replicationState.HasState(consts.ReplicationPerformanceStandby) { + + b.Logger().Debug("starting periodic func") + if !b.updatePassword { + b.Logger().Debug("periodic func", "rotate-root", "no rotate-root update") + return nil + } - config, err := b.getConfig(ctx, sys.Storage) - if err != nil { - return err - } + config, err := b.getConfig(ctx, sys.Storage) + if err != nil { + return err + } - // Config can be nil if deleted or when the engine is enabled - // but not yet configured. - if config == nil { - return nil - } + // Config can be nil if deleted or when the engine is enabled + // but not yet configured. + if config == nil { + return nil + } - // Password should be at least a minute old before we process it - if config.NewClientSecret == "" || (time.Since(config.NewClientSecretCreated) < time.Minute) { - return nil - } + // Password should be at least a minute old before we process it + if config.NewClientSecret == "" || (time.Since(config.NewClientSecretCreated) < time.Minute) { + return nil + } - b.Logger().Debug("periodic func", "rotate-root", "new password detected, swapping in storage") - client, err := b.getClient(ctx, sys.Storage) - if err != nil { - return err - } + b.Logger().Debug("periodic func", "rotate-root", "new password detected, swapping in storage") + client, err := b.getClient(ctx, sys.Storage) + if err != nil { + return err + } - apps, err := client.provider.ListApplications(ctx, fmt.Sprintf("appId eq '%s'", config.ClientID)) - if err != nil { - return err - } + apps, err := client.provider.ListApplications(ctx, fmt.Sprintf("appId eq '%s'", config.ClientID)) + if err != nil { + return err + } - if len(apps) == 0 { - return fmt.Errorf("no application found") - } - if len(apps) > 1 { - return fmt.Errorf("multiple applications found - double check your client_id") - } + if len(apps) == 0 { + return fmt.Errorf("no application found") + } + if len(apps) > 1 { + return fmt.Errorf("multiple applications found - double check your client_id") + } - app := apps[0] + app := apps[0] - credsToDelete := []string{} - for _, cred := range app.PasswordCredentials { - if *cred.KeyID != config.NewClientSecretKeyID { - credsToDelete = append(credsToDelete, *cred.KeyID) + credsToDelete := []string{} + for _, cred := range app.PasswordCredentials { + if *cred.KeyID != config.NewClientSecretKeyID { + credsToDelete = append(credsToDelete, *cred.KeyID) + } } - } - if len(credsToDelete) != 0 { - b.Logger().Debug("periodic func", "rotate-root", "removing old passwords from Azure") - err = removeApplicationPasswords(ctx, client.provider, *app.ID, credsToDelete...) + if len(credsToDelete) != 0 { + b.Logger().Debug("periodic func", "rotate-root", "removing old passwords from Azure") + err = removeApplicationPasswords(ctx, client.provider, *app.ID, credsToDelete...) + if err != nil { + return err + } + } + + b.Logger().Debug("periodic func", "rotate-root", "updating config with new password") + config.ClientSecret = config.NewClientSecret + config.ClientSecretKeyID = config.NewClientSecretKeyID + config.RootPasswordExpirationDate = config.NewClientSecretExpirationDate + config.NewClientSecret = "" + config.NewClientSecretKeyID = "" + config.NewClientSecretCreated = time.Time{} + + err = b.saveConfig(ctx, config, sys.Storage) if err != nil { return err } - } - - b.Logger().Debug("periodic func", "rotate-root", "updating config with new password") - config.ClientSecret = config.NewClientSecret - config.ClientSecretKeyID = config.NewClientSecretKeyID - config.RootPasswordExpirationDate = config.NewClientSecretExpirationDate - config.NewClientSecret = "" - config.NewClientSecretKeyID = "" - config.NewClientSecretCreated = time.Time{} - err = b.saveConfig(ctx, config, sys.Storage) - if err != nil { - return err + b.updatePassword = false } - b.updatePassword = false - return nil }