From 88313f0398a87f3d637a0819dfd4649671bf6d03 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Tue, 16 Jan 2018 13:51:55 -0500 Subject: [PATCH] Update replication state logic. Fixes #3727 --- vault/auth.go | 2 +- vault/core.go | 7 +++---- vault/dynamic_system_view.go | 2 +- vault/logical_system.go | 16 ++++++++-------- vault/mount.go | 4 ++-- vault/policy_store.go | 2 +- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/vault/auth.go b/vault/auth.go index e2e804670..c8091f2cf 100644 --- a/vault/auth.go +++ b/vault/auth.go @@ -193,7 +193,7 @@ func (c *Core) disableCredential(path string) error { } switch { - case entry.Local, !c.replicationState.HasState(consts.ReplicationPerformanceSecondary): + case entry.Local, !c.ReplicationState().HasState(consts.ReplicationPerformanceSecondary): // Have writable storage, remove the whole thing if err := logical.ClearView(view); err != nil { c.logger.Error("core: failed to clear view for path being unmounted", "error", err, "path", path) diff --git a/vault/core.go b/vault/core.go index eeb251ce9..80da22aea 100644 --- a/vault/core.go +++ b/vault/core.go @@ -359,7 +359,7 @@ type Core struct { atomicPrimaryFailoverAddrs *atomic.Value // replicationState keeps the current replication state cached for quick // lookup - replicationState consts.ReplicationState + replicationState *uint32 // uiEnabled indicates whether Vault Web UI is enabled or not uiEnabled bool @@ -490,6 +490,7 @@ func NewCore(conf *CoreConfig) (*Core, error) { clusterPeerClusterAddrsCache: cache.New(3*heartbeatInterval, time.Second), enableMlock: !conf.DisableMlock, rawEnabled: conf.EnableRaw, + replicationState: new(uint32), atomicPrimaryClusterAddrs: new(atomic.Value), atomicPrimaryFailoverAddrs: new(atomic.Value), } @@ -2104,9 +2105,7 @@ func (c *Core) emitMetrics(stopCh chan struct{}) { } func (c *Core) ReplicationState() consts.ReplicationState { - c.stateLock.RLock() - defer c.stateLock.RUnlock() - return c.replicationState + return consts.ReplicationState(atomic.LoadUint32(c.replicationState)) } func (c *Core) SealAccess() *SealAccess { diff --git a/vault/dynamic_system_view.go b/vault/dynamic_system_view.go index 4064f0a4c..cda3c03e9 100644 --- a/vault/dynamic_system_view.go +++ b/vault/dynamic_system_view.go @@ -88,7 +88,7 @@ func (d dynamicSystemView) CachingDisabled() bool { // Checks if this is a primary Vault instance. Caller should hold the stateLock // in read mode. func (d dynamicSystemView) ReplicationState() consts.ReplicationState { - return d.core.replicationState + return d.core.ReplicationState() } // ResponseWrapData wraps the given data in a cubbyhole and returns the diff --git a/vault/logical_system.go b/vault/logical_system.go index 6611d227b..1b531f689 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -1382,7 +1382,7 @@ func (b *SystemBackend) handleMountTable(ctx context.Context, req *logical.Reque // handleMount is used to mount a new path func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { - repState := b.Core.replicationState + repState := b.Core.ReplicationState() local := data.Get("local").(bool) if !local && repState.HasState(consts.ReplicationPerformanceSecondary) { @@ -1511,7 +1511,7 @@ func (b *SystemBackend) handleUnmount(ctx context.Context, req *logical.Request, path := data.Get("path").(string) path = sanitizeMountPath(path) - repState := b.Core.replicationState + repState := b.Core.ReplicationState() entry := b.Core.router.MatchingMountEntry(path) if entry != nil && !entry.Local && repState.HasState(consts.ReplicationPerformanceSecondary) { return logical.ErrorResponse("cannot unmount a non-local mount on a replication secondary"), nil @@ -1535,7 +1535,7 @@ func (b *SystemBackend) handleUnmount(ctx context.Context, req *logical.Request, // handleRemount is used to remount a path func (b *SystemBackend) handleRemount(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { - repState := b.Core.replicationState + repState := b.Core.ReplicationState() // Get the paths fromPath := data.Get("from").(string) @@ -1641,7 +1641,7 @@ func (b *SystemBackend) handleMountTuneWrite(ctx context.Context, req *logical.R // handleTuneWriteCommon is used to set config settings on a path func (b *SystemBackend) handleTuneWriteCommon(path string, data *framework.FieldData) (*logical.Response, error) { - repState := b.Core.replicationState + repState := b.Core.ReplicationState() path = sanitizeMountPath(path) @@ -1904,7 +1904,7 @@ func (b *SystemBackend) handleAuthTable(ctx context.Context, req *logical.Reques // handleEnableAuth is used to enable a new credential backend func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { - repState := b.Core.replicationState + repState := b.Core.ReplicationState() local := data.Get("local").(bool) if !local && repState.HasState(consts.ReplicationPerformanceSecondary) { return logical.ErrorResponse("cannot add a non-local mount to a replication secondary"), nil @@ -1979,7 +1979,7 @@ func (b *SystemBackend) handleDisableAuth(ctx context.Context, req *logical.Requ fullPath := credentialRoutePrefix + path - repState := b.Core.replicationState + repState := b.Core.ReplicationState() entry := b.Core.router.MatchingMountEntry(fullPath) if entry != nil && !entry.Local && repState.HasState(consts.ReplicationPerformanceSecondary) { return logical.ErrorResponse("cannot unmount a non-local mount on a replication secondary"), nil @@ -2225,7 +2225,7 @@ func (b *SystemBackend) handleAuditHash(ctx context.Context, req *logical.Reques // handleEnableAudit is used to enable a new audit backend func (b *SystemBackend) handleEnableAudit(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { - repState := b.Core.replicationState + repState := b.Core.ReplicationState() local := data.Get("local").(bool) if !local && repState.HasState(consts.ReplicationPerformanceSecondary) { @@ -2387,7 +2387,7 @@ func (b *SystemBackend) handleKeyStatus(ctx context.Context, req *logical.Reques // handleRotate is used to trigger a key rotation func (b *SystemBackend) handleRotate(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { - repState := b.Core.replicationState + repState := b.Core.ReplicationState() if repState.HasState(consts.ReplicationPerformanceSecondary) { return logical.ErrorResponse("cannot rotate on a replication secondary"), nil } diff --git a/vault/mount.go b/vault/mount.go index 7e3cab478..23589be85 100644 --- a/vault/mount.go +++ b/vault/mount.go @@ -360,7 +360,7 @@ func (c *Core) unmountInternal(path string) error { } switch { - case entry.Local, !c.replicationState.HasState(consts.ReplicationPerformanceSecondary): + case entry.Local, !c.ReplicationState().HasState(consts.ReplicationPerformanceSecondary): // Have writable storage, remove the whole thing if err := logical.ClearView(view); err != nil { c.logger.Error("core: failed to clear view for path being unmounted", "error", err, "path", path) @@ -610,7 +610,7 @@ func (c *Core) loadMounts() error { // ensure this comes over. If we upgrade first, we simply don't // create the mount, so we won't conflict when we sync. If this is // local (e.g. cubbyhole) we do still add it. - if !foundRequired && (!c.replicationState.HasState(consts.ReplicationPerformanceSecondary) || requiredMount.Local) { + if !foundRequired && (!c.ReplicationState().HasState(consts.ReplicationPerformanceSecondary) || requiredMount.Local) { c.mounts.Entries = append(c.mounts.Entries, requiredMount) needPersist = true } diff --git a/vault/policy_store.go b/vault/policy_store.go index e0e86c471..2ff4640a8 100644 --- a/vault/policy_store.go +++ b/vault/policy_store.go @@ -184,7 +184,7 @@ func (c *Core) setupPolicyStore() error { sysView := &dynamicSystemView{core: c} c.policyStore = NewPolicyStore(c.systemBarrierView, sysView) - if c.replicationState.HasState(consts.ReplicationPerformanceSecondary) { + if c.ReplicationState().HasState(consts.ReplicationPerformanceSecondary) { // Policies will sync from the primary return nil }