Skip to content

Commit

Permalink
Backport v0.13.x: only run periodic func on active instance in primar…
Browse files Browse the repository at this point in the history
…y cluster or local mount (#118) (#119)

* fix: only run periodic func on active instance in primary cluster or local mount (#118)

* make fmt

* use verified publisher image

* try latest tag

* use hashicorp prefix in docker run

* wrong container name location
  • Loading branch information
austingebauer committed Jul 12, 2023
1 parent 47502c2 commit 20c5f48
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 62 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ jobs:
- name: Test that it loads with Vault
if: matrix.os == 'linux' && matrix.arch == 'amd64'
run: |
docker pull vault &&
docker run -d --name vault --mount type=bind,src=${PWD}/bin,dst=/vault/file --cap-add=IPC_LOCK -e VAULT_ADDR='http://127.0.0.1:8200' -e 'VAULT_TOKEN=myroot' -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' -e 'VAULT_DEV_LISTEN_ADDRESS=127.0.0.1:8200' vault server -dev -dev-plugin-dir /vault/file &&
docker pull hashicorp/vault:latest &&
docker run -d --name vault --mount type=bind,src=${PWD}/bin,dst=/vault/file --cap-add=IPC_LOCK -e VAULT_ADDR='http://127.0.0.1:8200' -e 'VAULT_TOKEN=myroot' -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' -e 'VAULT_DEV_LISTEN_ADDRESS=127.0.0.1:8200' hashicorp/vault server -dev -dev-plugin-dir /vault/file &&
timeout 30 sh -c 'until docker exec -t vault vault status; do sleep 1; done' &&
docker exec -t vault vault auth enable vault-plugin-auth-azure
Expand Down
130 changes: 70 additions & 60 deletions backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/logical"
)

Expand Down Expand Up @@ -83,83 +84,92 @@ func backend() *azureAuthBackend {
// available immediately, and hence we check periodically and delete the old credential
// only once the new credential is at least a minute old
func (b *azureAuthBackend) 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.config(ctx, sys.Storage)
if err != nil {
return err
}
config, err := b.config(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")
provider, err := b.getProvider(ctx, config)
if err != nil {
return err
}
b.Logger().Debug("periodic func", "rotate-root", "new password detected, swapping in storage")
provider, err := b.getProvider(ctx, config)
if err != nil {
return err
}

client, err := provider.MSGraphClient()
if err != nil {
return err
}
client, err := provider.MSGraphClient()
if err != nil {
return err
}

apps, err := client.ListApplications(ctx, fmt.Sprintf("appId eq '%s'", config.ClientID))
if err != nil {
return err
}
apps, err := client.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, *app.ID, credsToDelete...)
if len(credsToDelete) != 0 {
b.Logger().Debug("periodic func", "rotate-root", "removing old passwords from Azure")
err = removeApplicationPasswords(ctx, client, *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
}

Expand Down

0 comments on commit 20c5f48

Please sign in to comment.