mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-29 17:52:32 +00:00 
			
		
		
		
	api/leader: fix deadlock when namespace is set on leader calls (#24256)
* api/leader: fix deadlock when namespace is set on leader calls * Add cl
This commit is contained in:
		
							
								
								
									
										4
									
								
								changelog/24256.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								changelog/24256.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| ```release-note:bug | ||||
| api: Fix deadlock on calls to sys/leader with a namespace configured | ||||
| on the request. | ||||
| ``` | ||||
							
								
								
									
										23
									
								
								vault/ha.go
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								vault/ha.go
									
									
									
									
									
								
							| @@ -150,30 +150,41 @@ func (c *Core) Leader() (isLeader bool, leaderAddr, clusterAddr string, err erro | ||||
| 	if c.Sealed() { | ||||
| 		return false, "", "", consts.ErrSealed | ||||
| 	} | ||||
|  | ||||
| 	c.stateLock.RLock() | ||||
| 	defer c.stateLock.RUnlock() | ||||
|  | ||||
| 	return c.LeaderLocked() | ||||
| } | ||||
|  | ||||
| func (c *Core) LeaderLocked() (isLeader bool, leaderAddr, clusterAddr string, err error) { | ||||
| 	// Check if HA enabled. We don't need the lock for this check as it's set | ||||
| 	// on startup and never modified | ||||
| 	if c.ha == nil { | ||||
| 		return false, "", "", ErrHANotEnabled | ||||
| 	} | ||||
|  | ||||
| 	// Check if sealed | ||||
| 	if c.Sealed() { | ||||
| 		return false, "", "", consts.ErrSealed | ||||
| 	} | ||||
|  | ||||
| 	// Check if we are the leader | ||||
| 	if !c.standby { | ||||
| 		c.stateLock.RUnlock() | ||||
| 		return true, c.redirectAddr, c.ClusterAddr(), nil | ||||
| 	} | ||||
|  | ||||
| 	// Initialize a lock | ||||
| 	lock, err := c.ha.LockWith(CoreLockPath, "read") | ||||
| 	if err != nil { | ||||
| 		c.stateLock.RUnlock() | ||||
| 		return false, "", "", err | ||||
| 	} | ||||
|  | ||||
| 	// Read the value | ||||
| 	held, leaderUUID, err := lock.Value() | ||||
| 	if err != nil { | ||||
| 		c.stateLock.RUnlock() | ||||
| 		return false, "", "", err | ||||
| 	} | ||||
| 	if !held { | ||||
| 		c.stateLock.RUnlock() | ||||
| 		return false, "", "", nil | ||||
| 	} | ||||
|  | ||||
| @@ -188,13 +199,11 @@ func (c *Core) Leader() (isLeader bool, leaderAddr, clusterAddr string, err erro | ||||
| 	// If the leader hasn't changed, return the cached value; nothing changes | ||||
| 	// mid-leadership, and the barrier caches anyways | ||||
| 	if leaderUUID == localLeaderUUID && localRedirectAddr != "" { | ||||
| 		c.stateLock.RUnlock() | ||||
| 		return false, localRedirectAddr, localClusterAddr, nil | ||||
| 	} | ||||
|  | ||||
| 	c.logger.Trace("found new active node information, refreshing") | ||||
|  | ||||
| 	defer c.stateLock.RUnlock() | ||||
| 	c.leaderParamsLock.Lock() | ||||
| 	defer c.leaderParamsLock.Unlock() | ||||
|  | ||||
|   | ||||
| @@ -5150,8 +5150,15 @@ type LeaderResponse struct { | ||||
| } | ||||
|  | ||||
| func (core *Core) GetLeaderStatus() (*LeaderResponse, error) { | ||||
| 	core.stateLock.RLock() | ||||
| 	defer core.stateLock.RUnlock() | ||||
|  | ||||
| 	return core.GetLeaderStatusLocked() | ||||
| } | ||||
|  | ||||
| func (core *Core) GetLeaderStatusLocked() (*LeaderResponse, error) { | ||||
| 	haEnabled := true | ||||
| 	isLeader, address, clusterAddr, err := core.Leader() | ||||
| 	isLeader, address, clusterAddr, err := core.LeaderLocked() | ||||
| 	if errwrap.Contains(err, ErrHANotEnabled.Error()) { | ||||
| 		haEnabled = false | ||||
| 		err = nil | ||||
| @@ -5165,10 +5172,10 @@ func (core *Core) GetLeaderStatus() (*LeaderResponse, error) { | ||||
| 		IsSelf:               isLeader, | ||||
| 		LeaderAddress:        address, | ||||
| 		LeaderClusterAddress: clusterAddr, | ||||
| 		PerfStandby:          core.PerfStandby(), | ||||
| 		PerfStandby:          core.perfStandby, | ||||
| 	} | ||||
| 	if isLeader { | ||||
| 		resp.ActiveTime = core.ActiveTime() | ||||
| 		resp.ActiveTime = core.activeTime | ||||
| 	} | ||||
| 	if resp.PerfStandby { | ||||
| 		resp.PerfStandbyLastRemoteWAL = core.EntLastRemoteWAL() | ||||
| @@ -5176,7 +5183,7 @@ func (core *Core) GetLeaderStatus() (*LeaderResponse, error) { | ||||
| 		resp.LastWAL = core.EntLastWAL() | ||||
| 	} | ||||
|  | ||||
| 	resp.RaftCommittedIndex, resp.RaftAppliedIndex = core.GetRaftIndexes() | ||||
| 	resp.RaftCommittedIndex, resp.RaftAppliedIndex = core.GetRaftIndexesLocked() | ||||
| 	return resp, nil | ||||
| } | ||||
|  | ||||
| @@ -5200,7 +5207,7 @@ func (b *SystemBackend) handleSealStatus(ctx context.Context, req *logical.Reque | ||||
| } | ||||
|  | ||||
| func (b *SystemBackend) handleLeaderStatus(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { | ||||
| 	status, err := b.Core.GetLeaderStatus() | ||||
| 	status, err := b.Core.GetLeaderStatusLocked() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|   | ||||
| @@ -70,7 +70,10 @@ func (c *Core) GetRaftNodeID() string { | ||||
| func (c *Core) GetRaftIndexes() (committed uint64, applied uint64) { | ||||
| 	c.stateLock.RLock() | ||||
| 	defer c.stateLock.RUnlock() | ||||
| 	return c.GetRaftIndexesLocked() | ||||
| } | ||||
|  | ||||
| func (c *Core) GetRaftIndexesLocked() (committed uint64, applied uint64) { | ||||
| 	raftStorage, ok := c.underlyingPhysical.(*raft.RaftBackend) | ||||
| 	if !ok { | ||||
| 		return 0, 0 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Steven Clark
					Steven Clark