github.com/nats-io/nats-server/v2@v2.11.0-preview.2/server/jwt_test.go (about) 1 // Copyright 2018-2020 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "bufio" 18 "encoding/base64" 19 "encoding/json" 20 "errors" 21 "fmt" 22 "io" 23 "net/http" 24 "net/http/httptest" 25 "os" 26 "path/filepath" 27 "strings" 28 "sync" 29 "sync/atomic" 30 "testing" 31 "time" 32 33 "github.com/nats-io/jwt/v2" 34 "github.com/nats-io/nats.go" 35 "github.com/nats-io/nkeys" 36 ) 37 38 var ( 39 // This matches ./configs/nkeys_jwts/test.seed 40 oSeed = []byte("SOAFYNORQLQFJYBYNUGC5D7SH2MXMUX5BFEWWGHN3EK4VGG5TPT5DZP7QU") 41 // This matches ./configs/nkeys/op.jwt 42 ojwt = "eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJhdWQiOiJURVNUUyIsImV4cCI6MTg1OTEyMTI3NSwianRpIjoiWE5MWjZYWVBIVE1ESlFSTlFPSFVPSlFHV0NVN01JNVc1SlhDWk5YQllVS0VRVzY3STI1USIsImlhdCI6MTU0Mzc2MTI3NSwiaXNzIjoiT0NBVDMzTVRWVTJWVU9JTUdOR1VOWEo2NkFIMlJMU0RBRjNNVUJDWUFZNVFNSUw2NU5RTTZYUUciLCJuYW1lIjoiU3luYWRpYSBDb21tdW5pY2F0aW9ucyBJbmMuIiwibmJmIjoxNTQzNzYxMjc1LCJzdWIiOiJPQ0FUMzNNVFZVMlZVT0lNR05HVU5YSjY2QUgyUkxTREFGM01VQkNZQVk1UU1JTDY1TlFNNlhRRyIsInR5cGUiOiJvcGVyYXRvciIsIm5hdHMiOnsic2lnbmluZ19rZXlzIjpbIk9EU0tSN01ZRlFaNU1NQUo2RlBNRUVUQ1RFM1JJSE9GTFRZUEpSTUFWVk40T0xWMllZQU1IQ0FDIiwiT0RTS0FDU1JCV1A1MzdEWkRSVko2NTdKT0lHT1BPUTZLRzdUNEhONk9LNEY2SUVDR1hEQUhOUDIiLCJPRFNLSTM2TFpCNDRPWTVJVkNSNlA1MkZaSlpZTVlXWlZXTlVEVExFWjVUSzJQTjNPRU1SVEFCUiJdfX0.hyfz6E39BMUh0GLzovFfk3wT4OfualftjdJ_eYkLfPvu5tZubYQ_Pn9oFYGCV_6yKy3KMGhWGUCyCdHaPhalBw" 43 oKp nkeys.KeyPair 44 ) 45 46 func init() { 47 var err error 48 oKp, err = nkeys.FromSeed(oSeed) 49 if err != nil { 50 panic(fmt.Sprintf("Parsing oSeed failed with: %v", err)) 51 } 52 } 53 54 func chanRecv(t *testing.T, recvChan <-chan struct{}, limit time.Duration) { 55 t.Helper() 56 select { 57 case <-recvChan: 58 case <-time.After(limit): 59 t.Fatal("Should have received from channel") 60 } 61 } 62 63 func opTrustBasicSetup() *Server { 64 kp, _ := nkeys.FromSeed(oSeed) 65 pub, _ := kp.PublicKey() 66 opts := defaultServerOptions 67 opts.TrustedKeys = []string{pub} 68 s, c, _, _ := rawSetup(opts) 69 c.close() 70 return s 71 } 72 73 func buildMemAccResolver(s *Server) { 74 mr := &MemAccResolver{} 75 s.SetAccountResolver(mr) 76 } 77 78 func addAccountToMemResolver(s *Server, pub, jwtclaim string) { 79 s.AccountResolver().Store(pub, jwtclaim) 80 } 81 82 func createClient(t *testing.T, s *Server, akp nkeys.KeyPair) (*testAsyncClient, *bufio.Reader, string) { 83 return createClientWithIssuer(t, s, akp, "") 84 } 85 86 func createClientWithIssuer(t *testing.T, s *Server, akp nkeys.KeyPair, optIssuerAccount string) (*testAsyncClient, *bufio.Reader, string) { 87 t.Helper() 88 nkp, _ := nkeys.CreateUser() 89 pub, _ := nkp.PublicKey() 90 nuc := jwt.NewUserClaims(pub) 91 if optIssuerAccount != "" { 92 nuc.IssuerAccount = optIssuerAccount 93 } 94 ujwt, err := nuc.Encode(akp) 95 if err != nil { 96 t.Fatalf("Error generating user JWT: %v", err) 97 } 98 c, cr, l := newClientForServer(s) 99 100 // Sign Nonce 101 var info nonceInfo 102 json.Unmarshal([]byte(l[5:]), &info) 103 sigraw, _ := nkp.Sign([]byte(info.Nonce)) 104 sig := base64.RawURLEncoding.EncodeToString(sigraw) 105 106 cs := fmt.Sprintf("CONNECT {\"jwt\":%q,\"sig\":\"%s\"}\r\nPING\r\n", ujwt, sig) 107 return c, cr, cs 108 } 109 110 func setupJWTTestWithClaims(t *testing.T, nac *jwt.AccountClaims, nuc *jwt.UserClaims, expected string) (*Server, nkeys.KeyPair, *testAsyncClient, *bufio.Reader) { 111 t.Helper() 112 113 akp, _ := nkeys.CreateAccount() 114 apub, _ := akp.PublicKey() 115 if nac == nil { 116 nac = jwt.NewAccountClaims(apub) 117 } else { 118 nac.Subject = apub 119 } 120 ajwt, err := nac.Encode(oKp) 121 if err != nil { 122 t.Fatalf("Error generating account JWT: %v", err) 123 } 124 125 nkp, _ := nkeys.CreateUser() 126 pub, _ := nkp.PublicKey() 127 if nuc == nil { 128 nuc = jwt.NewUserClaims(pub) 129 } else { 130 nuc.Subject = pub 131 } 132 jwt, err := nuc.Encode(akp) 133 if err != nil { 134 t.Fatalf("Error generating user JWT: %v", err) 135 } 136 137 s := opTrustBasicSetup() 138 buildMemAccResolver(s) 139 addAccountToMemResolver(s, apub, ajwt) 140 141 c, cr, l := newClientForServer(s) 142 143 // Sign Nonce 144 var info nonceInfo 145 json.Unmarshal([]byte(l[5:]), &info) 146 sigraw, _ := nkp.Sign([]byte(info.Nonce)) 147 sig := base64.RawURLEncoding.EncodeToString(sigraw) 148 149 // PING needed to flush the +OK/-ERR to us. 150 cs := fmt.Sprintf("CONNECT {\"jwt\":%q,\"sig\":\"%s\",\"verbose\":true,\"pedantic\":true}\r\nPING\r\n", jwt, sig) 151 wg := sync.WaitGroup{} 152 wg.Add(1) 153 go func() { 154 c.parse([]byte(cs)) 155 wg.Done() 156 }() 157 l, _ = cr.ReadString('\n') 158 if !strings.HasPrefix(l, expected) { 159 t.Fatalf("Expected %q, got %q", expected, l) 160 } 161 wg.Wait() 162 163 return s, akp, c, cr 164 } 165 166 func setupJWTTestWitAccountClaims(t *testing.T, nac *jwt.AccountClaims, expected string) (*Server, nkeys.KeyPair, *testAsyncClient, *bufio.Reader) { 167 t.Helper() 168 return setupJWTTestWithClaims(t, nac, nil, expected) 169 } 170 171 // This is used in test to create account claims and pass it 172 // to setupJWTTestWitAccountClaims. 173 func newJWTTestAccountClaims() *jwt.AccountClaims { 174 // We call NewAccountClaims() because it sets some defaults. 175 // However, this call needs a subject, but the real subject will 176 // be set in setupJWTTestWitAccountClaims(). Use some temporary one 177 // here. 178 return jwt.NewAccountClaims("temp") 179 } 180 181 func setupJWTTestWithUserClaims(t *testing.T, nuc *jwt.UserClaims, expected string) (*Server, *testAsyncClient, *bufio.Reader) { 182 t.Helper() 183 s, _, c, cr := setupJWTTestWithClaims(t, nil, nuc, expected) 184 return s, c, cr 185 } 186 187 // This is used in test to create user claims and pass it 188 // to setupJWTTestWithUserClaims. 189 func newJWTTestUserClaims() *jwt.UserClaims { 190 // As of now, tests could simply do &jwt.UserClaims{}, but in 191 // case some defaults are later added, we call NewUserClaims(). 192 // However, this call needs a subject, but the real subject will 193 // be set in setupJWTTestWithUserClaims(). Use some temporary one 194 // here. 195 return jwt.NewUserClaims("temp") 196 } 197 198 func TestJWTUser(t *testing.T) { 199 s := opTrustBasicSetup() 200 defer s.Shutdown() 201 202 // Check to make sure we would have an authTimer 203 if !s.info.AuthRequired { 204 t.Fatalf("Expect the server to require auth") 205 } 206 207 c, cr, _ := newClientForServer(s) 208 defer c.close() 209 210 // Don't send jwt field, should fail. 211 c.parseAsync("CONNECT {\"verbose\":true,\"pedantic\":true}\r\nPING\r\n") 212 l, _ := cr.ReadString('\n') 213 if !strings.HasPrefix(l, "-ERR ") { 214 t.Fatalf("Expected an error") 215 } 216 217 okp, _ := nkeys.FromSeed(oSeed) 218 219 // Create an account that will be expired. 220 akp, _ := nkeys.CreateAccount() 221 apub, _ := akp.PublicKey() 222 nac := jwt.NewAccountClaims(apub) 223 ajwt, err := nac.Encode(okp) 224 if err != nil { 225 t.Fatalf("Error generating account JWT: %v", err) 226 } 227 228 c, cr, cs := createClient(t, s, akp) 229 defer c.close() 230 231 // PING needed to flush the +OK/-ERR to us. 232 // This should fail too since no account resolver is defined. 233 c.parseAsync(cs) 234 l, _ = cr.ReadString('\n') 235 if !strings.HasPrefix(l, "-ERR ") { 236 t.Fatalf("Expected an error") 237 } 238 239 // Ok now let's walk through and make sure all is good. 240 // We will set the account resolver by hand to a memory resolver. 241 buildMemAccResolver(s) 242 addAccountToMemResolver(s, apub, ajwt) 243 244 c, cr, cs = createClient(t, s, akp) 245 defer c.close() 246 247 c.parseAsync(cs) 248 l, _ = cr.ReadString('\n') 249 if !strings.HasPrefix(l, "PONG") { 250 t.Fatalf("Expected a PONG, got %q", l) 251 } 252 } 253 254 func TestJWTUserBadTrusted(t *testing.T) { 255 s := opTrustBasicSetup() 256 defer s.Shutdown() 257 258 // Check to make sure we would have an authTimer 259 if !s.info.AuthRequired { 260 t.Fatalf("Expect the server to require auth") 261 } 262 // Now place bad trusted key 263 s.mu.Lock() 264 s.trustedKeys = []string{"bad"} 265 s.mu.Unlock() 266 267 buildMemAccResolver(s) 268 269 okp, _ := nkeys.FromSeed(oSeed) 270 271 // Create an account that will be expired. 272 akp, _ := nkeys.CreateAccount() 273 apub, _ := akp.PublicKey() 274 nac := jwt.NewAccountClaims(apub) 275 ajwt, err := nac.Encode(okp) 276 if err != nil { 277 t.Fatalf("Error generating account JWT: %v", err) 278 } 279 addAccountToMemResolver(s, apub, ajwt) 280 281 c, cr, cs := createClient(t, s, akp) 282 defer c.close() 283 c.parseAsync(cs) 284 l, _ := cr.ReadString('\n') 285 if !strings.HasPrefix(l, "-ERR ") { 286 t.Fatalf("Expected an error") 287 } 288 } 289 290 // Test that if a user tries to connect with an expired user JWT we do the right thing. 291 func TestJWTUserExpired(t *testing.T) { 292 nuc := newJWTTestUserClaims() 293 nuc.IssuedAt = time.Now().Add(-10 * time.Second).Unix() 294 nuc.Expires = time.Now().Add(-2 * time.Second).Unix() 295 s, c, _ := setupJWTTestWithUserClaims(t, nuc, "-ERR ") 296 c.close() 297 s.Shutdown() 298 } 299 300 func TestJWTUserExpiresAfterConnect(t *testing.T) { 301 nuc := newJWTTestUserClaims() 302 nuc.IssuedAt = time.Now().Unix() 303 nuc.Expires = time.Now().Add(time.Second).Unix() 304 s, c, cr := setupJWTTestWithUserClaims(t, nuc, "+OK") 305 defer s.Shutdown() 306 defer c.close() 307 l, err := cr.ReadString('\n') 308 if err != nil { 309 t.Fatalf("Received %v", err) 310 } 311 if !strings.HasPrefix(l, "PONG") { 312 t.Fatalf("Expected a PONG") 313 } 314 315 // Now we should expire after 1 second or so. 316 time.Sleep(1250 * time.Millisecond) 317 318 l, err = cr.ReadString('\n') 319 if err != nil { 320 t.Fatalf("Received %v", err) 321 } 322 if !strings.HasPrefix(l, "-ERR ") { 323 t.Fatalf("Expected an error") 324 } 325 if !strings.Contains(l, "Expired") { 326 t.Fatalf("Expected 'Expired' to be in the error") 327 } 328 } 329 330 func TestJWTUserPermissionClaims(t *testing.T) { 331 nuc := newJWTTestUserClaims() 332 nuc.Permissions.Pub.Allow.Add("foo") 333 nuc.Permissions.Pub.Allow.Add("bar") 334 nuc.Permissions.Pub.Deny.Add("baz") 335 nuc.Permissions.Sub.Allow.Add("foo") 336 nuc.Permissions.Sub.Allow.Add("bar") 337 nuc.Permissions.Sub.Deny.Add("baz") 338 339 s, c, _ := setupJWTTestWithUserClaims(t, nuc, "+OK") 340 defer s.Shutdown() 341 defer c.close() 342 343 // Now check client to make sure permissions transferred. 344 c.mu.Lock() 345 defer c.mu.Unlock() 346 347 if c.perms == nil { 348 t.Fatalf("Expected client permissions to be set") 349 } 350 351 if lpa := c.perms.pub.allow.Count(); lpa != 2 { 352 t.Fatalf("Expected 2 publish allow subjects, got %d", lpa) 353 } 354 if lpd := c.perms.pub.deny.Count(); lpd != 1 { 355 t.Fatalf("Expected 1 publish deny subjects, got %d", lpd) 356 } 357 if lsa := c.perms.sub.allow.Count(); lsa != 2 { 358 t.Fatalf("Expected 2 subscribe allow subjects, got %d", lsa) 359 } 360 if lsd := c.perms.sub.deny.Count(); lsd != 1 { 361 t.Fatalf("Expected 1 subscribe deny subjects, got %d", lsd) 362 } 363 } 364 365 func TestJWTUserResponsePermissionClaims(t *testing.T) { 366 nuc := newJWTTestUserClaims() 367 nuc.Permissions.Resp = &jwt.ResponsePermission{ 368 MaxMsgs: 22, 369 Expires: 100 * time.Millisecond, 370 } 371 s, c, _ := setupJWTTestWithUserClaims(t, nuc, "+OK") 372 defer s.Shutdown() 373 defer c.close() 374 375 // Now check client to make sure permissions transferred. 376 c.mu.Lock() 377 defer c.mu.Unlock() 378 379 if c.perms == nil { 380 t.Fatalf("Expected client permissions to be set") 381 } 382 if c.perms.pub.allow == nil { 383 t.Fatalf("Expected client perms for pub allow to be non-nil") 384 } 385 if lpa := c.perms.pub.allow.Count(); lpa != 0 { 386 t.Fatalf("Expected 0 publish allow subjects, got %d", lpa) 387 } 388 if c.perms.resp == nil { 389 t.Fatalf("Expected client perms for response permissions to be non-nil") 390 } 391 if c.perms.resp.MaxMsgs != nuc.Permissions.Resp.MaxMsgs { 392 t.Fatalf("Expected client perms for response permissions MaxMsgs to be same as jwt: %d vs %d", 393 c.perms.resp.MaxMsgs, nuc.Permissions.Resp.MaxMsgs) 394 } 395 if c.perms.resp.Expires != nuc.Permissions.Resp.Expires { 396 t.Fatalf("Expected client perms for response permissions Expires to be same as jwt: %v vs %v", 397 c.perms.resp.Expires, nuc.Permissions.Resp.Expires) 398 } 399 } 400 401 func TestJWTUserResponsePermissionClaimsDefaultValues(t *testing.T) { 402 nuc := newJWTTestUserClaims() 403 nuc.Permissions.Resp = &jwt.ResponsePermission{} 404 s, c, _ := setupJWTTestWithUserClaims(t, nuc, "+OK") 405 defer s.Shutdown() 406 defer c.close() 407 408 // Now check client to make sure permissions transferred 409 // and defaults are set. 410 c.mu.Lock() 411 defer c.mu.Unlock() 412 413 if c.perms == nil { 414 t.Fatalf("Expected client permissions to be set") 415 } 416 if c.perms.pub.allow == nil { 417 t.Fatalf("Expected client perms for pub allow to be non-nil") 418 } 419 if lpa := c.perms.pub.allow.Count(); lpa != 0 { 420 t.Fatalf("Expected 0 publish allow subjects, got %d", lpa) 421 } 422 if c.perms.resp == nil { 423 t.Fatalf("Expected client perms for response permissions to be non-nil") 424 } 425 if c.perms.resp.MaxMsgs != DEFAULT_ALLOW_RESPONSE_MAX_MSGS { 426 t.Fatalf("Expected client perms for response permissions MaxMsgs to be default %v, got %v", 427 DEFAULT_ALLOW_RESPONSE_MAX_MSGS, c.perms.resp.MaxMsgs) 428 } 429 if c.perms.resp.Expires != DEFAULT_ALLOW_RESPONSE_EXPIRATION { 430 t.Fatalf("Expected client perms for response permissions Expires to be default %v, got %v", 431 DEFAULT_ALLOW_RESPONSE_EXPIRATION, c.perms.resp.Expires) 432 } 433 } 434 435 func TestJWTUserResponsePermissionClaimsNegativeValues(t *testing.T) { 436 nuc := newJWTTestUserClaims() 437 nuc.Permissions.Resp = &jwt.ResponsePermission{ 438 MaxMsgs: -1, 439 Expires: -1 * time.Second, 440 } 441 s, c, _ := setupJWTTestWithUserClaims(t, nuc, "+OK") 442 defer s.Shutdown() 443 defer c.close() 444 445 // Now check client to make sure permissions transferred 446 // and negative values are transferred. 447 c.mu.Lock() 448 defer c.mu.Unlock() 449 450 if c.perms == nil { 451 t.Fatalf("Expected client permissions to be set") 452 } 453 if c.perms.pub.allow == nil { 454 t.Fatalf("Expected client perms for pub allow to be non-nil") 455 } 456 if lpa := c.perms.pub.allow.Count(); lpa != 0 { 457 t.Fatalf("Expected 0 publish allow subjects, got %d", lpa) 458 } 459 if c.perms.resp == nil { 460 t.Fatalf("Expected client perms for response permissions to be non-nil") 461 } 462 if c.perms.resp.MaxMsgs != -1 { 463 t.Fatalf("Expected client perms for response permissions MaxMsgs to be %v, got %v", 464 -1, c.perms.resp.MaxMsgs) 465 } 466 if c.perms.resp.Expires != -1*time.Second { 467 t.Fatalf("Expected client perms for response permissions Expires to be %v, got %v", 468 -1*time.Second, c.perms.resp.Expires) 469 } 470 } 471 472 func TestJWTAccountExpired(t *testing.T) { 473 nac := newJWTTestAccountClaims() 474 nac.IssuedAt = time.Now().Add(-10 * time.Second).Unix() 475 nac.Expires = time.Now().Add(-2 * time.Second).Unix() 476 s, _, c, _ := setupJWTTestWitAccountClaims(t, nac, "-ERR ") 477 defer s.Shutdown() 478 defer c.close() 479 } 480 481 func TestJWTAccountExpiresAfterConnect(t *testing.T) { 482 nac := newJWTTestAccountClaims() 483 now := time.Now() 484 nac.IssuedAt = now.Add(-10 * time.Second).Unix() 485 nac.Expires = now.Round(time.Second).Add(time.Second).Unix() 486 s, akp, c, cr := setupJWTTestWitAccountClaims(t, nac, "+OK") 487 defer s.Shutdown() 488 defer c.close() 489 490 apub, _ := akp.PublicKey() 491 acc, err := s.LookupAccount(apub) 492 if acc == nil || err != nil { 493 t.Fatalf("Expected to retrieve the account") 494 } 495 496 if l, _ := cr.ReadString('\n'); !strings.HasPrefix(l, "PONG") { 497 t.Fatalf("Expected PONG, got %q", l) 498 } 499 500 // Wait for the account to be expired. 501 checkFor(t, 3*time.Second, 100*time.Millisecond, func() error { 502 if acc.IsExpired() { 503 return nil 504 } 505 return fmt.Errorf("Account not expired yet") 506 }) 507 508 l, _ := cr.ReadString('\n') 509 if !strings.HasPrefix(l, "-ERR ") { 510 t.Fatalf("Expected an error, got %q", l) 511 } 512 if !strings.Contains(l, "Expired") { 513 t.Fatalf("Expected 'Expired' to be in the error") 514 } 515 516 // Now make sure that accounts that have expired return an error. 517 c, cr, cs := createClient(t, s, akp) 518 defer c.close() 519 c.parseAsync(cs) 520 l, _ = cr.ReadString('\n') 521 if !strings.HasPrefix(l, "-ERR ") { 522 t.Fatalf("Expected an error") 523 } 524 } 525 526 func TestJWTAccountRenew(t *testing.T) { 527 nac := newJWTTestAccountClaims() 528 // Create an account that has expired. 529 nac.IssuedAt = time.Now().Add(-10 * time.Second).Unix() 530 nac.Expires = time.Now().Add(-2 * time.Second).Unix() 531 // Expect an error 532 s, akp, c, _ := setupJWTTestWitAccountClaims(t, nac, "-ERR ") 533 defer s.Shutdown() 534 defer c.close() 535 536 okp, _ := nkeys.FromSeed(oSeed) 537 apub, _ := akp.PublicKey() 538 539 // Now update with new expiration 540 nac.IssuedAt = time.Now().Unix() 541 nac.Expires = time.Now().Add(5 * time.Second).Unix() 542 ajwt, err := nac.Encode(okp) 543 if err != nil { 544 t.Fatalf("Error generating account JWT: %v", err) 545 } 546 547 // Update the account 548 addAccountToMemResolver(s, apub, ajwt) 549 acc, _ := s.LookupAccount(apub) 550 if acc == nil { 551 t.Fatalf("Expected to retrieve the account") 552 } 553 s.UpdateAccountClaims(acc, nac) 554 555 // Now make sure we can connect. 556 c, cr, cs := createClient(t, s, akp) 557 defer c.close() 558 c.parseAsync(cs) 559 if l, _ := cr.ReadString('\n'); !strings.HasPrefix(l, "PONG") { 560 t.Fatalf("Expected a PONG, got: %q", l) 561 } 562 } 563 564 func TestJWTAccountRenewFromResolver(t *testing.T) { 565 s := opTrustBasicSetup() 566 defer s.Shutdown() 567 buildMemAccResolver(s) 568 569 okp, _ := nkeys.FromSeed(oSeed) 570 571 akp, _ := nkeys.CreateAccount() 572 apub, _ := akp.PublicKey() 573 nac := jwt.NewAccountClaims(apub) 574 nac.IssuedAt = time.Now().Add(-10 * time.Second).Unix() 575 nac.Expires = time.Now().Add(time.Second).Unix() 576 ajwt, err := nac.Encode(okp) 577 if err != nil { 578 t.Fatalf("Error generating account JWT: %v", err) 579 } 580 581 addAccountToMemResolver(s, apub, ajwt) 582 // Force it to be loaded by the server and start the expiration timer. 583 acc, _ := s.LookupAccount(apub) 584 if acc == nil { 585 t.Fatalf("Could not retrieve account for %q", apub) 586 } 587 588 // Create a new user 589 c, cr, cs := createClient(t, s, akp) 590 defer c.close() 591 // Wait for expiration. 592 time.Sleep(1250 * time.Millisecond) 593 594 c.parseAsync(cs) 595 l, _ := cr.ReadString('\n') 596 if !strings.HasPrefix(l, "-ERR ") { 597 t.Fatalf("Expected an error") 598 } 599 600 // Now update with new expiration 601 nac.IssuedAt = time.Now().Unix() 602 nac.Expires = time.Now().Add(5 * time.Second).Unix() 603 ajwt, err = nac.Encode(okp) 604 if err != nil { 605 t.Fatalf("Error generating account JWT: %v", err) 606 } 607 608 // Update the account 609 addAccountToMemResolver(s, apub, ajwt) 610 // Make sure the too quick update suppression does not bite us. 611 acc.mu.Lock() 612 acc.updated = time.Now().UTC().Add(-1 * time.Hour) 613 acc.mu.Unlock() 614 615 // Do not update the account directly. The resolver should 616 // happen automatically. 617 618 // Now make sure we can connect. 619 c, cr, cs = createClient(t, s, akp) 620 defer c.close() 621 c.parseAsync(cs) 622 l, _ = cr.ReadString('\n') 623 if !strings.HasPrefix(l, "PONG") { 624 t.Fatalf("Expected a PONG, got: %q", l) 625 } 626 } 627 628 func TestJWTAccountBasicImportExport(t *testing.T) { 629 s := opTrustBasicSetup() 630 defer s.Shutdown() 631 buildMemAccResolver(s) 632 633 okp, _ := nkeys.FromSeed(oSeed) 634 635 // Create accounts and imports/exports. 636 fooKP, _ := nkeys.CreateAccount() 637 fooPub, _ := fooKP.PublicKey() 638 fooAC := jwt.NewAccountClaims(fooPub) 639 640 // Now create Exports. 641 streamExport := &jwt.Export{Subject: "foo", Type: jwt.Stream} 642 streamExport2 := &jwt.Export{Subject: "private", Type: jwt.Stream, TokenReq: true} 643 serviceExport := &jwt.Export{Subject: "req.echo", Type: jwt.Service, TokenReq: true} 644 serviceExport2 := &jwt.Export{Subject: "req.add", Type: jwt.Service, TokenReq: true} 645 646 fooAC.Exports.Add(streamExport, streamExport2, serviceExport, serviceExport2) 647 fooJWT, err := fooAC.Encode(okp) 648 if err != nil { 649 t.Fatalf("Error generating account JWT: %v", err) 650 } 651 652 addAccountToMemResolver(s, fooPub, fooJWT) 653 654 acc, _ := s.LookupAccount(fooPub) 655 if acc == nil { 656 t.Fatalf("Expected to retrieve the account") 657 } 658 659 // Check to make sure exports transferred over. 660 if les := len(acc.exports.streams); les != 2 { 661 t.Fatalf("Expected exports streams len of 2, got %d", les) 662 } 663 if les := len(acc.exports.services); les != 2 { 664 t.Fatalf("Expected exports services len of 2, got %d", les) 665 } 666 _, ok := acc.exports.streams["foo"] 667 if !ok { 668 t.Fatalf("Expected to map a stream export") 669 } 670 se, ok := acc.exports.services["req.echo"] 671 if !ok || se == nil { 672 t.Fatalf("Expected to map a service export") 673 } 674 if !se.tokenReq { 675 t.Fatalf("Expected the service export to require tokens") 676 } 677 678 barKP, _ := nkeys.CreateAccount() 679 barPub, _ := barKP.PublicKey() 680 barAC := jwt.NewAccountClaims(barPub) 681 682 streamImport := &jwt.Import{Account: fooPub, Subject: "foo", To: "import.foo", Type: jwt.Stream} 683 serviceImport := &jwt.Import{Account: fooPub, Subject: "req.echo", Type: jwt.Service} 684 barAC.Imports.Add(streamImport, serviceImport) 685 barJWT, err := barAC.Encode(okp) 686 if err != nil { 687 t.Fatalf("Error generating account JWT: %v", err) 688 } 689 addAccountToMemResolver(s, barPub, barJWT) 690 691 acc, _ = s.LookupAccount(barPub) 692 if acc == nil { 693 t.Fatalf("Expected to retrieve the account") 694 } 695 if les := len(acc.imports.streams); les != 1 { 696 t.Fatalf("Expected imports streams len of 1, got %d", les) 697 } 698 // Our service import should have failed without a token. 699 if les := len(acc.imports.services); les != 0 { 700 t.Fatalf("Expected imports services len of 0, got %d", les) 701 } 702 703 // Now add in a bad activation token. 704 barAC = jwt.NewAccountClaims(barPub) 705 serviceImport = &jwt.Import{Account: fooPub, Subject: "req.echo", Token: "not a token", Type: jwt.Service} 706 barAC.Imports.Add(serviceImport) 707 barJWT, err = barAC.Encode(okp) 708 if err != nil { 709 t.Fatalf("Error generating account JWT: %v", err) 710 } 711 addAccountToMemResolver(s, barPub, barJWT) 712 713 s.UpdateAccountClaims(acc, barAC) 714 715 // Our service import should have failed with a bad token. 716 if les := len(acc.imports.services); les != 0 { 717 t.Fatalf("Expected imports services len of 0, got %d", les) 718 } 719 720 // Now make a correct one. 721 barAC = jwt.NewAccountClaims(barPub) 722 serviceImport = &jwt.Import{Account: fooPub, Subject: "req.echo", Type: jwt.Service} 723 724 activation := jwt.NewActivationClaims(barPub) 725 activation.ImportSubject = "req.echo" 726 activation.ImportType = jwt.Service 727 actJWT, err := activation.Encode(fooKP) 728 if err != nil { 729 t.Fatalf("Error generating activation token: %v", err) 730 } 731 serviceImport.Token = actJWT 732 barAC.Imports.Add(serviceImport) 733 barJWT, err = barAC.Encode(okp) 734 if err != nil { 735 t.Fatalf("Error generating account JWT: %v", err) 736 } 737 738 vr := jwt.ValidationResults{} 739 barAC.Validate(&vr) 740 if vr.IsBlocking(true) { 741 t.Fatalf("Error generating account JWT: %v", vr) 742 } 743 744 addAccountToMemResolver(s, barPub, barJWT) 745 s.UpdateAccountClaims(acc, barAC) 746 // Our service import should have succeeded. 747 if les := len(acc.imports.services); les != 1 { 748 t.Fatalf("Expected imports services len of 1, got %d", les) 749 } 750 751 // Now streams 752 barAC = jwt.NewAccountClaims(barPub) 753 streamImport = &jwt.Import{Account: fooPub, Subject: "private", To: "import.private", Type: jwt.Stream} 754 755 barAC.Imports.Add(streamImport) 756 barJWT, err = barAC.Encode(okp) 757 if err != nil { 758 t.Fatalf("Error generating account JWT: %v", err) 759 } 760 addAccountToMemResolver(s, barPub, barJWT) 761 s.UpdateAccountClaims(acc, barAC) 762 // Our stream import should have not succeeded. 763 if les := len(acc.imports.streams); les != 0 { 764 t.Fatalf("Expected imports services len of 0, got %d", les) 765 } 766 767 // Now add in activation. 768 barAC = jwt.NewAccountClaims(barPub) 769 streamImport = &jwt.Import{Account: fooPub, Subject: "private", To: "import.private", Type: jwt.Stream} 770 771 activation = jwt.NewActivationClaims(barPub) 772 activation.ImportSubject = "private" 773 activation.ImportType = jwt.Stream 774 actJWT, err = activation.Encode(fooKP) 775 if err != nil { 776 t.Fatalf("Error generating activation token: %v", err) 777 } 778 streamImport.Token = actJWT 779 barAC.Imports.Add(streamImport) 780 barJWT, err = barAC.Encode(okp) 781 if err != nil { 782 t.Fatalf("Error generating account JWT: %v", err) 783 } 784 addAccountToMemResolver(s, barPub, barJWT) 785 s.UpdateAccountClaims(acc, barAC) 786 // Our stream import should have not succeeded. 787 if les := len(acc.imports.streams); les != 1 { 788 t.Fatalf("Expected imports services len of 1, got %d", les) 789 } 790 } 791 792 func TestJWTAccountExportWithResponseType(t *testing.T) { 793 s := opTrustBasicSetup() 794 defer s.Shutdown() 795 buildMemAccResolver(s) 796 797 okp, _ := nkeys.FromSeed(oSeed) 798 799 // Create accounts and imports/exports. 800 fooKP, _ := nkeys.CreateAccount() 801 fooPub, _ := fooKP.PublicKey() 802 fooAC := jwt.NewAccountClaims(fooPub) 803 804 // Now create Exports. 805 serviceStreamExport := &jwt.Export{Subject: "test.stream", Type: jwt.Service, ResponseType: jwt.ResponseTypeStream, TokenReq: false} 806 serviceChunkExport := &jwt.Export{Subject: "test.chunk", Type: jwt.Service, ResponseType: jwt.ResponseTypeChunked, TokenReq: false} 807 serviceSingletonExport := &jwt.Export{Subject: "test.single", Type: jwt.Service, ResponseType: jwt.ResponseTypeSingleton, TokenReq: true} 808 serviceDefExport := &jwt.Export{Subject: "test.def", Type: jwt.Service, TokenReq: true} 809 serviceOldExport := &jwt.Export{Subject: "test.old", Type: jwt.Service, TokenReq: false} 810 811 fooAC.Exports.Add(serviceStreamExport, serviceSingletonExport, serviceChunkExport, serviceDefExport, serviceOldExport) 812 fooJWT, err := fooAC.Encode(okp) 813 if err != nil { 814 t.Fatalf("Error generating account JWT: %v", err) 815 } 816 817 addAccountToMemResolver(s, fooPub, fooJWT) 818 819 fooAcc, _ := s.LookupAccount(fooPub) 820 if fooAcc == nil { 821 t.Fatalf("Expected to retrieve the account") 822 } 823 824 services := fooAcc.exports.services 825 826 if len(services) != 5 { 827 t.Fatalf("Expected 4 services") 828 } 829 830 se, ok := services["test.stream"] 831 if !ok || se == nil { 832 t.Fatalf("Expected to map a service export") 833 } 834 if se.tokenReq { 835 t.Fatalf("Expected the service export to not require tokens") 836 } 837 if se.respType != Streamed { 838 t.Fatalf("Expected the service export to respond with a stream") 839 } 840 841 se, ok = services["test.chunk"] 842 if !ok || se == nil { 843 t.Fatalf("Expected to map a service export") 844 } 845 if se.tokenReq { 846 t.Fatalf("Expected the service export to not require tokens") 847 } 848 if se.respType != Chunked { 849 t.Fatalf("Expected the service export to respond with a stream") 850 } 851 852 se, ok = services["test.def"] 853 if !ok || se == nil { 854 t.Fatalf("Expected to map a service export") 855 } 856 if !se.tokenReq { 857 t.Fatalf("Expected the service export to not require tokens") 858 } 859 if se.respType != Singleton { 860 t.Fatalf("Expected the service export to respond with a stream") 861 } 862 863 se, ok = services["test.single"] 864 if !ok || se == nil { 865 t.Fatalf("Expected to map a service export") 866 } 867 if !se.tokenReq { 868 t.Fatalf("Expected the service export to not require tokens") 869 } 870 if se.respType != Singleton { 871 t.Fatalf("Expected the service export to respond with a stream") 872 } 873 874 se, ok = services["test.old"] 875 if !ok || se == nil || len(se.approved) > 0 { 876 t.Fatalf("Service with a singleton response and no tokens should not be nil and have no approvals") 877 } 878 } 879 880 func expectPong(t *testing.T, cr *bufio.Reader) { 881 t.Helper() 882 l, _ := cr.ReadString('\n') 883 if !strings.HasPrefix(l, "PONG") { 884 t.Fatalf("Expected a PONG, got %q", l) 885 } 886 } 887 888 func expectMsg(t *testing.T, cr *bufio.Reader, sub, payload string) { 889 t.Helper() 890 l, _ := cr.ReadString('\n') 891 expected := "MSG " + sub 892 if !strings.HasPrefix(l, expected) { 893 t.Fatalf("Expected %q, got %q", expected, l) 894 } 895 l, _ = cr.ReadString('\n') 896 if l != payload+"\r\n" { 897 t.Fatalf("Expected %q, got %q", payload, l) 898 } 899 expectPong(t, cr) 900 } 901 902 func TestJWTAccountImportExportUpdates(t *testing.T) { 903 s := opTrustBasicSetup() 904 defer s.Shutdown() 905 buildMemAccResolver(s) 906 907 okp, _ := nkeys.FromSeed(oSeed) 908 909 // Create accounts and imports/exports. 910 fooKP, _ := nkeys.CreateAccount() 911 fooPub, _ := fooKP.PublicKey() 912 fooAC := jwt.NewAccountClaims(fooPub) 913 streamExport := &jwt.Export{Subject: "foo", Type: jwt.Stream} 914 915 fooAC.Exports.Add(streamExport) 916 fooJWT, err := fooAC.Encode(okp) 917 if err != nil { 918 t.Fatalf("Error generating account JWT: %v", err) 919 } 920 addAccountToMemResolver(s, fooPub, fooJWT) 921 922 barKP, _ := nkeys.CreateAccount() 923 barPub, _ := barKP.PublicKey() 924 barAC := jwt.NewAccountClaims(barPub) 925 streamImport := &jwt.Import{Account: fooPub, Subject: "foo", To: "import", Type: jwt.Stream} 926 927 barAC.Imports.Add(streamImport) 928 barJWT, err := barAC.Encode(okp) 929 if err != nil { 930 t.Fatalf("Error generating account JWT: %v", err) 931 } 932 addAccountToMemResolver(s, barPub, barJWT) 933 934 // Create a client. 935 c, cr, cs := createClient(t, s, barKP) 936 defer c.close() 937 938 c.parseAsync(cs) 939 expectPong(t, cr) 940 941 c.parseAsync("SUB import.foo 1\r\nPING\r\n") 942 expectPong(t, cr) 943 944 checkShadow := func(expected int) { 945 t.Helper() 946 c.mu.Lock() 947 defer c.mu.Unlock() 948 sub := c.subs["1"] 949 if ls := len(sub.shadow); ls != expected { 950 t.Fatalf("Expected shadows to be %d, got %d", expected, ls) 951 } 952 } 953 954 // We created a SUB on foo which should create a shadow subscription. 955 checkShadow(1) 956 957 // Now update bar and remove the import which should make the shadow go away. 958 barAC = jwt.NewAccountClaims(barPub) 959 barJWT, _ = barAC.Encode(okp) 960 addAccountToMemResolver(s, barPub, barJWT) 961 acc, _ := s.LookupAccount(barPub) 962 s.UpdateAccountClaims(acc, barAC) 963 964 checkShadow(0) 965 966 // Now add it back and make sure the shadow comes back. 967 streamImport = &jwt.Import{Account: string(fooPub), Subject: "foo", To: "import", Type: jwt.Stream} 968 barAC.Imports.Add(streamImport) 969 barJWT, _ = barAC.Encode(okp) 970 addAccountToMemResolver(s, barPub, barJWT) 971 s.UpdateAccountClaims(acc, barAC) 972 973 checkShadow(1) 974 975 // Now change export and make sure it goes away as well. So no exports anymore. 976 fooAC = jwt.NewAccountClaims(fooPub) 977 fooJWT, _ = fooAC.Encode(okp) 978 addAccountToMemResolver(s, fooPub, fooJWT) 979 acc, _ = s.LookupAccount(fooPub) 980 s.UpdateAccountClaims(acc, fooAC) 981 checkShadow(0) 982 983 // Now add it in but with permission required. 984 streamExport = &jwt.Export{Subject: "foo", Type: jwt.Stream, TokenReq: true} 985 fooAC.Exports.Add(streamExport) 986 fooJWT, _ = fooAC.Encode(okp) 987 addAccountToMemResolver(s, fooPub, fooJWT) 988 s.UpdateAccountClaims(acc, fooAC) 989 990 checkShadow(0) 991 992 // Now put it back as normal. 993 fooAC = jwt.NewAccountClaims(fooPub) 994 streamExport = &jwt.Export{Subject: "foo", Type: jwt.Stream} 995 fooAC.Exports.Add(streamExport) 996 fooJWT, _ = fooAC.Encode(okp) 997 addAccountToMemResolver(s, fooPub, fooJWT) 998 s.UpdateAccountClaims(acc, fooAC) 999 1000 checkShadow(1) 1001 } 1002 1003 func TestJWTAccountImportActivationExpires(t *testing.T) { 1004 s := opTrustBasicSetup() 1005 defer s.Shutdown() 1006 buildMemAccResolver(s) 1007 1008 okp, _ := nkeys.FromSeed(oSeed) 1009 1010 // Create accounts and imports/exports. 1011 fooKP, _ := nkeys.CreateAccount() 1012 fooPub, _ := fooKP.PublicKey() 1013 fooAC := jwt.NewAccountClaims(fooPub) 1014 streamExport := &jwt.Export{Subject: "foo", Type: jwt.Stream, TokenReq: true} 1015 fooAC.Exports.Add(streamExport) 1016 1017 fooJWT, err := fooAC.Encode(okp) 1018 if err != nil { 1019 t.Fatalf("Error generating account JWT: %v", err) 1020 } 1021 1022 addAccountToMemResolver(s, fooPub, fooJWT) 1023 acc, _ := s.LookupAccount(fooPub) 1024 if acc == nil { 1025 t.Fatalf("Expected to retrieve the account") 1026 } 1027 1028 barKP, _ := nkeys.CreateAccount() 1029 barPub, _ := barKP.PublicKey() 1030 barAC := jwt.NewAccountClaims(barPub) 1031 streamImport := &jwt.Import{Account: fooPub, Subject: "foo", To: "import.", Type: jwt.Stream} 1032 1033 activation := jwt.NewActivationClaims(barPub) 1034 activation.ImportSubject = "foo" 1035 activation.ImportType = jwt.Stream 1036 now := time.Now() 1037 activation.IssuedAt = now.Add(-10 * time.Second).Unix() 1038 // These are second resolution. So round up before adding a second. 1039 activation.Expires = now.Round(time.Second).Add(time.Second).Unix() 1040 actJWT, err := activation.Encode(fooKP) 1041 if err != nil { 1042 t.Fatalf("Error generating activation token: %v", err) 1043 } 1044 streamImport.Token = actJWT 1045 barAC.Imports.Add(streamImport) 1046 barJWT, err := barAC.Encode(okp) 1047 if err != nil { 1048 t.Fatalf("Error generating account JWT: %v", err) 1049 } 1050 addAccountToMemResolver(s, barPub, barJWT) 1051 if acc, _ := s.LookupAccount(barPub); acc == nil { 1052 t.Fatalf("Expected to retrieve the account") 1053 } 1054 1055 // Create a client. 1056 c, cr, cs := createClient(t, s, barKP) 1057 defer c.close() 1058 1059 c.parseAsync(cs) 1060 expectPong(t, cr) 1061 1062 c.parseAsync("SUB import.foo 1\r\nPING\r\n") 1063 expectPong(t, cr) 1064 1065 checkShadow := func(t *testing.T, expected int) { 1066 t.Helper() 1067 checkFor(t, 3*time.Second, 15*time.Millisecond, func() error { 1068 c.mu.Lock() 1069 defer c.mu.Unlock() 1070 sub := c.subs["1"] 1071 if ls := len(sub.shadow); ls != expected { 1072 return fmt.Errorf("Expected shadows to be %d, got %d", expected, ls) 1073 } 1074 return nil 1075 }) 1076 } 1077 1078 // We created a SUB on foo which should create a shadow subscription. 1079 checkShadow(t, 1) 1080 1081 time.Sleep(1250 * time.Millisecond) 1082 1083 // Should have expired and been removed. 1084 checkShadow(t, 0) 1085 } 1086 1087 func TestJWTAccountLimitsSubs(t *testing.T) { 1088 fooAC := newJWTTestAccountClaims() 1089 fooAC.Limits.Subs = 10 1090 s, fooKP, c, _ := setupJWTTestWitAccountClaims(t, fooAC, "+OK") 1091 defer s.Shutdown() 1092 defer c.close() 1093 1094 okp, _ := nkeys.FromSeed(oSeed) 1095 fooPub, _ := fooKP.PublicKey() 1096 1097 // Create a client. 1098 c, cr, cs := createClient(t, s, fooKP) 1099 defer c.close() 1100 1101 c.parseAsync(cs) 1102 expectPong(t, cr) 1103 1104 // Check to make sure we have the limit set. 1105 // Account first 1106 fooAcc, _ := s.LookupAccount(fooPub) 1107 fooAcc.mu.RLock() 1108 if fooAcc.msubs != 10 { 1109 fooAcc.mu.RUnlock() 1110 t.Fatalf("Expected account to have msubs of 10, got %d", fooAcc.msubs) 1111 } 1112 fooAcc.mu.RUnlock() 1113 // Now test that the client has limits too. 1114 c.mu.Lock() 1115 if c.msubs != 10 { 1116 c.mu.Unlock() 1117 t.Fatalf("Expected client msubs to be 10, got %d", c.msubs) 1118 } 1119 c.mu.Unlock() 1120 1121 // Now make sure its enforced. 1122 /// These should all work ok. 1123 for i := 0; i < 10; i++ { 1124 c.parseAsync(fmt.Sprintf("SUB foo %d\r\nPING\r\n", i)) 1125 expectPong(t, cr) 1126 } 1127 1128 // This one should fail. 1129 c.parseAsync("SUB foo 22\r\n") 1130 l, _ := cr.ReadString('\n') 1131 if !strings.HasPrefix(l, "-ERR") { 1132 t.Fatalf("Expected an ERR, got: %v", l) 1133 } 1134 if !strings.Contains(l, "maximum subscriptions exceeded") { 1135 t.Fatalf("Expected an ERR for max subscriptions exceeded, got: %v", l) 1136 } 1137 1138 // Now update the claims and expect if max is lower to be disconnected. 1139 fooAC.Limits.Subs = 5 1140 fooJWT, err := fooAC.Encode(okp) 1141 if err != nil { 1142 t.Fatalf("Error generating account JWT: %v", err) 1143 } 1144 addAccountToMemResolver(s, fooPub, fooJWT) 1145 s.UpdateAccountClaims(fooAcc, fooAC) 1146 l, _ = cr.ReadString('\n') 1147 if !strings.HasPrefix(l, "-ERR") { 1148 t.Fatalf("Expected an ERR, got: %v", l) 1149 } 1150 if !strings.Contains(l, "maximum subscriptions exceeded") { 1151 t.Fatalf("Expected an ERR for max subscriptions exceeded, got: %v", l) 1152 } 1153 } 1154 1155 func TestJWTAccountLimitsSubsButServerOverrides(t *testing.T) { 1156 s := opTrustBasicSetup() 1157 defer s.Shutdown() 1158 buildMemAccResolver(s) 1159 1160 // override with server setting of 2. 1161 opts := s.getOpts() 1162 opts.MaxSubs = 2 1163 1164 okp, _ := nkeys.FromSeed(oSeed) 1165 1166 // Create accounts and imports/exports. 1167 fooKP, _ := nkeys.CreateAccount() 1168 fooPub, _ := fooKP.PublicKey() 1169 fooAC := jwt.NewAccountClaims(fooPub) 1170 fooAC.Limits.Subs = 10 1171 fooJWT, err := fooAC.Encode(okp) 1172 if err != nil { 1173 t.Fatalf("Error generating account JWT: %v", err) 1174 } 1175 addAccountToMemResolver(s, fooPub, fooJWT) 1176 fooAcc, _ := s.LookupAccount(fooPub) 1177 fooAcc.mu.RLock() 1178 if fooAcc.msubs != 10 { 1179 fooAcc.mu.RUnlock() 1180 t.Fatalf("Expected account to have msubs of 10, got %d", fooAcc.msubs) 1181 } 1182 fooAcc.mu.RUnlock() 1183 1184 // Create a client. 1185 c, cr, cs := createClient(t, s, fooKP) 1186 defer c.close() 1187 1188 c.parseAsync(cs) 1189 expectPong(t, cr) 1190 1191 c.parseAsync("SUB foo 1\r\nSUB bar 2\r\nSUB baz 3\r\nPING\r\n") 1192 l, _ := cr.ReadString('\n') 1193 1194 if !strings.HasPrefix(l, "-ERR ") { 1195 t.Fatalf("Expected an error") 1196 } 1197 if !strings.Contains(l, "maximum subscriptions exceeded") { 1198 t.Fatalf("Expected an ERR for max subscriptions exceeded, got: %v", l) 1199 } 1200 // Read last PONG so does not hold up test. 1201 cr.ReadString('\n') 1202 } 1203 1204 func TestJWTAccountLimitsMaxPayload(t *testing.T) { 1205 fooAC := newJWTTestAccountClaims() 1206 fooAC.Limits.Payload = 8 1207 s, fooKP, c, _ := setupJWTTestWitAccountClaims(t, fooAC, "+OK") 1208 defer s.Shutdown() 1209 defer c.close() 1210 1211 fooPub, _ := fooKP.PublicKey() 1212 1213 // Create a client. 1214 c, cr, cs := createClient(t, s, fooKP) 1215 defer c.close() 1216 1217 c.parseAsync(cs) 1218 expectPong(t, cr) 1219 1220 // Check to make sure we have the limit set. 1221 // Account first 1222 fooAcc, _ := s.LookupAccount(fooPub) 1223 fooAcc.mu.RLock() 1224 if fooAcc.mpay != 8 { 1225 fooAcc.mu.RUnlock() 1226 t.Fatalf("Expected account to have mpay of 8, got %d", fooAcc.mpay) 1227 } 1228 fooAcc.mu.RUnlock() 1229 // Now test that the client has limits too. 1230 c.mu.Lock() 1231 if c.mpay != 8 { 1232 c.mu.Unlock() 1233 t.Fatalf("Expected client to have mpay of 10, got %d", c.mpay) 1234 } 1235 c.mu.Unlock() 1236 1237 c.parseAsync("PUB foo 4\r\nXXXX\r\nPING\r\n") 1238 expectPong(t, cr) 1239 1240 c.parseAsync("PUB foo 10\r\nXXXXXXXXXX\r\nPING\r\n") 1241 l, _ := cr.ReadString('\n') 1242 if !strings.HasPrefix(l, "-ERR ") { 1243 t.Fatalf("Expected an error") 1244 } 1245 if !strings.Contains(l, "Maximum Payload") { 1246 t.Fatalf("Expected an ERR for max payload violation, got: %v", l) 1247 } 1248 } 1249 1250 func TestJWTAccountLimitsMaxPayloadButServerOverrides(t *testing.T) { 1251 s := opTrustBasicSetup() 1252 defer s.Shutdown() 1253 buildMemAccResolver(s) 1254 1255 // override with server setting of 4. 1256 opts := s.getOpts() 1257 opts.MaxPayload = 4 1258 1259 okp, _ := nkeys.FromSeed(oSeed) 1260 1261 // Create accounts and imports/exports. 1262 fooKP, _ := nkeys.CreateAccount() 1263 fooPub, _ := fooKP.PublicKey() 1264 fooAC := jwt.NewAccountClaims(fooPub) 1265 fooAC.Limits.Payload = 8 1266 fooJWT, err := fooAC.Encode(okp) 1267 if err != nil { 1268 t.Fatalf("Error generating account JWT: %v", err) 1269 } 1270 addAccountToMemResolver(s, fooPub, fooJWT) 1271 1272 // Create a client. 1273 c, cr, cs := createClient(t, s, fooKP) 1274 defer c.close() 1275 1276 c.parseAsync(cs) 1277 expectPong(t, cr) 1278 1279 c.parseAsync("PUB foo 6\r\nXXXXXX\r\nPING\r\n") 1280 l, _ := cr.ReadString('\n') 1281 if !strings.HasPrefix(l, "-ERR ") { 1282 t.Fatalf("Expected an error") 1283 } 1284 if !strings.Contains(l, "Maximum Payload") { 1285 t.Fatalf("Expected an ERR for max payload violation, got: %v", l) 1286 } 1287 } 1288 1289 func TestJWTAccountLimitsMaxConns(t *testing.T) { 1290 fooAC := newJWTTestAccountClaims() 1291 fooAC.Limits.Conn = 8 1292 s, fooKP, c, _ := setupJWTTestWitAccountClaims(t, fooAC, "+OK") 1293 defer s.Shutdown() 1294 defer c.close() 1295 1296 newClient := func(expPre string) *testAsyncClient { 1297 t.Helper() 1298 // Create a client. 1299 c, cr, cs := createClient(t, s, fooKP) 1300 c.parseAsync(cs) 1301 l, _ := cr.ReadString('\n') 1302 if !strings.HasPrefix(l, expPre) { 1303 t.Fatalf("Expected a response starting with %q, got %q", expPre, l) 1304 } 1305 return c 1306 } 1307 1308 // A connection is created in setupJWTTestWitAccountClaims(), so limit 1309 // to 7 here (8 total). 1310 for i := 0; i < 7; i++ { 1311 c := newClient("PONG") 1312 defer c.close() 1313 } 1314 // Now this one should fail. 1315 c = newClient("-ERR ") 1316 c.close() 1317 } 1318 1319 // This will test that we can switch from a public export to a private 1320 // one and back with export claims to make sure the claim update mechanism 1321 // is working properly. 1322 func TestJWTAccountServiceImportAuthSwitch(t *testing.T) { 1323 s := opTrustBasicSetup() 1324 defer s.Shutdown() 1325 buildMemAccResolver(s) 1326 1327 okp, _ := nkeys.FromSeed(oSeed) 1328 1329 // Create accounts and imports/exports. 1330 fooKP, _ := nkeys.CreateAccount() 1331 fooPub, _ := fooKP.PublicKey() 1332 fooAC := jwt.NewAccountClaims(fooPub) 1333 serviceExport := &jwt.Export{Subject: "ngs.usage.*", Type: jwt.Service} 1334 fooAC.Exports.Add(serviceExport) 1335 fooJWT, err := fooAC.Encode(okp) 1336 if err != nil { 1337 t.Fatalf("Error generating account JWT: %v", err) 1338 } 1339 addAccountToMemResolver(s, fooPub, fooJWT) 1340 1341 barKP, _ := nkeys.CreateAccount() 1342 barPub, _ := barKP.PublicKey() 1343 barAC := jwt.NewAccountClaims(barPub) 1344 serviceImport := &jwt.Import{Account: fooPub, Subject: "ngs.usage", To: "ngs.usage.DEREK", Type: jwt.Service} 1345 barAC.Imports.Add(serviceImport) 1346 barJWT, err := barAC.Encode(okp) 1347 if err != nil { 1348 t.Fatalf("Error generating account JWT: %v", err) 1349 } 1350 addAccountToMemResolver(s, barPub, barJWT) 1351 1352 // Create a client that will send the request 1353 ca, cra, csa := createClient(t, s, barKP) 1354 defer ca.close() 1355 ca.parseAsync(csa) 1356 expectPong(t, cra) 1357 1358 // Create the client that will respond to the requests. 1359 cb, crb, csb := createClient(t, s, fooKP) 1360 defer cb.close() 1361 cb.parseAsync(csb) 1362 expectPong(t, crb) 1363 1364 // Create Subscriber. 1365 cb.parseAsync("SUB ngs.usage.* 1\r\nPING\r\n") 1366 expectPong(t, crb) 1367 1368 // Send Request 1369 ca.parseAsync("PUB ngs.usage 2\r\nhi\r\nPING\r\n") 1370 expectPong(t, cra) 1371 1372 // We should receive the request mapped into our account. PING needed to flush. 1373 cb.parseAsync("PING\r\n") 1374 expectMsg(t, crb, "ngs.usage.DEREK", "hi") 1375 1376 // Now update to make the export private. 1377 fooACPrivate := jwt.NewAccountClaims(fooPub) 1378 serviceExport = &jwt.Export{Subject: "ngs.usage.*", Type: jwt.Service, TokenReq: true} 1379 fooACPrivate.Exports.Add(serviceExport) 1380 fooJWTPrivate, err := fooACPrivate.Encode(okp) 1381 if err != nil { 1382 t.Fatalf("Error generating account JWT: %v", err) 1383 } 1384 addAccountToMemResolver(s, fooPub, fooJWTPrivate) 1385 acc, _ := s.LookupAccount(fooPub) 1386 s.UpdateAccountClaims(acc, fooACPrivate) 1387 1388 // Send Another Request 1389 ca.parseAsync("PUB ngs.usage 2\r\nhi\r\nPING\r\n") 1390 expectPong(t, cra) 1391 1392 // We should not receive the request this time. 1393 cb.parseAsync("PING\r\n") 1394 expectPong(t, crb) 1395 1396 // Now put it back again to public and make sure it works again. 1397 addAccountToMemResolver(s, fooPub, fooJWT) 1398 s.UpdateAccountClaims(acc, fooAC) 1399 1400 // Send Request 1401 ca.parseAsync("PUB ngs.usage 2\r\nhi\r\nPING\r\n") 1402 expectPong(t, cra) 1403 1404 // We should receive the request mapped into our account. PING needed to flush. 1405 cb.parseAsync("PING\r\n") 1406 expectMsg(t, crb, "ngs.usage.DEREK", "hi") 1407 } 1408 1409 func TestJWTAccountServiceImportExpires(t *testing.T) { 1410 s := opTrustBasicSetup() 1411 defer s.Shutdown() 1412 buildMemAccResolver(s) 1413 1414 okp, _ := nkeys.FromSeed(oSeed) 1415 1416 // Create accounts and imports/exports. 1417 fooKP, _ := nkeys.CreateAccount() 1418 fooPub, _ := fooKP.PublicKey() 1419 fooAC := jwt.NewAccountClaims(fooPub) 1420 serviceExport := &jwt.Export{Subject: "foo", Type: jwt.Service} 1421 1422 fooAC.Exports.Add(serviceExport) 1423 fooJWT, err := fooAC.Encode(okp) 1424 if err != nil { 1425 t.Fatalf("Error generating account JWT: %v", err) 1426 } 1427 addAccountToMemResolver(s, fooPub, fooJWT) 1428 1429 barKP, _ := nkeys.CreateAccount() 1430 barPub, _ := barKP.PublicKey() 1431 barAC := jwt.NewAccountClaims(barPub) 1432 serviceImport := &jwt.Import{Account: fooPub, Subject: "foo", Type: jwt.Service} 1433 1434 barAC.Imports.Add(serviceImport) 1435 barJWT, err := barAC.Encode(okp) 1436 if err != nil { 1437 t.Fatalf("Error generating account JWT: %v", err) 1438 } 1439 addAccountToMemResolver(s, barPub, barJWT) 1440 1441 // Create a client that will send the request 1442 ca, cra, csa := createClient(t, s, barKP) 1443 defer ca.close() 1444 ca.parseAsync(csa) 1445 expectPong(t, cra) 1446 1447 // Create the client that will respond to the requests. 1448 cb, crb, csb := createClient(t, s, fooKP) 1449 defer cb.close() 1450 cb.parseAsync(csb) 1451 expectPong(t, crb) 1452 1453 // Create Subscriber. 1454 cb.parseAsync("SUB foo 1\r\nPING\r\n") 1455 expectPong(t, crb) 1456 1457 // Send Request 1458 ca.parseAsync("PUB foo 2\r\nhi\r\nPING\r\n") 1459 expectPong(t, cra) 1460 1461 // We should receive the request. PING needed to flush. 1462 cb.parseAsync("PING\r\n") 1463 expectMsg(t, crb, "foo", "hi") 1464 1465 // Now update the exported service to require auth. 1466 fooAC = jwt.NewAccountClaims(fooPub) 1467 serviceExport = &jwt.Export{Subject: "foo", Type: jwt.Service, TokenReq: true} 1468 1469 fooAC.Exports.Add(serviceExport) 1470 fooJWT, err = fooAC.Encode(okp) 1471 if err != nil { 1472 t.Fatalf("Error generating account JWT: %v", err) 1473 } 1474 addAccountToMemResolver(s, fooPub, fooJWT) 1475 acc, _ := s.LookupAccount(fooPub) 1476 s.UpdateAccountClaims(acc, fooAC) 1477 1478 // Send Another Request 1479 ca.parseAsync("PUB foo 2\r\nhi\r\nPING\r\n") 1480 expectPong(t, cra) 1481 1482 // We should not receive the request this time. 1483 cb.parseAsync("PING\r\n") 1484 expectPong(t, crb) 1485 1486 // Now get an activation token such that it will work, but will expire. 1487 barAC = jwt.NewAccountClaims(barPub) 1488 serviceImport = &jwt.Import{Account: fooPub, Subject: "foo", Type: jwt.Service} 1489 1490 now := time.Now() 1491 activation := jwt.NewActivationClaims(barPub) 1492 activation.ImportSubject = "foo" 1493 activation.ImportType = jwt.Service 1494 activation.IssuedAt = now.Add(-10 * time.Second).Unix() 1495 activation.Expires = now.Add(time.Second).Round(time.Second).Unix() 1496 actJWT, err := activation.Encode(fooKP) 1497 if err != nil { 1498 t.Fatalf("Error generating activation token: %v", err) 1499 } 1500 serviceImport.Token = actJWT 1501 1502 barAC.Imports.Add(serviceImport) 1503 barJWT, err = barAC.Encode(okp) 1504 if err != nil { 1505 t.Fatalf("Error generating account JWT: %v", err) 1506 } 1507 addAccountToMemResolver(s, barPub, barJWT) 1508 acc, _ = s.LookupAccount(barPub) 1509 s.UpdateAccountClaims(acc, barAC) 1510 1511 // Now it should work again. 1512 // Send Another Request 1513 ca.parseAsync("PUB foo 3\r\nhi2\r\nPING\r\n") 1514 expectPong(t, cra) 1515 1516 // We should receive the request. PING needed to flush. 1517 cb.parseAsync("PING\r\n") 1518 expectMsg(t, crb, "foo", "hi2") 1519 1520 // Now wait for it to expire, then retry. 1521 waitTime := time.Duration(activation.Expires-time.Now().Unix()) * time.Second 1522 time.Sleep(waitTime + 250*time.Millisecond) 1523 1524 // Send Another Request 1525 ca.parseAsync("PUB foo 3\r\nhi3\r\nPING\r\n") 1526 expectPong(t, cra) 1527 1528 // We should NOT receive the request. PING needed to flush. 1529 cb.parseAsync("PING\r\n") 1530 expectPong(t, crb) 1531 } 1532 1533 func TestJWTAccountURLResolver(t *testing.T) { 1534 for _, test := range []struct { 1535 name string 1536 useTLS bool 1537 }{ 1538 {"plain", false}, 1539 {"tls", true}, 1540 } { 1541 t.Run(test.name, func(t *testing.T) { 1542 kp, _ := nkeys.FromSeed(oSeed) 1543 akp, _ := nkeys.CreateAccount() 1544 apub, _ := akp.PublicKey() 1545 nac := jwt.NewAccountClaims(apub) 1546 ajwt, err := nac.Encode(kp) 1547 if err != nil { 1548 t.Fatalf("Error generating account JWT: %v", err) 1549 } 1550 1551 hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1552 w.Write([]byte(ajwt)) 1553 }) 1554 var ts *httptest.Server 1555 if test.useTLS { 1556 tc := &TLSConfigOpts{ 1557 CertFile: "../test/configs/certs/server-cert.pem", 1558 KeyFile: "../test/configs/certs/server-key.pem", 1559 CaFile: "../test/configs/certs/ca.pem", 1560 } 1561 tlsConfig, err := GenTLSConfig(tc) 1562 if err != nil { 1563 t.Fatalf("Error generating tls config: %v", err) 1564 } 1565 ts = httptest.NewUnstartedServer(hf) 1566 ts.TLS = tlsConfig 1567 ts.StartTLS() 1568 } else { 1569 ts = httptest.NewServer(hf) 1570 } 1571 defer ts.Close() 1572 1573 confTemplate := ` 1574 operator: %s 1575 listen: 127.0.0.1:-1 1576 resolver: URL("%s/ngs/v1/accounts/jwt/") 1577 resolver_tls { 1578 cert_file: "../test/configs/certs/client-cert.pem" 1579 key_file: "../test/configs/certs/client-key.pem" 1580 ca_file: "../test/configs/certs/ca.pem" 1581 } 1582 ` 1583 conf := createConfFile(t, []byte(fmt.Sprintf(confTemplate, ojwt, ts.URL))) 1584 1585 s, opts := RunServerWithConfig(conf) 1586 pub, _ := kp.PublicKey() 1587 opts.TrustedKeys = []string{pub} 1588 defer s.Shutdown() 1589 1590 acc, _ := s.LookupAccount(apub) 1591 if acc == nil { 1592 t.Fatalf("Expected to receive an account") 1593 } 1594 if acc.Name != apub { 1595 t.Fatalf("Account name did not match claim key") 1596 } 1597 }) 1598 } 1599 } 1600 1601 func TestJWTAccountURLResolverTimeout(t *testing.T) { 1602 kp, _ := nkeys.FromSeed(oSeed) 1603 akp, _ := nkeys.CreateAccount() 1604 apub, _ := akp.PublicKey() 1605 nac := jwt.NewAccountClaims(apub) 1606 ajwt, err := nac.Encode(kp) 1607 if err != nil { 1608 t.Fatalf("Error generating account JWT: %v", err) 1609 } 1610 1611 basePath := "/ngs/v1/accounts/jwt/" 1612 1613 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1614 if r.URL.Path == basePath { 1615 w.Write([]byte("ok")) 1616 return 1617 } 1618 // Purposely be slow on account lookup. 1619 time.Sleep(200 * time.Millisecond) 1620 w.Write([]byte(ajwt)) 1621 })) 1622 defer ts.Close() 1623 1624 confTemplate := ` 1625 listen: 127.0.0.1:-1 1626 resolver: URL("%s%s") 1627 ` 1628 conf := createConfFile(t, []byte(fmt.Sprintf(confTemplate, ts.URL, basePath))) 1629 1630 s, opts := RunServerWithConfig(conf) 1631 pub, _ := kp.PublicKey() 1632 opts.TrustedKeys = []string{pub} 1633 defer s.Shutdown() 1634 1635 // Lower default timeout to speed-up test 1636 s.AccountResolver().(*URLAccResolver).c.Timeout = 50 * time.Millisecond 1637 1638 acc, _ := s.LookupAccount(apub) 1639 if acc != nil { 1640 t.Fatalf("Expected to not receive an account due to timeout") 1641 } 1642 } 1643 1644 func TestJWTAccountURLResolverNoFetchOnReload(t *testing.T) { 1645 kp, _ := nkeys.FromSeed(oSeed) 1646 akp, _ := nkeys.CreateAccount() 1647 apub, _ := akp.PublicKey() 1648 nac := jwt.NewAccountClaims(apub) 1649 ajwt, err := nac.Encode(kp) 1650 if err != nil { 1651 t.Fatalf("Error generating account JWT: %v", err) 1652 } 1653 1654 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1655 w.Write([]byte(ajwt)) 1656 })) 1657 defer ts.Close() 1658 1659 confTemplate := ` 1660 operator: %s 1661 listen: 127.0.0.1:-1 1662 resolver: URL("%s/ngs/v1/accounts/jwt/") 1663 ` 1664 conf := createConfFile(t, []byte(fmt.Sprintf(confTemplate, ojwt, ts.URL))) 1665 1666 s, _ := RunServerWithConfig(conf) 1667 defer s.Shutdown() 1668 1669 acc, _ := s.LookupAccount(apub) 1670 if acc == nil { 1671 t.Fatalf("Expected to receive an account") 1672 } 1673 1674 // Reload would produce a DATA race during the DeepEqual check for the account resolver, 1675 // so close the current one and we will create a new one that keeps track of fetch calls. 1676 ts.Close() 1677 1678 fetch := int32(0) 1679 ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1680 atomic.AddInt32(&fetch, 1) 1681 w.Write([]byte(ajwt)) 1682 })) 1683 defer ts.Close() 1684 1685 changeCurrentConfigContentWithNewContent(t, conf, []byte(fmt.Sprintf(confTemplate, ojwt, ts.URL))) 1686 1687 if err := s.Reload(); err != nil { 1688 t.Fatalf("Error on reload: %v", err) 1689 } 1690 if atomic.LoadInt32(&fetch) != 0 { 1691 t.Fatalf("Fetch invoked during reload") 1692 } 1693 1694 // Now stop the resolver and make sure that on startup, we report URL resolver failure 1695 s.Shutdown() 1696 s = nil 1697 ts.Close() 1698 1699 opts := LoadConfig(conf) 1700 if s, err := NewServer(opts); err == nil || !strings.Contains(err.Error(), "could not fetch") { 1701 if s != nil { 1702 s.Shutdown() 1703 } 1704 t.Fatalf("Expected error regarding account resolver, got %v", err) 1705 } 1706 } 1707 1708 func TestJWTAccountURLResolverFetchFailureInServer1(t *testing.T) { 1709 const subj = "test" 1710 const crossAccSubj = "test" 1711 // Create Exporting Account 1712 expkp, _ := nkeys.CreateAccount() 1713 exppub, _ := expkp.PublicKey() 1714 expac := jwt.NewAccountClaims(exppub) 1715 expac.Exports.Add(&jwt.Export{ 1716 Subject: crossAccSubj, 1717 Type: jwt.Stream, 1718 }) 1719 expjwt, err := expac.Encode(oKp) 1720 if err != nil { 1721 t.Fatalf("Error generating account JWT: %v", err) 1722 } 1723 // Create importing Account 1724 impkp, _ := nkeys.CreateAccount() 1725 imppub, _ := impkp.PublicKey() 1726 impac := jwt.NewAccountClaims(imppub) 1727 impac.Imports.Add(&jwt.Import{ 1728 Account: exppub, 1729 Subject: crossAccSubj, 1730 Type: jwt.Stream, 1731 }) 1732 impjwt, err := impac.Encode(oKp) 1733 if err != nil { 1734 t.Fatalf("Error generating account JWT: %v", err) 1735 } 1736 // Simulate an account server that drops the first request to exppub 1737 chanImpA := make(chan struct{}, 10) 1738 defer close(chanImpA) 1739 chanExpS := make(chan struct{}, 10) 1740 defer close(chanExpS) 1741 chanExpF := make(chan struct{}, 1) 1742 defer close(chanExpF) 1743 failureCnt := int32(0) 1744 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1745 if r.URL.Path == "/A/" { 1746 // Server startup 1747 w.Write(nil) 1748 chanImpA <- struct{}{} 1749 } else if r.URL.Path == "/A/"+imppub { 1750 w.Write([]byte(impjwt)) 1751 chanImpA <- struct{}{} 1752 } else if r.URL.Path == "/A/"+exppub { 1753 if atomic.AddInt32(&failureCnt, 1) <= 1 { 1754 // skip the write to simulate the failure 1755 chanExpF <- struct{}{} 1756 } else { 1757 w.Write([]byte(expjwt)) 1758 chanExpS <- struct{}{} 1759 } 1760 } else { 1761 t.Fatal("not expected") 1762 } 1763 })) 1764 defer ts.Close() 1765 // Create server 1766 confA := createConfFile(t, []byte(fmt.Sprintf(` 1767 listen: 127.0.0.1:-1 1768 operator: %s 1769 resolver: URL("%s/A/") 1770 `, ojwt, ts.URL))) 1771 sA := RunServer(LoadConfig(confA)) 1772 defer sA.Shutdown() 1773 // server observed one fetch on startup 1774 chanRecv(t, chanImpA, 10*time.Second) 1775 // Create first client 1776 ncA := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, impkp)) 1777 defer ncA.Close() 1778 // create a test subscription 1779 subA, err := ncA.SubscribeSync(subj) 1780 if err != nil { 1781 t.Fatalf("Expected no error during subscribe: %v", err) 1782 } 1783 defer subA.Unsubscribe() 1784 // Connect of client triggered a fetch of both accounts 1785 // the fetch for the imported account will fail 1786 chanRecv(t, chanImpA, 10*time.Second) 1787 chanRecv(t, chanExpF, 10*time.Second) 1788 // create second client for user exporting 1789 ncB := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, expkp)) 1790 defer ncB.Close() 1791 chanRecv(t, chanExpS, 10*time.Second) 1792 // Connect of client triggered another fetch, this time passing 1793 checkSubInterest(t, sA, imppub, subj, 10*time.Second) 1794 checkSubInterest(t, sA, exppub, crossAccSubj, 10*time.Second) // Will fail as a result of this issue 1795 } 1796 1797 func TestJWTAccountURLResolverFetchFailurePushReorder(t *testing.T) { 1798 const subj = "test" 1799 const crossAccSubj = "test" 1800 // Create System Account 1801 syskp, _ := nkeys.CreateAccount() 1802 syspub, _ := syskp.PublicKey() 1803 sysAc := jwt.NewAccountClaims(syspub) 1804 sysjwt, err := sysAc.Encode(oKp) 1805 if err != nil { 1806 t.Fatalf("Error generating account JWT: %v", err) 1807 } 1808 // Create Exporting Account 1809 expkp, _ := nkeys.CreateAccount() 1810 exppub, _ := expkp.PublicKey() 1811 expac := jwt.NewAccountClaims(exppub) 1812 expjwt1, err := expac.Encode(oKp) 1813 if err != nil { 1814 t.Fatalf("Error generating account JWT: %v", err) 1815 } 1816 expac.Exports.Add(&jwt.Export{ 1817 Subject: crossAccSubj, 1818 Type: jwt.Stream, 1819 }) 1820 expjwt2, err := expac.Encode(oKp) 1821 if err != nil { 1822 t.Fatalf("Error generating account JWT: %v", err) 1823 } 1824 // Create importing Account 1825 impkp, _ := nkeys.CreateAccount() 1826 imppub, _ := impkp.PublicKey() 1827 impac := jwt.NewAccountClaims(imppub) 1828 impac.Imports.Add(&jwt.Import{ 1829 Account: exppub, 1830 Subject: crossAccSubj, 1831 Type: jwt.Stream, 1832 }) 1833 impjwt, err := impac.Encode(oKp) 1834 if err != nil { 1835 t.Fatalf("Error generating account JWT: %v", err) 1836 } 1837 // Simulate an account server that does not serve the updated jwt for exppub 1838 chanImpA := make(chan struct{}, 10) 1839 defer close(chanImpA) 1840 chanExpS := make(chan struct{}, 10) 1841 defer close(chanExpS) 1842 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1843 if r.URL.Path == "/A/" { 1844 // Server startup 1845 w.Write(nil) 1846 chanImpA <- struct{}{} 1847 } else if r.URL.Path == "/A/"+imppub { 1848 w.Write([]byte(impjwt)) 1849 chanImpA <- struct{}{} 1850 } else if r.URL.Path == "/A/"+exppub { 1851 // respond with jwt that does not have the export 1852 // this simulates an ordering issue 1853 w.Write([]byte(expjwt1)) 1854 chanExpS <- struct{}{} 1855 } else if r.URL.Path == "/A/"+syspub { 1856 w.Write([]byte(sysjwt)) 1857 } else { 1858 t.Fatal("not expected") 1859 } 1860 })) 1861 defer ts.Close() 1862 confA := createConfFile(t, []byte(fmt.Sprintf(` 1863 listen: 127.0.0.1:-1 1864 operator: %s 1865 resolver: URL("%s/A/") 1866 system_account: %s 1867 `, ojwt, ts.URL, syspub))) 1868 sA := RunServer(LoadConfig(confA)) 1869 defer sA.Shutdown() 1870 // server observed one fetch on startup 1871 chanRecv(t, chanImpA, 10*time.Second) 1872 // Create first client 1873 ncA := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, impkp)) 1874 defer ncA.Close() 1875 // create a test subscription 1876 subA, err := ncA.SubscribeSync(subj) 1877 if err != nil { 1878 t.Fatalf("Expected no error during subscribe: %v", err) 1879 } 1880 defer subA.Unsubscribe() 1881 // Connect of client triggered a fetch of both accounts 1882 // the fetch for the imported account will fail 1883 chanRecv(t, chanImpA, 10*time.Second) 1884 chanRecv(t, chanExpS, 10*time.Second) 1885 // create second client for user exporting 1886 ncB := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, expkp)) 1887 defer ncB.Close() 1888 // update expjwt2, this will correct the import issue 1889 sysc := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, syskp)) 1890 defer sysc.Close() 1891 natsPub(t, sysc, fmt.Sprintf(accUpdateEventSubjNew, exppub), []byte(expjwt2)) 1892 sysc.Flush() 1893 // updating expjwt should cause this to pass 1894 checkSubInterest(t, sA, imppub, subj, 10*time.Second) 1895 checkSubInterest(t, sA, exppub, crossAccSubj, 10*time.Second) // Will fail as a result of this issue 1896 } 1897 1898 type captureDebugLogger struct { 1899 DummyLogger 1900 dbgCh chan string 1901 } 1902 1903 func (l *captureDebugLogger) Debugf(format string, v ...any) { 1904 select { 1905 case l.dbgCh <- fmt.Sprintf(format, v...): 1906 default: 1907 } 1908 } 1909 1910 func TestJWTAccountURLResolverPermanentFetchFailure(t *testing.T) { 1911 const crossAccSubj = "test" 1912 expkp, _ := nkeys.CreateAccount() 1913 exppub, _ := expkp.PublicKey() 1914 impkp, _ := nkeys.CreateAccount() 1915 imppub, _ := impkp.PublicKey() 1916 // Create System Account 1917 syskp, _ := nkeys.CreateAccount() 1918 syspub, _ := syskp.PublicKey() 1919 sysAc := jwt.NewAccountClaims(syspub) 1920 sysjwt, err := sysAc.Encode(oKp) 1921 if err != nil { 1922 t.Fatalf("Error generating account JWT: %v", err) 1923 } 1924 // Create 2 Accounts. Each importing from the other, but NO matching export 1925 expac := jwt.NewAccountClaims(exppub) 1926 expac.Imports.Add(&jwt.Import{ 1927 Account: imppub, 1928 Subject: crossAccSubj, 1929 Type: jwt.Stream, 1930 }) 1931 expjwt, err := expac.Encode(oKp) 1932 if err != nil { 1933 t.Fatalf("Error generating account JWT: %v", err) 1934 } 1935 // Create importing Account 1936 impac := jwt.NewAccountClaims(imppub) 1937 impac.Imports.Add(&jwt.Import{ 1938 Account: exppub, 1939 Subject: crossAccSubj, 1940 Type: jwt.Stream, 1941 }) 1942 impjwt, err := impac.Encode(oKp) 1943 if err != nil { 1944 t.Fatalf("Error generating account JWT: %v", err) 1945 } 1946 // Simulate an account server that does not serve the updated jwt for exppub 1947 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1948 if r.URL.Path == "/A/" { 1949 // Server startup 1950 w.Write(nil) 1951 } else if r.URL.Path == "/A/"+imppub { 1952 w.Write([]byte(impjwt)) 1953 } else if r.URL.Path == "/A/"+exppub { 1954 w.Write([]byte(expjwt)) 1955 } else if r.URL.Path == "/A/"+syspub { 1956 w.Write([]byte(sysjwt)) 1957 } else { 1958 t.Fatal("not expected") 1959 } 1960 })) 1961 defer ts.Close() 1962 confA := createConfFile(t, []byte(fmt.Sprintf(` 1963 listen: 127.0.0.1:-1 1964 operator: %s 1965 resolver: URL("%s/A/") 1966 system_account: %s 1967 `, ojwt, ts.URL, syspub))) 1968 o := LoadConfig(confA) 1969 sA := RunServer(o) 1970 defer sA.Shutdown() 1971 l := &captureDebugLogger{dbgCh: make(chan string, 100)} // has enough space to not block 1972 sA.SetLogger(l, true, false) 1973 // Create clients 1974 ncA := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, impkp)) 1975 defer ncA.Close() 1976 ncB := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, expkp)) 1977 defer ncB.Close() 1978 sysc := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, syskp)) 1979 defer sysc.Close() 1980 // push accounts 1981 natsPub(t, sysc, fmt.Sprintf(accUpdateEventSubjNew, imppub), []byte(impjwt)) 1982 natsPub(t, sysc, fmt.Sprintf(accUpdateEventSubjOld, exppub), []byte(expjwt)) 1983 sysc.Flush() 1984 importErrCnt := 0 1985 tmr := time.NewTimer(500 * time.Millisecond) 1986 defer tmr.Stop() 1987 for { 1988 select { 1989 case line := <-l.dbgCh: 1990 if strings.HasPrefix(line, "Error adding stream import to account") { 1991 importErrCnt++ 1992 } 1993 case <-tmr.C: 1994 // connecting and updating, each cause 3 traces (2 + 1 on iteration) 1995 if importErrCnt != 6 { 1996 t.Fatalf("Expected 6 debug traces, got %d", importErrCnt) 1997 } 1998 return 1999 } 2000 } 2001 } 2002 2003 func TestJWTAccountURLResolverFetchFailureInCluster(t *testing.T) { 2004 assertChanLen := func(x int, chans ...chan struct{}) { 2005 t.Helper() 2006 for _, c := range chans { 2007 if len(c) != x { 2008 t.Fatalf("length of channel is not %d", x) 2009 } 2010 } 2011 } 2012 const subj = ">" 2013 const crossAccSubj = "test" 2014 // Create Exporting Account 2015 expkp, _ := nkeys.CreateAccount() 2016 exppub, _ := expkp.PublicKey() 2017 expac := jwt.NewAccountClaims(exppub) 2018 expac.Exports.Add(&jwt.Export{ 2019 Subject: crossAccSubj, 2020 Type: jwt.Stream, 2021 }) 2022 expjwt, err := expac.Encode(oKp) 2023 if err != nil { 2024 t.Fatalf("Error generating account JWT: %v", err) 2025 } 2026 // Create importing Account 2027 impkp, _ := nkeys.CreateAccount() 2028 imppub, _ := impkp.PublicKey() 2029 impac := jwt.NewAccountClaims(imppub) 2030 impac.Imports.Add(&jwt.Import{ 2031 Account: exppub, 2032 Subject: crossAccSubj, 2033 Type: jwt.Stream, 2034 }) 2035 impac.Exports.Add(&jwt.Export{ 2036 Subject: "srvc", 2037 Type: jwt.Service, 2038 }) 2039 impjwt, err := impac.Encode(oKp) 2040 if err != nil { 2041 t.Fatalf("Error generating account JWT: %v", err) 2042 } 2043 // Create User 2044 nkp, _ := nkeys.CreateUser() 2045 uSeed, _ := nkp.Seed() 2046 upub, _ := nkp.PublicKey() 2047 nuc := newJWTTestUserClaims() 2048 nuc.Subject = upub 2049 uJwt, err := nuc.Encode(impkp) 2050 if err != nil { 2051 t.Fatalf("Error generating user JWT: %v", err) 2052 } 2053 creds := genCredsFile(t, uJwt, uSeed) 2054 // Simulate an account server that drops the first request to /B/acc 2055 chanImpA := make(chan struct{}, 4) 2056 defer close(chanImpA) 2057 chanImpB := make(chan struct{}, 4) 2058 defer close(chanImpB) 2059 chanExpA := make(chan struct{}, 4) 2060 defer close(chanExpA) 2061 chanExpB := make(chan struct{}, 4) 2062 defer close(chanExpB) 2063 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 2064 if r.URL.Path == "/A/" { 2065 // Server A startup 2066 w.Write(nil) 2067 chanImpA <- struct{}{} 2068 } else if r.URL.Path == "/B/" { 2069 // Server B startup 2070 w.Write(nil) 2071 chanImpB <- struct{}{} 2072 } else if r.URL.Path == "/A/"+imppub { 2073 // First Client connecting to Server A 2074 w.Write([]byte(impjwt)) 2075 chanImpA <- struct{}{} 2076 } else if r.URL.Path == "/B/"+imppub { 2077 // Second Client connecting to Server B 2078 w.Write([]byte(impjwt)) 2079 chanImpB <- struct{}{} 2080 } else if r.URL.Path == "/A/"+exppub { 2081 // First Client connecting to Server A 2082 w.Write([]byte(expjwt)) 2083 chanExpA <- struct{}{} 2084 } else if r.URL.Path == "/B/"+exppub { 2085 // Second Client connecting to Server B 2086 w.Write([]byte(expjwt)) 2087 chanExpB <- struct{}{} 2088 } else { 2089 t.Fatal("not expected") 2090 } 2091 })) 2092 defer ts.Close() 2093 // Create seed server A 2094 confA := createConfFile(t, []byte(fmt.Sprintf(` 2095 listen: 127.0.0.1:-1 2096 operator: %s 2097 resolver: URL("%s/A/") 2098 cluster { 2099 name: clust 2100 no_advertise: true 2101 listen: 127.0.0.1:-1 2102 } 2103 `, ojwt, ts.URL))) 2104 sA := RunServer(LoadConfig(confA)) 2105 defer sA.Shutdown() 2106 // Create Server B (using no_advertise to prevent failover) 2107 confB := createConfFile(t, []byte(fmt.Sprintf(` 2108 listen: 127.0.0.1:-1 2109 operator: %s 2110 resolver: URL("%s/B/") 2111 cluster { 2112 name: clust 2113 no_advertise: true 2114 listen: 127.0.0.1:-1 2115 routes [ 2116 nats-route://127.0.0.1:%d 2117 ] 2118 } 2119 `, ojwt, ts.URL, sA.opts.Cluster.Port))) 2120 sB := RunServer(LoadConfig(confB)) 2121 defer sB.Shutdown() 2122 // startup cluster 2123 checkClusterFormed(t, sA, sB) 2124 // Both server observed one fetch on startup 2125 chanRecv(t, chanImpA, 10*time.Second) 2126 chanRecv(t, chanImpB, 10*time.Second) 2127 assertChanLen(0, chanImpA, chanImpB, chanExpA, chanExpB) 2128 // Create first client, directly connects to A 2129 urlA := fmt.Sprintf("nats://%s:%d", sA.opts.Host, sA.opts.Port) 2130 ncA, err := nats.Connect(urlA, nats.UserCredentials(creds), 2131 nats.DisconnectErrHandler(func(_ *nats.Conn, err error) { 2132 if err != nil { 2133 t.Fatal("error not expected in this test", err) 2134 } 2135 }), 2136 nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 2137 t.Fatal("error not expected in this test", err) 2138 }), 2139 ) 2140 if err != nil { 2141 t.Fatalf("Expected to connect, got %v %s", err, urlA) 2142 } 2143 defer ncA.Close() 2144 // create a test subscription 2145 subA, err := ncA.SubscribeSync(subj) 2146 if err != nil { 2147 t.Fatalf("Expected no error during subscribe: %v", err) 2148 } 2149 defer subA.Unsubscribe() 2150 // Connect of client triggered a fetch by Server A 2151 chanRecv(t, chanImpA, 10*time.Second) 2152 chanRecv(t, chanExpA, 10*time.Second) 2153 assertChanLen(0, chanImpA, chanImpB, chanExpA, chanExpB) 2154 //time.Sleep(10 * time.Second) 2155 // create second client, directly connect to B 2156 urlB := fmt.Sprintf("nats://%s:%d", sB.opts.Host, sB.opts.Port) 2157 ncB, err := nats.Connect(urlB, nats.UserCredentials(creds), nats.NoReconnect()) 2158 if err != nil { 2159 t.Fatalf("Expected to connect, got %v %s", err, urlB) 2160 } 2161 defer ncB.Close() 2162 // Connect of client triggered a fetch by Server B 2163 chanRecv(t, chanImpB, 10*time.Second) 2164 chanRecv(t, chanExpB, 10*time.Second) 2165 assertChanLen(0, chanImpA, chanImpB, chanExpA, chanExpB) 2166 checkClusterFormed(t, sA, sB) 2167 // the route subscription was lost due to the failed fetch 2168 // Now we test if some recover mechanism is in play 2169 checkSubInterest(t, sB, imppub, subj, 10*time.Second) // Will fail as a result of this issue 2170 checkSubInterest(t, sB, exppub, crossAccSubj, 10*time.Second) // Will fail as a result of this issue 2171 if err := ncB.Publish(subj, []byte("msg")); err != nil { 2172 t.Fatalf("Expected to publish %v", err) 2173 } 2174 // expect the message from B to flow to A 2175 if m, err := subA.NextMsg(10 * time.Second); err != nil { 2176 t.Fatalf("Expected to receive a message %v", err) 2177 } else if string(m.Data) != "msg" { 2178 t.Fatalf("Expected to receive 'msg', got: %s", string(m.Data)) 2179 } 2180 assertChanLen(0, chanImpA, chanImpB, chanExpA, chanExpB) 2181 } 2182 2183 func TestJWTAccountURLResolverReturnDifferentOperator(t *testing.T) { 2184 // Create a valid chain of op/acc/usr using a different operator 2185 // This is so we can test if the server rejects this chain. 2186 // Create Operator 2187 op, _ := nkeys.CreateOperator() 2188 // Create Account, this account is the one returned by the resolver 2189 akp, _ := nkeys.CreateAccount() 2190 apub, _ := akp.PublicKey() 2191 nac := jwt.NewAccountClaims(apub) 2192 ajwt, err := nac.Encode(op) 2193 if err != nil { 2194 t.Fatalf("Error generating account JWT: %v", err) 2195 } 2196 // Create User 2197 nkp, _ := nkeys.CreateUser() 2198 uSeed, _ := nkp.Seed() 2199 upub, _ := nkp.PublicKey() 2200 nuc := newJWTTestUserClaims() 2201 nuc.Subject = upub 2202 uJwt, err := nuc.Encode(akp) 2203 if err != nil { 2204 t.Fatalf("Error generating user JWT: %v", err) 2205 } 2206 creds := genCredsFile(t, uJwt, uSeed) 2207 // Simulate an account server that was hijacked/mis configured 2208 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 2209 w.Write([]byte(ajwt)) 2210 })) 2211 defer ts.Close() 2212 // Create Server 2213 confA := createConfFile(t, []byte(fmt.Sprintf(` 2214 listen: 127.0.0.1:-1 2215 operator: %s 2216 resolver: URL("%s/A/") 2217 `, ojwt, ts.URL))) 2218 sA, _ := RunServerWithConfig(confA) 2219 defer sA.Shutdown() 2220 // Create first client, directly connects to A 2221 urlA := fmt.Sprintf("nats://%s:%d", sA.opts.Host, sA.opts.Port) 2222 if _, err := nats.Connect(urlA, nats.UserCredentials(creds), 2223 nats.DisconnectErrHandler(func(_ *nats.Conn, err error) { 2224 if err != nil { 2225 t.Fatal("error not expected in this test", err) 2226 } 2227 }), 2228 nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 2229 t.Fatal("error not expected in this test", err) 2230 }), 2231 ); err == nil { 2232 t.Fatal("Expected connect to fail") 2233 } 2234 // Test if the server has the account in memory. (shouldn't) 2235 if v, ok := sA.accounts.Load(apub); ok { 2236 t.Fatalf("Expected account to NOT be in memory: %v", v.(*Account)) 2237 } 2238 } 2239 2240 func TestJWTUserSigningKey(t *testing.T) { 2241 s := opTrustBasicSetup() 2242 defer s.Shutdown() 2243 2244 // Check to make sure we would have an authTimer 2245 if !s.info.AuthRequired { 2246 t.Fatalf("Expect the server to require auth") 2247 } 2248 2249 c, cr, _ := newClientForServer(s) 2250 defer c.close() 2251 // Don't send jwt field, should fail. 2252 c.parseAsync("CONNECT {\"verbose\":true,\"pedantic\":true}\r\nPING\r\n") 2253 l, _ := cr.ReadString('\n') 2254 if !strings.HasPrefix(l, "-ERR ") { 2255 t.Fatalf("Expected an error") 2256 } 2257 2258 okp, _ := nkeys.FromSeed(oSeed) 2259 2260 // Create an account 2261 akp, _ := nkeys.CreateAccount() 2262 apub, _ := akp.PublicKey() 2263 2264 // Create a signing key for the account 2265 askp, _ := nkeys.CreateAccount() 2266 aspub, _ := askp.PublicKey() 2267 2268 nac := jwt.NewAccountClaims(apub) 2269 ajwt, err := nac.Encode(okp) 2270 if err != nil { 2271 t.Fatalf("Error generating account JWT: %v", err) 2272 } 2273 2274 // Create a client with the account signing key 2275 c, cr, cs := createClientWithIssuer(t, s, askp, apub) 2276 defer c.close() 2277 2278 // PING needed to flush the +OK/-ERR to us. 2279 // This should fail too since no account resolver is defined. 2280 c.parseAsync(cs) 2281 l, _ = cr.ReadString('\n') 2282 if !strings.HasPrefix(l, "-ERR ") { 2283 t.Fatalf("Expected an error") 2284 } 2285 2286 // Ok now let's walk through and make sure all is good. 2287 // We will set the account resolver by hand to a memory resolver. 2288 buildMemAccResolver(s) 2289 addAccountToMemResolver(s, apub, ajwt) 2290 2291 // Create a client with a signing key 2292 c, cr, cs = createClientWithIssuer(t, s, askp, apub) 2293 defer c.close() 2294 // should fail because the signing key is not known 2295 c.parseAsync(cs) 2296 l, _ = cr.ReadString('\n') 2297 if !strings.HasPrefix(l, "-ERR ") { 2298 t.Fatalf("Expected an error: %v", l) 2299 } 2300 2301 // add a signing key 2302 nac.SigningKeys.Add(aspub) 2303 // update the memory resolver 2304 acc, _ := s.LookupAccount(apub) 2305 s.UpdateAccountClaims(acc, nac) 2306 2307 // Create a client with a signing key 2308 c, cr, cs = createClientWithIssuer(t, s, askp, apub) 2309 defer c.close() 2310 2311 // expect this to work 2312 c.parseAsync(cs) 2313 l, _ = cr.ReadString('\n') 2314 if !strings.HasPrefix(l, "PONG") { 2315 t.Fatalf("Expected a PONG, got %q", l) 2316 } 2317 2318 isClosed := func() bool { 2319 c.mu.Lock() 2320 defer c.mu.Unlock() 2321 return c.isClosed() 2322 } 2323 2324 if isClosed() { 2325 t.Fatal("expected client to be alive") 2326 } 2327 // remove the signing key should bounce client 2328 nac.SigningKeys = nil 2329 acc, _ = s.LookupAccount(apub) 2330 s.UpdateAccountClaims(acc, nac) 2331 2332 if !isClosed() { 2333 t.Fatal("expected client to be gone") 2334 } 2335 } 2336 2337 func TestJWTAccountImportSignerRemoved(t *testing.T) { 2338 s := opTrustBasicSetup() 2339 defer s.Shutdown() 2340 buildMemAccResolver(s) 2341 2342 okp, _ := nkeys.FromSeed(oSeed) 2343 2344 // Exporter keys 2345 srvKP, _ := nkeys.CreateAccount() 2346 srvPK, _ := srvKP.PublicKey() 2347 srvSignerKP, _ := nkeys.CreateAccount() 2348 srvSignerPK, _ := srvSignerKP.PublicKey() 2349 2350 // Importer keys 2351 clientKP, _ := nkeys.CreateAccount() 2352 clientPK, _ := clientKP.PublicKey() 2353 2354 createSrvJwt := func(signingKeys ...string) (string, *jwt.AccountClaims) { 2355 ac := jwt.NewAccountClaims(srvPK) 2356 ac.SigningKeys.Add(signingKeys...) 2357 ac.Exports.Add(&jwt.Export{Subject: "foo", Type: jwt.Service, TokenReq: true}) 2358 ac.Exports.Add(&jwt.Export{Subject: "bar", Type: jwt.Stream, TokenReq: true}) 2359 token, err := ac.Encode(okp) 2360 if err != nil { 2361 t.Fatalf("Error generating exporter JWT: %v", err) 2362 } 2363 return token, ac 2364 } 2365 2366 createImportToken := func(sub string, kind jwt.ExportType) string { 2367 actC := jwt.NewActivationClaims(clientPK) 2368 actC.IssuerAccount = srvPK 2369 actC.ImportType = kind 2370 actC.ImportSubject = jwt.Subject(sub) 2371 token, err := actC.Encode(srvSignerKP) 2372 if err != nil { 2373 t.Fatal(err) 2374 } 2375 return token 2376 } 2377 2378 createClientJwt := func() string { 2379 ac := jwt.NewAccountClaims(clientPK) 2380 ac.Imports.Add(&jwt.Import{Account: srvPK, Subject: "foo", Type: jwt.Service, Token: createImportToken("foo", jwt.Service)}) 2381 ac.Imports.Add(&jwt.Import{Account: srvPK, Subject: "bar", Type: jwt.Stream, Token: createImportToken("bar", jwt.Stream)}) 2382 token, err := ac.Encode(okp) 2383 if err != nil { 2384 t.Fatalf("Error generating importer JWT: %v", err) 2385 } 2386 return token 2387 } 2388 2389 srvJWT, _ := createSrvJwt(srvSignerPK) 2390 addAccountToMemResolver(s, srvPK, srvJWT) 2391 2392 clientJWT := createClientJwt() 2393 addAccountToMemResolver(s, clientPK, clientJWT) 2394 2395 // Create a client that will send the request 2396 client, clientReader, clientCS := createClient(t, s, clientKP) 2397 defer client.close() 2398 client.parseAsync(clientCS) 2399 expectPong(t, clientReader) 2400 2401 checkShadow := func(expected int) { 2402 t.Helper() 2403 client.mu.Lock() 2404 defer client.mu.Unlock() 2405 sub := client.subs["1"] 2406 count := 0 2407 if sub != nil { 2408 count = len(sub.shadow) 2409 } 2410 if count != expected { 2411 t.Fatalf("Expected shadows to be %d, got %d", expected, count) 2412 } 2413 } 2414 2415 checkShadow(0) 2416 // Create the client that will respond to the requests. 2417 srv, srvReader, srvCS := createClient(t, s, srvKP) 2418 defer srv.close() 2419 srv.parseAsync(srvCS) 2420 expectPong(t, srvReader) 2421 2422 // Create Subscriber. 2423 srv.parseAsync("SUB foo 1\r\nPING\r\n") 2424 expectPong(t, srvReader) 2425 2426 // Send Request 2427 client.parseAsync("PUB foo 2\r\nhi\r\nPING\r\n") 2428 expectPong(t, clientReader) 2429 2430 // We should receive the request. PING needed to flush. 2431 srv.parseAsync("PING\r\n") 2432 expectMsg(t, srvReader, "foo", "hi") 2433 2434 client.parseAsync("SUB bar 1\r\nPING\r\n") 2435 expectPong(t, clientReader) 2436 checkShadow(1) 2437 2438 srv.parseAsync("PUB bar 2\r\nhi\r\nPING\r\n") 2439 expectPong(t, srvReader) 2440 2441 // We should receive from stream. PING needed to flush. 2442 client.parseAsync("PING\r\n") 2443 expectMsg(t, clientReader, "bar", "hi") 2444 2445 // Now update the exported service no signer 2446 srvJWT, srvAC := createSrvJwt() 2447 addAccountToMemResolver(s, srvPK, srvJWT) 2448 acc, _ := s.LookupAccount(srvPK) 2449 s.UpdateAccountClaims(acc, srvAC) 2450 2451 // Send Another Request 2452 client.parseAsync("PUB foo 2\r\nhi\r\nPING\r\n") 2453 expectPong(t, clientReader) 2454 2455 // We should not receive the request this time. 2456 srv.parseAsync("PING\r\n") 2457 expectPong(t, srvReader) 2458 2459 // Publish on the stream 2460 srv.parseAsync("PUB bar 2\r\nhi\r\nPING\r\n") 2461 expectPong(t, srvReader) 2462 2463 // We should not receive from the stream this time 2464 client.parseAsync("PING\r\n") 2465 expectPong(t, clientReader) 2466 checkShadow(0) 2467 } 2468 2469 func TestJWTAccountImportSignerDeadlock(t *testing.T) { 2470 s := opTrustBasicSetup() 2471 defer s.Shutdown() 2472 buildMemAccResolver(s) 2473 2474 okp, _ := nkeys.FromSeed(oSeed) 2475 2476 // Exporter keys 2477 srvKP, _ := nkeys.CreateAccount() 2478 srvPK, _ := srvKP.PublicKey() 2479 srvSignerKP, _ := nkeys.CreateAccount() 2480 srvSignerPK, _ := srvSignerKP.PublicKey() 2481 2482 // Importer keys 2483 clientKP, _ := nkeys.CreateAccount() 2484 clientPK, _ := clientKP.PublicKey() 2485 2486 createSrvJwt := func(signingKeys ...string) (string, *jwt.AccountClaims) { 2487 ac := jwt.NewAccountClaims(srvPK) 2488 ac.SigningKeys.Add(signingKeys...) 2489 ac.Exports.Add(&jwt.Export{Subject: "foo", Type: jwt.Service, TokenReq: true}) 2490 ac.Exports.Add(&jwt.Export{Subject: "bar", Type: jwt.Stream, TokenReq: true}) 2491 token, err := ac.Encode(okp) 2492 if err != nil { 2493 t.Fatalf("Error generating exporter JWT: %v", err) 2494 } 2495 return token, ac 2496 } 2497 2498 createImportToken := func(sub string, kind jwt.ExportType) string { 2499 actC := jwt.NewActivationClaims(clientPK) 2500 actC.IssuerAccount = srvPK 2501 actC.ImportType = kind 2502 actC.ImportSubject = jwt.Subject(sub) 2503 token, err := actC.Encode(srvSignerKP) 2504 if err != nil { 2505 t.Fatal(err) 2506 } 2507 return token 2508 } 2509 2510 createClientJwt := func() string { 2511 ac := jwt.NewAccountClaims(clientPK) 2512 ac.Imports.Add(&jwt.Import{Account: srvPK, Subject: "foo", Type: jwt.Service, Token: createImportToken("foo", jwt.Service)}) 2513 ac.Imports.Add(&jwt.Import{Account: srvPK, Subject: "bar", Type: jwt.Stream, Token: createImportToken("bar", jwt.Stream)}) 2514 token, err := ac.Encode(okp) 2515 if err != nil { 2516 t.Fatalf("Error generating importer JWT: %v", err) 2517 } 2518 return token 2519 } 2520 2521 srvJWT, _ := createSrvJwt(srvSignerPK) 2522 addAccountToMemResolver(s, srvPK, srvJWT) 2523 2524 clientJWT := createClientJwt() 2525 addAccountToMemResolver(s, clientPK, clientJWT) 2526 2527 acc, _ := s.LookupAccount(srvPK) 2528 // Have a go routine that constantly gets/releases the acc's write lock. 2529 // There was a bug that could cause AddServiceImportWithClaim to deadlock. 2530 ch := make(chan bool, 1) 2531 wg := sync.WaitGroup{} 2532 wg.Add(1) 2533 go func() { 2534 defer wg.Done() 2535 for { 2536 select { 2537 case <-ch: 2538 return 2539 default: 2540 acc.mu.Lock() 2541 acc.mu.Unlock() 2542 time.Sleep(time.Millisecond) 2543 } 2544 } 2545 }() 2546 2547 // Create a client that will send the request 2548 client, clientReader, clientCS := createClient(t, s, clientKP) 2549 defer client.close() 2550 client.parseAsync(clientCS) 2551 expectPong(t, clientReader) 2552 2553 close(ch) 2554 wg.Wait() 2555 } 2556 2557 func TestJWTAccountImportWrongIssuerAccount(t *testing.T) { 2558 s := opTrustBasicSetup() 2559 defer s.Shutdown() 2560 buildMemAccResolver(s) 2561 2562 l := &captureErrorLogger{errCh: make(chan string, 2)} 2563 s.SetLogger(l, false, false) 2564 2565 okp, _ := nkeys.FromSeed(oSeed) 2566 2567 // Exporter keys 2568 srvKP, _ := nkeys.CreateAccount() 2569 srvPK, _ := srvKP.PublicKey() 2570 srvSignerKP, _ := nkeys.CreateAccount() 2571 srvSignerPK, _ := srvSignerKP.PublicKey() 2572 2573 // Importer keys 2574 clientKP, _ := nkeys.CreateAccount() 2575 clientPK, _ := clientKP.PublicKey() 2576 2577 createSrvJwt := func(signingKeys ...string) (string, *jwt.AccountClaims) { 2578 ac := jwt.NewAccountClaims(srvPK) 2579 ac.SigningKeys.Add(signingKeys...) 2580 ac.Exports.Add(&jwt.Export{Subject: "foo", Type: jwt.Service, TokenReq: true}) 2581 ac.Exports.Add(&jwt.Export{Subject: "bar", Type: jwt.Stream, TokenReq: true}) 2582 token, err := ac.Encode(okp) 2583 if err != nil { 2584 t.Fatalf("Error generating exporter JWT: %v", err) 2585 } 2586 return token, ac 2587 } 2588 2589 createImportToken := func(sub string, kind jwt.ExportType) string { 2590 actC := jwt.NewActivationClaims(clientPK) 2591 // Reference ourselves, which is wrong. 2592 actC.IssuerAccount = clientPK 2593 actC.ImportType = kind 2594 actC.ImportSubject = jwt.Subject(sub) 2595 token, err := actC.Encode(srvSignerKP) 2596 if err != nil { 2597 t.Fatal(err) 2598 } 2599 return token 2600 } 2601 2602 createClientJwt := func() string { 2603 ac := jwt.NewAccountClaims(clientPK) 2604 ac.Imports.Add(&jwt.Import{Account: srvPK, Subject: "foo", Type: jwt.Service, Token: createImportToken("foo", jwt.Service)}) 2605 ac.Imports.Add(&jwt.Import{Account: srvPK, Subject: "bar", Type: jwt.Stream, Token: createImportToken("bar", jwt.Stream)}) 2606 token, err := ac.Encode(okp) 2607 if err != nil { 2608 t.Fatalf("Error generating importer JWT: %v", err) 2609 } 2610 return token 2611 } 2612 2613 srvJWT, _ := createSrvJwt(srvSignerPK) 2614 addAccountToMemResolver(s, srvPK, srvJWT) 2615 2616 clientJWT := createClientJwt() 2617 addAccountToMemResolver(s, clientPK, clientJWT) 2618 2619 // Create a client that will send the request 2620 client, clientReader, clientCS := createClient(t, s, clientKP) 2621 defer client.close() 2622 client.parseAsync(clientCS) 2623 if l, _, err := clientReader.ReadLine(); err != nil { 2624 t.Fatalf("Expected no Error, got: %v", err) 2625 } else if !strings.Contains(string(l), "-ERR 'Authorization Violation'") { 2626 t.Fatalf("Expected Error, got: %v", l) 2627 } 2628 } 2629 2630 func TestJWTUserRevokedOnAccountUpdate(t *testing.T) { 2631 nac := newJWTTestAccountClaims() 2632 s, akp, c, cr := setupJWTTestWitAccountClaims(t, nac, "+OK") 2633 defer s.Shutdown() 2634 defer c.close() 2635 2636 expectPong(t, cr) 2637 2638 okp, _ := nkeys.FromSeed(oSeed) 2639 apub, _ := akp.PublicKey() 2640 2641 c.mu.Lock() 2642 pub := c.user.Nkey 2643 c.mu.Unlock() 2644 2645 // Now revoke the user. 2646 nac.Revoke(pub) 2647 2648 ajwt, err := nac.Encode(okp) 2649 if err != nil { 2650 t.Fatalf("Error generating account JWT: %v", err) 2651 } 2652 2653 // Update the account on the server. 2654 addAccountToMemResolver(s, apub, ajwt) 2655 acc, err := s.LookupAccount(apub) 2656 if err != nil { 2657 t.Fatalf("Error looking up the account: %v", err) 2658 } 2659 2660 // This is simulating a system update for the account claims. 2661 go s.updateAccountWithClaimJWT(acc, ajwt) 2662 2663 l, _ := cr.ReadString('\n') 2664 if !strings.HasPrefix(l, "-ERR ") { 2665 t.Fatalf("Expected an error") 2666 } 2667 if !strings.Contains(l, "Revoked") { 2668 t.Fatalf("Expected 'Revoked' to be in the error") 2669 } 2670 } 2671 2672 func TestJWTUserRevoked(t *testing.T) { 2673 okp, _ := nkeys.FromSeed(oSeed) 2674 2675 // Create a new user that we will make sure has been revoked. 2676 nkp, _ := nkeys.CreateUser() 2677 pub, _ := nkp.PublicKey() 2678 nuc := jwt.NewUserClaims(pub) 2679 2680 akp, _ := nkeys.CreateAccount() 2681 apub, _ := akp.PublicKey() 2682 nac := jwt.NewAccountClaims(apub) 2683 // Revoke the user right away. 2684 nac.Revoke(pub) 2685 ajwt, err := nac.Encode(okp) 2686 if err != nil { 2687 t.Fatalf("Error generating account JWT: %v", err) 2688 } 2689 2690 // Sign for the user. 2691 jwt, err := nuc.Encode(akp) 2692 if err != nil { 2693 t.Fatalf("Error generating user JWT: %v", err) 2694 } 2695 2696 s := opTrustBasicSetup() 2697 defer s.Shutdown() 2698 buildMemAccResolver(s) 2699 addAccountToMemResolver(s, apub, ajwt) 2700 2701 c, cr, l := newClientForServer(s) 2702 defer c.close() 2703 2704 // Sign Nonce 2705 var info nonceInfo 2706 json.Unmarshal([]byte(l[5:]), &info) 2707 sigraw, _ := nkp.Sign([]byte(info.Nonce)) 2708 sig := base64.RawURLEncoding.EncodeToString(sigraw) 2709 2710 // PING needed to flush the +OK/-ERR to us. 2711 cs := fmt.Sprintf("CONNECT {\"jwt\":%q,\"sig\":\"%s\"}\r\nPING\r\n", jwt, sig) 2712 2713 c.parseAsync(cs) 2714 2715 l, _ = cr.ReadString('\n') 2716 if !strings.HasPrefix(l, "-ERR ") { 2717 t.Fatalf("Expected an error") 2718 } 2719 if !strings.Contains(l, "Authorization") { 2720 t.Fatalf("Expected 'Revoked' to be in the error") 2721 } 2722 } 2723 2724 // Test that an account update that revokes an import authorization cancels the import. 2725 func TestJWTImportTokenRevokedAfter(t *testing.T) { 2726 s := opTrustBasicSetup() 2727 defer s.Shutdown() 2728 buildMemAccResolver(s) 2729 2730 okp, _ := nkeys.FromSeed(oSeed) 2731 2732 // Create accounts and imports/exports. 2733 fooKP, _ := nkeys.CreateAccount() 2734 fooPub, _ := fooKP.PublicKey() 2735 fooAC := jwt.NewAccountClaims(fooPub) 2736 2737 // Now create Exports. 2738 export := &jwt.Export{Subject: "foo.private", Type: jwt.Stream, TokenReq: true} 2739 2740 fooAC.Exports.Add(export) 2741 fooJWT, err := fooAC.Encode(okp) 2742 if err != nil { 2743 t.Fatalf("Error generating account JWT: %v", err) 2744 } 2745 2746 addAccountToMemResolver(s, fooPub, fooJWT) 2747 2748 barKP, _ := nkeys.CreateAccount() 2749 barPub, _ := barKP.PublicKey() 2750 barAC := jwt.NewAccountClaims(barPub) 2751 simport := &jwt.Import{Account: fooPub, Subject: "foo.private", Type: jwt.Stream} 2752 2753 activation := jwt.NewActivationClaims(barPub) 2754 activation.ImportSubject = "foo.private" 2755 activation.ImportType = jwt.Stream 2756 actJWT, err := activation.Encode(fooKP) 2757 if err != nil { 2758 t.Fatalf("Error generating activation token: %v", err) 2759 } 2760 2761 simport.Token = actJWT 2762 barAC.Imports.Add(simport) 2763 barJWT, err := barAC.Encode(okp) 2764 if err != nil { 2765 t.Fatalf("Error generating account JWT: %v", err) 2766 } 2767 addAccountToMemResolver(s, barPub, barJWT) 2768 2769 // Now revoke the export. 2770 decoded, _ := jwt.DecodeActivationClaims(actJWT) 2771 export.Revoke(decoded.Subject) 2772 2773 fooJWT, err = fooAC.Encode(okp) 2774 if err != nil { 2775 t.Fatalf("Error generating account JWT: %v", err) 2776 } 2777 2778 addAccountToMemResolver(s, fooPub, fooJWT) 2779 2780 fooAcc, _ := s.LookupAccount(fooPub) 2781 if fooAcc == nil { 2782 t.Fatalf("Expected to retrieve the account") 2783 } 2784 2785 // Now lookup bar account and make sure it was revoked. 2786 acc, _ := s.LookupAccount(barPub) 2787 if acc == nil { 2788 t.Fatalf("Expected to retrieve the account") 2789 } 2790 if les := len(acc.imports.streams); les != 0 { 2791 t.Fatalf("Expected imports streams len of 0, got %d", les) 2792 } 2793 } 2794 2795 // Test that an account update that revokes an import authorization cancels the import. 2796 func TestJWTImportTokenRevokedBefore(t *testing.T) { 2797 s := opTrustBasicSetup() 2798 defer s.Shutdown() 2799 buildMemAccResolver(s) 2800 2801 okp, _ := nkeys.FromSeed(oSeed) 2802 2803 // Create accounts and imports/exports. 2804 fooKP, _ := nkeys.CreateAccount() 2805 fooPub, _ := fooKP.PublicKey() 2806 fooAC := jwt.NewAccountClaims(fooPub) 2807 2808 // Now create Exports. 2809 export := &jwt.Export{Subject: "foo.private", Type: jwt.Stream, TokenReq: true} 2810 2811 fooAC.Exports.Add(export) 2812 2813 // Import account 2814 barKP, _ := nkeys.CreateAccount() 2815 barPub, _ := barKP.PublicKey() 2816 barAC := jwt.NewAccountClaims(barPub) 2817 simport := &jwt.Import{Account: fooPub, Subject: "foo.private", Type: jwt.Stream} 2818 2819 activation := jwt.NewActivationClaims(barPub) 2820 activation.ImportSubject = "foo.private" 2821 activation.ImportType = jwt.Stream 2822 actJWT, err := activation.Encode(fooKP) 2823 if err != nil { 2824 t.Fatalf("Error generating activation token: %v", err) 2825 } 2826 2827 simport.Token = actJWT 2828 barAC.Imports.Add(simport) 2829 2830 // Now revoke the export. 2831 decoded, _ := jwt.DecodeActivationClaims(actJWT) 2832 export.Revoke(decoded.Subject) 2833 2834 fooJWT, err := fooAC.Encode(okp) 2835 if err != nil { 2836 t.Fatalf("Error generating account JWT: %v", err) 2837 } 2838 2839 addAccountToMemResolver(s, fooPub, fooJWT) 2840 2841 barJWT, err := barAC.Encode(okp) 2842 if err != nil { 2843 t.Fatalf("Error generating account JWT: %v", err) 2844 } 2845 addAccountToMemResolver(s, barPub, barJWT) 2846 2847 fooAcc, _ := s.LookupAccount(fooPub) 2848 if fooAcc == nil { 2849 t.Fatalf("Expected to retrieve the account") 2850 } 2851 2852 // Now lookup bar account and make sure it was revoked. 2853 acc, _ := s.LookupAccount(barPub) 2854 if acc == nil { 2855 t.Fatalf("Expected to retrieve the account") 2856 } 2857 if les := len(acc.imports.streams); les != 0 { 2858 t.Fatalf("Expected imports streams len of 0, got %d", les) 2859 } 2860 } 2861 2862 func TestJWTCircularAccountServiceImport(t *testing.T) { 2863 s := opTrustBasicSetup() 2864 defer s.Shutdown() 2865 buildMemAccResolver(s) 2866 2867 okp, _ := nkeys.FromSeed(oSeed) 2868 2869 // Create accounts 2870 fooKP, _ := nkeys.CreateAccount() 2871 fooPub, _ := fooKP.PublicKey() 2872 fooAC := jwt.NewAccountClaims(fooPub) 2873 2874 barKP, _ := nkeys.CreateAccount() 2875 barPub, _ := barKP.PublicKey() 2876 barAC := jwt.NewAccountClaims(barPub) 2877 2878 // Create service export/import for account foo 2879 serviceExport := &jwt.Export{Subject: "foo", Type: jwt.Service, TokenReq: true} 2880 serviceImport := &jwt.Import{Account: barPub, Subject: "bar", Type: jwt.Service} 2881 2882 fooAC.Exports.Add(serviceExport) 2883 fooAC.Imports.Add(serviceImport) 2884 fooJWT, err := fooAC.Encode(okp) 2885 if err != nil { 2886 t.Fatalf("Error generating account JWT: %v", err) 2887 } 2888 2889 addAccountToMemResolver(s, fooPub, fooJWT) 2890 2891 // Create service export/import for account bar 2892 serviceExport = &jwt.Export{Subject: "bar", Type: jwt.Service, TokenReq: true} 2893 serviceImport = &jwt.Import{Account: fooPub, Subject: "foo", Type: jwt.Service} 2894 2895 barAC.Exports.Add(serviceExport) 2896 barAC.Imports.Add(serviceImport) 2897 barJWT, err := barAC.Encode(okp) 2898 if err != nil { 2899 t.Fatalf("Error generating account JWT: %v", err) 2900 } 2901 2902 addAccountToMemResolver(s, barPub, barJWT) 2903 2904 c, cr, cs := createClient(t, s, fooKP) 2905 defer c.close() 2906 2907 c.parseAsync(cs) 2908 expectPong(t, cr) 2909 2910 c.parseAsync("SUB foo 1\r\nPING\r\n") 2911 expectPong(t, cr) 2912 } 2913 2914 // This test ensures that connected clients are properly evicted 2915 // (no deadlock) if the max conns of an account has been lowered 2916 // and the account is being updated (following expiration during 2917 // a lookup). 2918 func TestJWTAccountLimitsMaxConnsAfterExpired(t *testing.T) { 2919 s := opTrustBasicSetup() 2920 defer s.Shutdown() 2921 buildMemAccResolver(s) 2922 2923 okp, _ := nkeys.FromSeed(oSeed) 2924 2925 // Create accounts and imports/exports. 2926 fooKP, _ := nkeys.CreateAccount() 2927 fooPub, _ := fooKP.PublicKey() 2928 fooAC := jwt.NewAccountClaims(fooPub) 2929 fooAC.Limits.Conn = 10 2930 fooJWT, err := fooAC.Encode(okp) 2931 if err != nil { 2932 t.Fatalf("Error generating account JWT: %v", err) 2933 } 2934 addAccountToMemResolver(s, fooPub, fooJWT) 2935 2936 newClient := func(expPre string) *testAsyncClient { 2937 t.Helper() 2938 // Create a client. 2939 c, cr, cs := createClient(t, s, fooKP) 2940 c.parseAsync(cs) 2941 l, _ := cr.ReadString('\n') 2942 if !strings.HasPrefix(l, expPre) { 2943 t.Fatalf("Expected a response starting with %q, got %q", expPre, l) 2944 } 2945 go func() { 2946 for { 2947 if _, _, err := cr.ReadLine(); err != nil { 2948 return 2949 } 2950 } 2951 }() 2952 return c 2953 } 2954 2955 for i := 0; i < 4; i++ { 2956 c := newClient("PONG") 2957 defer c.close() 2958 } 2959 2960 // We will simulate that the account has expired. When 2961 // a new client will connect, the server will do a lookup 2962 // and find the account expired, which then will cause 2963 // a fetch and a rebuild of the account. Since max conns 2964 // is now lower, some clients should have been removed. 2965 acc, _ := s.LookupAccount(fooPub) 2966 acc.mu.Lock() 2967 acc.expired = true 2968 acc.updated = time.Now().UTC().Add(-2 * time.Second) // work around updating to quickly 2969 acc.mu.Unlock() 2970 2971 // Now update with new expiration and max connections lowered to 2 2972 fooAC.Limits.Conn = 2 2973 fooJWT, err = fooAC.Encode(okp) 2974 if err != nil { 2975 t.Fatalf("Error generating account JWT: %v", err) 2976 } 2977 addAccountToMemResolver(s, fooPub, fooJWT) 2978 2979 // Cause the lookup that will detect that account was expired 2980 // and rebuild it, and kick clients out. 2981 c := newClient("-ERR ") 2982 defer c.close() 2983 2984 acc, _ = s.LookupAccount(fooPub) 2985 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 2986 acc.mu.RLock() 2987 numClients := len(acc.clients) 2988 acc.mu.RUnlock() 2989 if numClients != 2 { 2990 return fmt.Errorf("Should have 2 clients, got %v", numClients) 2991 } 2992 return nil 2993 }) 2994 } 2995 2996 func TestJWTBearerToken(t *testing.T) { 2997 okp, _ := nkeys.FromSeed(oSeed) 2998 akp, _ := nkeys.CreateAccount() 2999 apub, _ := akp.PublicKey() 3000 nac := jwt.NewAccountClaims(apub) 3001 ajwt, err := nac.Encode(okp) 3002 if err != nil { 3003 t.Fatalf("Error generating account JWT: %v", err) 3004 } 3005 3006 nkp, _ := nkeys.CreateUser() 3007 pub, _ := nkp.PublicKey() 3008 nuc := newJWTTestUserClaims() 3009 nuc.Subject = pub 3010 // Set bearer token. 3011 nuc.BearerToken = true 3012 jwt, err := nuc.Encode(akp) 3013 if err != nil { 3014 t.Fatalf("Error generating user JWT: %v", err) 3015 } 3016 3017 s := opTrustBasicSetup() 3018 defer s.Shutdown() 3019 buildMemAccResolver(s) 3020 addAccountToMemResolver(s, apub, ajwt) 3021 3022 c, cr, _ := newClientForServer(s) 3023 defer c.close() 3024 3025 // Skip nonce signature... 3026 3027 // PING needed to flush the +OK/-ERR to us. 3028 cs := fmt.Sprintf("CONNECT {\"jwt\":%q,\"verbose\":true,\"pedantic\":true}\r\nPING\r\n", jwt) 3029 wg := sync.WaitGroup{} 3030 wg.Add(1) 3031 go func() { 3032 c.parse([]byte(cs)) 3033 wg.Done() 3034 }() 3035 l, _ := cr.ReadString('\n') 3036 if !strings.HasPrefix(l, "+OK") { 3037 t.Fatalf("Expected +OK, got %s", l) 3038 } 3039 wg.Wait() 3040 } 3041 3042 func TestJWTBearerWithIssuerSameAsAccountToken(t *testing.T) { 3043 okp, _ := nkeys.FromSeed(oSeed) 3044 akp, _ := nkeys.CreateAccount() 3045 apub, _ := akp.PublicKey() 3046 nac := jwt.NewAccountClaims(apub) 3047 ajwt, err := nac.Encode(okp) 3048 if err != nil { 3049 t.Fatalf("Error generating account JWT: %v", err) 3050 } 3051 3052 nkp, _ := nkeys.CreateUser() 3053 pub, _ := nkp.PublicKey() 3054 nuc := newJWTTestUserClaims() 3055 // we are setting the issuer account here to trigger verification 3056 // of the issuer - the account has no signing keys, but the issuer 3057 // account is set to the public key of the account which should be OK. 3058 nuc.IssuerAccount = apub 3059 nuc.Subject = pub 3060 // Set bearer token. 3061 nuc.BearerToken = true 3062 jwt, err := nuc.Encode(akp) 3063 if err != nil { 3064 t.Fatalf("Error generating user JWT: %v", err) 3065 } 3066 3067 s := opTrustBasicSetup() 3068 defer s.Shutdown() 3069 buildMemAccResolver(s) 3070 addAccountToMemResolver(s, apub, ajwt) 3071 3072 c, cr, _ := newClientForServer(s) 3073 defer c.close() 3074 3075 // Skip nonce signature... 3076 3077 // PING needed to flush the +OK/-ERR to us. 3078 cs := fmt.Sprintf("CONNECT {\"jwt\":%q,\"verbose\":true,\"pedantic\":true}\r\nPING\r\n", jwt) 3079 wg := sync.WaitGroup{} 3080 wg.Add(1) 3081 go func() { 3082 c.parse([]byte(cs)) 3083 wg.Done() 3084 }() 3085 l, _ := cr.ReadString('\n') 3086 if !strings.HasPrefix(l, "+OK") { 3087 t.Fatalf("Expected +OK, got %s", l) 3088 } 3089 wg.Wait() 3090 } 3091 3092 func TestJWTBearerWithBadIssuerToken(t *testing.T) { 3093 okp, _ := nkeys.FromSeed(oSeed) 3094 akp, _ := nkeys.CreateAccount() 3095 apub, _ := akp.PublicKey() 3096 nac := jwt.NewAccountClaims(apub) 3097 ajwt, err := nac.Encode(okp) 3098 if err != nil { 3099 t.Fatalf("Error generating account JWT: %v", err) 3100 } 3101 3102 nkp, _ := nkeys.CreateUser() 3103 pub, _ := nkp.PublicKey() 3104 nuc := newJWTTestUserClaims() 3105 bakp, _ := nkeys.CreateAccount() 3106 bapub, _ := bakp.PublicKey() 3107 nuc.IssuerAccount = bapub 3108 nuc.Subject = pub 3109 // Set bearer token. 3110 nuc.BearerToken = true 3111 jwt, err := nuc.Encode(akp) 3112 if err != nil { 3113 t.Fatalf("Error generating user JWT: %v", err) 3114 } 3115 3116 s := opTrustBasicSetup() 3117 defer s.Shutdown() 3118 buildMemAccResolver(s) 3119 addAccountToMemResolver(s, apub, ajwt) 3120 3121 c, cr, _ := newClientForServer(s) 3122 defer c.close() 3123 3124 // Skip nonce signature... 3125 3126 // PING needed to flush the +OK/-ERR to us. 3127 cs := fmt.Sprintf("CONNECT {\"jwt\":%q,\"verbose\":true,\"pedantic\":true}\r\nPING\r\n", jwt) 3128 wg := sync.WaitGroup{} 3129 wg.Add(1) 3130 go func() { 3131 c.parse([]byte(cs)) 3132 wg.Done() 3133 }() 3134 l, _ := cr.ReadString('\n') 3135 if !strings.HasPrefix(l, "-ERR") { 3136 t.Fatalf("Expected -ERR, got %s", l) 3137 } 3138 wg.Wait() 3139 } 3140 3141 func TestJWTExpiredUserCredentialsRenewal(t *testing.T) { 3142 createTmpFile := func(t *testing.T, content []byte) string { 3143 t.Helper() 3144 conf := createTempFile(t, _EMPTY_) 3145 fName := conf.Name() 3146 conf.Close() 3147 if err := os.WriteFile(fName, content, 0666); err != nil { 3148 t.Fatalf("Error writing conf file: %v", err) 3149 } 3150 return fName 3151 } 3152 waitTime := func(ch chan bool, timeout time.Duration) error { 3153 select { 3154 case <-ch: 3155 return nil 3156 case <-time.After(timeout): 3157 } 3158 return errors.New("timeout") 3159 } 3160 3161 okp, _ := nkeys.FromSeed(oSeed) 3162 akp, err := nkeys.CreateAccount() 3163 if err != nil { 3164 t.Fatalf("Error generating account") 3165 } 3166 aPub, _ := akp.PublicKey() 3167 nac := jwt.NewAccountClaims(aPub) 3168 aJwt, err := nac.Encode(okp) 3169 if err != nil { 3170 t.Fatalf("Error generating account JWT: %v", err) 3171 } 3172 3173 kp, _ := nkeys.FromSeed(oSeed) 3174 oPub, _ := kp.PublicKey() 3175 opts := defaultServerOptions 3176 opts.TrustedKeys = []string{oPub} 3177 s := RunServer(&opts) 3178 if s == nil { 3179 t.Fatal("Server did not start") 3180 } 3181 defer s.Shutdown() 3182 buildMemAccResolver(s) 3183 addAccountToMemResolver(s, aPub, aJwt) 3184 3185 nkp, _ := nkeys.CreateUser() 3186 pub, _ := nkp.PublicKey() 3187 uSeed, _ := nkp.Seed() 3188 nuc := newJWTTestUserClaims() 3189 nuc.Subject = pub 3190 nuc.Expires = time.Now().Add(time.Second).Unix() 3191 uJwt, err := nuc.Encode(akp) 3192 if err != nil { 3193 t.Fatalf("Error generating user JWT: %v", err) 3194 } 3195 3196 creds, err := jwt.FormatUserConfig(uJwt, uSeed) 3197 if err != nil { 3198 t.Fatalf("Error encoding credentials: %v", err) 3199 } 3200 chainedFile := createTmpFile(t, creds) 3201 3202 rch := make(chan bool) 3203 3204 url := fmt.Sprintf("nats://%s:%d", s.opts.Host, s.opts.Port) 3205 nc, err := nats.Connect(url, 3206 nats.UserCredentials(chainedFile), 3207 nats.ReconnectWait(25*time.Millisecond), 3208 nats.ReconnectJitter(0, 0), 3209 nats.MaxReconnects(2), 3210 nats.ErrorHandler(noOpErrHandler), 3211 nats.ReconnectHandler(func(nc *nats.Conn) { 3212 rch <- true 3213 }), 3214 ) 3215 if err != nil { 3216 t.Fatalf("Expected to connect, got %v %s", err, url) 3217 } 3218 defer nc.Close() 3219 3220 // Place new credentials underneath. 3221 nuc.Expires = time.Now().Add(30 * time.Second).Unix() 3222 uJwt, err = nuc.Encode(akp) 3223 if err != nil { 3224 t.Fatalf("Error encoding user jwt: %v", err) 3225 } 3226 creds, err = jwt.FormatUserConfig(uJwt, uSeed) 3227 if err != nil { 3228 t.Fatalf("Error encoding credentials: %v", err) 3229 } 3230 if err := os.WriteFile(chainedFile, creds, 0666); err != nil { 3231 t.Fatalf("Error writing conf file: %v", err) 3232 } 3233 3234 // Make sure we get disconnected and reconnected first. 3235 if err := waitTime(rch, 2*time.Second); err != nil { 3236 t.Fatal("Should have reconnected.") 3237 } 3238 3239 // We should not have been closed. 3240 if nc.IsClosed() { 3241 t.Fatal("Got disconnected when we should have reconnected.") 3242 } 3243 3244 // Check that we clear the lastErr that can cause the disconnect. 3245 // Our reconnect CB will happen before the clear. So check after a bit. 3246 time.Sleep(50 * time.Millisecond) 3247 if nc.LastError() != nil { 3248 t.Fatalf("Expected lastErr to be cleared, got %q", nc.LastError()) 3249 } 3250 } 3251 3252 func updateJwt(t *testing.T, url string, creds string, jwt string, respCnt int) int { 3253 t.Helper() 3254 require_NextMsg := func(sub *nats.Subscription) bool { 3255 t.Helper() 3256 msg := natsNexMsg(t, sub, time.Second) 3257 content := make(map[string]any) 3258 json.Unmarshal(msg.Data, &content) 3259 if _, ok := content["data"]; ok { 3260 return true 3261 } 3262 return false 3263 } 3264 c := natsConnect(t, url, nats.UserCredentials(creds), 3265 nats.DisconnectErrHandler(func(_ *nats.Conn, err error) { 3266 if err != nil { 3267 t.Fatal("error not expected in this test", err) 3268 } 3269 }), 3270 nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 3271 t.Fatal("error not expected in this test", err) 3272 }), 3273 ) 3274 defer c.Close() 3275 resp := c.NewRespInbox() 3276 sub := natsSubSync(t, c, resp) 3277 err := sub.AutoUnsubscribe(respCnt) 3278 require_NoError(t, err) 3279 require_NoError(t, c.PublishRequest(accClaimsReqSubj, resp, []byte(jwt))) 3280 passCnt := 0 3281 for i := 0; i < respCnt; i++ { 3282 if require_NextMsg(sub) { 3283 passCnt++ 3284 } 3285 } 3286 return passCnt 3287 } 3288 3289 func require_JWTAbsent(t *testing.T, dir string, pub string) { 3290 t.Helper() 3291 _, err := os.Stat(filepath.Join(dir, pub+".jwt")) 3292 require_Error(t, err) 3293 require_True(t, os.IsNotExist(err)) 3294 } 3295 3296 func require_JWTPresent(t *testing.T, dir string, pub string) { 3297 t.Helper() 3298 _, err := os.Stat(filepath.Join(dir, pub+".jwt")) 3299 require_NoError(t, err) 3300 } 3301 3302 func require_JWTEqual(t *testing.T, dir string, pub string, jwt string) { 3303 t.Helper() 3304 content, err := os.ReadFile(filepath.Join(dir, pub+".jwt")) 3305 require_NoError(t, err) 3306 require_Equal(t, string(content), jwt) 3307 } 3308 3309 func createTempFile(t testing.TB, prefix string) *os.File { 3310 t.Helper() 3311 tempDir := t.TempDir() 3312 f, err := os.CreateTemp(tempDir, prefix) 3313 require_NoError(t, err) 3314 return f 3315 } 3316 3317 func removeDir(t testing.TB, dir string) { 3318 t.Helper() 3319 if err := os.RemoveAll(dir); err != nil { 3320 t.Fatal(err) 3321 } 3322 } 3323 3324 func removeFile(t testing.TB, p string) { 3325 t.Helper() 3326 if err := os.Remove(p); err != nil { 3327 t.Fatal(err) 3328 } 3329 } 3330 3331 func writeJWT(t *testing.T, dir string, pub string, jwt string) { 3332 t.Helper() 3333 err := os.WriteFile(filepath.Join(dir, pub+".jwt"), []byte(jwt), 0644) 3334 require_NoError(t, err) 3335 } 3336 3337 func TestJWTAccountNATSResolverFetch(t *testing.T) { 3338 origEventsHBInterval := eventsHBInterval 3339 eventsHBInterval = 50 * time.Millisecond // speed up eventing 3340 defer func() { eventsHBInterval = origEventsHBInterval }() 3341 require_NoLocalOrRemoteConnections := func(account string, srvs ...*Server) { 3342 t.Helper() 3343 for _, srv := range srvs { 3344 if acc, ok := srv.accounts.Load(account); ok { 3345 checkAccClientsCount(t, acc.(*Account), 0) 3346 } 3347 } 3348 } 3349 // After each connection check, require_XConnection and connect assures that 3350 // listed server have no connections for the account used 3351 require_1Connection := func(url, creds, acc string, srvs ...*Server) { 3352 t.Helper() 3353 func() { 3354 t.Helper() 3355 c := natsConnect(t, url, nats.UserCredentials(creds)) 3356 defer c.Close() 3357 if _, err := nats.Connect(url, nats.UserCredentials(creds)); err == nil { 3358 t.Fatal("Second connection was supposed to fail due to limits") 3359 } else if !strings.Contains(err.Error(), ErrTooManyAccountConnections.Error()) { 3360 t.Fatal("Second connection was supposed to fail with too many conns") 3361 } 3362 }() 3363 require_NoLocalOrRemoteConnections(acc, srvs...) 3364 } 3365 require_2Connection := func(url, creds, acc string, srvs ...*Server) { 3366 t.Helper() 3367 func() { 3368 t.Helper() 3369 c1 := natsConnect(t, url, nats.UserCredentials(creds)) 3370 defer c1.Close() 3371 c2 := natsConnect(t, url, nats.UserCredentials(creds)) 3372 defer c2.Close() 3373 if _, err := nats.Connect(url, nats.UserCredentials(creds)); err == nil { 3374 t.Fatal("Third connection was supposed to fail due to limits") 3375 } else if !strings.Contains(err.Error(), ErrTooManyAccountConnections.Error()) { 3376 t.Fatal("Third connection was supposed to fail with too many conns") 3377 } 3378 }() 3379 require_NoLocalOrRemoteConnections(acc, srvs...) 3380 } 3381 connect := func(url string, credsfile string, acc string, srvs ...*Server) { 3382 t.Helper() 3383 nc := natsConnect(t, url, nats.UserCredentials(credsfile), nats.Timeout(5*time.Second)) 3384 nc.Close() 3385 require_NoLocalOrRemoteConnections(acc, srvs...) 3386 } 3387 createAccountAndUser := func(limit bool, done chan struct{}, pubKey, jwt1, jwt2, creds *string) { 3388 t.Helper() 3389 kp, _ := nkeys.CreateAccount() 3390 *pubKey, _ = kp.PublicKey() 3391 claim := jwt.NewAccountClaims(*pubKey) 3392 if limit { 3393 claim.Limits.Conn = 1 3394 } 3395 var err error 3396 *jwt1, err = claim.Encode(oKp) 3397 require_NoError(t, err) 3398 // need to assure that create time differs (resolution is sec) 3399 time.Sleep(time.Millisecond * 1100) 3400 // create updated claim allowing more connections 3401 if limit { 3402 claim.Limits.Conn = 2 3403 } 3404 *jwt2, err = claim.Encode(oKp) 3405 require_NoError(t, err) 3406 ukp, _ := nkeys.CreateUser() 3407 seed, _ := ukp.Seed() 3408 upub, _ := ukp.PublicKey() 3409 uclaim := newJWTTestUserClaims() 3410 uclaim.Subject = upub 3411 ujwt, err := uclaim.Encode(kp) 3412 require_NoError(t, err) 3413 *creds = genCredsFile(t, ujwt, seed) 3414 done <- struct{}{} 3415 } 3416 // Create Accounts and corresponding user creds. Do so concurrently to speed up the test 3417 doneChan := make(chan struct{}, 5) 3418 defer close(doneChan) 3419 var syspub, sysjwt, dummy1, sysCreds string 3420 go createAccountAndUser(false, doneChan, &syspub, &sysjwt, &dummy1, &sysCreds) 3421 var apub, ajwt1, ajwt2, aCreds string 3422 go createAccountAndUser(true, doneChan, &apub, &ajwt1, &ajwt2, &aCreds) 3423 var bpub, bjwt1, bjwt2, bCreds string 3424 go createAccountAndUser(true, doneChan, &bpub, &bjwt1, &bjwt2, &bCreds) 3425 var cpub, cjwt1, cjwt2, cCreds string 3426 go createAccountAndUser(true, doneChan, &cpub, &cjwt1, &cjwt2, &cCreds) 3427 var dpub, djwt1, dummy2, dCreds string // extra user used later in the test in order to test limits 3428 go createAccountAndUser(true, doneChan, &dpub, &djwt1, &dummy2, &dCreds) 3429 for i := 0; i < cap(doneChan); i++ { 3430 <-doneChan 3431 } 3432 // Create one directory for each server 3433 dirA := t.TempDir() 3434 dirB := t.TempDir() 3435 dirC := t.TempDir() 3436 // simulate a restart of the server by storing files in them 3437 // Server A/B will completely sync, so after startup each server 3438 // will contain the union off all stored/configured jwt 3439 // Server C will send out lookup requests for jwt it does not store itself 3440 writeJWT(t, dirA, apub, ajwt1) 3441 writeJWT(t, dirB, bpub, bjwt1) 3442 writeJWT(t, dirC, cpub, cjwt1) 3443 // Create seed server A (using no_advertise to prevent fail over) 3444 confA := createConfFile(t, []byte(fmt.Sprintf(` 3445 listen: 127.0.0.1:-1 3446 server_name: srv-A 3447 operator: %s 3448 system_account: %s 3449 resolver: { 3450 type: full 3451 dir: '%s' 3452 interval: "200ms" 3453 limit: 4 3454 } 3455 resolver_preload: { 3456 %s: %s 3457 } 3458 cluster { 3459 name: clust 3460 listen: 127.0.0.1:-1 3461 no_advertise: true 3462 } 3463 `, ojwt, syspub, dirA, cpub, cjwt1))) 3464 sA, _ := RunServerWithConfig(confA) 3465 defer sA.Shutdown() 3466 // during startup resolver_preload causes the directory to contain data 3467 require_JWTPresent(t, dirA, cpub) 3468 // Create Server B (using no_advertise to prevent fail over) 3469 confB := createConfFile(t, []byte(fmt.Sprintf(` 3470 listen: 127.0.0.1:-1 3471 server_name: srv-B 3472 operator: %s 3473 system_account: %s 3474 resolver: { 3475 type: full 3476 3477 dir: '%s' 3478 interval: "200ms" 3479 limit: 4 3480 } 3481 cluster { 3482 name: clust 3483 listen: 127.0.0.1:-1 3484 no_advertise: true 3485 routes [ 3486 nats-route://127.0.0.1:%d 3487 ] 3488 } 3489 `, ojwt, syspub, dirB, sA.opts.Cluster.Port))) 3490 sB, _ := RunServerWithConfig(confB) 3491 defer sB.Shutdown() 3492 // Create Server C (using no_advertise to prevent fail over) 3493 fmtC := ` 3494 listen: 127.0.0.1:-1 3495 server_name: srv-C 3496 operator: %s 3497 system_account: %s 3498 resolver: { 3499 type: cache 3500 dir: '%s' 3501 ttl: "%dms" 3502 limit: 4 3503 } 3504 cluster { 3505 name: clust 3506 listen: 127.0.0.1:-1 3507 no_advertise: true 3508 routes [ 3509 nats-route://127.0.0.1:%d 3510 ] 3511 } 3512 ` 3513 confClongTTL := createConfFile(t, []byte(fmt.Sprintf(fmtC, ojwt, syspub, dirC, 10000, sA.opts.Cluster.Port))) 3514 confCshortTTL := createConfFile(t, []byte(fmt.Sprintf(fmtC, ojwt, syspub, dirC, 1000, sA.opts.Cluster.Port))) 3515 sC, _ := RunServerWithConfig(confClongTTL) // use long ttl to assure it is not kicking 3516 defer sC.Shutdown() 3517 // startup cluster 3518 checkClusterFormed(t, sA, sB, sC) 3519 time.Sleep(500 * time.Millisecond) // wait for the protocol to converge 3520 // Check all accounts 3521 require_JWTPresent(t, dirA, apub) // was already present on startup 3522 require_JWTPresent(t, dirB, apub) // was copied from server A 3523 require_JWTAbsent(t, dirC, apub) 3524 require_JWTPresent(t, dirA, bpub) // was copied from server B 3525 require_JWTPresent(t, dirB, bpub) // was already present on startup 3526 require_JWTAbsent(t, dirC, bpub) 3527 require_JWTPresent(t, dirA, cpub) // was present in preload 3528 require_JWTPresent(t, dirB, cpub) // was copied from server A 3529 require_JWTPresent(t, dirC, cpub) // was already present on startup 3530 // This is to test that connecting to it still works 3531 require_JWTAbsent(t, dirA, syspub) 3532 require_JWTAbsent(t, dirB, syspub) 3533 require_JWTAbsent(t, dirC, syspub) 3534 // system account client can connect to every server 3535 connect(sA.ClientURL(), sysCreds, "") 3536 connect(sB.ClientURL(), sysCreds, "") 3537 connect(sC.ClientURL(), sysCreds, "") 3538 checkClusterFormed(t, sA, sB, sC) 3539 // upload system account and require a response from each server 3540 passCnt := updateJwt(t, sA.ClientURL(), sysCreds, sysjwt, 3) 3541 require_True(t, passCnt == 3) 3542 require_JWTPresent(t, dirA, syspub) // was just received 3543 require_JWTPresent(t, dirB, syspub) // was just received 3544 require_JWTPresent(t, dirC, syspub) // was just received 3545 // Only files missing are in C, which is only caching 3546 connect(sC.ClientURL(), aCreds, apub, sA, sB, sC) 3547 connect(sC.ClientURL(), bCreds, bpub, sA, sB, sC) 3548 require_JWTPresent(t, dirC, apub) // was looked up form A or B 3549 require_JWTPresent(t, dirC, bpub) // was looked up from A or B 3550 // Check limits and update jwt B connecting to server A 3551 for port, v := range map[string]struct{ pub, jwt, creds string }{ 3552 sB.ClientURL(): {bpub, bjwt2, bCreds}, 3553 sC.ClientURL(): {cpub, cjwt2, cCreds}, 3554 } { 3555 require_1Connection(sA.ClientURL(), v.creds, v.pub, sA, sB, sC) 3556 require_1Connection(sB.ClientURL(), v.creds, v.pub, sA, sB, sC) 3557 require_1Connection(sC.ClientURL(), v.creds, v.pub, sA, sB, sC) 3558 passCnt := updateJwt(t, port, sysCreds, v.jwt, 3) 3559 require_True(t, passCnt == 3) 3560 require_2Connection(sA.ClientURL(), v.creds, v.pub, sA, sB, sC) 3561 require_2Connection(sB.ClientURL(), v.creds, v.pub, sA, sB, sC) 3562 require_2Connection(sC.ClientURL(), v.creds, v.pub, sA, sB, sC) 3563 require_JWTEqual(t, dirA, v.pub, v.jwt) 3564 require_JWTEqual(t, dirB, v.pub, v.jwt) 3565 require_JWTEqual(t, dirC, v.pub, v.jwt) 3566 } 3567 // Simulates A having missed an update 3568 // shutting B down as it has it will directly connect to A and connect right away 3569 sB.Shutdown() 3570 writeJWT(t, dirB, apub, ajwt2) // this will be copied to server A 3571 sB, _ = RunServerWithConfig(confB) 3572 defer sB.Shutdown() 3573 checkClusterFormed(t, sA, sB, sC) 3574 time.Sleep(500 * time.Millisecond) // wait for the protocol to converge 3575 // Restart server C. this is a workaround to force C to do a lookup in the absence of account cleanup 3576 sC.Shutdown() 3577 sC, _ = RunServerWithConfig(confClongTTL) //TODO remove this once we clean up accounts 3578 defer sC.Shutdown() 3579 require_JWTEqual(t, dirA, apub, ajwt2) // was copied from server B 3580 require_JWTEqual(t, dirB, apub, ajwt2) // was restarted with this 3581 require_JWTEqual(t, dirC, apub, ajwt1) // still contains old cached value 3582 require_2Connection(sA.ClientURL(), aCreds, apub, sA, sB, sC) 3583 require_2Connection(sB.ClientURL(), aCreds, apub, sA, sB, sC) 3584 require_1Connection(sC.ClientURL(), aCreds, apub, sA, sB, sC) 3585 // Restart server C. this is a workaround to force C to do a lookup in the absence of account cleanup 3586 sC.Shutdown() 3587 sC, _ = RunServerWithConfig(confCshortTTL) //TODO remove this once we clean up accounts 3588 defer sC.Shutdown() 3589 require_JWTEqual(t, dirC, apub, ajwt1) // still contains old cached value 3590 checkClusterFormed(t, sA, sB, sC) 3591 // Force next connect to do a lookup exceeds ttl 3592 fname := filepath.Join(dirC, apub+".jwt") 3593 checkFor(t, 2*time.Second, 100*time.Millisecond, func() error { 3594 _, err := os.Stat(fname) 3595 if os.IsNotExist(err) { 3596 return nil 3597 } 3598 return fmt.Errorf("File not removed in time") 3599 }) 3600 connect(sC.ClientURL(), aCreds, apub, sA, sB, sC) // When lookup happens 3601 require_JWTEqual(t, dirC, apub, ajwt2) // was looked up form A or B 3602 require_2Connection(sC.ClientURL(), aCreds, apub, sA, sB, sC) 3603 // Test exceeding limit. For the exclusive directory resolver, limit is a stop gap measure. 3604 // It is not expected to be hit. When hit the administrator is supposed to take action. 3605 passCnt = updateJwt(t, sA.ClientURL(), sysCreds, djwt1, 3) 3606 require_True(t, passCnt == 1) // Only Server C updated 3607 for _, srv := range []*Server{sA, sB, sC} { 3608 if a, ok := srv.accounts.Load(syspub); ok { 3609 acc := a.(*Account) 3610 checkFor(t, time.Second, 20*time.Millisecond, func() error { 3611 acc.mu.Lock() 3612 defer acc.mu.Unlock() 3613 if acc.ctmr != nil { 3614 return fmt.Errorf("Timer still exists") 3615 } 3616 return nil 3617 }) 3618 } 3619 } 3620 } 3621 3622 func TestJWTAccountNATSResolverCrossClusterFetch(t *testing.T) { 3623 connect := func(url string, credsfile string) { 3624 t.Helper() 3625 nc := natsConnect(t, url, nats.UserCredentials(credsfile)) 3626 nc.Close() 3627 } 3628 createAccountAndUser := func(done chan struct{}, pubKey, jwt1, jwt2, creds *string) { 3629 t.Helper() 3630 kp, _ := nkeys.CreateAccount() 3631 *pubKey, _ = kp.PublicKey() 3632 claim := jwt.NewAccountClaims(*pubKey) 3633 var err error 3634 *jwt1, err = claim.Encode(oKp) 3635 require_NoError(t, err) 3636 // need to assure that create time differs (resolution is sec) 3637 time.Sleep(time.Millisecond * 1100) 3638 // create updated claim 3639 claim.Tags.Add("tag") 3640 *jwt2, err = claim.Encode(oKp) 3641 require_NoError(t, err) 3642 ukp, _ := nkeys.CreateUser() 3643 seed, _ := ukp.Seed() 3644 upub, _ := ukp.PublicKey() 3645 uclaim := newJWTTestUserClaims() 3646 uclaim.Subject = upub 3647 ujwt, err := uclaim.Encode(kp) 3648 require_NoError(t, err) 3649 *creds = genCredsFile(t, ujwt, seed) 3650 done <- struct{}{} 3651 } 3652 // Create Accounts and corresponding user creds. Do so concurrently to speed up the test 3653 doneChan := make(chan struct{}, 3) 3654 defer close(doneChan) 3655 var syspub, sysjwt, dummy1, sysCreds string 3656 go createAccountAndUser(doneChan, &syspub, &sysjwt, &dummy1, &sysCreds) 3657 var apub, ajwt1, ajwt2, aCreds string 3658 go createAccountAndUser(doneChan, &apub, &ajwt1, &ajwt2, &aCreds) 3659 var bpub, bjwt1, bjwt2, bCreds string 3660 go createAccountAndUser(doneChan, &bpub, &bjwt1, &bjwt2, &bCreds) 3661 for i := 0; i < cap(doneChan); i++ { 3662 <-doneChan 3663 } 3664 // Create one directory for each server 3665 dirAA := t.TempDir() 3666 dirAB := t.TempDir() 3667 dirBA := t.TempDir() 3668 dirBB := t.TempDir() 3669 // simulate a restart of the server by storing files in them 3670 // Server AA & AB will completely sync 3671 // Server BA & BB will completely sync 3672 // Be aware that no syncing will occur between cluster 3673 writeJWT(t, dirAA, apub, ajwt1) 3674 writeJWT(t, dirBA, bpub, bjwt1) 3675 // Create seed server A (using no_advertise to prevent fail over) 3676 confAA := createConfFile(t, []byte(fmt.Sprintf(` 3677 listen: 127.0.0.1:-1 3678 server_name: srv-A-A 3679 operator: %s 3680 system_account: %s 3681 resolver: { 3682 type: full 3683 dir: '%s' 3684 interval: "200ms" 3685 } 3686 gateway: { 3687 name: "clust-A" 3688 listen: 127.0.0.1:-1 3689 } 3690 cluster { 3691 name: clust-A 3692 listen: 127.0.0.1:-1 3693 no_advertise: true 3694 } 3695 `, ojwt, syspub, dirAA))) 3696 sAA, _ := RunServerWithConfig(confAA) 3697 defer sAA.Shutdown() 3698 // Create Server B (using no_advertise to prevent fail over) 3699 confAB := createConfFile(t, []byte(fmt.Sprintf(` 3700 listen: 127.0.0.1:-1 3701 server_name: srv-A-B 3702 operator: %s 3703 system_account: %s 3704 resolver: { 3705 type: full 3706 dir: '%s' 3707 interval: "200ms" 3708 } 3709 gateway: { 3710 name: "clust-A" 3711 listen: 127.0.0.1:-1 3712 } 3713 cluster { 3714 name: clust-A 3715 listen: 127.0.0.1:-1 3716 no_advertise: true 3717 routes [ 3718 nats-route://127.0.0.1:%d 3719 ] 3720 } 3721 `, ojwt, syspub, dirAB, sAA.opts.Cluster.Port))) 3722 sAB, _ := RunServerWithConfig(confAB) 3723 defer sAB.Shutdown() 3724 // Create Server C (using no_advertise to prevent fail over) 3725 confBA := createConfFile(t, []byte(fmt.Sprintf(` 3726 listen: 127.0.0.1:-1 3727 server_name: srv-B-A 3728 operator: %s 3729 system_account: %s 3730 resolver: { 3731 type: full 3732 dir: '%s' 3733 interval: "200ms" 3734 } 3735 gateway: { 3736 name: "clust-B" 3737 listen: 127.0.0.1:-1 3738 gateways: [ 3739 {name: "clust-A", url: "nats://127.0.0.1:%d"}, 3740 ] 3741 } 3742 cluster { 3743 name: clust-B 3744 listen: 127.0.0.1:-1 3745 no_advertise: true 3746 } 3747 `, ojwt, syspub, dirBA, sAA.opts.Gateway.Port))) 3748 sBA, _ := RunServerWithConfig(confBA) 3749 defer sBA.Shutdown() 3750 // Create Server BA (using no_advertise to prevent fail over) 3751 confBB := createConfFile(t, []byte(fmt.Sprintf(` 3752 listen: 127.0.0.1:-1 3753 server_name: srv-B-B 3754 operator: %s 3755 system_account: %s 3756 resolver: { 3757 type: full 3758 dir: '%s' 3759 interval: "200ms" 3760 } 3761 cluster { 3762 name: clust-B 3763 listen: 127.0.0.1:-1 3764 no_advertise: true 3765 routes [ 3766 nats-route://127.0.0.1:%d 3767 ] 3768 } 3769 gateway: { 3770 name: "clust-B" 3771 listen: 127.0.0.1:-1 3772 gateways: [ 3773 {name: "clust-A", url: "nats://127.0.0.1:%d"}, 3774 ] 3775 } 3776 `, ojwt, syspub, dirBB, sBA.opts.Cluster.Port, sAA.opts.Cluster.Port))) 3777 sBB, _ := RunServerWithConfig(confBB) 3778 defer sBB.Shutdown() 3779 // Assert topology 3780 checkClusterFormed(t, sAA, sAB) 3781 checkClusterFormed(t, sBA, sBB) 3782 waitForOutboundGateways(t, sAA, 1, 5*time.Second) 3783 waitForOutboundGateways(t, sAB, 1, 5*time.Second) 3784 waitForOutboundGateways(t, sBA, 1, 5*time.Second) 3785 waitForOutboundGateways(t, sBB, 1, 5*time.Second) 3786 time.Sleep(500 * time.Millisecond) // wait for the protocol to converge 3787 updateJwt(t, sAA.ClientURL(), sysCreds, sysjwt, 4) // update system account jwt on all server 3788 require_JWTEqual(t, dirAA, syspub, sysjwt) // assure this update made it to every server 3789 require_JWTEqual(t, dirAB, syspub, sysjwt) // assure this update made it to every server 3790 require_JWTEqual(t, dirBA, syspub, sysjwt) // assure this update made it to every server 3791 require_JWTEqual(t, dirBB, syspub, sysjwt) // assure this update made it to every server 3792 require_JWTAbsent(t, dirAA, bpub) // assure that jwt are not synced across cluster 3793 require_JWTAbsent(t, dirAB, bpub) // assure that jwt are not synced across cluster 3794 require_JWTAbsent(t, dirBA, apub) // assure that jwt are not synced across cluster 3795 require_JWTAbsent(t, dirBB, apub) // assure that jwt are not synced across cluster 3796 connect(sAA.ClientURL(), aCreds) // connect to cluster where jwt was initially stored 3797 connect(sAB.ClientURL(), aCreds) // connect to cluster where jwt was initially stored 3798 connect(sBA.ClientURL(), bCreds) // connect to cluster where jwt was initially stored 3799 connect(sBB.ClientURL(), bCreds) // connect to cluster where jwt was initially stored 3800 time.Sleep(500 * time.Millisecond) // wait for the protocol to (NOT) converge 3801 require_JWTAbsent(t, dirAA, bpub) // assure that jwt are still not synced across cluster 3802 require_JWTAbsent(t, dirAB, bpub) // assure that jwt are still not synced across cluster 3803 require_JWTAbsent(t, dirBA, apub) // assure that jwt are still not synced across cluster 3804 require_JWTAbsent(t, dirBB, apub) // assure that jwt are still not synced across cluster 3805 // We have verified that account B does not exist in cluster A, neither does account A in cluster B 3806 // Despite that clients from account B can connect to server A, same for account A in cluster B 3807 connect(sAA.ClientURL(), bCreds) // connect to cluster where jwt was not initially stored 3808 connect(sAB.ClientURL(), bCreds) // connect to cluster where jwt was not initially stored 3809 connect(sBA.ClientURL(), aCreds) // connect to cluster where jwt was not initially stored 3810 connect(sBB.ClientURL(), aCreds) // connect to cluster where jwt was not initially stored 3811 require_JWTEqual(t, dirAA, bpub, bjwt1) // assure that now jwt used in connect is stored 3812 require_JWTEqual(t, dirAB, bpub, bjwt1) // assure that now jwt used in connect is stored 3813 require_JWTEqual(t, dirBA, apub, ajwt1) // assure that now jwt used in connect is stored 3814 require_JWTEqual(t, dirBB, apub, ajwt1) // assure that now jwt used in connect is stored 3815 updateJwt(t, sAA.ClientURL(), sysCreds, bjwt2, 4) // update bjwt, expect updates from everywhere 3816 updateJwt(t, sBA.ClientURL(), sysCreds, ajwt2, 4) // update ajwt, expect updates from everywhere 3817 require_JWTEqual(t, dirAA, bpub, bjwt2) // assure that jwt got updated accordingly 3818 require_JWTEqual(t, dirAB, bpub, bjwt2) // assure that jwt got updated accordingly 3819 require_JWTEqual(t, dirBA, apub, ajwt2) // assure that jwt got updated accordingly 3820 require_JWTEqual(t, dirBB, apub, ajwt2) // assure that jwt got updated accordingly 3821 } 3822 3823 func newTimeRange(start time.Time, dur time.Duration) jwt.TimeRange { 3824 return jwt.TimeRange{Start: start.Format("15:04:05"), End: start.Add(dur).Format("15:04:05")} 3825 } 3826 3827 func createUserWithLimit(t *testing.T, accKp nkeys.KeyPair, expiration time.Time, limits func(*jwt.UserPermissionLimits)) string { 3828 t.Helper() 3829 ukp, _ := nkeys.CreateUser() 3830 seed, _ := ukp.Seed() 3831 upub, _ := ukp.PublicKey() 3832 uclaim := newJWTTestUserClaims() 3833 uclaim.Subject = upub 3834 if limits != nil { 3835 limits(&uclaim.UserPermissionLimits) 3836 } 3837 if !expiration.IsZero() { 3838 uclaim.Expires = expiration.Unix() 3839 } 3840 vr := jwt.ValidationResults{} 3841 uclaim.Validate(&vr) 3842 require_Len(t, len(vr.Errors()), 0) 3843 ujwt, err := uclaim.Encode(accKp) 3844 require_NoError(t, err) 3845 return genCredsFile(t, ujwt, seed) 3846 } 3847 3848 func TestJWTUserLimits(t *testing.T) { 3849 // helper for time 3850 inAnHour := time.Now().Add(time.Hour) 3851 inTwoHours := time.Now().Add(2 * time.Hour) 3852 doNotExpire := time.Now().AddDate(1, 0, 0) 3853 // create account 3854 kp, _ := nkeys.CreateAccount() 3855 aPub, _ := kp.PublicKey() 3856 claim := jwt.NewAccountClaims(aPub) 3857 aJwt, err := claim.Encode(oKp) 3858 require_NoError(t, err) 3859 conf := createConfFile(t, []byte(fmt.Sprintf(` 3860 listen: 127.0.0.1:-1 3861 operator: %s 3862 resolver: MEM 3863 resolver_preload: { 3864 %s: %s 3865 } 3866 `, ojwt, aPub, aJwt))) 3867 sA, _ := RunServerWithConfig(conf) 3868 defer sA.Shutdown() 3869 for _, v := range []struct { 3870 pass bool 3871 f func(*jwt.UserPermissionLimits) 3872 }{ 3873 {true, nil}, 3874 {false, func(j *jwt.UserPermissionLimits) { j.Src.Set("8.8.8.8/8") }}, 3875 {true, func(j *jwt.UserPermissionLimits) { j.Src.Set("8.8.8.8/0") }}, 3876 {true, func(j *jwt.UserPermissionLimits) { j.Src.Set("127.0.0.1/8") }}, 3877 {true, func(j *jwt.UserPermissionLimits) { j.Src.Set("8.8.8.8/8,127.0.0.1/8") }}, 3878 {false, func(j *jwt.UserPermissionLimits) { j.Src.Set("8.8.8.8/8,9.9.9.9/8") }}, 3879 {true, func(j *jwt.UserPermissionLimits) { j.Times = append(j.Times, newTimeRange(time.Now(), time.Hour)) }}, 3880 {false, func(j *jwt.UserPermissionLimits) { 3881 j.Times = append(j.Times, newTimeRange(time.Now().Add(time.Hour), time.Hour)) 3882 }}, 3883 {true, func(j *jwt.UserPermissionLimits) { 3884 j.Times = append(j.Times, newTimeRange(inAnHour, time.Hour), newTimeRange(time.Now(), time.Hour)) 3885 }}, // last one is within range 3886 {false, func(j *jwt.UserPermissionLimits) { 3887 j.Times = append(j.Times, newTimeRange(inAnHour, time.Hour), newTimeRange(inTwoHours, time.Hour)) 3888 }}, // out of range 3889 {false, func(j *jwt.UserPermissionLimits) { 3890 j.Times = append(j.Times, newTimeRange(inAnHour, 3*time.Hour), newTimeRange(inTwoHours, 2*time.Hour)) 3891 }}, // overlapping [a[]b] out of range*/ 3892 {false, func(j *jwt.UserPermissionLimits) { 3893 j.Times = append(j.Times, newTimeRange(inAnHour, 3*time.Hour), newTimeRange(inTwoHours, time.Hour)) 3894 }}, // overlapping [a[b]] out of range 3895 // next day tests where end < begin 3896 {true, func(j *jwt.UserPermissionLimits) { j.Times = append(j.Times, newTimeRange(time.Now(), 25*time.Hour)) }}, 3897 {true, func(j *jwt.UserPermissionLimits) { j.Times = append(j.Times, newTimeRange(time.Now(), -time.Hour)) }}, 3898 } { 3899 t.Run("", func(t *testing.T) { 3900 creds := createUserWithLimit(t, kp, doNotExpire, v.f) 3901 if c, err := nats.Connect(sA.ClientURL(), nats.UserCredentials(creds)); err == nil { 3902 c.Close() 3903 if !v.pass { 3904 t.Fatalf("Expected failure got none") 3905 } 3906 } else if v.pass { 3907 t.Fatalf("Expected success got %v", err) 3908 } else if !strings.Contains(err.Error(), "Authorization Violation") { 3909 t.Fatalf("Expected error other than %v", err) 3910 } 3911 }) 3912 } 3913 } 3914 3915 func TestJWTTimeExpiration(t *testing.T) { 3916 validFor := 1500 * time.Millisecond 3917 validRange := 500 * time.Millisecond 3918 doNotExpire := time.Now().AddDate(1, 0, 0) 3919 // create account 3920 kp, _ := nkeys.CreateAccount() 3921 aPub, _ := kp.PublicKey() 3922 claim := jwt.NewAccountClaims(aPub) 3923 aJwt, err := claim.Encode(oKp) 3924 require_NoError(t, err) 3925 conf := createConfFile(t, []byte(fmt.Sprintf(` 3926 listen: 127.0.0.1:-1 3927 operator: %s 3928 resolver: MEM 3929 resolver_preload: { 3930 %s: %s 3931 } 3932 `, ojwt, aPub, aJwt))) 3933 sA, _ := RunServerWithConfig(conf) 3934 defer sA.Shutdown() 3935 for _, l := range []string{"", "Europe/Berlin", "America/New_York"} { 3936 t.Run("simple expiration "+l, func(t *testing.T) { 3937 start := time.Now() 3938 creds := createUserWithLimit(t, kp, doNotExpire, func(j *jwt.UserPermissionLimits) { 3939 if l == _EMPTY_ { 3940 j.Times = []jwt.TimeRange{newTimeRange(start, validFor)} 3941 } else { 3942 loc, err := time.LoadLocation(l) 3943 require_NoError(t, err) 3944 j.Times = []jwt.TimeRange{newTimeRange(start.In(loc), validFor)} 3945 j.Locale = l 3946 } 3947 }) 3948 disconnectChan := make(chan struct{}) 3949 defer close(disconnectChan) 3950 errChan := make(chan struct{}) 3951 defer close(errChan) 3952 c := natsConnect(t, sA.ClientURL(), 3953 nats.UserCredentials(creds), 3954 nats.DisconnectErrHandler(func(conn *nats.Conn, err error) { 3955 if err != io.EOF { 3956 return 3957 } 3958 disconnectChan <- struct{}{} 3959 }), 3960 nats.ErrorHandler(func(conn *nats.Conn, s *nats.Subscription, err error) { 3961 if err != nats.ErrAuthExpired { 3962 return 3963 } 3964 now := time.Now() 3965 stop := start.Add(validFor) 3966 // assure event happens within a second of stop 3967 if stop.Add(-validRange).Before(stop) && now.Before(stop.Add(validRange)) { 3968 errChan <- struct{}{} 3969 } 3970 })) 3971 defer c.Close() 3972 chanRecv(t, errChan, 10*time.Second) 3973 chanRecv(t, disconnectChan, 10*time.Second) 3974 require_True(t, c.IsReconnecting()) 3975 require_False(t, c.IsConnected()) 3976 }) 3977 } 3978 t.Run("double expiration", func(t *testing.T) { 3979 start1 := time.Now() 3980 start2 := start1.Add(2 * validFor) 3981 creds := createUserWithLimit(t, kp, doNotExpire, func(j *jwt.UserPermissionLimits) { 3982 j.Times = []jwt.TimeRange{newTimeRange(start1, validFor), newTimeRange(start2, validFor)} 3983 }) 3984 errChan := make(chan struct{}) 3985 defer close(errChan) 3986 reConnectChan := make(chan struct{}) 3987 defer close(reConnectChan) 3988 c := natsConnect(t, sA.ClientURL(), 3989 nats.UserCredentials(creds), 3990 nats.ReconnectHandler(func(conn *nats.Conn) { 3991 reConnectChan <- struct{}{} 3992 }), 3993 nats.ErrorHandler(func(conn *nats.Conn, s *nats.Subscription, err error) { 3994 if err != nats.ErrAuthExpired { 3995 return 3996 } 3997 now := time.Now() 3998 stop := start1.Add(validFor) 3999 // assure event happens within a second of stop 4000 if stop.Add(-validRange).Before(stop) && now.Before(stop.Add(validRange)) { 4001 errChan <- struct{}{} 4002 return 4003 } 4004 stop = start2.Add(validFor) 4005 // assure event happens within a second of stop 4006 if stop.Add(-validRange).Before(stop) && now.Before(stop.Add(validRange)) { 4007 errChan <- struct{}{} 4008 } 4009 })) 4010 defer c.Close() 4011 chanRecv(t, errChan, 10*time.Second) 4012 chanRecv(t, reConnectChan, 10*time.Second) 4013 require_False(t, c.IsReconnecting()) 4014 require_True(t, c.IsConnected()) 4015 chanRecv(t, errChan, 10*time.Second) 4016 }) 4017 t.Run("lower jwt expiration overwrites time", func(t *testing.T) { 4018 start := time.Now() 4019 creds := createUserWithLimit(t, kp, start.Add(validFor), func(j *jwt.UserPermissionLimits) { j.Times = []jwt.TimeRange{newTimeRange(start, 2*validFor)} }) 4020 disconnectChan := make(chan struct{}) 4021 defer close(disconnectChan) 4022 errChan := make(chan struct{}) 4023 defer close(errChan) 4024 c := natsConnect(t, sA.ClientURL(), 4025 nats.UserCredentials(creds), 4026 nats.DisconnectErrHandler(func(conn *nats.Conn, err error) { 4027 if err != io.EOF { 4028 return 4029 } 4030 disconnectChan <- struct{}{} 4031 }), 4032 nats.ErrorHandler(func(conn *nats.Conn, s *nats.Subscription, err error) { 4033 if err != nats.ErrAuthExpired { 4034 return 4035 } 4036 now := time.Now() 4037 stop := start.Add(validFor) 4038 // assure event happens within a second of stop 4039 if stop.Add(-validRange).Before(stop) && now.Before(stop.Add(validRange)) { 4040 errChan <- struct{}{} 4041 } 4042 })) 4043 defer c.Close() 4044 chanRecv(t, errChan, 10*time.Second) 4045 chanRecv(t, disconnectChan, 10*time.Second) 4046 require_True(t, c.IsReconnecting()) 4047 require_False(t, c.IsConnected()) 4048 }) 4049 } 4050 4051 func NewJwtAccountClaim(name string) (nkeys.KeyPair, string, *jwt.AccountClaims) { 4052 sysKp, _ := nkeys.CreateAccount() 4053 sysPub, _ := sysKp.PublicKey() 4054 claim := jwt.NewAccountClaims(sysPub) 4055 claim.Name = name 4056 return sysKp, sysPub, claim 4057 } 4058 4059 func TestJWTSysImportForDifferentAccount(t *testing.T) { 4060 _, sysPub, sysClaim := NewJwtAccountClaim("SYS") 4061 sysClaim.Exports.Add(&jwt.Export{ 4062 Type: jwt.Service, 4063 Subject: "$SYS.REQ.ACCOUNT.*.INFO", 4064 }) 4065 sysJwt, err := sysClaim.Encode(oKp) 4066 require_NoError(t, err) 4067 4068 // create account 4069 aKp, aPub, claim := NewJwtAccountClaim("A") 4070 claim.Imports.Add(&jwt.Import{ 4071 Type: jwt.Service, 4072 Subject: "$SYS.REQ.ACCOUNT.*.INFO", 4073 LocalSubject: "COMMON.ADVISORY.SYS.REQ.ACCOUNT.*.INFO", 4074 Account: sysPub, 4075 }) 4076 aJwt, err := claim.Encode(oKp) 4077 require_NoError(t, err) 4078 4079 conf := createConfFile(t, []byte(fmt.Sprintf(` 4080 listen: 127.0.0.1:-1 4081 operator: %s 4082 system_account: %s 4083 resolver: MEM 4084 resolver_preload: { 4085 %s: %s 4086 %s: %s 4087 } 4088 `, ojwt, sysPub, sysPub, sysJwt, aPub, aJwt))) 4089 sA, _ := RunServerWithConfig(conf) 4090 defer sA.Shutdown() 4091 4092 nc := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, aKp)) 4093 defer nc.Close() 4094 // user for account a requests for a different account, the system account 4095 m, err := nc.Request(fmt.Sprintf("COMMON.ADVISORY.SYS.REQ.ACCOUNT.%s.INFO", sysPub), nil, time.Second) 4096 require_NoError(t, err) 4097 resp := &ServerAPIResponse{} 4098 require_NoError(t, json.Unmarshal(m.Data, resp)) 4099 require_True(t, resp.Error == nil) 4100 } 4101 4102 func TestJWTSysImportFromNothing(t *testing.T) { 4103 _, sysPub, sysClaim := NewJwtAccountClaim("SYS") 4104 sysJwt, err := sysClaim.Encode(oKp) 4105 require_NoError(t, err) 4106 4107 // create account 4108 aKp, aPub, claim := NewJwtAccountClaim("A") 4109 claim.Imports.Add(&jwt.Import{ 4110 Type: jwt.Service, 4111 // fails as it's not for own account, but system account 4112 Subject: jwt.Subject(fmt.Sprintf("$SYS.REQ.ACCOUNT.%s.CONNZ", sysPub)), 4113 LocalSubject: "fail1", 4114 Account: sysPub, 4115 }) 4116 claim.Imports.Add(&jwt.Import{ 4117 Type: jwt.Service, 4118 // fails as it's not for own account but all accounts 4119 Subject: "$SYS.REQ.ACCOUNT.*.CONNZ", 4120 LocalSubject: "fail2.*", 4121 Account: sysPub, 4122 }) 4123 claim.Imports.Add(&jwt.Import{ 4124 Type: jwt.Service, 4125 Subject: jwt.Subject(fmt.Sprintf("$SYS.REQ.ACCOUNT.%s.CONNZ", aPub)), 4126 LocalSubject: "pass", 4127 Account: sysPub, 4128 }) 4129 aJwt, err := claim.Encode(oKp) 4130 require_NoError(t, err) 4131 4132 conf := createConfFile(t, []byte(fmt.Sprintf(` 4133 listen: 127.0.0.1:-1 4134 operator: %s 4135 system_account: %s 4136 resolver: MEM 4137 resolver_preload: { 4138 %s: %s 4139 %s: %s 4140 } 4141 `, ojwt, sysPub, sysPub, sysJwt, aPub, aJwt))) 4142 sA, _ := RunServerWithConfig(conf) 4143 defer sA.Shutdown() 4144 4145 nc := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, aKp)) 4146 defer nc.Close() 4147 // user for account a requests for a different account, the system account 4148 _, err = nc.Request("pass", nil, time.Second) 4149 require_NoError(t, err) 4150 // default import 4151 _, err = nc.Request("$SYS.REQ.ACCOUNT.PING.CONNZ", nil, time.Second) 4152 require_NoError(t, err) 4153 _, err = nc.Request("fail1", nil, time.Second) 4154 require_Error(t, err) 4155 require_Contains(t, err.Error(), "no responders") 4156 // fails even for own account, as the import itself is bad 4157 _, err = nc.Request("fail2."+aPub, nil, time.Second) 4158 require_Error(t, err) 4159 require_Contains(t, err.Error(), "no responders") 4160 } 4161 4162 func TestJWTSysImportOverwritePublic(t *testing.T) { 4163 _, sysPub, sysClaim := NewJwtAccountClaim("SYS") 4164 // this changes the export permissions to allow for requests for every account 4165 sysClaim.Exports.Add(&jwt.Export{ 4166 Type: jwt.Service, 4167 Subject: "$SYS.REQ.ACCOUNT.*.>", 4168 }) 4169 sysJwt, err := sysClaim.Encode(oKp) 4170 require_NoError(t, err) 4171 4172 // create account 4173 aKp, aPub, claim := NewJwtAccountClaim("A") 4174 claim.Imports.Add(&jwt.Import{ 4175 Type: jwt.Service, 4176 Subject: jwt.Subject(fmt.Sprintf("$SYS.REQ.ACCOUNT.%s.CONNZ", sysPub)), 4177 LocalSubject: "pass1", 4178 Account: sysPub, 4179 }) 4180 claim.Imports.Add(&jwt.Import{ 4181 Type: jwt.Service, 4182 Subject: jwt.Subject(fmt.Sprintf("$SYS.REQ.ACCOUNT.%s.CONNZ", aPub)), 4183 LocalSubject: "pass2", 4184 Account: sysPub, 4185 }) 4186 claim.Imports.Add(&jwt.Import{ 4187 Type: jwt.Service, 4188 Subject: "$SYS.REQ.ACCOUNT.*.CONNZ", 4189 LocalSubject: "pass3.*", 4190 Account: sysPub, 4191 }) 4192 aJwt, err := claim.Encode(oKp) 4193 require_NoError(t, err) 4194 4195 conf := createConfFile(t, []byte(fmt.Sprintf(` 4196 listen: 127.0.0.1:-1 4197 operator: %s 4198 system_account: %s 4199 resolver: MEM 4200 resolver_preload: { 4201 %s: %s 4202 %s: %s 4203 } 4204 `, ojwt, sysPub, sysPub, sysJwt, aPub, aJwt))) 4205 sA, _ := RunServerWithConfig(conf) 4206 defer sA.Shutdown() 4207 4208 nc := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, aKp)) 4209 defer nc.Close() 4210 // user for account a requests for a different account, the system account 4211 _, err = nc.Request("pass1", nil, time.Second) 4212 require_NoError(t, err) 4213 _, err = nc.Request("pass2", nil, time.Second) 4214 require_NoError(t, err) 4215 _, err = nc.Request("pass3."+sysPub, nil, time.Second) 4216 require_NoError(t, err) 4217 _, err = nc.Request("pass3."+aPub, nil, time.Second) 4218 require_NoError(t, err) 4219 _, err = nc.Request("pass3.PING", nil, time.Second) 4220 require_NoError(t, err) 4221 } 4222 4223 func TestJWTSysImportOverwriteToken(t *testing.T) { 4224 _, sysPub, sysClaim := NewJwtAccountClaim("SYS") 4225 // this changes the export permissions in a way that the internal imports can't satisfy 4226 sysClaim.Exports.Add(&jwt.Export{ 4227 Type: jwt.Service, 4228 Subject: "$SYS.REQ.>", 4229 TokenReq: true, 4230 }) 4231 4232 sysJwt, err := sysClaim.Encode(oKp) 4233 require_NoError(t, err) 4234 4235 // create account 4236 aKp, aPub, claim := NewJwtAccountClaim("A") 4237 aJwt, err := claim.Encode(oKp) 4238 require_NoError(t, err) 4239 4240 conf := createConfFile(t, []byte(fmt.Sprintf(` 4241 listen: 127.0.0.1:-1 4242 operator: %s 4243 system_account: %s 4244 resolver: MEM 4245 resolver_preload: { 4246 %s: %s 4247 %s: %s 4248 } 4249 `, ojwt, sysPub, sysPub, sysJwt, aPub, aJwt))) 4250 sA, _ := RunServerWithConfig(conf) 4251 defer sA.Shutdown() 4252 4253 nc := natsConnect(t, sA.ClientURL(), createUserCreds(t, nil, aKp)) 4254 defer nc.Close() 4255 // make sure the internal import still got added 4256 _, err = nc.Request("$SYS.REQ.ACCOUNT.PING.CONNZ", nil, time.Second) 4257 require_NoError(t, err) 4258 } 4259 4260 func TestJWTLimits(t *testing.T) { 4261 doNotExpire := time.Now().AddDate(1, 0, 0) 4262 // create account 4263 kp, _ := nkeys.CreateAccount() 4264 aPub, _ := kp.PublicKey() 4265 claim := jwt.NewAccountClaims(aPub) 4266 aJwt, err := claim.Encode(oKp) 4267 require_NoError(t, err) 4268 conf := createConfFile(t, []byte(fmt.Sprintf(` 4269 listen: 127.0.0.1:-1 4270 operator: %s 4271 resolver: MEM 4272 resolver_preload: { 4273 %s: %s 4274 } 4275 `, ojwt, aPub, aJwt))) 4276 sA, _ := RunServerWithConfig(conf) 4277 defer sA.Shutdown() 4278 errChan := make(chan struct{}) 4279 defer close(errChan) 4280 t.Run("subs", func(t *testing.T) { 4281 creds := createUserWithLimit(t, kp, doNotExpire, func(j *jwt.UserPermissionLimits) { j.Subs = 1 }) 4282 c := natsConnect(t, sA.ClientURL(), nats.UserCredentials(creds), 4283 nats.DisconnectErrHandler(func(conn *nats.Conn, err error) { 4284 if e := conn.LastError(); e != nil && strings.Contains(e.Error(), "maximum subscriptions exceeded") { 4285 errChan <- struct{}{} 4286 } 4287 }), 4288 ) 4289 defer c.Close() 4290 if _, err := c.Subscribe("foo", func(msg *nats.Msg) {}); err != nil { 4291 t.Fatalf("couldn't subscribe: %v", err) 4292 } 4293 if _, err = c.Subscribe("bar", func(msg *nats.Msg) {}); err != nil { 4294 t.Fatalf("expected error got: %v", err) 4295 } 4296 chanRecv(t, errChan, time.Second) 4297 }) 4298 t.Run("payload", func(t *testing.T) { 4299 creds := createUserWithLimit(t, kp, doNotExpire, func(j *jwt.UserPermissionLimits) { j.Payload = 5 }) 4300 c := natsConnect(t, sA.ClientURL(), nats.UserCredentials(creds)) 4301 defer c.Close() 4302 if err := c.Flush(); err != nil { 4303 t.Fatalf("flush failed %v", err) 4304 } 4305 if err := c.Publish("foo", []byte("world")); err != nil { 4306 t.Fatalf("couldn't publish: %v", err) 4307 } 4308 if err := c.Publish("foo", []byte("worldX")); err != nats.ErrMaxPayload { 4309 t.Fatalf("couldn't publish: %v", err) 4310 } 4311 }) 4312 } 4313 4314 func TestJwtTemplates(t *testing.T) { 4315 kp, _ := nkeys.CreateAccount() 4316 aPub, _ := kp.PublicKey() 4317 ukp, _ := nkeys.CreateUser() 4318 upub, _ := ukp.PublicKey() 4319 uclaim := newJWTTestUserClaims() 4320 uclaim.Name = "myname" 4321 uclaim.Subject = upub 4322 uclaim.SetScoped(true) 4323 uclaim.IssuerAccount = aPub 4324 uclaim.Tags.Add("foo:foo1") 4325 uclaim.Tags.Add("foo:foo2") 4326 uclaim.Tags.Add("bar:bar1") 4327 uclaim.Tags.Add("bar:bar2") 4328 uclaim.Tags.Add("bar:bar3") 4329 4330 lim := jwt.UserPermissionLimits{} 4331 lim.Pub.Allow.Add("{{tag(foo)}}.none.{{tag(bar)}}") 4332 lim.Pub.Deny.Add("{{tag(foo)}}.{{account-tag(acc)}}") 4333 lim.Sub.Allow.Add("{{tag(NOT_THERE)}}") // expect to not emit this 4334 lim.Sub.Deny.Add("foo.{{name()}}.{{subject()}}.{{account-name()}}.{{account-subject()}}.bar") 4335 acc := &Account{nameTag: "accname", tags: []string{"acc:acc1", "acc:acc2"}} 4336 4337 resLim, err := processUserPermissionsTemplate(lim, uclaim, acc) 4338 require_NoError(t, err) 4339 4340 test := func(expectedSubjects []string, res jwt.StringList) { 4341 t.Helper() 4342 require_True(t, len(res) == len(expectedSubjects)) 4343 for _, expetedSubj := range expectedSubjects { 4344 require_True(t, res.Contains(expetedSubj)) 4345 } 4346 } 4347 4348 test(resLim.Pub.Allow, []string{"foo1.none.bar1", "foo1.none.bar2", "foo1.none.bar3", 4349 "foo2.none.bar1", "foo2.none.bar2", "foo2.none.bar3"}) 4350 4351 test(resLim.Pub.Deny, []string{"foo1.acc1", "foo1.acc2", "foo2.acc1", "foo2.acc2"}) 4352 4353 require_True(t, len(resLim.Sub.Allow) == 0) 4354 require_True(t, len(resLim.Sub.Deny) == 2) 4355 require_Contains(t, resLim.Sub.Deny[0], fmt.Sprintf("foo.myname.%s.accname.%s.bar", upub, aPub)) 4356 // added in to compensate for sub allow not resolving 4357 require_Contains(t, resLim.Sub.Deny[1], ">") 4358 4359 lim.Pub.Deny.Add("{{tag(NOT_THERE)}}") 4360 _, err = processUserPermissionsTemplate(lim, uclaim, acc) 4361 require_Error(t, err) 4362 require_Contains(t, err.Error(), "generated invalid subject") 4363 } 4364 4365 func TestJwtTemplateGoodTagAfterBadTag(t *testing.T) { 4366 kp, _ := nkeys.CreateAccount() 4367 aPub, _ := kp.PublicKey() 4368 ukp, _ := nkeys.CreateUser() 4369 upub, _ := ukp.PublicKey() 4370 uclaim := newJWTTestUserClaims() 4371 uclaim.Name = "myname" 4372 uclaim.Subject = upub 4373 uclaim.SetScoped(true) 4374 uclaim.IssuerAccount = aPub 4375 uclaim.Tags.Add("foo:foo1") 4376 4377 lim := jwt.UserPermissionLimits{} 4378 lim.Pub.Deny.Add("{{tag(NOT_THERE)}}.{{tag(foo)}}") 4379 acc := &Account{nameTag: "accname", tags: []string{"acc:acc1", "acc:acc2"}} 4380 4381 _, err := processUserPermissionsTemplate(lim, uclaim, acc) 4382 require_Error(t, err) 4383 require_Contains(t, err.Error(), "generated invalid subject") 4384 } 4385 4386 func TestJWTLimitsTemplate(t *testing.T) { 4387 kp, _ := nkeys.CreateAccount() 4388 aPub, _ := kp.PublicKey() 4389 claim := jwt.NewAccountClaims(aPub) 4390 aSignScopedKp, aSignScopedPub := createKey(t) 4391 signer := jwt.NewUserScope() 4392 signer.Key = aSignScopedPub 4393 signer.Template.Pub.Deny.Add("denied") 4394 signer.Template.Pub.Allow.Add("foo.{{name()}}") 4395 signer.Template.Sub.Allow.Add("foo.{{name()}}") 4396 claim.SigningKeys.AddScopedSigner(signer) 4397 aJwt, err := claim.Encode(oKp) 4398 require_NoError(t, err) 4399 conf := createConfFile(t, []byte(fmt.Sprintf(` 4400 listen: 127.0.0.1:-1 4401 operator: %s 4402 resolver: MEM 4403 resolver_preload: { 4404 %s: %s 4405 } 4406 `, ojwt, aPub, aJwt))) 4407 sA, _ := RunServerWithConfig(conf) 4408 defer sA.Shutdown() 4409 errChan := make(chan struct{}) 4410 defer close(errChan) 4411 4412 ukp, _ := nkeys.CreateUser() 4413 seed, _ := ukp.Seed() 4414 upub, _ := ukp.PublicKey() 4415 uclaim := newJWTTestUserClaims() 4416 uclaim.Name = "myname" 4417 uclaim.Subject = upub 4418 uclaim.SetScoped(true) 4419 uclaim.IssuerAccount = aPub 4420 4421 ujwt, err := uclaim.Encode(aSignScopedKp) 4422 require_NoError(t, err) 4423 creds := genCredsFile(t, ujwt, seed) 4424 4425 t.Run("pass", func(t *testing.T) { 4426 c := natsConnect(t, sA.ClientURL(), nats.UserCredentials(creds)) 4427 defer c.Close() 4428 sub, err := c.SubscribeSync("foo.myname") 4429 require_NoError(t, err) 4430 require_NoError(t, c.Flush()) 4431 require_NoError(t, c.Publish("foo.myname", nil)) 4432 _, err = sub.NextMsg(time.Second) 4433 require_NoError(t, err) 4434 }) 4435 t.Run("fail", func(t *testing.T) { 4436 c := natsConnect(t, sA.ClientURL(), nats.UserCredentials(creds), 4437 nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 4438 if strings.Contains(err.Error(), `nats: Permissions Violation for Publish to "foo.othername"`) { 4439 errChan <- struct{}{} 4440 } 4441 })) 4442 defer c.Close() 4443 require_NoError(t, c.Publish("foo.othername", nil)) 4444 select { 4445 case <-errChan: 4446 case <-time.After(time.Second * 2): 4447 require_True(t, false) 4448 } 4449 }) 4450 } 4451 4452 func TestJWTNoOperatorMode(t *testing.T) { 4453 for _, login := range []bool{true, false} { 4454 t.Run("", func(t *testing.T) { 4455 opts := DefaultOptions() 4456 if login { 4457 opts.Users = append(opts.Users, &User{Username: "u", Password: "pwd"}) 4458 } 4459 sA := RunServer(opts) 4460 defer sA.Shutdown() 4461 kp, _ := nkeys.CreateAccount() 4462 creds := createUserWithLimit(t, kp, time.Now().Add(time.Hour), nil) 4463 url := sA.ClientURL() 4464 if login { 4465 url = fmt.Sprintf("nats://u:pwd@%s:%d", sA.opts.Host, sA.opts.Port) 4466 } 4467 c := natsConnect(t, url, nats.UserCredentials(creds)) 4468 defer c.Close() 4469 sA.mu.Lock() 4470 defer sA.mu.Unlock() 4471 if len(sA.clients) != 1 { 4472 t.Fatalf("Expected exactly one client") 4473 } 4474 for _, v := range sA.clients { 4475 if v.opts.JWT != "" { 4476 t.Fatalf("Expected no jwt %v", v.opts.JWT) 4477 } 4478 } 4479 }) 4480 } 4481 } 4482 4483 func TestJWTUserRevocation(t *testing.T) { 4484 test := func(all bool) { 4485 createAccountAndUser := func(done chan struct{}, pubKey, jwt1, jwt2, creds1, creds2 *string) { 4486 t.Helper() 4487 kp, _ := nkeys.CreateAccount() 4488 *pubKey, _ = kp.PublicKey() 4489 claim := jwt.NewAccountClaims(*pubKey) 4490 var err error 4491 *jwt1, err = claim.Encode(oKp) 4492 require_NoError(t, err) 4493 4494 ukp, _ := nkeys.CreateUser() 4495 seed, _ := ukp.Seed() 4496 upub, _ := ukp.PublicKey() 4497 uclaim := newJWTTestUserClaims() 4498 uclaim.Subject = upub 4499 4500 ujwt1, err := uclaim.Encode(kp) 4501 require_NoError(t, err) 4502 *creds1 = genCredsFile(t, ujwt1, seed) 4503 4504 // create updated claim need to assure that issue time differs 4505 if all { 4506 claim.Revoke(jwt.All) // revokes all jwt from now on 4507 } else { 4508 claim.Revoke(upub) // revokes this jwt from now on 4509 } 4510 time.Sleep(time.Millisecond * 1100) 4511 *jwt2, err = claim.Encode(oKp) 4512 require_NoError(t, err) 4513 4514 ujwt2, err := uclaim.Encode(kp) 4515 require_NoError(t, err) 4516 *creds2 = genCredsFile(t, ujwt2, seed) 4517 4518 done <- struct{}{} 4519 } 4520 // Create Accounts and corresponding revoked and non revoked user creds. Do so concurrently to speed up the test 4521 doneChan := make(chan struct{}, 2) 4522 defer close(doneChan) 4523 var syspub, sysjwt, dummy1, sysCreds, dummyCreds string 4524 go createAccountAndUser(doneChan, &syspub, &sysjwt, &dummy1, &sysCreds, &dummyCreds) 4525 var apub, ajwt1, ajwt2, aCreds1, aCreds2 string 4526 go createAccountAndUser(doneChan, &apub, &ajwt1, &ajwt2, &aCreds1, &aCreds2) 4527 for i := 0; i < cap(doneChan); i++ { 4528 <-doneChan 4529 } 4530 dirSrv := t.TempDir() 4531 conf := createConfFile(t, []byte(fmt.Sprintf(` 4532 listen: 127.0.0.1:-1 4533 operator: %s 4534 system_account: %s 4535 resolver: { 4536 type: full 4537 dir: '%s' 4538 } 4539 `, ojwt, syspub, dirSrv))) 4540 srv, _ := RunServerWithConfig(conf) 4541 defer srv.Shutdown() 4542 updateJwt(t, srv.ClientURL(), sysCreds, sysjwt, 1) // update system account jwt 4543 updateJwt(t, srv.ClientURL(), sysCreds, ajwt1, 1) // set account jwt without revocation 4544 ncSys := natsConnect(t, srv.ClientURL(), nats.UserCredentials(sysCreds), nats.Name("conn name")) 4545 defer ncSys.Close() 4546 ncChan := make(chan *nats.Msg, 10) 4547 defer close(ncChan) 4548 sub, _ := ncSys.ChanSubscribe(fmt.Sprintf(disconnectEventSubj, apub), ncChan) // observe disconnect message 4549 defer sub.Unsubscribe() 4550 // use credentials that will be revoked ans assure that the connection will be disconnected 4551 nc := natsConnect(t, srv.ClientURL(), nats.UserCredentials(aCreds1), 4552 nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 4553 if err != nil && strings.Contains(err.Error(), "authentication revoked") { 4554 doneChan <- struct{}{} 4555 } 4556 }), 4557 ) 4558 defer nc.Close() 4559 // update account jwt to contain revocation 4560 if updateJwt(t, srv.ClientURL(), sysCreds, ajwt2, 1) != 1 { 4561 t.Fatalf("Expected jwt update to pass") 4562 } 4563 // assure that nc got disconnected due to the revocation 4564 select { 4565 case <-doneChan: 4566 case <-time.After(time.Second): 4567 t.Fatalf("Expected connection to have failed") 4568 } 4569 m := <-ncChan 4570 require_Len(t, strings.Count(string(m.Data), apub), 2) 4571 require_True(t, strings.Contains(string(m.Data), `"jwt":"eyJ0`)) 4572 // try again with old credentials. Expected to fail 4573 if nc1, err := nats.Connect(srv.ClientURL(), nats.UserCredentials(aCreds1)); err == nil { 4574 nc1.Close() 4575 t.Fatalf("Expected revoked credentials to fail") 4576 } 4577 // Assure new creds pass 4578 nc2 := natsConnect(t, srv.ClientURL(), nats.UserCredentials(aCreds2)) 4579 defer nc2.Close() 4580 } 4581 t.Run("specific-key", func(t *testing.T) { 4582 test(false) 4583 }) 4584 t.Run("all-key", func(t *testing.T) { 4585 test(true) 4586 }) 4587 } 4588 4589 func TestJWTActivationRevocation(t *testing.T) { 4590 test := func(all bool) { 4591 sysKp, syspub := createKey(t) 4592 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 4593 sysCreds := newUser(t, sysKp) 4594 4595 aExpKp, aExpPub := createKey(t) 4596 aExpClaim := jwt.NewAccountClaims(aExpPub) 4597 aExpClaim.Name = "Export" 4598 aExpClaim.Exports.Add(&jwt.Export{ 4599 Subject: "foo", 4600 Type: jwt.Stream, 4601 TokenReq: true, 4602 }) 4603 aExp1Jwt := encodeClaim(t, aExpClaim, aExpPub) 4604 aExpCreds := newUser(t, aExpKp) 4605 4606 aImpKp, aImpPub := createKey(t) 4607 4608 ac := &jwt.ActivationClaims{} 4609 ac.Subject = aImpPub 4610 ac.ImportSubject = "foo" 4611 ac.ImportType = jwt.Stream 4612 token, err := ac.Encode(aExpKp) 4613 require_NoError(t, err) 4614 4615 revPubKey := aImpPub 4616 if all { 4617 revPubKey = jwt.All 4618 } 4619 4620 aExpClaim.Exports[0].RevokeAt(revPubKey, time.Now()) 4621 aExp2Jwt := encodeClaim(t, aExpClaim, aExpPub) 4622 4623 aExpClaim.Exports[0].ClearRevocation(revPubKey) 4624 aExp3Jwt := encodeClaim(t, aExpClaim, aExpPub) 4625 4626 aImpClaim := jwt.NewAccountClaims(aImpPub) 4627 aImpClaim.Name = "Import" 4628 aImpClaim.Imports.Add(&jwt.Import{ 4629 Subject: "foo", 4630 Type: jwt.Stream, 4631 Account: aExpPub, 4632 Token: token, 4633 }) 4634 aImpJwt := encodeClaim(t, aImpClaim, aImpPub) 4635 aImpCreds := newUser(t, aImpKp) 4636 4637 dirSrv := t.TempDir() 4638 conf := createConfFile(t, []byte(fmt.Sprintf(` 4639 listen: 127.0.0.1:-1 4640 operator: %s 4641 system_account: %s 4642 resolver: { 4643 type: full 4644 dir: '%s' 4645 } 4646 `, ojwt, syspub, dirSrv))) 4647 4648 t.Run("token-expired-on-connect", func(t *testing.T) { 4649 srv, _ := RunServerWithConfig(conf) 4650 defer srv.Shutdown() 4651 defer removeDir(t, dirSrv) // clean jwt directory 4652 4653 updateJwt(t, srv.ClientURL(), sysCreds, sysJwt, 1) // update system account jwt 4654 updateJwt(t, srv.ClientURL(), sysCreds, aExp2Jwt, 1) // set account jwt without revocation 4655 updateJwt(t, srv.ClientURL(), sysCreds, aImpJwt, 1) 4656 4657 ncExp1 := natsConnect(t, srv.ClientURL(), nats.UserCredentials(aExpCreds)) 4658 defer ncExp1.Close() 4659 4660 ncImp := natsConnect(t, srv.ClientURL(), nats.UserCredentials(aImpCreds)) 4661 defer ncImp.Close() 4662 4663 sub, err := ncImp.SubscribeSync("foo") 4664 require_NoError(t, err) 4665 require_NoError(t, ncImp.Flush()) 4666 require_NoError(t, ncExp1.Publish("foo", []byte("1"))) 4667 _, err = sub.NextMsg(time.Second) 4668 require_Error(t, err) 4669 require_Equal(t, err.Error(), "nats: timeout") 4670 }) 4671 4672 t.Run("token-expired-on-update", func(t *testing.T) { 4673 srv, _ := RunServerWithConfig(conf) 4674 defer srv.Shutdown() 4675 defer removeDir(t, dirSrv) // clean jwt directory 4676 4677 updateJwt(t, srv.ClientURL(), sysCreds, sysJwt, 1) // update system account jwt 4678 updateJwt(t, srv.ClientURL(), sysCreds, aExp1Jwt, 1) // set account jwt without revocation 4679 updateJwt(t, srv.ClientURL(), sysCreds, aImpJwt, 1) 4680 4681 ncExp1 := natsConnect(t, srv.ClientURL(), nats.UserCredentials(aExpCreds)) 4682 defer ncExp1.Close() 4683 4684 ncImp := natsConnect(t, srv.ClientURL(), nats.UserCredentials(aImpCreds)) 4685 defer ncImp.Close() 4686 4687 sub, err := ncImp.SubscribeSync("foo") 4688 require_NoError(t, err) 4689 require_NoError(t, ncImp.Flush()) 4690 require_NoError(t, ncExp1.Publish("foo", []byte("1"))) 4691 m1, err := sub.NextMsg(time.Second) 4692 require_NoError(t, err) 4693 require_Equal(t, string(m1.Data), "1") 4694 4695 updateJwt(t, srv.ClientURL(), sysCreds, aExp2Jwt, 1) // set account jwt with revocation 4696 4697 require_NoError(t, ncExp1.Publish("foo", []byte("2"))) 4698 _, err = sub.NextMsg(time.Second) 4699 require_Error(t, err) 4700 require_Equal(t, err.Error(), "nats: timeout") 4701 4702 updateJwt(t, srv.ClientURL(), sysCreds, aExp3Jwt, 1) // set account with revocation cleared 4703 4704 require_NoError(t, ncExp1.Publish("foo", []byte("3"))) 4705 m2, err := sub.NextMsg(time.Second) 4706 require_NoError(t, err) 4707 require_Equal(t, string(m2.Data), "3") 4708 }) 4709 } 4710 t.Run("specific-key", func(t *testing.T) { 4711 test(false) 4712 }) 4713 t.Run("all-key", func(t *testing.T) { 4714 test(true) 4715 }) 4716 } 4717 4718 func TestJWTAccountFetchTimeout(t *testing.T) { 4719 createAccountAndUser := func(pubKey, jwt1, creds1 *string) { 4720 t.Helper() 4721 kp, _ := nkeys.CreateAccount() 4722 *pubKey, _ = kp.PublicKey() 4723 claim := jwt.NewAccountClaims(*pubKey) 4724 var err error 4725 *jwt1, err = claim.Encode(oKp) 4726 require_NoError(t, err) 4727 ukp, _ := nkeys.CreateUser() 4728 seed, _ := ukp.Seed() 4729 upub, _ := ukp.PublicKey() 4730 uclaim := newJWTTestUserClaims() 4731 uclaim.Subject = upub 4732 ujwt1, err := uclaim.Encode(kp) 4733 require_NoError(t, err) 4734 *creds1 = genCredsFile(t, ujwt1, seed) 4735 } 4736 for _, cfg := range []string{ 4737 `type: full`, 4738 `type: cache`, 4739 } { 4740 t.Run("", func(t *testing.T) { 4741 var syspub, sysjwt, sysCreds string 4742 createAccountAndUser(&syspub, &sysjwt, &sysCreds) 4743 var apub, ajwt1, aCreds1 string 4744 createAccountAndUser(&apub, &ajwt1, &aCreds1) 4745 dirSrv := t.TempDir() 4746 conf := createConfFile(t, []byte(fmt.Sprintf(` 4747 listen: 127.0.0.1:-1 4748 operator: %s 4749 system_account: %s 4750 resolver: { 4751 %s 4752 timeout: "100ms" 4753 dir: '%s' 4754 } 4755 `, ojwt, syspub, cfg, dirSrv))) 4756 srv, _ := RunServerWithConfig(conf) 4757 defer srv.Shutdown() 4758 updateJwt(t, srv.ClientURL(), sysCreds, sysjwt, 1) // update system account jwt 4759 start := time.Now() 4760 nc, err := nats.Connect(srv.ClientURL(), nats.UserCredentials(aCreds1)) 4761 if err == nil { 4762 t.Fatal("expected an error, got none") 4763 } else if !strings.Contains(err.Error(), "Authorization Violation") { 4764 t.Fatalf("expected an authorization violation, got: %v", err) 4765 } 4766 if time.Since(start) > 300*time.Millisecond { 4767 t.Fatal("expected timeout earlier") 4768 } 4769 defer nc.Close() 4770 }) 4771 } 4772 } 4773 4774 func TestJWTAccountOps(t *testing.T) { 4775 op, _ := nkeys.CreateOperator() 4776 opPk, _ := op.PublicKey() 4777 sk, _ := nkeys.CreateOperator() 4778 skPk, _ := sk.PublicKey() 4779 opClaim := jwt.NewOperatorClaims(opPk) 4780 opClaim.SigningKeys.Add(skPk) 4781 opJwt, err := opClaim.Encode(op) 4782 require_NoError(t, err) 4783 createAccountAndUser := func(pubKey, jwt1, creds1 *string) { 4784 t.Helper() 4785 kp, _ := nkeys.CreateAccount() 4786 *pubKey, _ = kp.PublicKey() 4787 claim := jwt.NewAccountClaims(*pubKey) 4788 var err error 4789 *jwt1, err = claim.Encode(sk) 4790 require_NoError(t, err) 4791 4792 ukp, _ := nkeys.CreateUser() 4793 seed, _ := ukp.Seed() 4794 upub, _ := ukp.PublicKey() 4795 uclaim := newJWTTestUserClaims() 4796 uclaim.Subject = upub 4797 4798 ujwt1, err := uclaim.Encode(kp) 4799 require_NoError(t, err) 4800 *creds1 = genCredsFile(t, ujwt1, seed) 4801 } 4802 generateRequest := func(accs []string, kp nkeys.KeyPair) []byte { 4803 t.Helper() 4804 opk, _ := kp.PublicKey() 4805 c := jwt.NewGenericClaims(opk) 4806 c.Data["accounts"] = accs 4807 cJwt, err := c.Encode(kp) 4808 if err != nil { 4809 t.Fatalf("Expected no error %v", err) 4810 } 4811 return []byte(cJwt) 4812 } 4813 for _, cfg := range []string{ 4814 `type: full 4815 allow_delete: true`, 4816 `type: cache`, 4817 } { 4818 t.Run("", func(t *testing.T) { 4819 var syspub, sysjwt, sysCreds string 4820 createAccountAndUser(&syspub, &sysjwt, &sysCreds) 4821 var apub, ajwt1, aCreds1 string 4822 createAccountAndUser(&apub, &ajwt1, &aCreds1) 4823 dirSrv := t.TempDir() 4824 conf := createConfFile(t, []byte(fmt.Sprintf(` 4825 listen: 127.0.0.1:-1 4826 operator: %s 4827 system_account: %s 4828 resolver: { 4829 %s 4830 dir: '%s' 4831 } 4832 `, opJwt, syspub, cfg, dirSrv))) 4833 disconnectErrChan := make(chan struct{}, 1) 4834 defer close(disconnectErrChan) 4835 srv, _ := RunServerWithConfig(conf) 4836 defer srv.Shutdown() 4837 updateJwt(t, srv.ClientURL(), sysCreds, sysjwt, 1) // update system account jwt 4838 // push jwt (for full resolver) 4839 updateJwt(t, srv.ClientURL(), sysCreds, ajwt1, 1) // set jwt 4840 nc := natsConnect(t, srv.ClientURL(), nats.UserCredentials(sysCreds)) 4841 defer nc.Close() 4842 // simulate nas resolver in case of a lookup request (cache) 4843 nc.Subscribe(fmt.Sprintf(accLookupReqSubj, apub), func(msg *nats.Msg) { 4844 msg.Respond([]byte(ajwt1)) 4845 }) 4846 // connect so there is a reason to cache the request and so disconnect can be observed 4847 ncA := natsConnect(t, srv.ClientURL(), nats.UserCredentials(aCreds1), nats.NoReconnect(), 4848 nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 4849 if err != nil && strings.Contains(err.Error(), "account authentication expired") { 4850 disconnectErrChan <- struct{}{} 4851 } 4852 })) 4853 defer ncA.Close() 4854 resp, err := nc.Request(accListReqSubj, nil, time.Second) 4855 require_NoError(t, err) 4856 require_True(t, strings.Contains(string(resp.Data), apub)) 4857 require_True(t, strings.Contains(string(resp.Data), syspub)) 4858 // delete nothing 4859 resp, err = nc.Request(accDeleteReqSubj, generateRequest([]string{}, op), time.Second) 4860 require_NoError(t, err) 4861 require_True(t, strings.Contains(string(resp.Data), `"message":"deleted 0 accounts"`)) 4862 // issue delete, twice to also delete a non existing account 4863 // also switch which key used to sign the request 4864 for i := 0; i < 2; i++ { 4865 resp, err = nc.Request(accDeleteReqSubj, generateRequest([]string{apub}, sk), time.Second) 4866 require_NoError(t, err) 4867 require_True(t, strings.Contains(string(resp.Data), `"message":"deleted 1 accounts"`)) 4868 resp, err = nc.Request(accListReqSubj, nil, time.Second) 4869 require_False(t, strings.Contains(string(resp.Data), apub)) 4870 require_True(t, strings.Contains(string(resp.Data), syspub)) 4871 require_NoError(t, err) 4872 if i > 0 { 4873 continue 4874 } 4875 select { 4876 case <-disconnectErrChan: 4877 case <-time.After(time.Second): 4878 t.Fatal("Callback not executed") 4879 } 4880 } 4881 }) 4882 } 4883 } 4884 4885 func createKey(t *testing.T) (nkeys.KeyPair, string) { 4886 t.Helper() 4887 kp, _ := nkeys.CreateAccount() 4888 syspub, _ := kp.PublicKey() 4889 return kp, syspub 4890 } 4891 4892 func encodeClaim(t *testing.T, claim *jwt.AccountClaims, _ string) string { 4893 t.Helper() 4894 theJWT, err := claim.Encode(oKp) 4895 require_NoError(t, err) 4896 return theJWT 4897 } 4898 4899 // returns user creds 4900 func newUserEx(t *testing.T, accKp nkeys.KeyPair, scoped bool, issuerAccount string) string { 4901 ukp, _ := nkeys.CreateUser() 4902 seed, _ := ukp.Seed() 4903 upub, _ := ukp.PublicKey() 4904 uclaim := newJWTTestUserClaims() 4905 uclaim.Subject = upub 4906 uclaim.SetScoped(scoped) 4907 if issuerAccount != _EMPTY_ { 4908 uclaim.IssuerAccount = issuerAccount 4909 } 4910 ujwt, err := uclaim.Encode(accKp) 4911 require_NoError(t, err) 4912 return genCredsFile(t, ujwt, seed) 4913 } 4914 4915 // returns user creds 4916 func newUser(t *testing.T, accKp nkeys.KeyPair) string { 4917 return newUserEx(t, accKp, false, "") 4918 } 4919 4920 func TestJWTHeader(t *testing.T) { 4921 sysKp, syspub := createKey(t) 4922 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 4923 sysCreds := newUser(t, sysKp) 4924 4925 test := func(share bool) { 4926 aExpKp, aExpPub := createKey(t) 4927 aExpClaim := jwt.NewAccountClaims(aExpPub) 4928 aExpClaim.Exports.Add(&jwt.Export{ 4929 Name: "test", 4930 Subject: "srvc", 4931 Type: jwt.Service, 4932 TokenReq: false, 4933 Latency: &jwt.ServiceLatency{ 4934 Sampling: jwt.Headers, 4935 Results: "res", 4936 }, 4937 }) 4938 aExpJwt := encodeClaim(t, aExpClaim, aExpPub) 4939 aExpCreds := newUser(t, aExpKp) 4940 4941 aImpKp, aImpPub := createKey(t) 4942 aImpClaim := jwt.NewAccountClaims(aImpPub) 4943 aImpClaim.Imports.Add(&jwt.Import{ 4944 Name: "test", 4945 Subject: "srvc", 4946 Account: aExpPub, 4947 Type: jwt.Service, 4948 Share: share, 4949 }) 4950 aImpJwt := encodeClaim(t, aImpClaim, aImpPub) 4951 aImpCreds := newUser(t, aImpKp) 4952 4953 dirSrv := t.TempDir() 4954 conf := createConfFile(t, []byte(fmt.Sprintf(` 4955 listen: 127.0.0.1:-1 4956 operator: %s 4957 system_account: %s 4958 resolver: { 4959 type: full 4960 dir: '%s' 4961 } 4962 `, ojwt, syspub, dirSrv))) 4963 srv, _ := RunServerWithConfig(conf) 4964 defer srv.Shutdown() 4965 updateJwt(t, srv.ClientURL(), sysCreds, sysJwt, 1) // update system account jwt 4966 updateJwt(t, srv.ClientURL(), sysCreds, aExpJwt, 1) 4967 updateJwt(t, srv.ClientURL(), sysCreds, aImpJwt, 1) 4968 4969 expNc := natsConnect(t, srv.ClientURL(), nats.UserCredentials(aExpCreds)) 4970 defer expNc.Close() 4971 resChan := make(chan *nats.Msg, 1) 4972 expNc.ChanSubscribe("res", resChan) 4973 sub, err := expNc.Subscribe("srvc", func(msg *nats.Msg) { 4974 msg.Respond(nil) 4975 }) 4976 require_NoError(t, err) 4977 defer sub.Unsubscribe() 4978 4979 impNc := natsConnect(t, srv.ClientURL(), nats.UserCredentials(aImpCreds)) 4980 defer impNc.Close() 4981 // send request w/o header 4982 _, err = impNc.Request("srvc", []byte("msg1"), time.Second) 4983 require_NoError(t, err) 4984 require_True(t, len(resChan) == 0) 4985 4986 _, err = impNc.RequestMsg(&nats.Msg{ 4987 Subject: "srvc", Data: []byte("msg2"), Header: nats.Header{ 4988 "X-B3-Sampled": []string{"1"}, 4989 "Share": []string{"Me"}}}, time.Second) 4990 require_NoError(t, err) 4991 select { 4992 case <-time.After(time.Second): 4993 t.Fatalf("should have received a response") 4994 case m := <-resChan: 4995 obj := map[string]any{} 4996 err = json.Unmarshal(m.Data, &obj) 4997 require_NoError(t, err) 4998 // test if shared is honored 4999 reqInfo := obj["requestor"].(map[string]any) 5000 // fields always set 5001 require_True(t, reqInfo["acc"] != nil) 5002 require_True(t, reqInfo["rtt"] != nil) 5003 5004 // fields only set when shared 5005 _, ok1 := reqInfo["lang"] 5006 _, ok2 := reqInfo["ver"] 5007 _, ok3 := reqInfo["host"] 5008 _, ok4 := reqInfo["start"] 5009 if !share { 5010 ok1 = !ok1 5011 ok2 = !ok2 5012 ok3 = !ok3 5013 ok4 = !ok4 5014 } 5015 require_True(t, ok1) 5016 require_True(t, ok2) 5017 require_True(t, ok3) 5018 require_True(t, ok4) 5019 5020 } 5021 require_True(t, len(resChan) == 0) 5022 } 5023 test(true) 5024 test(false) 5025 } 5026 5027 func TestJWTAccountImportsWithWildcardSupport(t *testing.T) { 5028 test := func(aExpPub, aExpJwt, aExpCreds, aImpPub, aImpJwt, aImpCreds string, jsEnabled bool, exSubExpect, exPub, imReq, imSubExpect string) { 5029 t.Helper() 5030 5031 var jsSetting string 5032 if jsEnabled { 5033 jsSetting = "jetstream: {max_mem_store: 10Mb, max_file_store: 10Mb}" 5034 } 5035 5036 _, aSysPub := createKey(t) 5037 aSysClaim := jwt.NewAccountClaims(aSysPub) 5038 aSysJwt := encodeClaim(t, aSysClaim, aSysPub) 5039 cf := createConfFile(t, []byte(fmt.Sprintf(` 5040 port: -1 5041 operator = %s 5042 resolver = MEMORY 5043 resolver_preload = { 5044 %s : "%s" 5045 %s : "%s" 5046 %s : "%s" 5047 } 5048 system_account: %s 5049 %s 5050 `, ojwt, aExpPub, aExpJwt, aImpPub, aImpJwt, aSysPub, aSysJwt, aSysPub, jsSetting))) 5051 5052 s, opts := RunServerWithConfig(cf) 5053 defer s.Shutdown() 5054 5055 ncExp := natsConnect(t, fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port), nats.UserCredentials(aExpCreds)) 5056 defer ncExp.Close() 5057 5058 ncImp := natsConnect(t, fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port), nats.UserCredentials(aImpCreds)) 5059 defer ncImp.Close() 5060 5061 // Create subscriber for the service endpoint in foo. 5062 _, err := ncExp.Subscribe(exSubExpect, func(m *nats.Msg) { 5063 m.Respond([]byte("yes!")) 5064 }) 5065 require_NoError(t, err) 5066 ncExp.Flush() 5067 5068 // Now test service import. 5069 if resp, err := ncImp.Request(imReq, []byte("yes?"), time.Second); err != nil { 5070 t.Fatalf("Expected a response to request %s got: %v", imReq, err) 5071 } else if string(resp.Data) != "yes!" { 5072 t.Fatalf("Expected a response of %q, got %q", "yes!", resp.Data) 5073 } 5074 subBar, err := ncImp.SubscribeSync(imSubExpect) 5075 require_NoError(t, err) 5076 ncImp.Flush() 5077 5078 ncExp.Publish(exPub, []byte("event!")) 5079 5080 if m, err := subBar.NextMsg(time.Second); err != nil { 5081 t.Fatalf("Expected a stream message got %v", err) 5082 } else if string(m.Data) != "event!" { 5083 t.Fatalf("Expected a response of %q, got %q", "event!", m.Data) 5084 } 5085 } 5086 createExporter := func() (string, string, string) { 5087 t.Helper() 5088 aExpKp, aExpPub := createKey(t) 5089 aExpClaim := jwt.NewAccountClaims(aExpPub) 5090 aExpClaim.Name = "Export" 5091 aExpClaim.Exports.Add(&jwt.Export{ 5092 Subject: "$request.*.$in.*.>", 5093 Type: jwt.Service, 5094 }, &jwt.Export{ 5095 Subject: "$events.*.$in.*.>", 5096 Type: jwt.Stream, 5097 }) 5098 aExpJwt := encodeClaim(t, aExpClaim, aExpPub) 5099 aExpCreds := newUser(t, aExpKp) 5100 return aExpPub, aExpJwt, aExpCreds 5101 } 5102 t.Run("To", func(t *testing.T) { 5103 aExpPub, aExpJwt, aExpCreds := createExporter() 5104 aImpKp, aImpPub := createKey(t) 5105 aImpClaim := jwt.NewAccountClaims(aImpPub) 5106 aImpClaim.Name = "Import" 5107 aImpClaim.Imports.Add(&jwt.Import{ 5108 Subject: "my.request.*.*.>", 5109 Type: jwt.Service, 5110 To: "$request.*.$in.*.>", // services have local and remote switched between Subject and To 5111 Account: aExpPub, 5112 }, &jwt.Import{ 5113 Subject: "$events.*.$in.*.>", 5114 Type: jwt.Stream, 5115 To: "prefix", 5116 Account: aExpPub, 5117 }) 5118 aImpJwt := encodeClaim(t, aImpClaim, aImpPub) 5119 aImpCreds := newUser(t, aImpKp) 5120 test(aExpPub, aExpJwt, aExpCreds, aImpPub, aImpJwt, aImpCreds, false, 5121 "$request.1.$in.2.bar", "$events.1.$in.2.bar", 5122 "my.request.1.2.bar", "prefix.$events.1.$in.2.bar") 5123 }) 5124 t.Run("LocalSubject-No-Reorder", func(t *testing.T) { 5125 aExpPub, aExpJwt, aExpCreds := createExporter() 5126 aImpKp, aImpPub := createKey(t) 5127 aImpClaim := jwt.NewAccountClaims(aImpPub) 5128 aImpClaim.Name = "Import" 5129 aImpClaim.Imports.Add(&jwt.Import{ 5130 Subject: "$request.*.$in.*.>", 5131 Type: jwt.Service, 5132 LocalSubject: "my.request.*.*.>", 5133 Account: aExpPub, 5134 }, &jwt.Import{ 5135 Subject: "$events.*.$in.*.>", 5136 Type: jwt.Stream, 5137 LocalSubject: "my.events.*.*.>", 5138 Account: aExpPub, 5139 }) 5140 aImpJwt := encodeClaim(t, aImpClaim, aImpPub) 5141 aImpCreds := newUser(t, aImpKp) 5142 test(aExpPub, aExpJwt, aExpCreds, aImpPub, aImpJwt, aImpCreds, false, 5143 "$request.1.$in.2.bar", "$events.1.$in.2.bar", 5144 "my.request.1.2.bar", "my.events.1.2.bar") 5145 }) 5146 t.Run("LocalSubject-Reorder", func(t *testing.T) { 5147 for _, jsEnabled := range []bool{false, true} { 5148 t.Run(fmt.Sprintf("%t", jsEnabled), func(t *testing.T) { 5149 aExpPub, aExpJwt, aExpCreds := createExporter() 5150 aImpKp, aImpPub := createKey(t) 5151 aImpClaim := jwt.NewAccountClaims(aImpPub) 5152 aImpClaim.Name = "Import" 5153 aImpClaim.Imports.Add(&jwt.Import{ 5154 Subject: "$request.*.$in.*.>", 5155 Type: jwt.Service, 5156 LocalSubject: "my.request.$2.$1.>", 5157 Account: aExpPub, 5158 }, &jwt.Import{ 5159 Subject: "$events.*.$in.*.>", 5160 Type: jwt.Stream, 5161 LocalSubject: "my.events.$2.$1.>", 5162 Account: aExpPub, 5163 }) 5164 aImpJwt := encodeClaim(t, aImpClaim, aImpPub) 5165 aImpCreds := newUser(t, aImpKp) 5166 test(aExpPub, aExpJwt, aExpCreds, aImpPub, aImpJwt, aImpCreds, jsEnabled, 5167 "$request.2.$in.1.bar", "$events.1.$in.2.bar", 5168 "my.request.1.2.bar", "my.events.2.1.bar") 5169 }) 5170 } 5171 }) 5172 } 5173 5174 func TestJWTAccountTokenImportMisuse(t *testing.T) { 5175 sysKp, syspub := createKey(t) 5176 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 5177 sysCreds := newUser(t, sysKp) 5178 5179 aExpKp, aExpPub := createKey(t) 5180 aExpClaim := jwt.NewAccountClaims(aExpPub) 5181 aExpClaim.Name = "Export" 5182 aExpClaim.Exports.Add(&jwt.Export{ 5183 Subject: "$events.*.$in.*.>", 5184 Type: jwt.Stream, 5185 TokenReq: true, 5186 }, &jwt.Export{ 5187 Subject: "foo", 5188 Type: jwt.Stream, 5189 TokenReq: true, 5190 }) 5191 aExpJwt := encodeClaim(t, aExpClaim, aExpPub) 5192 5193 createImportingAccountClaim := func(aImpKp nkeys.KeyPair, aExpPub string, ac *jwt.ActivationClaims) (string, string) { 5194 t.Helper() 5195 token, err := ac.Encode(aExpKp) 5196 require_NoError(t, err) 5197 5198 aImpPub, err := aImpKp.PublicKey() 5199 require_NoError(t, err) 5200 aImpClaim := jwt.NewAccountClaims(aImpPub) 5201 aImpClaim.Name = "Import" 5202 aImpClaim.Imports.Add(&jwt.Import{ 5203 Subject: "$events.*.$in.*.>", 5204 Type: jwt.Stream, 5205 Account: aExpPub, 5206 Token: token, 5207 }) 5208 aImpJwt := encodeClaim(t, aImpClaim, aImpPub) 5209 aImpCreds := newUser(t, aImpKp) 5210 return aImpJwt, aImpCreds 5211 } 5212 5213 testConnect := func(aExpPub, aExpJwt, aImpPub, aImpJwt, aImpCreds string) { 5214 t.Helper() 5215 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 5216 if r.URL.Path == "/A/" { 5217 // Server startup 5218 w.Write(nil) 5219 } else if r.URL.Path == "/A/"+aExpPub { 5220 w.Write([]byte(aExpJwt)) 5221 } else if r.URL.Path == "/A/"+aImpPub { 5222 w.Write([]byte(aImpJwt)) 5223 } else { 5224 t.Fatal("not expected") 5225 } 5226 })) 5227 defer ts.Close() 5228 cf := createConfFile(t, []byte(fmt.Sprintf(` 5229 listen: 127.0.0.1:-1 5230 operator: %s 5231 resolver: URL("%s/A/") 5232 `, ojwt, ts.URL))) 5233 5234 s, opts := RunServerWithConfig(cf) 5235 defer s.Shutdown() 5236 5237 ncImp, err := nats.Connect(fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port), nats.UserCredentials(aImpCreds)) 5238 require_Error(t, err) // misuse needs to result in an error 5239 defer ncImp.Close() 5240 } 5241 5242 testNatsResolver := func(aImpJwt string) { 5243 t.Helper() 5244 dirSrv := t.TempDir() 5245 cf := createConfFile(t, []byte(fmt.Sprintf(` 5246 listen: 127.0.0.1:-1 5247 operator: %s 5248 system_account: %s 5249 resolver: { 5250 type: full 5251 dir: '%s' 5252 } 5253 `, ojwt, syspub, dirSrv))) 5254 5255 s, _ := RunServerWithConfig(cf) 5256 defer s.Shutdown() 5257 5258 require_True(t, updateJwt(t, s.ClientURL(), sysCreds, sysJwt, 1) == 1) 5259 require_True(t, updateJwt(t, s.ClientURL(), sysCreds, aExpJwt, 1) == 1) 5260 require_True(t, updateJwt(t, s.ClientURL(), sysCreds, aImpJwt, 1) == 0) // assure this did not succeed 5261 } 5262 5263 t.Run("wrong-account", func(t *testing.T) { 5264 aImpKp, aImpPub := createKey(t) 5265 ac := &jwt.ActivationClaims{} 5266 _, ac.Subject = createKey(t) // on purpose issue this token for another account 5267 ac.ImportSubject = "$events.*.$in.*.>" 5268 ac.ImportType = jwt.Stream 5269 5270 aImpJwt, aImpCreds := createImportingAccountClaim(aImpKp, aExpPub, ac) 5271 testConnect(aExpPub, aExpJwt, aImpPub, aImpJwt, aImpCreds) 5272 testNatsResolver(aImpJwt) 5273 }) 5274 5275 t.Run("different-subject", func(t *testing.T) { 5276 aImpKp, aImpPub := createKey(t) 5277 ac := &jwt.ActivationClaims{} 5278 ac.Subject = aImpPub 5279 ac.ImportSubject = "foo" // on purpose use a subject from another export 5280 ac.ImportType = jwt.Stream 5281 5282 aImpJwt, aImpCreds := createImportingAccountClaim(aImpKp, aExpPub, ac) 5283 testConnect(aExpPub, aExpJwt, aImpPub, aImpJwt, aImpCreds) 5284 testNatsResolver(aImpJwt) 5285 }) 5286 5287 t.Run("non-existing-subject", func(t *testing.T) { 5288 aImpKp, aImpPub := createKey(t) 5289 ac := &jwt.ActivationClaims{} 5290 ac.Subject = aImpPub 5291 ac.ImportSubject = "does-not-exist-or-from-different-export" // on purpose use a non exported subject 5292 ac.ImportType = jwt.Stream 5293 5294 aImpJwt, aImpCreds := createImportingAccountClaim(aImpKp, aExpPub, ac) 5295 testConnect(aExpPub, aExpJwt, aImpPub, aImpJwt, aImpCreds) 5296 testNatsResolver(aImpJwt) 5297 }) 5298 } 5299 5300 func TestJWTResponseThreshold(t *testing.T) { 5301 respThresh := 20 * time.Millisecond 5302 aExpKp, aExpPub := createKey(t) 5303 aExpClaim := jwt.NewAccountClaims(aExpPub) 5304 aExpClaim.Name = "Export" 5305 aExpClaim.Exports.Add(&jwt.Export{ 5306 Subject: "srvc", 5307 Type: jwt.Service, 5308 ResponseThreshold: respThresh, 5309 }) 5310 aExpJwt := encodeClaim(t, aExpClaim, aExpPub) 5311 aExpCreds := newUser(t, aExpKp) 5312 5313 aImpKp, aImpPub := createKey(t) 5314 aImpClaim := jwt.NewAccountClaims(aImpPub) 5315 aImpClaim.Name = "Import" 5316 aImpClaim.Imports.Add(&jwt.Import{ 5317 Subject: "srvc", 5318 Type: jwt.Service, 5319 Account: aExpPub, 5320 }) 5321 aImpJwt := encodeClaim(t, aImpClaim, aImpPub) 5322 aImpCreds := newUser(t, aImpKp) 5323 5324 cf := createConfFile(t, []byte(fmt.Sprintf(` 5325 port: -1 5326 operator = %s 5327 resolver = MEMORY 5328 resolver_preload = { 5329 %s : "%s" 5330 %s : "%s" 5331 } 5332 `, ojwt, aExpPub, aExpJwt, aImpPub, aImpJwt))) 5333 5334 s, opts := RunServerWithConfig(cf) 5335 defer s.Shutdown() 5336 5337 ncExp := natsConnect(t, fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port), nats.UserCredentials(aExpCreds)) 5338 defer ncExp.Close() 5339 5340 ncImp := natsConnect(t, fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port), nats.UserCredentials(aImpCreds)) 5341 defer ncImp.Close() 5342 5343 delayChan := make(chan time.Duration, 1) 5344 5345 // Create subscriber for the service endpoint in foo. 5346 _, err := ncExp.Subscribe("srvc", func(m *nats.Msg) { 5347 time.Sleep(<-delayChan) 5348 m.Respond([]byte("yes!")) 5349 }) 5350 require_NoError(t, err) 5351 ncExp.Flush() 5352 5353 t.Run("No-Timeout", func(t *testing.T) { 5354 delayChan <- respThresh / 2 5355 if resp, err := ncImp.Request("srvc", []byte("yes?"), 4*respThresh); err != nil { 5356 t.Fatalf("Expected a response to request srvc got: %v", err) 5357 } else if string(resp.Data) != "yes!" { 5358 t.Fatalf("Expected a response of %q, got %q", "yes!", resp.Data) 5359 } 5360 }) 5361 t.Run("Timeout", func(t *testing.T) { 5362 delayChan <- 2 * respThresh 5363 if _, err := ncImp.Request("srvc", []byte("yes?"), 4*respThresh); err == nil || err != nats.ErrTimeout { 5364 t.Fatalf("Expected a timeout") 5365 } 5366 }) 5367 } 5368 5369 func TestJWTJetStreamTiers(t *testing.T) { 5370 sysKp, syspub := createKey(t) 5371 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 5372 sysCreds := newUser(t, sysKp) 5373 5374 accKp, accPub := createKey(t) 5375 accClaim := jwt.NewAccountClaims(accPub) 5376 accClaim.Name = "acc" 5377 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5378 DiskStorage: 1100, MemoryStorage: 0, Consumer: 2, Streams: 2} 5379 accJwt1 := encodeClaim(t, accClaim, accPub) 5380 accCreds := newUser(t, accKp) 5381 5382 start := time.Now() 5383 5384 storeDir := t.TempDir() 5385 5386 dirSrv := t.TempDir() 5387 cf := createConfFile(t, []byte(fmt.Sprintf(` 5388 listen: 127.0.0.1:-1 5389 server_name: s1 5390 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 5391 leaf { 5392 listen: 127.0.0.1:-1 5393 } 5394 operator: %s 5395 system_account: %s 5396 resolver: { 5397 type: full 5398 dir: '%s' 5399 } 5400 `, storeDir, ojwt, syspub, dirSrv))) 5401 5402 s, _ := RunServerWithConfig(cf) 5403 defer s.Shutdown() 5404 5405 updateJwt(t, s.ClientURL(), sysCreds, sysJwt, 1) 5406 updateJwt(t, s.ClientURL(), sysCreds, accJwt1, 1) 5407 5408 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(accCreds)) 5409 defer nc.Close() 5410 5411 js, err := nc.JetStream() 5412 require_NoError(t, err) 5413 5414 // Test tiers up to stream limits 5415 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-1", Replicas: 1, Subjects: []string{"testR1-1"}}) 5416 require_NoError(t, err) 5417 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-2", Replicas: 1, Subjects: []string{"testR1-2"}}) 5418 require_NoError(t, err) 5419 5420 // Test exceeding tiered stream limit 5421 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-3", Replicas: 1, Subjects: []string{"testR1-3"}}) 5422 require_Error(t, err) 5423 require_Equal(t, err.Error(), "nats: maximum number of streams reached") 5424 5425 // Test tiers up to consumer limits 5426 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur1", AckPolicy: nats.AckExplicitPolicy}) 5427 require_NoError(t, err) 5428 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur3", AckPolicy: nats.AckExplicitPolicy}) 5429 require_NoError(t, err) 5430 5431 // test exceeding tiered consumer limits 5432 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur4", AckPolicy: nats.AckExplicitPolicy}) 5433 require_Error(t, err) 5434 require_Equal(t, err.Error(), "nats: maximum consumers limit reached") 5435 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur5", AckPolicy: nats.AckExplicitPolicy}) 5436 require_Error(t, err) 5437 require_Equal(t, err.Error(), "nats: maximum consumers limit reached") 5438 5439 // test tiered storage limit 5440 msg := [512]byte{} 5441 _, err = js.Publish("testR1-1", msg[:]) 5442 require_NoError(t, err) 5443 _, err = js.Publish("testR1-2", msg[:]) 5444 require_NoError(t, err) 5445 5446 // test exceeding tiered storage limit 5447 _, err = js.Publish("testR1-1", []byte("1")) 5448 require_Error(t, err) 5449 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 5450 5451 time.Sleep(time.Second - time.Since(start)) // make sure the time stamp changes 5452 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5453 DiskStorage: 1650, MemoryStorage: 0, Consumer: 1, Streams: 3} 5454 accJwt2 := encodeClaim(t, accClaim, accPub) 5455 updateJwt(t, s.ClientURL(), sysCreds, accJwt2, 1) 5456 5457 // test same sequence as before, add stream, fail add stream, add consumer, fail add consumer, publish, fail publish 5458 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-3", Replicas: 1, Subjects: []string{"testR1-3"}}) 5459 require_NoError(t, err) 5460 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-4", Replicas: 1, Subjects: []string{"testR1-4"}}) 5461 require_Error(t, err) 5462 require_Equal(t, err.Error(), "nats: maximum number of streams reached") 5463 _, err = js.AddConsumer("testR1-3", &nats.ConsumerConfig{Durable: "dur6", AckPolicy: nats.AckExplicitPolicy}) 5464 require_NoError(t, err) 5465 _, err = js.AddConsumer("testR1-3", &nats.ConsumerConfig{Durable: "dur7", AckPolicy: nats.AckExplicitPolicy}) 5466 require_Error(t, err) 5467 require_Equal(t, err.Error(), "nats: maximum consumers limit reached") 5468 _, err = js.Publish("testR1-3", msg[:]) 5469 require_Error(t, err) 5470 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 5471 } 5472 5473 func TestJWTJetStreamMaxAckPending(t *testing.T) { 5474 sysKp, syspub := createKey(t) 5475 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 5476 sysCreds := newUser(t, sysKp) 5477 5478 accKp, accPub := createKey(t) 5479 accClaim := jwt.NewAccountClaims(accPub) 5480 accClaim.Name = "acc" 5481 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5482 DiskStorage: jwt.NoLimit, MemoryStorage: jwt.NoLimit, 5483 Consumer: jwt.NoLimit, Streams: jwt.NoLimit, MaxAckPending: int64(1000), 5484 } 5485 accJwt1 := encodeClaim(t, accClaim, accPub) 5486 accCreds := newUser(t, accKp) 5487 5488 start := time.Now() 5489 5490 storeDir := t.TempDir() 5491 5492 dirSrv := t.TempDir() 5493 cf := createConfFile(t, []byte(fmt.Sprintf(` 5494 listen: 127.0.0.1:-1 5495 server_name: s1 5496 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 5497 leaf { 5498 listen: 127.0.0.1:-1 5499 } 5500 operator: %s 5501 system_account: %s 5502 resolver: { 5503 type: full 5504 dir: '%s' 5505 } 5506 `, storeDir, ojwt, syspub, dirSrv))) 5507 5508 s, _ := RunServerWithConfig(cf) 5509 defer s.Shutdown() 5510 5511 updateJwt(t, s.ClientURL(), sysCreds, sysJwt, 1) 5512 updateJwt(t, s.ClientURL(), sysCreds, accJwt1, 1) 5513 5514 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(accCreds)) 5515 defer nc.Close() 5516 5517 js, err := nc.JetStream() 5518 require_NoError(t, err) 5519 5520 _, err = js.AddStream(&nats.StreamConfig{Name: "foo", Replicas: 1}) 5521 require_NoError(t, err) 5522 5523 _, err = js.AddConsumer("foo", &nats.ConsumerConfig{ 5524 Durable: "dur1", AckPolicy: nats.AckAllPolicy, MaxAckPending: 2000}) 5525 require_Error(t, err) 5526 require_Equal(t, err.Error(), "nats: consumer max ack pending exceeds system limit of 1000") 5527 5528 ci, err := js.AddConsumer("foo", &nats.ConsumerConfig{ 5529 Durable: "dur2", AckPolicy: nats.AckAllPolicy, MaxAckPending: 500}) 5530 require_NoError(t, err) 5531 require_True(t, ci.Config.MaxAckPending == 500) 5532 5533 _, err = js.UpdateConsumer("foo", &nats.ConsumerConfig{ 5534 Durable: "dur2", AckPolicy: nats.AckAllPolicy, MaxAckPending: 2000}) 5535 require_Error(t, err) 5536 require_Equal(t, err.Error(), "nats: consumer max ack pending exceeds system limit of 1000") 5537 5538 time.Sleep(time.Second - time.Since(start)) // make sure the time stamp changes 5539 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5540 DiskStorage: jwt.NoLimit, MemoryStorage: jwt.NoLimit, Consumer: jwt.NoLimit, 5541 Streams: jwt.NoLimit, MaxAckPending: int64(2000)} 5542 accJwt2 := encodeClaim(t, accClaim, accPub) 5543 updateJwt(t, s.ClientURL(), sysCreds, accJwt2, 1) 5544 5545 ci, err = js.UpdateConsumer("foo", &nats.ConsumerConfig{ 5546 Durable: "dur2", AckPolicy: nats.AckAllPolicy, MaxAckPending: 2000}) 5547 require_NoError(t, err) 5548 require_True(t, ci.Config.MaxAckPending == 2000) 5549 } 5550 5551 func TestJWTJetStreamMaxStreamBytes(t *testing.T) { 5552 sysKp, syspub := createKey(t) 5553 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 5554 sysCreds := newUser(t, sysKp) 5555 5556 accKp, accPub := createKey(t) 5557 accClaim := jwt.NewAccountClaims(accPub) 5558 accClaim.Name = "acc" 5559 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5560 DiskStorage: jwt.NoLimit, MemoryStorage: jwt.NoLimit, 5561 Consumer: jwt.NoLimit, Streams: jwt.NoLimit, 5562 DiskMaxStreamBytes: 1024, MaxBytesRequired: false, 5563 } 5564 accJwt1 := encodeClaim(t, accClaim, accPub) 5565 accCreds := newUser(t, accKp) 5566 5567 start := time.Now() 5568 5569 storeDir := t.TempDir() 5570 5571 dirSrv := t.TempDir() 5572 cf := createConfFile(t, []byte(fmt.Sprintf(` 5573 listen: 127.0.0.1:-1 5574 server_name: s1 5575 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 5576 leaf { 5577 listen: 127.0.0.1:-1 5578 } 5579 operator: %s 5580 system_account: %s 5581 resolver: { 5582 type: full 5583 dir: '%s' 5584 } 5585 `, storeDir, ojwt, syspub, dirSrv))) 5586 5587 s, _ := RunServerWithConfig(cf) 5588 defer s.Shutdown() 5589 5590 updateJwt(t, s.ClientURL(), sysCreds, sysJwt, 1) 5591 updateJwt(t, s.ClientURL(), sysCreds, accJwt1, 1) 5592 5593 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(accCreds)) 5594 defer nc.Close() 5595 5596 js, err := nc.JetStream() 5597 require_NoError(t, err) 5598 5599 _, err = js.AddStream(&nats.StreamConfig{Name: "foo", Replicas: 1, MaxBytes: 2048}) 5600 require_Error(t, err) 5601 require_Equal(t, err.Error(), "nats: stream max bytes exceeds account limit max stream bytes") 5602 _, err = js.AddStream(&nats.StreamConfig{Name: "foo", Replicas: 1, MaxBytes: 1024}) 5603 require_NoError(t, err) 5604 5605 msg := [900]byte{} 5606 _, err = js.AddStream(&nats.StreamConfig{Name: "baz", Replicas: 1}) 5607 require_NoError(t, err) 5608 _, err = js.Publish("baz", msg[:]) 5609 require_NoError(t, err) 5610 _, err = js.Publish("baz", msg[:]) // exceeds max stream bytes 5611 require_Error(t, err) 5612 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 5613 5614 time.Sleep(time.Second - time.Since(start)) // make sure the time stamp changes 5615 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5616 DiskStorage: jwt.NoLimit, MemoryStorage: jwt.NoLimit, Consumer: jwt.NoLimit, Streams: jwt.NoLimit, 5617 DiskMaxStreamBytes: 2048, MaxBytesRequired: true} 5618 accJwt2 := encodeClaim(t, accClaim, accPub) 5619 updateJwt(t, s.ClientURL(), sysCreds, accJwt2, 1) 5620 5621 _, err = js.AddStream(&nats.StreamConfig{Name: "bar", Replicas: 1, MaxBytes: 3000}) 5622 require_Error(t, err) 5623 require_Equal(t, err.Error(), "nats: stream max bytes exceeds account limit max stream bytes") 5624 _, err = js.AddStream(&nats.StreamConfig{Name: "bar", Replicas: 1, MaxBytes: 2048}) 5625 require_NoError(t, err) 5626 5627 // test if we can push more messages into the stream 5628 _, err = js.Publish("baz", msg[:]) // exceeds max stream bytes 5629 require_Error(t, err) 5630 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 5631 5632 // test disabling max bytes required 5633 _, err = js.UpdateStream(&nats.StreamConfig{Name: "bar", Replicas: 1}) 5634 require_Error(t, err) 5635 require_Equal(t, err.Error(), "nats: account requires a stream config to have max bytes set") 5636 } 5637 5638 func TestJWTQueuePermissions(t *testing.T) { 5639 aExpKp, aExpPub := createKey(t) 5640 aExpClaim := jwt.NewAccountClaims(aExpPub) 5641 aExpJwt := encodeClaim(t, aExpClaim, aExpPub) 5642 newUser := func(t *testing.T, permType string) string { 5643 ukp, _ := nkeys.CreateUser() 5644 seed, _ := ukp.Seed() 5645 upub, _ := ukp.PublicKey() 5646 uclaim := newJWTTestUserClaims() 5647 uclaim.Subject = upub 5648 switch permType { 5649 case "allow": 5650 uclaim.Permissions.Sub.Allow.Add("foo.> *.dev") 5651 case "deny": 5652 uclaim.Permissions.Sub.Deny.Add("foo.> *.dev") 5653 } 5654 ujwt, err := uclaim.Encode(aExpKp) 5655 require_NoError(t, err) 5656 return genCredsFile(t, ujwt, seed) 5657 } 5658 confFileName := createConfFile(t, []byte(fmt.Sprintf(` 5659 port: -1 5660 operator = %s 5661 resolver = MEMORY 5662 resolver_preload = { 5663 %s : %s 5664 }`, ojwt, aExpPub, aExpJwt))) 5665 opts, err := ProcessConfigFile(confFileName) 5666 if err != nil { 5667 t.Fatalf("Received unexpected error %s", err) 5668 } 5669 opts.NoLog, opts.NoSigs = true, true 5670 errChan := make(chan error, 1) 5671 defer close(errChan) 5672 s := RunServer(opts) 5673 defer s.Shutdown() 5674 5675 for _, test := range []struct { 5676 permType string 5677 queue string 5678 errExpected bool 5679 }{ 5680 {"allow", "queue.dev", false}, 5681 {"allow", "", true}, 5682 {"allow", "bad", true}, 5683 {"deny", "", false}, 5684 {"deny", "queue.dev", true}, 5685 } { 5686 t.Run(test.permType+test.queue, func(t *testing.T) { 5687 usrCreds := newUser(t, test.permType) 5688 nc, err := nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", opts.Port), 5689 nats.ErrorHandler(func(conn *nats.Conn, s *nats.Subscription, err error) { 5690 errChan <- err 5691 }), 5692 nats.UserCredentials(usrCreds)) 5693 if err != nil { 5694 t.Fatalf("No error expected: %v", err) 5695 } 5696 defer nc.Close() 5697 if test.queue == "" { 5698 if _, err := nc.Subscribe("foo.bar", func(msg *nats.Msg) {}); err != nil { 5699 t.Fatalf("no error expected: %v", err) 5700 } 5701 } else { 5702 if _, err := nc.QueueSubscribe("foo.bar", test.queue, func(msg *nats.Msg) {}); err != nil { 5703 t.Fatalf("no error expected: %v", err) 5704 } 5705 } 5706 nc.Flush() 5707 select { 5708 case err := <-errChan: 5709 if !test.errExpected { 5710 t.Fatalf("Expected no error, got %v", err) 5711 } 5712 if !strings.Contains(err.Error(), `Permissions Violation for Subscription to "foo.bar"`) { 5713 t.Fatalf("error %v", err) 5714 } 5715 case <-time.After(150 * time.Millisecond): 5716 if test.errExpected { 5717 t.Fatal("Expected an error") 5718 } 5719 } 5720 }) 5721 5722 } 5723 } 5724 5725 func TestJWScopedSigningKeys(t *testing.T) { 5726 sysKp, syspub := createKey(t) 5727 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 5728 sysCreds := newUser(t, sysKp) 5729 5730 _, aExpPub := createKey(t) 5731 accClaim := jwt.NewAccountClaims(aExpPub) 5732 accClaim.Name = "acc" 5733 5734 aSignNonScopedKp, aSignNonScopedPub := createKey(t) 5735 accClaim.SigningKeys.Add(aSignNonScopedPub) 5736 5737 aSignScopedKp, aSignScopedPub := createKey(t) 5738 signer := jwt.NewUserScope() 5739 signer.Key = aSignScopedPub 5740 signer.Template.Pub.Deny.Add("denied") 5741 signer.Template.Payload = 5 5742 accClaim.SigningKeys.AddScopedSigner(signer) 5743 accJwt := encodeClaim(t, accClaim, aExpPub) 5744 5745 aNonScopedCreds := newUserEx(t, aSignNonScopedKp, false, aExpPub) 5746 aBadScopedCreds := newUserEx(t, aSignScopedKp, false, aExpPub) 5747 aScopedCreds := newUserEx(t, aSignScopedKp, true, aExpPub) 5748 5749 dirSrv := t.TempDir() 5750 cf := createConfFile(t, []byte(fmt.Sprintf(` 5751 listen: 127.0.0.1:-1 5752 operator: %s 5753 system_account: %s 5754 resolver: { 5755 type: full 5756 dir: '%s' 5757 } 5758 `, ojwt, syspub, dirSrv))) 5759 s, opts := RunServerWithConfig(cf) 5760 defer s.Shutdown() 5761 5762 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 5763 errChan := make(chan error, 1) 5764 defer close(errChan) 5765 awaitError := func(expected bool) { 5766 t.Helper() 5767 select { 5768 case err := <-errChan: 5769 if !expected { 5770 t.Fatalf("Expected no error, got %v", err) 5771 } 5772 case <-time.After(150 * time.Millisecond): 5773 if expected { 5774 t.Fatal("Expected an error") 5775 } 5776 } 5777 } 5778 errHdlr := nats.ErrorHandler(func(conn *nats.Conn, s *nats.Subscription, err error) { 5779 errChan <- err 5780 }) 5781 if updateJwt(t, url, sysCreds, sysJwt, 1) != 1 { 5782 t.Error("Expected update to pass") 5783 } else if updateJwt(t, url, sysCreds, accJwt, 1) != 1 { 5784 t.Error("Expected update to pass") 5785 } 5786 t.Run("bad-scoped-signing-key", func(t *testing.T) { 5787 _, err := nats.Connect(url, nats.UserCredentials(aBadScopedCreds)) 5788 require_Error(t, err) 5789 }) 5790 t.Run("regular-signing-key", func(t *testing.T) { 5791 nc := natsConnect(t, url, nats.UserCredentials(aNonScopedCreds), errHdlr) 5792 defer nc.Close() 5793 nc.Flush() 5794 err := nc.Publish("denied", nil) 5795 require_NoError(t, err) 5796 nc.Flush() 5797 awaitError(false) 5798 }) 5799 t.Run("scoped-signing-key-client-side", func(t *testing.T) { 5800 nc := natsConnect(t, url, nats.UserCredentials(aScopedCreds), errHdlr) 5801 defer nc.Close() 5802 nc.Flush() 5803 err := nc.Publish("too-long", []byte("way.too.long.for.payload.limit")) 5804 require_Error(t, err) 5805 require_True(t, strings.Contains(err.Error(), ErrMaxPayload.Error())) 5806 }) 5807 t.Run("scoped-signing-key-server-side", func(t *testing.T) { 5808 nc := natsConnect(t, url, nats.UserCredentials(aScopedCreds), errHdlr) 5809 defer nc.Close() 5810 nc.Flush() 5811 err := nc.Publish("denied", nil) 5812 require_NoError(t, err) 5813 nc.Flush() 5814 awaitError(true) 5815 }) 5816 t.Run("scoped-signing-key-reload", func(t *testing.T) { 5817 reconChan := make(chan struct{}, 1) 5818 defer close(reconChan) 5819 msgChan := make(chan *nats.Msg, 2) 5820 defer close(msgChan) 5821 nc := natsConnect(t, url, nats.UserCredentials(aScopedCreds), errHdlr, 5822 nats.DisconnectErrHandler(func(conn *nats.Conn, err error) { 5823 if err != nil { 5824 errChan <- err 5825 } 5826 }), 5827 nats.ReconnectHandler(func(conn *nats.Conn) { 5828 reconChan <- struct{}{} 5829 }), 5830 ) 5831 defer nc.Close() 5832 _, err := nc.ChanSubscribe("denied", msgChan) 5833 require_NoError(t, err) 5834 nc.Flush() 5835 err = nc.Publish("denied", nil) 5836 require_NoError(t, err) 5837 awaitError(true) 5838 require_Len(t, len(msgChan), 0) 5839 // Alter scoped permissions and update 5840 signer.Template.Payload = -1 5841 signer.Template.Pub.Deny.Remove("denied") 5842 accClaim.SigningKeys.AddScopedSigner(signer) 5843 accUpdatedJwt := encodeClaim(t, accClaim, aExpPub) 5844 if updateJwt(t, url, sysCreds, accUpdatedJwt, 1) != 1 { 5845 t.Error("Expected update to pass") 5846 } 5847 // disconnect triggered by update 5848 awaitError(true) 5849 <-reconChan 5850 nc.Flush() 5851 err = nc.Publish("denied", []byte("way.too.long.for.old.payload.limit")) 5852 require_NoError(t, err) 5853 awaitError(false) 5854 msg := <-msgChan 5855 require_Equal(t, string(msg.Data), "way.too.long.for.old.payload.limit") 5856 require_Len(t, len(msgChan), 0) 5857 }) 5858 require_Len(t, len(errChan), 0) 5859 } 5860 5861 func TestJWTStrictSigningKeys(t *testing.T) { 5862 newAccount := func(opKp nkeys.KeyPair) (nkeys.KeyPair, nkeys.KeyPair, string, *jwt.AccountClaims, string) { 5863 accId, err := nkeys.CreateAccount() 5864 require_NoError(t, err) 5865 accIdPub, err := accId.PublicKey() 5866 require_NoError(t, err) 5867 5868 accSig, err := nkeys.CreateAccount() 5869 require_NoError(t, err) 5870 accSigPub, err := accSig.PublicKey() 5871 require_NoError(t, err) 5872 5873 aClaim := jwt.NewAccountClaims(accIdPub) 5874 aClaim.SigningKeys.Add(accSigPub) 5875 theJwt, err := aClaim.Encode(opKp) 5876 require_NoError(t, err) 5877 return accId, accSig, accIdPub, aClaim, theJwt 5878 } 5879 5880 opId, err := nkeys.CreateOperator() 5881 require_NoError(t, err) 5882 opIdPub, err := opId.PublicKey() 5883 require_NoError(t, err) 5884 5885 opSig, err := nkeys.CreateOperator() 5886 require_NoError(t, err) 5887 opSigPub, err := opSig.PublicKey() 5888 require_NoError(t, err) 5889 5890 aBadBadKp, aBadGoodKp, aBadPub, _, aBadJwt := newAccount(opId) 5891 aGoodBadKp, aGoodGoodKp, aGoodPub, _, aGoodJwt := newAccount(opSig) 5892 _, aSysKp, aSysPub, _, aSysJwt := newAccount(opSig) 5893 5894 oClaim := jwt.NewOperatorClaims(opIdPub) 5895 oClaim.StrictSigningKeyUsage = true 5896 oClaim.SigningKeys.Add(opSigPub) 5897 oClaim.SystemAccount = aSysPub 5898 oJwt, err := oClaim.Encode(opId) 5899 require_NoError(t, err) 5900 5901 uBadBadCreds := newUserEx(t, aBadBadKp, false, aBadPub) 5902 uBadGoodCreds := newUserEx(t, aBadGoodKp, false, aBadPub) 5903 uGoodBadCreds := newUserEx(t, aGoodBadKp, false, aGoodPub) 5904 uGoodGoodCreds := newUserEx(t, aGoodGoodKp, false, aGoodPub) 5905 uSysCreds := newUserEx(t, aSysKp, false, aSysPub) 5906 5907 connectTest := func(url string) { 5908 for _, test := range []struct { 5909 creds string 5910 fail bool 5911 }{ 5912 {uBadBadCreds, true}, 5913 {uBadGoodCreds, true}, 5914 {uGoodBadCreds, true}, 5915 {uGoodGoodCreds, false}, 5916 } { 5917 nc, err := nats.Connect(url, nats.UserCredentials(test.creds)) 5918 nc.Close() 5919 if test.fail { 5920 require_Error(t, err) 5921 } else { 5922 require_NoError(t, err) 5923 } 5924 } 5925 } 5926 5927 t.Run("resolver", func(t *testing.T) { 5928 dirSrv := t.TempDir() 5929 cf := createConfFile(t, []byte(fmt.Sprintf(` 5930 port: -1 5931 operator = %s 5932 resolver: { 5933 type: full 5934 dir: '%s' 5935 } 5936 resolver_preload = { 5937 %s : "%s" 5938 } 5939 `, oJwt, dirSrv, aSysPub, aSysJwt))) 5940 s, _ := RunServerWithConfig(cf) 5941 defer s.Shutdown() 5942 url := s.ClientURL() 5943 if updateJwt(t, url, uSysCreds, aBadJwt, 1) != 0 { 5944 t.Fatal("Expected negative response") 5945 } 5946 if updateJwt(t, url, uSysCreds, aGoodJwt, 1) != 1 { 5947 t.Fatal("Expected positive response") 5948 } 5949 connectTest(url) 5950 }) 5951 5952 t.Run("mem-resolver", func(t *testing.T) { 5953 cf := createConfFile(t, []byte(fmt.Sprintf(` 5954 port: -1 5955 operator = %s 5956 resolver: MEMORY 5957 resolver_preload = { 5958 %s : "%s" 5959 %s : "%s" 5960 %s : "%s" 5961 } 5962 `, oJwt, aSysPub, aSysJwt, aBadPub, aBadJwt, aGoodPub, aGoodJwt))) 5963 s, _ := RunServerWithConfig(cf) 5964 defer s.Shutdown() 5965 connectTest(s.ClientURL()) 5966 }) 5967 } 5968 5969 func TestJWTAccountProtectedImport(t *testing.T) { 5970 srvFmt := ` 5971 port: -1 5972 operator = %s 5973 resolver: MEMORY 5974 resolver_preload = { 5975 %s : "%s" 5976 %s : "%s" 5977 } ` 5978 setupAccounts := func(pass bool) (nkeys.KeyPair, string, string, string, nkeys.KeyPair, string, string, string, string) { 5979 // Create accounts and imports/exports. 5980 exportKP, _ := nkeys.CreateAccount() 5981 exportPub, _ := exportKP.PublicKey() 5982 exportAC := jwt.NewAccountClaims(exportPub) 5983 exportAC.Exports.Add(&jwt.Export{Subject: "service.*", Type: jwt.Service, AccountTokenPosition: 2}) 5984 exportAC.Exports.Add(&jwt.Export{Subject: "stream.*", Type: jwt.Stream, AccountTokenPosition: 2}) 5985 exportJWT, err := exportAC.Encode(oKp) 5986 require_NoError(t, err) 5987 // create alternative exporter jwt without account token pos set 5988 exportAC.Exports = jwt.Exports{} 5989 exportAC.Exports.Add(&jwt.Export{Subject: "service.*", Type: jwt.Service}) 5990 exportAC.Exports.Add(&jwt.Export{Subject: "stream.*", Type: jwt.Stream}) 5991 exportJWTNoPos, err := exportAC.Encode(oKp) 5992 require_NoError(t, err) 5993 5994 importKP, _ := nkeys.CreateAccount() 5995 importPub, _ := importKP.PublicKey() 5996 importAc := jwt.NewAccountClaims(importPub) 5997 srvcSub, strmSub := "service.foo", "stream.foo" 5998 if pass { 5999 srvcSub = fmt.Sprintf("service.%s", importPub) 6000 strmSub = fmt.Sprintf("stream.%s", importPub) 6001 } 6002 importAc.Imports.Add(&jwt.Import{Account: exportPub, Subject: jwt.Subject(srvcSub), Type: jwt.Service}) 6003 importAc.Imports.Add(&jwt.Import{Account: exportPub, Subject: jwt.Subject(strmSub), Type: jwt.Stream}) 6004 importJWT, err := importAc.Encode(oKp) 6005 require_NoError(t, err) 6006 6007 return exportKP, exportPub, exportJWT, exportJWTNoPos, importKP, importPub, importJWT, srvcSub, strmSub 6008 } 6009 t.Run("pass", func(t *testing.T) { 6010 exportKp, exportPub, exportJWT, _, importKp, importPub, importJWT, srvcSub, strmSub := setupAccounts(true) 6011 cf := createConfFile(t, []byte(fmt.Sprintf(srvFmt, ojwt, exportPub, exportJWT, importPub, importJWT))) 6012 s, _ := RunServerWithConfig(cf) 6013 defer s.Shutdown() 6014 ncExp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, exportKp)) 6015 defer ncExp.Close() 6016 ncImp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, importKp)) 6017 defer ncImp.Close() 6018 t.Run("service", func(t *testing.T) { 6019 sub, err := ncExp.Subscribe("service.*", func(msg *nats.Msg) { 6020 msg.Respond([]byte("world")) 6021 }) 6022 defer sub.Unsubscribe() 6023 require_NoError(t, err) 6024 ncExp.Flush() 6025 msg, err := ncImp.Request(srvcSub, []byte("hello"), time.Second) 6026 require_NoError(t, err) 6027 require_Equal(t, string(msg.Data), "world") 6028 }) 6029 t.Run("stream", func(t *testing.T) { 6030 msgChan := make(chan *nats.Msg, 4) 6031 defer close(msgChan) 6032 sub, err := ncImp.ChanSubscribe(strmSub, msgChan) 6033 defer sub.Unsubscribe() 6034 require_NoError(t, err) 6035 ncImp.Flush() 6036 err = ncExp.Publish("stream.foo", []byte("hello")) 6037 require_NoError(t, err) 6038 err = ncExp.Publish(strmSub, []byte("hello")) 6039 require_NoError(t, err) 6040 msg := <-msgChan 6041 require_Equal(t, string(msg.Data), "hello") 6042 require_True(t, len(msgChan) == 0) 6043 }) 6044 }) 6045 t.Run("fail", func(t *testing.T) { 6046 exportKp, exportPub, exportJWT, _, importKp, importPub, importJWT, srvcSub, strmSub := setupAccounts(false) 6047 cf := createConfFile(t, []byte(fmt.Sprintf(srvFmt, ojwt, exportPub, exportJWT, importPub, importJWT))) 6048 s, _ := RunServerWithConfig(cf) 6049 defer s.Shutdown() 6050 ncExp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, exportKp)) 6051 defer ncExp.Close() 6052 ncImp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, importKp)) 6053 defer ncImp.Close() 6054 t.Run("service", func(t *testing.T) { 6055 sub, err := ncExp.Subscribe("service.*", func(msg *nats.Msg) { 6056 msg.Respond([]byte("world")) 6057 }) 6058 defer sub.Unsubscribe() 6059 require_NoError(t, err) 6060 ncExp.Flush() 6061 _, err = ncImp.Request(srvcSub, []byte("hello"), time.Second) 6062 require_Error(t, err) 6063 require_Contains(t, err.Error(), "no responders available for request") 6064 }) 6065 t.Run("stream", func(t *testing.T) { 6066 msgChan := make(chan *nats.Msg, 4) 6067 defer close(msgChan) 6068 _, err := ncImp.ChanSubscribe(strmSub, msgChan) 6069 require_NoError(t, err) 6070 ncImp.Flush() 6071 err = ncExp.Publish("stream.foo", []byte("hello")) 6072 require_NoError(t, err) 6073 err = ncExp.Publish(strmSub, []byte("hello")) 6074 require_NoError(t, err) 6075 select { 6076 case <-msgChan: 6077 t.Fatal("did not expect a message") 6078 case <-time.After(250 * time.Millisecond): 6079 } 6080 require_True(t, len(msgChan) == 0) 6081 }) 6082 }) 6083 t.Run("reload-off-2-on", func(t *testing.T) { 6084 exportKp, exportPub, exportJWTOn, exportJWTOff, importKp, _, importJWT, srvcSub, strmSub := setupAccounts(false) 6085 dirSrv := t.TempDir() 6086 // set up system account. Relying bootstrapping system account to not create JWT 6087 sysAcc, err := nkeys.CreateAccount() 6088 require_NoError(t, err) 6089 sysPub, err := sysAcc.PublicKey() 6090 require_NoError(t, err) 6091 sysUsrCreds := newUserEx(t, sysAcc, false, sysPub) 6092 cf := createConfFile(t, []byte(fmt.Sprintf(` 6093 port: -1 6094 operator = %s 6095 system_account = %s 6096 resolver: { 6097 type: full 6098 dir: '%s' 6099 }`, ojwt, sysPub, dirSrv))) 6100 s, _ := RunServerWithConfig(cf) 6101 defer s.Shutdown() 6102 updateJwt(t, s.ClientURL(), sysUsrCreds, importJWT, 1) 6103 updateJwt(t, s.ClientURL(), sysUsrCreds, exportJWTOff, 1) 6104 ncExp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, exportKp)) 6105 defer ncExp.Close() 6106 ncImp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, importKp)) 6107 defer ncImp.Close() 6108 msgChan := make(chan *nats.Msg, 4) 6109 defer close(msgChan) 6110 // ensure service passes 6111 subSrvc, err := ncExp.Subscribe("service.*", func(msg *nats.Msg) { 6112 msg.Respond([]byte("world")) 6113 }) 6114 defer subSrvc.Unsubscribe() 6115 require_NoError(t, err) 6116 ncExp.Flush() 6117 respMst, err := ncImp.Request(srvcSub, []byte("hello"), time.Second) 6118 require_NoError(t, err) 6119 require_Equal(t, string(respMst.Data), "world") 6120 // ensure stream passes 6121 subStrm, err := ncImp.ChanSubscribe(strmSub, msgChan) 6122 defer subStrm.Unsubscribe() 6123 require_NoError(t, err) 6124 ncImp.Flush() 6125 err = ncExp.Publish(strmSub, []byte("hello")) 6126 require_NoError(t, err) 6127 msg := <-msgChan 6128 require_Equal(t, string(msg.Data), "hello") 6129 require_True(t, len(msgChan) == 0) 6130 6131 updateJwt(t, s.ClientURL(), sysUsrCreds, exportJWTOn, 1) 6132 6133 // ensure service fails 6134 _, err = ncImp.Request(srvcSub, []byte("hello"), time.Second) 6135 require_Error(t, err) 6136 require_Contains(t, err.Error(), "timeout") 6137 s.AccountResolver().Store(exportPub, exportJWTOn) 6138 // ensure stream fails 6139 err = ncExp.Publish(strmSub, []byte("hello")) 6140 require_NoError(t, err) 6141 select { 6142 case <-msgChan: 6143 t.Fatal("did not expect a message") 6144 case <-time.After(250 * time.Millisecond): 6145 } 6146 require_True(t, len(msgChan) == 0) 6147 }) 6148 } 6149 6150 // Headers are ignored in claims update, but passing them should not cause error. 6151 func TestJWTClaimsUpdateWithHeaders(t *testing.T) { 6152 skp, spub := createKey(t) 6153 newUser(t, skp) 6154 6155 sclaim := jwt.NewAccountClaims(spub) 6156 encodeClaim(t, sclaim, spub) 6157 6158 akp, apub := createKey(t) 6159 newUser(t, akp) 6160 claim := jwt.NewAccountClaims(apub) 6161 jwtClaim := encodeClaim(t, claim, apub) 6162 6163 dirSrv := t.TempDir() 6164 6165 conf := createConfFile(t, []byte(fmt.Sprintf(` 6166 listen: 127.0.0.1:-1 6167 operator: %s 6168 system_account: %s 6169 resolver: { 6170 type: full 6171 dir: '%s' 6172 } 6173 `, ojwt, spub, dirSrv))) 6174 6175 s, _ := RunServerWithConfig(conf) 6176 defer s.Shutdown() 6177 6178 type zapi struct { 6179 Server *ServerInfo 6180 Data *Connz 6181 Error *ApiError 6182 } 6183 6184 sc := natsConnect(t, s.ClientURL(), createUserCreds(t, s, skp)) 6185 defer sc.Close() 6186 // Pass claims update with headers. 6187 msg := &nats.Msg{ 6188 Subject: "$SYS.REQ.CLAIMS.UPDATE", 6189 Data: []byte(jwtClaim), 6190 Header: map[string][]string{"key": {"value"}}, 6191 } 6192 resp, err := sc.RequestMsg(msg, time.Second) 6193 if err != nil { 6194 t.Fatalf("Unexpected error: %v", err) 6195 } 6196 var cz zapi 6197 if err := json.Unmarshal(resp.Data, &cz); err != nil { 6198 t.Fatalf("Unexpected error: %v", err) 6199 } 6200 if cz.Error != nil { 6201 t.Fatalf("Unexpected error: %+v", cz.Error) 6202 } 6203 } 6204 6205 func TestJWTMappings(t *testing.T) { 6206 sysKp, syspub := createKey(t) 6207 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 6208 sysCreds := newUser(t, sysKp) 6209 6210 // create two jwt, one with and one without mapping 6211 aKp, aPub := createKey(t) 6212 aClaim := jwt.NewAccountClaims(aPub) 6213 aJwtNoM := encodeClaim(t, aClaim, aPub) 6214 aClaim.AddMapping("foo1", jwt.WeightedMapping{Subject: "bar1"}) 6215 aJwtMap1 := encodeClaim(t, aClaim, aPub) 6216 6217 aClaim.Mappings = map[jwt.Subject][]jwt.WeightedMapping{} 6218 aClaim.AddMapping("foo2", jwt.WeightedMapping{Subject: "bar2"}) 6219 aJwtMap2 := encodeClaim(t, aClaim, aPub) 6220 6221 dirSrv := t.TempDir() 6222 conf := createConfFile(t, []byte(fmt.Sprintf(` 6223 listen: 127.0.0.1:-1 6224 operator: %s 6225 system_account: %s 6226 resolver: { 6227 type: full 6228 dir: '%s' 6229 } 6230 `, ojwt, syspub, dirSrv))) 6231 srv, _ := RunServerWithConfig(conf) 6232 defer srv.Shutdown() 6233 updateJwt(t, srv.ClientURL(), sysCreds, sysJwt, 1) // update system account jwt 6234 6235 test := func(pub, sub string, fail bool) { 6236 t.Helper() 6237 nc := natsConnect(t, srv.ClientURL(), createUserCreds(t, srv, aKp)) 6238 defer nc.Close() 6239 s, err := nc.SubscribeSync(sub) 6240 require_NoError(t, err) 6241 nc.Flush() 6242 err = nc.Publish(pub, nil) 6243 require_NoError(t, err) 6244 _, err = s.NextMsg(500 * time.Millisecond) 6245 switch { 6246 case fail && err == nil: 6247 t.Fatal("expected error, got none") 6248 case !fail && err != nil: 6249 t.Fatalf("expected no error, got %v", err) 6250 } 6251 } 6252 6253 // turn mappings on 6254 require_Len(t, 1, updateJwt(t, srv.ClientURL(), sysCreds, aJwtMap1, 1)) 6255 test("foo1", "bar1", false) 6256 // alter mappings 6257 require_Len(t, 1, updateJwt(t, srv.ClientURL(), sysCreds, aJwtMap2, 1)) 6258 test("foo1", "bar1", true) 6259 test("foo2", "bar2", false) 6260 // turn mappings off 6261 require_Len(t, 1, updateJwt(t, srv.ClientURL(), sysCreds, aJwtNoM, 1)) 6262 test("foo2", "bar2", true) 6263 } 6264 6265 func TestJWTOperatorPinnedAccounts(t *testing.T) { 6266 kps, pubs, jwts := [4]nkeys.KeyPair{}, [4]string{}, [4]string{} 6267 for i := 0; i < 4; i++ { 6268 kps[i], pubs[i] = createKey(t) 6269 jwts[i] = encodeClaim(t, jwt.NewAccountClaims(pubs[i]), pubs[i]) 6270 } 6271 // create system account user credentials, index 0 is handled as system account 6272 newUser(t, kps[0]) 6273 6274 cfgCommon := fmt.Sprintf(` 6275 listen: 127.0.0.1:-1 6276 operator: %s 6277 system_account: %s 6278 resolver: MEM 6279 resolver_preload: { 6280 %s:%s 6281 %s:%s 6282 %s:%s 6283 %s:%s 6284 }`, ojwt, pubs[0], pubs[0], jwts[0], pubs[1], jwts[1], pubs[2], jwts[2], pubs[3], jwts[3]) 6285 cfgFmt := cfgCommon + ` 6286 resolver_pinned_accounts: [%s, %s] 6287 ` 6288 conf := createConfFile(t, []byte(fmt.Sprintf(cfgFmt, pubs[1], pubs[2]))) 6289 srv, _ := RunServerWithConfig(conf) 6290 defer srv.Shutdown() 6291 6292 connectPass := func(keys ...nkeys.KeyPair) { 6293 for _, kp := range keys { 6294 nc, err := nats.Connect(srv.ClientURL(), createUserCreds(t, srv, kp)) 6295 require_NoError(t, err) 6296 defer nc.Close() 6297 } 6298 } 6299 var pinnedFail uint64 6300 connectFail := func(key nkeys.KeyPair) { 6301 _, err := nats.Connect(srv.ClientURL(), createUserCreds(t, srv, key)) 6302 require_Error(t, err) 6303 require_Contains(t, err.Error(), "Authorization Violation") 6304 v, err := srv.Varz(&VarzOptions{}) 6305 require_NoError(t, err) 6306 require_True(t, pinnedFail+1 == v.PinnedAccountFail) 6307 pinnedFail = v.PinnedAccountFail 6308 } 6309 6310 connectPass(kps[0], kps[1], kps[2]) // make sure user from accounts listed and system account (index 0) work 6311 connectFail(kps[3]) // make sure the other user does not work 6312 // reload and test again 6313 reloadUpdateConfig(t, srv, conf, fmt.Sprintf(cfgFmt, pubs[2], pubs[3])) 6314 connectPass(kps[0], kps[2], kps[3]) // make sure user from accounts listed and system account (index 0) work 6315 connectFail(kps[1]) // make sure the other user does not work 6316 // completely disable and test again 6317 reloadUpdateConfig(t, srv, conf, cfgCommon) 6318 connectPass(kps[0], kps[1], kps[2], kps[3]) // make sure every account and system account (index 0) can connect 6319 // re-enable and test again 6320 reloadUpdateConfig(t, srv, conf, fmt.Sprintf(cfgFmt, pubs[2], pubs[3])) 6321 connectPass(kps[0], kps[2], kps[3]) // make sure user from accounts listed and system account (index 0) work 6322 connectFail(kps[1]) // make sure the other user does not work 6323 } 6324 6325 func TestJWTNoSystemAccountButNatsResolver(t *testing.T) { 6326 dirSrv := t.TempDir() 6327 for _, resType := range []string{"full", "cache"} { 6328 t.Run(resType, func(t *testing.T) { 6329 conf := createConfFile(t, []byte(fmt.Sprintf(` 6330 listen: 127.0.0.1:-1 6331 operator: %s 6332 resolver: { 6333 type: %s 6334 dir: '%s' 6335 }`, ojwt, resType, dirSrv))) 6336 opts := LoadConfig(conf) 6337 s, err := NewServer(opts) 6338 // Since the server cannot be stopped, since it did not start, 6339 // let's manually close the account resolver to avoid leaking go routines. 6340 opts.AccountResolver.Close() 6341 s.Shutdown() 6342 require_Error(t, err) 6343 require_Contains(t, err.Error(), "the system account needs to be specified in configuration or the operator jwt") 6344 }) 6345 } 6346 } 6347 6348 func TestJWTAccountConnzAccessAfterClaimUpdate(t *testing.T) { 6349 skp, spub := createKey(t) 6350 newUser(t, skp) 6351 6352 sclaim := jwt.NewAccountClaims(spub) 6353 sclaim.AddMapping("foo.bar", jwt.WeightedMapping{Subject: "foo.baz"}) 6354 sjwt := encodeClaim(t, sclaim, spub) 6355 6356 // create two jwt, one with and one without mapping 6357 akp, apub := createKey(t) 6358 newUser(t, akp) 6359 claim := jwt.NewAccountClaims(apub) 6360 jwt1 := encodeClaim(t, claim, apub) 6361 claim.AddMapping("foo.bar", jwt.WeightedMapping{Subject: "foo.baz"}) 6362 jwt2 := encodeClaim(t, claim, apub) 6363 6364 dirSrv := t.TempDir() 6365 6366 conf := createConfFile(t, []byte(fmt.Sprintf(` 6367 listen: 127.0.0.1:-1 6368 operator: %s 6369 system_account: %s 6370 resolver: { 6371 type: full 6372 dir: '%s' 6373 } 6374 `, ojwt, spub, dirSrv))) 6375 6376 s, _ := RunServerWithConfig(conf) 6377 defer s.Shutdown() 6378 6379 type zapi struct { 6380 Server *ServerInfo 6381 Data *Connz 6382 Error *ApiError 6383 } 6384 6385 updateJWT := func(jwt string) { 6386 t.Helper() 6387 sc := natsConnect(t, s.ClientURL(), createUserCreds(t, s, skp)) 6388 defer sc.Close() 6389 resp, err := sc.Request("$SYS.REQ.CLAIMS.UPDATE", []byte(jwt), time.Second) 6390 if err != nil { 6391 t.Fatalf("Unexpected error: %v", err) 6392 } 6393 var cz zapi 6394 if err := json.Unmarshal(resp.Data, &cz); err != nil { 6395 t.Fatalf("Unexpected error: %v", err) 6396 } 6397 if cz.Error != nil { 6398 t.Fatalf("Unexpected error: %+v", cz.Error) 6399 } 6400 } 6401 6402 updateJWT(jwt1) 6403 6404 nc := natsConnect(t, s.ClientURL(), createUserCreds(t, s, akp)) 6405 defer nc.Close() 6406 6407 doRequest := func() { 6408 t.Helper() 6409 resp, err := nc.Request("$SYS.REQ.SERVER.PING.CONNZ", nil, time.Second) 6410 if err != nil { 6411 t.Fatalf("Unexpected error: %v", err) 6412 } 6413 var cz zapi 6414 if err := json.Unmarshal(resp.Data, &cz); err != nil { 6415 t.Fatalf("Unexpected error: %v", err) 6416 } 6417 if cz.Error != nil { 6418 t.Fatalf("Unexpected error: %+v", cz.Error) 6419 } 6420 } 6421 6422 doRequest() 6423 updateJWT(jwt2) 6424 // If we accidentally wipe the system import this will fail with no responders. 6425 doRequest() 6426 // Now test updating system account. 6427 updateJWT(sjwt) 6428 // If export was wiped this would fail with timeout. 6429 doRequest() 6430 } 6431 6432 func TestAccountWeightedMappingInSuperCluster(t *testing.T) { 6433 skp, spub := createKey(t) 6434 sysClaim := jwt.NewAccountClaims(spub) 6435 sysClaim.Name = "SYS" 6436 sysCreds := newUser(t, skp) 6437 6438 akp, apub := createKey(t) 6439 aUsr := createUserCreds(t, nil, akp) 6440 claim := jwt.NewAccountClaims(apub) 6441 aJwtMap := encodeClaim(t, claim, apub) 6442 6443 // We are using the createJetStreamSuperClusterWithTemplateAndModHook() 6444 // helper, but this test is not about JetStream... 6445 tmpl := ` 6446 listen: 127.0.0.1:-1 6447 server_name: %s 6448 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 6449 cluster { 6450 name: %s 6451 listen: 127.0.0.1:%d 6452 routes = [%s] 6453 } 6454 ` 6455 6456 sc := createJetStreamSuperClusterWithTemplateAndModHook(t, tmpl, 3, 3, 6457 func(serverName, clusterName, storeDir, conf string) string { 6458 dirSrv := t.TempDir() 6459 return fmt.Sprintf(`%s 6460 operator: %s 6461 system_account: %s 6462 resolver: { 6463 type: full 6464 dir: '%s' 6465 } 6466 `, conf, ojwt, spub, dirSrv) 6467 }, nil) 6468 defer sc.shutdown() 6469 6470 // Update from C2 6471 require_Len(t, 1, updateJwt(t, sc.clusterForName("C2").randomServer().ClientURL(), sysCreds, aJwtMap, 1)) 6472 6473 // We will connect our services in the C3 cluster. 6474 nc1 := natsConnect(t, sc.clusterForName("C3").randomServer().ClientURL(), aUsr) 6475 defer nc1.Close() 6476 nc2 := natsConnect(t, sc.clusterForName("C3").randomServer().ClientURL(), aUsr) 6477 defer nc2.Close() 6478 6479 natsSub(t, nc1, "foo", func(m *nats.Msg) { 6480 m.Respond([]byte("foo")) 6481 }) 6482 natsSub(t, nc1, "bar.v1", func(m *nats.Msg) { 6483 m.Respond([]byte("v1")) 6484 }) 6485 natsSub(t, nc2, "bar.v2", func(m *nats.Msg) { 6486 m.Respond([]byte("v2")) 6487 }) 6488 natsFlush(t, nc1) 6489 natsFlush(t, nc2) 6490 6491 // Now we will update the account to add weighted subject mapping 6492 claim.Mappings = map[jwt.Subject][]jwt.WeightedMapping{} 6493 // Start with foo->bar.v2 at 40%, the server will auto-add foo->foo at 60%. 6494 wm := []jwt.WeightedMapping{{Subject: "bar.v2", Weight: 40}} 6495 claim.AddMapping("foo", wm...) 6496 aJwtMap = encodeClaim(t, claim, apub) 6497 6498 // We will update from C2 6499 require_Len(t, 1, updateJwt(t, sc.clusterForName("C2").randomServer().ClientURL(), sysCreds, aJwtMap, 1)) 6500 6501 time.Sleep(time.Second) 6502 6503 // And we will publish from C1 6504 nc := natsConnect(t, sc.clusterForName("C1").randomServer().ClientURL(), aUsr) 6505 defer nc.Close() 6506 6507 var foo, v1, v2 int 6508 pubAndCount := func() { 6509 for i := 0; i < 1000; i++ { 6510 msg, err := nc.Request("foo", []byte("req"), 500*time.Millisecond) 6511 if err != nil { 6512 continue 6513 } 6514 switch string(msg.Data) { 6515 case "foo": 6516 foo++ 6517 case "v1": 6518 v1++ 6519 case "v2": 6520 v2++ 6521 } 6522 } 6523 } 6524 pubAndCount() 6525 if foo < 550 || foo > 650 { 6526 t.Fatalf("Expected foo to receive 60%%, got %v/1000", foo) 6527 } 6528 if v1 != 0 { 6529 t.Fatalf("Expected v1 to receive no message, got %v/1000", v1) 6530 } 6531 if v2 < 350 || v2 > 450 { 6532 t.Fatalf("Expected v2 to receive 40%%, got %v/1000", v2) 6533 } 6534 6535 // Now send a new update with foo-> bar.v2(40) and bar.v1(60). 6536 // The auto-add of "foo" should no longer be used by the server. 6537 wm = []jwt.WeightedMapping{ 6538 {Subject: "bar.v2", Weight: 40}, 6539 {Subject: "bar.v1", Weight: 60}, 6540 } 6541 claim.AddMapping("foo", wm...) 6542 aJwtMap = encodeClaim(t, claim, apub) 6543 6544 // We will update from C2 6545 require_Len(t, 1, updateJwt(t, sc.clusterForName("C2").randomServer().ClientURL(), sysCreds, aJwtMap, 1)) 6546 6547 time.Sleep(time.Second) 6548 6549 foo, v1, v2 = 0, 0, 0 6550 pubAndCount() 6551 if foo != 0 { 6552 t.Fatalf("Expected foo to receive no message, got %v/1000", foo) 6553 } 6554 if v1 < 550 || v1 > 650 { 6555 t.Fatalf("Expected v1 to receive 60%%, got %v/1000", v1) 6556 } 6557 if v2 < 350 || v2 > 450 { 6558 t.Fatalf("Expected v2 to receive 40%%, got %v/1000", v2) 6559 } 6560 } 6561 6562 func TestServerOperatorModeNoAuthRequired(t *testing.T) { 6563 _, spub := createKey(t) 6564 sysClaim := jwt.NewAccountClaims(spub) 6565 sysClaim.Name = "$SYS" 6566 sysJwt, err := sysClaim.Encode(oKp) 6567 require_NoError(t, err) 6568 6569 akp, apub := createKey(t) 6570 accClaim := jwt.NewAccountClaims(apub) 6571 accClaim.Name = "TEST" 6572 accJwt, err := accClaim.Encode(oKp) 6573 require_NoError(t, err) 6574 6575 ukp, _ := nkeys.CreateUser() 6576 seed, _ := ukp.Seed() 6577 upub, _ := ukp.PublicKey() 6578 nuc := jwt.NewUserClaims(upub) 6579 ujwt, err := nuc.Encode(akp) 6580 require_NoError(t, err) 6581 creds := genCredsFile(t, ujwt, seed) 6582 6583 dirSrv := t.TempDir() 6584 6585 conf := createConfFile(t, []byte(fmt.Sprintf(` 6586 listen: 127.0.0.1:-1 6587 server_name: srv-A 6588 operator: %s 6589 system_account: %s 6590 resolver: { 6591 type: full 6592 dir: '%s' 6593 interval: "200ms" 6594 limit: 4 6595 } 6596 resolver_preload: { 6597 %s: %s 6598 %s: %s 6599 } 6600 `, ojwt, spub, dirSrv, spub, sysJwt, apub, accJwt))) 6601 6602 s, _ := RunServerWithConfig(conf) 6603 defer s.Shutdown() 6604 6605 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(creds)) 6606 defer nc.Close() 6607 6608 require_True(t, nc.AuthRequired()) 6609 } 6610 6611 func TestServerOperatorModeUserInfoExpiration(t *testing.T) { 6612 _, spub := createKey(t) 6613 sysClaim := jwt.NewAccountClaims(spub) 6614 sysClaim.Name = "$SYS" 6615 sysJwt, err := sysClaim.Encode(oKp) 6616 require_NoError(t, err) 6617 6618 akp, apub := createKey(t) 6619 accClaim := jwt.NewAccountClaims(apub) 6620 accClaim.Name = "TEST" 6621 accJwt, err := accClaim.Encode(oKp) 6622 require_NoError(t, err) 6623 6624 conf := createConfFile(t, []byte(fmt.Sprintf(` 6625 listen: 127.0.0.1:-1 6626 operator: %s 6627 system_account: %s 6628 resolver: MEM 6629 resolver_preload: { 6630 %s: %s 6631 %s: %s 6632 } 6633 `, ojwt, spub, apub, accJwt, spub, sysJwt))) 6634 defer removeFile(t, conf) 6635 6636 s, _ := RunServerWithConfig(conf) 6637 defer s.Shutdown() 6638 6639 expires := time.Now().Add(time.Minute) 6640 creds := createUserWithLimit(t, akp, expires, func(j *jwt.UserPermissionLimits) {}) 6641 6642 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(creds)) 6643 defer nc.Close() 6644 6645 resp, err := nc.Request("$SYS.REQ.USER.INFO", nil, time.Second) 6646 require_NoError(t, err) 6647 now := time.Now() 6648 6649 response := ServerAPIResponse{Data: &UserInfo{}} 6650 err = json.Unmarshal(resp.Data, &response) 6651 require_NoError(t, err) 6652 6653 userInfo := response.Data.(*UserInfo) 6654 require_True(t, userInfo.Expires != 0) 6655 6656 // We need to round the expiration time to the second because the server 6657 // will truncate the expiration time to the second. 6658 expiresDurRounded := expires.Sub(now).Truncate(time.Second) 6659 6660 // Checking range to avoid flaky tests where the expiration time is 6661 // off by a couple of seconds. 6662 require_True(t, expiresDurRounded >= userInfo.Expires-2*time.Second && expiresDurRounded <= userInfo.Expires+2*time.Second) 6663 } 6664 6665 func TestJWTAccountNATSResolverWrongCreds(t *testing.T) { 6666 require_NoLocalOrRemoteConnections := func(account string, srvs ...*Server) { 6667 t.Helper() 6668 for _, srv := range srvs { 6669 if acc, ok := srv.accounts.Load(account); ok { 6670 checkAccClientsCount(t, acc.(*Account), 0) 6671 } 6672 } 6673 } 6674 connect := func(url string, credsfile string, acc string, srvs ...*Server) { 6675 t.Helper() 6676 nc := natsConnect(t, url, nats.UserCredentials(credsfile), nats.Timeout(5*time.Second)) 6677 nc.Close() 6678 require_NoLocalOrRemoteConnections(acc, srvs...) 6679 } 6680 createAccountAndUser := func(pubKey, jwt1, jwt2, creds *string) { 6681 t.Helper() 6682 kp, _ := nkeys.CreateAccount() 6683 *pubKey, _ = kp.PublicKey() 6684 claim := jwt.NewAccountClaims(*pubKey) 6685 var err error 6686 *jwt1, err = claim.Encode(oKp) 6687 require_NoError(t, err) 6688 *jwt2, err = claim.Encode(oKp) 6689 require_NoError(t, err) 6690 ukp, _ := nkeys.CreateUser() 6691 seed, _ := ukp.Seed() 6692 upub, _ := ukp.PublicKey() 6693 uclaim := newJWTTestUserClaims() 6694 uclaim.Subject = upub 6695 ujwt, err := uclaim.Encode(kp) 6696 require_NoError(t, err) 6697 *creds = genCredsFile(t, ujwt, seed) 6698 } 6699 // Create Accounts and corresponding user creds. 6700 var syspub, sysjwt, dummy1, sysCreds string 6701 createAccountAndUser(&syspub, &sysjwt, &dummy1, &sysCreds) 6702 6703 var apub, ajwt1, ajwt2, aCreds string 6704 createAccountAndUser(&apub, &ajwt1, &ajwt2, &aCreds) 6705 6706 var bpub, bjwt1, bjwt2, bCreds string 6707 createAccountAndUser(&bpub, &bjwt1, &bjwt2, &bCreds) 6708 6709 // The one that is going to be missing. 6710 var cpub, cjwt1, cjwt2, cCreds string 6711 createAccountAndUser(&cpub, &cjwt1, &cjwt2, &cCreds) 6712 // Create one directory for each server 6713 dirA := t.TempDir() 6714 dirB := t.TempDir() 6715 dirC := t.TempDir() 6716 6717 // Store accounts on servers A and B, then let C sync on its own. 6718 writeJWT(t, dirA, apub, ajwt1) 6719 writeJWT(t, dirB, bpub, bjwt1) 6720 6721 ///////////////////////////////////////// 6722 // // 6723 // Server A: has creds from client A // 6724 // // 6725 ///////////////////////////////////////// 6726 confA := createConfFile(t, []byte(fmt.Sprintf(` 6727 listen: 127.0.0.1:-1 6728 server_name: srv-A 6729 operator: %s 6730 system_account: %s 6731 debug: true 6732 resolver: { 6733 type: full 6734 dir: '%s' 6735 allow_delete: true 6736 timeout: "1.5s" 6737 interval: "200ms" 6738 } 6739 resolver_preload: { 6740 %s: %s 6741 } 6742 cluster { 6743 name: clust 6744 listen: 127.0.0.1:-1 6745 no_advertise: true 6746 } 6747 `, ojwt, syspub, dirA, apub, ajwt1))) 6748 sA, _ := RunServerWithConfig(confA) 6749 defer sA.Shutdown() 6750 require_JWTPresent(t, dirA, apub) 6751 6752 ///////////////////////////////////////// 6753 // // 6754 // Server B: has creds from client B // 6755 // // 6756 ///////////////////////////////////////// 6757 confB := createConfFile(t, []byte(fmt.Sprintf(` 6758 listen: 127.0.0.1:-1 6759 server_name: srv-B 6760 operator: %s 6761 system_account: %s 6762 resolver: { 6763 type: full 6764 dir: '%s' 6765 allow_delete: true 6766 timeout: "1.5s" 6767 interval: "200ms" 6768 } 6769 cluster { 6770 name: clust 6771 listen: 127.0.0.1:-1 6772 no_advertise: true 6773 routes [ 6774 nats-route://127.0.0.1:%d 6775 ] 6776 } 6777 `, ojwt, syspub, dirB, sA.opts.Cluster.Port))) 6778 sB, _ := RunServerWithConfig(confB) 6779 defer sB.Shutdown() 6780 6781 ///////////////////////////////////////// 6782 // // 6783 // Server C: has no creds // 6784 // // 6785 ///////////////////////////////////////// 6786 fmtC := ` 6787 listen: 127.0.0.1:-1 6788 server_name: srv-C 6789 operator: %s 6790 system_account: %s 6791 resolver: { 6792 type: full 6793 dir: '%s' 6794 allow_delete: true 6795 timeout: "1.5s" 6796 interval: "200ms" 6797 } 6798 cluster { 6799 name: clust 6800 listen: 127.0.0.1:-1 6801 no_advertise: true 6802 routes [ 6803 nats-route://127.0.0.1:%d 6804 ] 6805 } 6806 ` 6807 confClongTTL := createConfFile(t, []byte(fmt.Sprintf(fmtC, ojwt, syspub, dirC, sA.opts.Cluster.Port))) 6808 sC, _ := RunServerWithConfig(confClongTTL) // use long ttl to assure it is not kicking 6809 defer sC.Shutdown() 6810 6811 // startup cluster 6812 checkClusterFormed(t, sA, sB, sC) 6813 time.Sleep(1 * time.Second) // wait for the protocol to converge 6814 // // Check all accounts 6815 require_JWTPresent(t, dirA, apub) // was already present on startup 6816 require_JWTPresent(t, dirB, apub) // was copied from server A 6817 require_JWTPresent(t, dirA, bpub) // was copied from server B 6818 require_JWTPresent(t, dirB, bpub) // was already present on startup 6819 6820 // There should be no state about the missing account. 6821 require_JWTAbsent(t, dirA, cpub) 6822 require_JWTAbsent(t, dirB, cpub) 6823 require_JWTAbsent(t, dirC, cpub) 6824 6825 // system account client can connect to every server 6826 connect(sA.ClientURL(), sysCreds, "") 6827 connect(sB.ClientURL(), sysCreds, "") 6828 connect(sC.ClientURL(), sysCreds, "") 6829 6830 // A and B clients can connect to any server. 6831 connect(sA.ClientURL(), aCreds, "") 6832 connect(sB.ClientURL(), aCreds, "") 6833 connect(sC.ClientURL(), aCreds, "") 6834 connect(sA.ClientURL(), bCreds, "") 6835 connect(sB.ClientURL(), bCreds, "") 6836 connect(sC.ClientURL(), bCreds, "") 6837 6838 // Check that trying to connect with bad credentials should not hang until the fetch timeout 6839 // and instead return a faster response when an account is not found. 6840 _, err := nats.Connect(sC.ClientURL(), nats.UserCredentials(cCreds), nats.Timeout(500*time.Second)) 6841 if err != nil && !errors.Is(err, nats.ErrAuthorization) { 6842 t.Fatalf("Expected auth error: %v", err) 6843 } 6844 }