Skip to content

Commit

Permalink
nomad: only activate one-time auth tokens with 1.1.0 (#10952)
Browse files Browse the repository at this point in the history
Fix a panic in handling one-time auth tokens, used to support `nomad ui
--authenticate`.

If the nomad leader is a 1.1.x with some servers running as 1.0.x, the
pre-1.1.0 servers risk crashing and the cluster may lose quorum. That
can happen when `nomad authenticate -ui` command is issued, or when the
leader scans for expired tokens every 10 minutes.

Fixed #10943 .
  • Loading branch information
Mahmood Ali committed Jul 27, 2021
1 parent 62057de commit 3f80eab
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/10952.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
core: Fixed a panic that may arise when upgrading pre-1.1.0 cluster to 1.1.x and may cause cluster outage
```
12 changes: 12 additions & 0 deletions nomad/acl_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,10 @@ func (a *ACL) UpsertOneTimeToken(args *structs.OneTimeTokenUpsertRequest, reply
defer metrics.MeasureSince(
[]string{"nomad", "acl", "upsert_one_time_token"}, time.Now())

if !ServersMeetMinimumVersion(a.srv.Members(), minOneTimeAuthenticationTokenVersion, false) {
return fmt.Errorf("All servers should be running version %v or later to use one-time authentication tokens", minAutopilotVersion)
}

// Snapshot the state
state, err := a.srv.State().Snapshot()
if err != nil {
Expand Down Expand Up @@ -899,6 +903,10 @@ func (a *ACL) ExchangeOneTimeToken(args *structs.OneTimeTokenExchangeRequest, re
defer metrics.MeasureSince(
[]string{"nomad", "acl", "exchange_one_time_token"}, time.Now())

if !ServersMeetMinimumVersion(a.srv.Members(), minOneTimeAuthenticationTokenVersion, false) {
return fmt.Errorf("All servers should be running version %v or later to use one-time authentication tokens", minAutopilotVersion)
}

// Snapshot the state
state, err := a.srv.State().Snapshot()
if err != nil {
Expand Down Expand Up @@ -952,6 +960,10 @@ func (a *ACL) ExpireOneTimeTokens(args *structs.OneTimeTokenExpireRequest, reply
defer metrics.MeasureSince(
[]string{"nomad", "acl", "expire_one_time_tokens"}, time.Now())

if !ServersMeetMinimumVersion(a.srv.Members(), minOneTimeAuthenticationTokenVersion, false) {
return fmt.Errorf("All servers should be running version %v or later to use one-time authentication tokens", minAutopilotVersion)
}

// Check management level permissions
if a.srv.config.ACLEnabled {
if acl, err := a.srv.ResolveToken(args.AuthToken); err != nil {
Expand Down
6 changes: 6 additions & 0 deletions nomad/leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ var minClusterIDVersion = version.Must(version.NewVersion("0.10.4"))

var minJobRegisterAtomicEvalVersion = version.Must(version.NewVersion("0.12.1"))

var minOneTimeAuthenticationTokenVersion = version.Must(version.NewVersion("1.1.0"))

// monitorLeadership is used to monitor if we acquire or lose our role
// as the leader in the Raft cluster. There is some work the leader is
// expected to do, so we must react to changes
Expand Down Expand Up @@ -739,6 +741,10 @@ func (s *Server) schedulePeriodic(stopCh chan struct{}) {
s.evalBroker.Enqueue(s.coreJobEval(structs.CoreJobCSIVolumeClaimGC, index))
}
case <-oneTimeTokenGC.C:
if !ServersMeetMinimumVersion(s.Members(), minOneTimeAuthenticationTokenVersion, false) {
continue
}

if index, ok := getLatest(); ok {
s.evalBroker.Enqueue(s.coreJobEval(structs.CoreJobOneTimeTokenGC, index))
}
Expand Down

0 comments on commit 3f80eab

Please sign in to comment.