Skip to content

Commit

Permalink
leader: initialize keyring after we have consistent reads
Browse files Browse the repository at this point in the history
Wait until we're sure the FSM is current before we try to initialize the
keyring.

Also, if a key is rotated immediately following a leader election, plans that
are in-flight may get signed before the new leader has the key. Allow for a
short timeout-and-retry to avoid rejecting plans
  • Loading branch information
tgross committed Oct 21, 2022
1 parent 1c31df7 commit 45f7352
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
29 changes: 25 additions & 4 deletions nomad/encrypter.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,33 @@ const keyIDHeader = "kid"
// SignClaims signs the identity claim for the task and returns an
// encoded JWT with both the claim and its signature
func (e *Encrypter) SignClaims(claim *structs.IdentityClaims) (string, error) {
e.lock.RLock()
defer e.lock.RUnlock()

keyset, err := e.activeKeySetLocked()
getActiveKeyset := func() (*keyset, error) {
e.lock.RLock()
defer e.lock.RUnlock()
keyset, err := e.activeKeySetLocked()
return keyset, err
}

// If a key is rotated immediately following a leader election, plans that
// are in-flight may get signed before the new leader has the key. Allow for
// a short timeout-and-retry to avoid rejecting plans
keyset, err := getActiveKeyset()
if err != nil {
return "", err
ctx, cancel := context.WithTimeout(e.srv.shutdownCtx, 5*time.Second)
defer cancel()
for {
select {
case <-ctx.Done():
return "", err
default:
time.Sleep(50 * time.Millisecond)
keyset, err = getActiveKeyset()
if keyset != nil {
break
}
}
}
}

token := jwt.NewWithClaims(&jwt.SigningMethodEd25519{}, claim)
Expand Down
8 changes: 4 additions & 4 deletions nomad/leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,6 @@ func (s *Server) establishLeadership(stopCh chan struct{}) error {
// Initialize scheduler configuration.
schedulerConfig := s.getOrCreateSchedulerConfig()

// Create the first root key if it doesn't already exist
go s.initializeKeyring(stopCh)

// Initialize the ClusterID
_, _ = s.ClusterID()
// todo: use cluster ID for stuff, later!
Expand Down Expand Up @@ -350,6 +347,9 @@ func (s *Server) establishLeadership(stopCh chan struct{}) error {

// Further clean ups and follow up that don't block RPC consistency

// Create the first root key if it doesn't already exist
go s.initializeKeyring(stopCh)

// Restore the periodic dispatcher state
if err := s.restorePeriodicDispatcher(); err != nil {
return err
Expand Down Expand Up @@ -2005,7 +2005,7 @@ func (s *Server) initializeKeyring(stopCh <-chan struct{}) {
break
}
}
// we might have lost leadershuip during the version check
// we might have lost leadership during the version check
if !s.IsLeader() {
return
}
Expand Down

0 comments on commit 45f7352

Please sign in to comment.