Skip to content

Commit

Permalink
update account issuer always (#5886)
Browse files Browse the repository at this point in the history
changed to update the account issuer for an account to always update
otherwise the information shown in accountz will not be consistent with
the decoded JWT
  • Loading branch information
aricart committed Sep 13, 2024
1 parent bd5304b commit 66dafcf
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 4 deletions.
5 changes: 4 additions & 1 deletion server/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,10 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) (au
c.Debugf("Account JWT lookup error: %v", err)
return false
}
if !s.isTrustedIssuer(acc.Issuer) {
acc.mu.RLock()
aissuer := acc.Issuer
acc.mu.RUnlock()
if !s.isTrustedIssuer(aissuer) {
c.Debugf("Account JWT not signed by trusted operator")
return false
}
Expand Down
109 changes: 109 additions & 0 deletions server/monitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4189,6 +4189,115 @@ func TestMonitorAccountzOperatorMode(t *testing.T) {
require_Contains(t, body, `"leafnodes": 0,`)
}

func TestMonitorAccountzAccountIssuerUpdate(t *testing.T) {
// create an operator set of keys
okp, err := nkeys.CreateOperator()
require_NoError(t, err)
opk, err := okp.PublicKey()
require_NoError(t, err)

// create the system account
_, sysPK := createKey(t)
sysAc := jwt.NewAccountClaims(sysPK)
sysAc.Name = "SYS"
sysJwt, err := sysAc.Encode(okp)
require_NoError(t, err)

// create the operator with the system
oc := jwt.NewOperatorClaims(opk)
oc.Name = "O"
// add a signing keys
osk1, err := nkeys.CreateOperator()
require_NoError(t, err)
opk1, err := osk1.PublicKey()
require_NoError(t, err)
// add a second signing key
osk2, err := nkeys.CreateOperator()
require_NoError(t, err)
opk2, err := osk2.PublicKey()
require_NoError(t, err)
oc.SigningKeys.Add(opk1, opk2)
// set the system account
oc.SystemAccount = sysPK
// generate
oJWT, err := oc.Encode(okp)
require_NoError(t, err)

// create an account
akp, apk := createKey(t)
ac := jwt.NewAccountClaims(apk)
ac.Name = "A"
// sign with the signing key
aJWT, err := ac.Encode(osk1)
require_NoError(t, err)

// build the mem-resolver
conf := createConfFile(t, []byte(fmt.Sprintf(`
listen: 127.0.0.1:-1
http: 127.0.0.1:-1
operator = %s
resolver = MEMORY
system_account: %s
resolver_preload = {
%s : %s
%s : %s
}
`, oJWT, sysPK, sysPK, sysJwt, apk, aJWT)))

// start the server
s, _ := RunServerWithConfig(conf)
defer s.Shutdown()

// create an user for account A, or we don't see
// the account in accountsz
createUser := func() (string, string) {
ukp, _ := nkeys.CreateUser()
seed, _ := ukp.Seed()
upub, _ := ukp.PublicKey()
uclaim := newJWTTestUserClaims()
uclaim.Subject = upub
ujwt, err := uclaim.Encode(akp)
require_NoError(t, err)
return upub, genCredsFile(t, ujwt, seed)
}

_, aCreds := createUser()
// connect the user
nc, err := nats.Connect(s.ClientURL(), nats.UserCredentials(aCreds))
require_NoError(t, err)
defer nc.Close()

// lookup the account
data := readBody(t, fmt.Sprintf("http://127.0.0.1:%d%s?acc=%s", s.MonitorAddr().Port, AccountzPath, apk))
var ci Accountz
require_NoError(t, json.Unmarshal(data, &ci))
require_Equal(t, ci.Account.IssuerKey, opk1)

// now update the account
aJWT, err = ac.Encode(osk2)
require_NoError(t, err)

updatedConf := []byte(fmt.Sprintf(`
listen: 127.0.0.1:-1
http: 127.0.0.1:-1
operator = %s
resolver = MEMORY
system_account: %s
resolver_preload = {
%s : %s
%s : %s
}
`, oJWT, sysPK, sysPK, sysJwt, apk, aJWT))
// update the configuration file
require_NoError(t, os.WriteFile(conf, updatedConf, 0666))
// reload
require_NoError(t, s.Reload())

data = readBody(t, fmt.Sprintf("http://127.0.0.1:%d%s?acc=%s", s.MonitorAddr().Port, AccountzPath, apk))
require_NoError(t, json.Unmarshal(data, &ci))
require_Equal(t, ci.Account.IssuerKey, opk2)
}

func TestMonitorAuthorizedUsers(t *testing.T) {
kp, _ := nkeys.FromSeed(seed)
usrNKey, _ := kp.PublicKey()
Expand Down
6 changes: 3 additions & 3 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2049,9 +2049,9 @@ func (s *Server) updateAccountWithClaimJWT(acc *Account, claimJWT string) error
accClaims, _, err := s.verifyAccountClaims(claimJWT)
if err == nil && accClaims != nil {
acc.mu.Lock()
if acc.Issuer == _EMPTY_ {
acc.Issuer = accClaims.Issuer
}
// if an account is updated with a different operator signing key, we want to
// show a consistent issuer.
acc.Issuer = accClaims.Issuer
if acc.Name != accClaims.Subject {
acc.mu.Unlock()
return ErrAccountValidation
Expand Down

0 comments on commit 66dafcf

Please sign in to comment.