diff --git a/go.mod b/go.mod index 753893f6..07408231 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.17 require ( github.com/klauspost/compress v1.14.4 github.com/minio/highwayhash v1.0.2 - github.com/nats-io/jwt/v2 v2.2.1-0.20220429175140-9f4f1d5cc977 + github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a github.com/nats-io/nats.go v1.14.0 github.com/nats-io/nkeys v0.3.0 github.com/nats-io/nuid v1.0.1 diff --git a/go.sum b/go.sum index fe34d7f2..81e28446 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6 github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= -github.com/nats-io/jwt/v2 v2.2.1-0.20220429175140-9f4f1d5cc977 h1:cbP9xTzFVGWXCJtApKchvFZIIEDWKfLkThVYLonpOpQ= -github.com/nats-io/jwt/v2 v2.2.1-0.20220429175140-9f4f1d5cc977/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= +github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a h1:lem6QCvxR0Y28gth9P+wV2K/zYUUAkJ+55U8cpS0p5I= +github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= github.com/nats-io/nats.go v1.14.0 h1:/QLCss4vQ6wvDpbqXucsVRDi13tFIR6kTdau+nXzKJw= github.com/nats-io/nats.go v1.14.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= diff --git a/server/accounts.go b/server/accounts.go index cde23482..d1333955 100644 --- a/server/accounts.go +++ b/server/accounts.go @@ -2983,8 +2983,7 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim // update account signing keys a.signingKeys = nil - op, ok := s.keyToClaim[a.Issuer] - strict := ok && op.StrictSigningKeyUsage + _, strict := s.strictSigningKeyUsage[a.Issuer] if len(ac.SigningKeys) > 0 || !strict { a.signingKeys = make(map[string]jwt.Scope) } diff --git a/server/auth.go b/server/auth.go index f3a68350..e7b4d56a 100644 --- a/server/auth.go +++ b/server/auth.go @@ -607,12 +607,9 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo c.Debugf("Account JWT lookup error: %v", err) return false } - if isTrusted, noBearer := s.isTrustedIssuer(acc.Issuer); !isTrusted { + if !s.isTrustedIssuer(acc.Issuer) { c.Debugf("Account JWT not signed by trusted operator") return false - } else if noBearer && juc.BearerToken { - c.Debugf("Bearer Token are disallowed by operator") - return false } if scope, ok := acc.hasIssuer(juc.Issuer); !ok { c.Debugf("User JWT issuer is not known") diff --git a/server/events_test.go b/server/events_test.go index ced4c9d3..e2f12b51 100644 --- a/server/events_test.go +++ b/server/events_test.go @@ -45,10 +45,11 @@ func createAccount(s *Server) (*Account, nkeys.KeyPair) { return acc, akp } -func createUserCredsEx(t *testing.T, nuc *jwt.UserClaims, akp nkeys.KeyPair) nats.Option { +func createUserCreds(t *testing.T, s *Server, akp nkeys.KeyPair) nats.Option { t.Helper() kp, _ := nkeys.CreateUser() - nuc.Subject, _ = kp.PublicKey() + pub, _ := kp.PublicKey() + nuc := jwt.NewUserClaims(pub) ujwt, err := nuc.Encode(akp) if err != nil { t.Fatalf("Error generating user JWT: %v", err) @@ -63,10 +64,6 @@ func createUserCredsEx(t *testing.T, nuc *jwt.UserClaims, akp nkeys.KeyPair) nat return nats.UserJWT(userCB, sigCB) } -func createUserCreds(t *testing.T, s *Server, akp nkeys.KeyPair) nats.Option { - return createUserCredsEx(t, jwt.NewUserClaims("test"), akp) -} - func runTrustedServer(t *testing.T) (*Server, *Options) { t.Helper() opts := DefaultOptions() diff --git a/server/jwt_test.go b/server/jwt_test.go index 7c5c0329..a148ecf1 100644 --- a/server/jwt_test.go +++ b/server/jwt_test.go @@ -5760,50 +5760,6 @@ func TestJWTStrictSigningKeys(t *testing.T) { }) } -func TestJWTDisallowBearer(t *testing.T) { - opId, err := nkeys.CreateOperator() - require_NoError(t, err) - opIdPub, err := opId.PublicKey() - require_NoError(t, err) - oClaim := jwt.NewOperatorClaims(opIdPub) - oClaim.DisallowBearerToken = true - oJwt, err := oClaim.Encode(opId) - require_NoError(t, err) - - accId, err := nkeys.CreateAccount() - require_NoError(t, err) - accIdPub, err := accId.PublicKey() - require_NoError(t, err) - aClaim := jwt.NewAccountClaims(accIdPub) - accJwt, err := aClaim.Encode(opId) - require_NoError(t, err) - - uc := jwt.NewUserClaims("dummy") - uc.BearerToken = true - uOpt1 := createUserCredsEx(t, uc, accId) - uc.BearerToken = false - uOpt2 := createUserCredsEx(t, uc, accId) - - cf := createConfFile(t, []byte(fmt.Sprintf(` - port: -1 - operator = %s - resolver: MEMORY - resolver_preload = { - %s : "%s" - } - `, oJwt, accIdPub, accJwt))) - defer removeFile(t, cf) - s, _ := RunServerWithConfig(cf) - defer s.Shutdown() - - _, err = nats.Connect(s.ClientURL(), uOpt1) - require_Error(t, err) - - nc2, err := nats.Connect(s.ClientURL(), uOpt2) - require_NoError(t, err) - defer nc2.Close() -} - func TestJWTAccountProtectedImport(t *testing.T) { srvFmt := ` port: -1 diff --git a/server/server.go b/server/server.go index 36a3de56..1e97a16d 100644 --- a/server/server.go +++ b/server/server.go @@ -209,8 +209,8 @@ type Server struct { // Trusted public operator keys. trustedKeys []string - // map of trusted keys to operator claims - keyToClaim map[string]*jwt.OperatorClaims + // map of trusted keys to operator setting StrictSigningKeyUsage + strictSigningKeyUsage map[string]struct{} // We use this to minimize mem copies for requests to monitoring // endpoint /varz (when it comes from http). @@ -970,32 +970,27 @@ func (s *Server) ActivePeers() (peers []string) { return peers } -// isTrustedIssuer will check that the issuer is a trusted public key, -// and if true, will also return if the operator disallows use of bearer token. +// isTrustedIssuer will check that the issuer is a trusted public key. // This is used to make sure an account was signed by a trusted operator. -// If the account is not trusted, disallow bearer token will always be false. -func (s *Server) isTrustedIssuer(issuer string) (bool, bool) { +func (s *Server) isTrustedIssuer(issuer string) bool { s.mu.Lock() defer s.mu.Unlock() // If we are not running in trusted mode and there is no issuer, that is ok. if s.trustedKeys == nil && issuer == "" { - return true, false + return true } for _, tk := range s.trustedKeys { if tk == issuer { - if op, ok := s.keyToClaim[issuer]; ok { - return true, op.DisallowBearerToken - } - return true, false + return true } } - return false, false + return false } // processTrustedKeys will process binary stamped and // options-based trusted nkeys. Returns success. func (s *Server) processTrustedKeys() bool { - s.keyToClaim = map[string]*jwt.OperatorClaims{} + s.strictSigningKeyUsage = map[string]struct{}{} if trustedKeys != "" && !s.initStampedTrustedKeys() { return false } else if s.opts.TrustedKeys != nil { @@ -1006,9 +1001,11 @@ func (s *Server) processTrustedKeys() bool { } s.trustedKeys = append([]string(nil), s.opts.TrustedKeys...) for _, claim := range s.opts.TrustedOperators { - s.keyToClaim[claim.Subject] = claim + if !claim.StrictSigningKeyUsage { + continue + } for _, key := range claim.SigningKeys { - s.keyToClaim[key] = claim + s.strictSigningKeyUsage[key] = struct{}{} } } } @@ -1225,7 +1222,7 @@ func (s *Server) setSystemAccount(acc *Account) error { } // If we are running with trusted keys for an operator // make sure we check the account is legit. - if isTrusted, _ := s.isTrustedIssuer(acc.Issuer); !isTrusted { + if !s.isTrustedIssuer(acc.Issuer) { return ErrAccountValidation } @@ -1545,7 +1542,7 @@ func (s *Server) verifyAccountClaims(claimJWT string) (*jwt.AccountClaims, strin if err != nil { return nil, _EMPTY_, err } - if isTrusted, _ := s.isTrustedIssuer(accClaims.Issuer); !isTrusted { + if !s.isTrustedIssuer(accClaims.Issuer) { return nil, _EMPTY_, ErrAccountValidation } vr := jwt.CreateValidationResults()