get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/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 ...interface{}) { 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]interface{}) 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, pub 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]interface{}{} 4996 err = json.Unmarshal(m.Data, &obj) 4997 require_NoError(t, err) 4998 // test if shared is honored 4999 reqInfo := obj["requestor"].(map[string]interface{}) 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 aExpCreds := newUser(t, aExpKp) 5193 5194 createImportingAccountClaim := func(aImpKp nkeys.KeyPair, aExpPub string, ac *jwt.ActivationClaims) (string, string) { 5195 t.Helper() 5196 token, err := ac.Encode(aExpKp) 5197 require_NoError(t, err) 5198 5199 aImpPub, err := aImpKp.PublicKey() 5200 require_NoError(t, err) 5201 aImpClaim := jwt.NewAccountClaims(aImpPub) 5202 aImpClaim.Name = "Import" 5203 aImpClaim.Imports.Add(&jwt.Import{ 5204 Subject: "$events.*.$in.*.>", 5205 Type: jwt.Stream, 5206 Account: aExpPub, 5207 Token: token, 5208 }) 5209 aImpJwt := encodeClaim(t, aImpClaim, aImpPub) 5210 aImpCreds := newUser(t, aImpKp) 5211 return aImpJwt, aImpCreds 5212 } 5213 5214 testConnect := func(aExpPub, aExpJwt, aExpCreds, aImpPub, aImpJwt, aImpCreds string) { 5215 t.Helper() 5216 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 5217 if r.URL.Path == "/A/" { 5218 // Server startup 5219 w.Write(nil) 5220 } else if r.URL.Path == "/A/"+aExpPub { 5221 w.Write([]byte(aExpJwt)) 5222 } else if r.URL.Path == "/A/"+aImpPub { 5223 w.Write([]byte(aImpJwt)) 5224 } else { 5225 t.Fatal("not expected") 5226 } 5227 })) 5228 defer ts.Close() 5229 cf := createConfFile(t, []byte(fmt.Sprintf(` 5230 listen: 127.0.0.1:-1 5231 operator: %s 5232 resolver: URL("%s/A/") 5233 `, ojwt, ts.URL))) 5234 5235 s, opts := RunServerWithConfig(cf) 5236 defer s.Shutdown() 5237 5238 ncImp, err := nats.Connect(fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port), nats.UserCredentials(aImpCreds)) 5239 require_Error(t, err) // misuse needs to result in an error 5240 defer ncImp.Close() 5241 } 5242 5243 testNatsResolver := func(aImpJwt string) { 5244 t.Helper() 5245 dirSrv := t.TempDir() 5246 cf := createConfFile(t, []byte(fmt.Sprintf(` 5247 listen: 127.0.0.1:-1 5248 operator: %s 5249 system_account: %s 5250 resolver: { 5251 type: full 5252 dir: '%s' 5253 } 5254 `, ojwt, syspub, dirSrv))) 5255 5256 s, _ := RunServerWithConfig(cf) 5257 defer s.Shutdown() 5258 5259 require_True(t, updateJwt(t, s.ClientURL(), sysCreds, sysJwt, 1) == 1) 5260 require_True(t, updateJwt(t, s.ClientURL(), sysCreds, aExpJwt, 1) == 1) 5261 require_True(t, updateJwt(t, s.ClientURL(), sysCreds, aImpJwt, 1) == 0) // assure this did not succeed 5262 } 5263 5264 t.Run("wrong-account", func(t *testing.T) { 5265 aImpKp, aImpPub := createKey(t) 5266 ac := &jwt.ActivationClaims{} 5267 _, ac.Subject = createKey(t) // on purpose issue this token for another account 5268 ac.ImportSubject = "$events.*.$in.*.>" 5269 ac.ImportType = jwt.Stream 5270 5271 aImpJwt, aImpCreds := createImportingAccountClaim(aImpKp, aExpPub, ac) 5272 testConnect(aExpPub, aExpJwt, aExpCreds, aImpPub, aImpJwt, aImpCreds) 5273 testNatsResolver(aImpJwt) 5274 }) 5275 5276 t.Run("different-subject", func(t *testing.T) { 5277 aImpKp, aImpPub := createKey(t) 5278 ac := &jwt.ActivationClaims{} 5279 ac.Subject = aImpPub 5280 ac.ImportSubject = "foo" // on purpose use a subject from another export 5281 ac.ImportType = jwt.Stream 5282 5283 aImpJwt, aImpCreds := createImportingAccountClaim(aImpKp, aExpPub, ac) 5284 testConnect(aExpPub, aExpJwt, aExpCreds, aImpPub, aImpJwt, aImpCreds) 5285 testNatsResolver(aImpJwt) 5286 }) 5287 5288 t.Run("non-existing-subject", func(t *testing.T) { 5289 aImpKp, aImpPub := createKey(t) 5290 ac := &jwt.ActivationClaims{} 5291 ac.Subject = aImpPub 5292 ac.ImportSubject = "does-not-exist-or-from-different-export" // on purpose use a non exported subject 5293 ac.ImportType = jwt.Stream 5294 5295 aImpJwt, aImpCreds := createImportingAccountClaim(aImpKp, aExpPub, ac) 5296 testConnect(aExpPub, aExpJwt, aExpCreds, aImpPub, aImpJwt, aImpCreds) 5297 testNatsResolver(aImpJwt) 5298 }) 5299 } 5300 5301 func TestJWTResponseThreshold(t *testing.T) { 5302 respThresh := 20 * time.Millisecond 5303 aExpKp, aExpPub := createKey(t) 5304 aExpClaim := jwt.NewAccountClaims(aExpPub) 5305 aExpClaim.Name = "Export" 5306 aExpClaim.Exports.Add(&jwt.Export{ 5307 Subject: "srvc", 5308 Type: jwt.Service, 5309 ResponseThreshold: respThresh, 5310 }) 5311 aExpJwt := encodeClaim(t, aExpClaim, aExpPub) 5312 aExpCreds := newUser(t, aExpKp) 5313 5314 aImpKp, aImpPub := createKey(t) 5315 aImpClaim := jwt.NewAccountClaims(aImpPub) 5316 aImpClaim.Name = "Import" 5317 aImpClaim.Imports.Add(&jwt.Import{ 5318 Subject: "srvc", 5319 Type: jwt.Service, 5320 Account: aExpPub, 5321 }) 5322 aImpJwt := encodeClaim(t, aImpClaim, aImpPub) 5323 aImpCreds := newUser(t, aImpKp) 5324 5325 cf := createConfFile(t, []byte(fmt.Sprintf(` 5326 port: -1 5327 operator = %s 5328 resolver = MEMORY 5329 resolver_preload = { 5330 %s : "%s" 5331 %s : "%s" 5332 } 5333 `, ojwt, aExpPub, aExpJwt, aImpPub, aImpJwt))) 5334 5335 s, opts := RunServerWithConfig(cf) 5336 defer s.Shutdown() 5337 5338 ncExp := natsConnect(t, fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port), nats.UserCredentials(aExpCreds)) 5339 defer ncExp.Close() 5340 5341 ncImp := natsConnect(t, fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port), nats.UserCredentials(aImpCreds)) 5342 defer ncImp.Close() 5343 5344 delayChan := make(chan time.Duration, 1) 5345 5346 // Create subscriber for the service endpoint in foo. 5347 _, err := ncExp.Subscribe("srvc", func(m *nats.Msg) { 5348 time.Sleep(<-delayChan) 5349 m.Respond([]byte("yes!")) 5350 }) 5351 require_NoError(t, err) 5352 ncExp.Flush() 5353 5354 t.Run("No-Timeout", func(t *testing.T) { 5355 delayChan <- respThresh / 2 5356 if resp, err := ncImp.Request("srvc", []byte("yes?"), 4*respThresh); err != nil { 5357 t.Fatalf("Expected a response to request srvc got: %v", err) 5358 } else if string(resp.Data) != "yes!" { 5359 t.Fatalf("Expected a response of %q, got %q", "yes!", resp.Data) 5360 } 5361 }) 5362 t.Run("Timeout", func(t *testing.T) { 5363 delayChan <- 2 * respThresh 5364 if _, err := ncImp.Request("srvc", []byte("yes?"), 4*respThresh); err == nil || err != nats.ErrTimeout { 5365 t.Fatalf("Expected a timeout") 5366 } 5367 }) 5368 } 5369 5370 func TestJWTJetStreamTiers(t *testing.T) { 5371 sysKp, syspub := createKey(t) 5372 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 5373 sysCreds := newUser(t, sysKp) 5374 5375 accKp, accPub := createKey(t) 5376 accClaim := jwt.NewAccountClaims(accPub) 5377 accClaim.Name = "acc" 5378 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5379 DiskStorage: 1100, MemoryStorage: 0, Consumer: 2, Streams: 2} 5380 accJwt1 := encodeClaim(t, accClaim, accPub) 5381 accCreds := newUser(t, accKp) 5382 5383 start := time.Now() 5384 5385 storeDir := t.TempDir() 5386 5387 dirSrv := t.TempDir() 5388 cf := createConfFile(t, []byte(fmt.Sprintf(` 5389 listen: 127.0.0.1:-1 5390 server_name: s1 5391 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 5392 leaf { 5393 listen: 127.0.0.1:-1 5394 } 5395 operator: %s 5396 system_account: %s 5397 resolver: { 5398 type: full 5399 dir: '%s' 5400 } 5401 `, storeDir, ojwt, syspub, dirSrv))) 5402 5403 s, _ := RunServerWithConfig(cf) 5404 defer s.Shutdown() 5405 5406 updateJwt(t, s.ClientURL(), sysCreds, sysJwt, 1) 5407 updateJwt(t, s.ClientURL(), sysCreds, accJwt1, 1) 5408 5409 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(accCreds)) 5410 defer nc.Close() 5411 5412 js, err := nc.JetStream() 5413 require_NoError(t, err) 5414 5415 // Test tiers up to stream limits 5416 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-1", Replicas: 1, Subjects: []string{"testR1-1"}}) 5417 require_NoError(t, err) 5418 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-2", Replicas: 1, Subjects: []string{"testR1-2"}}) 5419 require_NoError(t, err) 5420 5421 // Test exceeding tiered stream limit 5422 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-3", Replicas: 1, Subjects: []string{"testR1-3"}}) 5423 require_Error(t, err) 5424 require_Equal(t, err.Error(), "nats: maximum number of streams reached") 5425 5426 // Test tiers up to consumer limits 5427 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur1", AckPolicy: nats.AckExplicitPolicy}) 5428 require_NoError(t, err) 5429 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur3", AckPolicy: nats.AckExplicitPolicy}) 5430 require_NoError(t, err) 5431 5432 // test exceeding tiered consumer limits 5433 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur4", AckPolicy: nats.AckExplicitPolicy}) 5434 require_Error(t, err) 5435 require_Equal(t, err.Error(), "nats: maximum consumers limit reached") 5436 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur5", AckPolicy: nats.AckExplicitPolicy}) 5437 require_Error(t, err) 5438 require_Equal(t, err.Error(), "nats: maximum consumers limit reached") 5439 5440 // test tiered storage limit 5441 msg := [512]byte{} 5442 _, err = js.Publish("testR1-1", msg[:]) 5443 require_NoError(t, err) 5444 _, err = js.Publish("testR1-2", msg[:]) 5445 require_NoError(t, err) 5446 5447 // test exceeding tiered storage limit 5448 _, err = js.Publish("testR1-1", []byte("1")) 5449 require_Error(t, err) 5450 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 5451 5452 time.Sleep(time.Second - time.Since(start)) // make sure the time stamp changes 5453 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5454 DiskStorage: 1650, MemoryStorage: 0, Consumer: 1, Streams: 3} 5455 accJwt2 := encodeClaim(t, accClaim, accPub) 5456 updateJwt(t, s.ClientURL(), sysCreds, accJwt2, 1) 5457 5458 // test same sequence as before, add stream, fail add stream, add consumer, fail add consumer, publish, fail publish 5459 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-3", Replicas: 1, Subjects: []string{"testR1-3"}}) 5460 require_NoError(t, err) 5461 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-4", Replicas: 1, Subjects: []string{"testR1-4"}}) 5462 require_Error(t, err) 5463 require_Equal(t, err.Error(), "nats: maximum number of streams reached") 5464 _, err = js.AddConsumer("testR1-3", &nats.ConsumerConfig{Durable: "dur6", AckPolicy: nats.AckExplicitPolicy}) 5465 require_NoError(t, err) 5466 _, err = js.AddConsumer("testR1-3", &nats.ConsumerConfig{Durable: "dur7", AckPolicy: nats.AckExplicitPolicy}) 5467 require_Error(t, err) 5468 require_Equal(t, err.Error(), "nats: maximum consumers limit reached") 5469 _, err = js.Publish("testR1-3", msg[:]) 5470 require_Error(t, err) 5471 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 5472 } 5473 5474 func TestJWTJetStreamMaxAckPending(t *testing.T) { 5475 sysKp, syspub := createKey(t) 5476 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 5477 sysCreds := newUser(t, sysKp) 5478 5479 accKp, accPub := createKey(t) 5480 accClaim := jwt.NewAccountClaims(accPub) 5481 accClaim.Name = "acc" 5482 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5483 DiskStorage: jwt.NoLimit, MemoryStorage: jwt.NoLimit, 5484 Consumer: jwt.NoLimit, Streams: jwt.NoLimit, MaxAckPending: int64(1000), 5485 } 5486 accJwt1 := encodeClaim(t, accClaim, accPub) 5487 accCreds := newUser(t, accKp) 5488 5489 start := time.Now() 5490 5491 storeDir := t.TempDir() 5492 5493 dirSrv := t.TempDir() 5494 cf := createConfFile(t, []byte(fmt.Sprintf(` 5495 listen: 127.0.0.1:-1 5496 server_name: s1 5497 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 5498 leaf { 5499 listen: 127.0.0.1:-1 5500 } 5501 operator: %s 5502 system_account: %s 5503 resolver: { 5504 type: full 5505 dir: '%s' 5506 } 5507 `, storeDir, ojwt, syspub, dirSrv))) 5508 5509 s, _ := RunServerWithConfig(cf) 5510 defer s.Shutdown() 5511 5512 updateJwt(t, s.ClientURL(), sysCreds, sysJwt, 1) 5513 updateJwt(t, s.ClientURL(), sysCreds, accJwt1, 1) 5514 5515 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(accCreds)) 5516 defer nc.Close() 5517 5518 js, err := nc.JetStream() 5519 require_NoError(t, err) 5520 5521 _, err = js.AddStream(&nats.StreamConfig{Name: "foo", Replicas: 1}) 5522 require_NoError(t, err) 5523 5524 _, err = js.AddConsumer("foo", &nats.ConsumerConfig{ 5525 Durable: "dur1", AckPolicy: nats.AckAllPolicy, MaxAckPending: 2000}) 5526 require_Error(t, err) 5527 require_Equal(t, err.Error(), "nats: consumer max ack pending exceeds system limit of 1000") 5528 5529 ci, err := js.AddConsumer("foo", &nats.ConsumerConfig{ 5530 Durable: "dur2", AckPolicy: nats.AckAllPolicy, MaxAckPending: 500}) 5531 require_NoError(t, err) 5532 require_True(t, ci.Config.MaxAckPending == 500) 5533 5534 _, err = js.UpdateConsumer("foo", &nats.ConsumerConfig{ 5535 Durable: "dur2", AckPolicy: nats.AckAllPolicy, MaxAckPending: 2000}) 5536 require_Error(t, err) 5537 require_Equal(t, err.Error(), "nats: consumer max ack pending exceeds system limit of 1000") 5538 5539 time.Sleep(time.Second - time.Since(start)) // make sure the time stamp changes 5540 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5541 DiskStorage: jwt.NoLimit, MemoryStorage: jwt.NoLimit, Consumer: jwt.NoLimit, 5542 Streams: jwt.NoLimit, MaxAckPending: int64(2000)} 5543 accJwt2 := encodeClaim(t, accClaim, accPub) 5544 updateJwt(t, s.ClientURL(), sysCreds, accJwt2, 1) 5545 5546 ci, err = js.UpdateConsumer("foo", &nats.ConsumerConfig{ 5547 Durable: "dur2", AckPolicy: nats.AckAllPolicy, MaxAckPending: 2000}) 5548 require_NoError(t, err) 5549 require_True(t, ci.Config.MaxAckPending == 2000) 5550 } 5551 5552 func TestJWTJetStreamMaxStreamBytes(t *testing.T) { 5553 sysKp, syspub := createKey(t) 5554 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 5555 sysCreds := newUser(t, sysKp) 5556 5557 accKp, accPub := createKey(t) 5558 accClaim := jwt.NewAccountClaims(accPub) 5559 accClaim.Name = "acc" 5560 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5561 DiskStorage: jwt.NoLimit, MemoryStorage: jwt.NoLimit, 5562 Consumer: jwt.NoLimit, Streams: jwt.NoLimit, 5563 DiskMaxStreamBytes: 1024, MaxBytesRequired: false, 5564 } 5565 accJwt1 := encodeClaim(t, accClaim, accPub) 5566 accCreds := newUser(t, accKp) 5567 5568 start := time.Now() 5569 5570 storeDir := t.TempDir() 5571 5572 dirSrv := t.TempDir() 5573 cf := createConfFile(t, []byte(fmt.Sprintf(` 5574 listen: 127.0.0.1:-1 5575 server_name: s1 5576 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 5577 leaf { 5578 listen: 127.0.0.1:-1 5579 } 5580 operator: %s 5581 system_account: %s 5582 resolver: { 5583 type: full 5584 dir: '%s' 5585 } 5586 `, storeDir, ojwt, syspub, dirSrv))) 5587 5588 s, _ := RunServerWithConfig(cf) 5589 defer s.Shutdown() 5590 5591 updateJwt(t, s.ClientURL(), sysCreds, sysJwt, 1) 5592 updateJwt(t, s.ClientURL(), sysCreds, accJwt1, 1) 5593 5594 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(accCreds)) 5595 defer nc.Close() 5596 5597 js, err := nc.JetStream() 5598 require_NoError(t, err) 5599 5600 _, err = js.AddStream(&nats.StreamConfig{Name: "foo", Replicas: 1, MaxBytes: 2048}) 5601 require_Error(t, err) 5602 require_Equal(t, err.Error(), "nats: stream max bytes exceeds account limit max stream bytes") 5603 _, err = js.AddStream(&nats.StreamConfig{Name: "foo", Replicas: 1, MaxBytes: 1024}) 5604 require_NoError(t, err) 5605 5606 msg := [900]byte{} 5607 _, err = js.AddStream(&nats.StreamConfig{Name: "baz", Replicas: 1}) 5608 require_NoError(t, err) 5609 _, err = js.Publish("baz", msg[:]) 5610 require_NoError(t, err) 5611 _, err = js.Publish("baz", msg[:]) // exceeds max stream bytes 5612 require_Error(t, err) 5613 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 5614 5615 time.Sleep(time.Second - time.Since(start)) // make sure the time stamp changes 5616 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 5617 DiskStorage: jwt.NoLimit, MemoryStorage: jwt.NoLimit, Consumer: jwt.NoLimit, Streams: jwt.NoLimit, 5618 DiskMaxStreamBytes: 2048, MaxBytesRequired: true} 5619 accJwt2 := encodeClaim(t, accClaim, accPub) 5620 updateJwt(t, s.ClientURL(), sysCreds, accJwt2, 1) 5621 5622 _, err = js.AddStream(&nats.StreamConfig{Name: "bar", Replicas: 1, MaxBytes: 3000}) 5623 require_Error(t, err) 5624 require_Equal(t, err.Error(), "nats: stream max bytes exceeds account limit max stream bytes") 5625 _, err = js.AddStream(&nats.StreamConfig{Name: "bar", Replicas: 1, MaxBytes: 2048}) 5626 require_NoError(t, err) 5627 5628 // test if we can push more messages into the stream 5629 _, err = js.Publish("baz", msg[:]) // exceeds max stream bytes 5630 require_Error(t, err) 5631 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 5632 5633 // test disabling max bytes required 5634 _, err = js.UpdateStream(&nats.StreamConfig{Name: "bar", Replicas: 1}) 5635 require_Error(t, err) 5636 require_Equal(t, err.Error(), "nats: account requires a stream config to have max bytes set") 5637 } 5638 5639 func TestJWTQueuePermissions(t *testing.T) { 5640 aExpKp, aExpPub := createKey(t) 5641 aExpClaim := jwt.NewAccountClaims(aExpPub) 5642 aExpJwt := encodeClaim(t, aExpClaim, aExpPub) 5643 newUser := func(t *testing.T, permType string) string { 5644 ukp, _ := nkeys.CreateUser() 5645 seed, _ := ukp.Seed() 5646 upub, _ := ukp.PublicKey() 5647 uclaim := newJWTTestUserClaims() 5648 uclaim.Subject = upub 5649 switch permType { 5650 case "allow": 5651 uclaim.Permissions.Sub.Allow.Add("foo.> *.dev") 5652 case "deny": 5653 uclaim.Permissions.Sub.Deny.Add("foo.> *.dev") 5654 } 5655 ujwt, err := uclaim.Encode(aExpKp) 5656 require_NoError(t, err) 5657 return genCredsFile(t, ujwt, seed) 5658 } 5659 confFileName := createConfFile(t, []byte(fmt.Sprintf(` 5660 port: -1 5661 operator = %s 5662 resolver = MEMORY 5663 resolver_preload = { 5664 %s : %s 5665 }`, ojwt, aExpPub, aExpJwt))) 5666 opts, err := ProcessConfigFile(confFileName) 5667 if err != nil { 5668 t.Fatalf("Received unexpected error %s", err) 5669 } 5670 opts.NoLog, opts.NoSigs = true, true 5671 errChan := make(chan error, 1) 5672 defer close(errChan) 5673 s := RunServer(opts) 5674 defer s.Shutdown() 5675 5676 for _, test := range []struct { 5677 permType string 5678 queue string 5679 errExpected bool 5680 }{ 5681 {"allow", "queue.dev", false}, 5682 {"allow", "", true}, 5683 {"allow", "bad", true}, 5684 {"deny", "", false}, 5685 {"deny", "queue.dev", true}, 5686 } { 5687 t.Run(test.permType+test.queue, func(t *testing.T) { 5688 usrCreds := newUser(t, test.permType) 5689 nc, err := nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", opts.Port), 5690 nats.ErrorHandler(func(conn *nats.Conn, s *nats.Subscription, err error) { 5691 errChan <- err 5692 }), 5693 nats.UserCredentials(usrCreds)) 5694 if err != nil { 5695 t.Fatalf("No error expected: %v", err) 5696 } 5697 defer nc.Close() 5698 if test.queue == "" { 5699 if _, err := nc.Subscribe("foo.bar", func(msg *nats.Msg) {}); err != nil { 5700 t.Fatalf("no error expected: %v", err) 5701 } 5702 } else { 5703 if _, err := nc.QueueSubscribe("foo.bar", test.queue, func(msg *nats.Msg) {}); err != nil { 5704 t.Fatalf("no error expected: %v", err) 5705 } 5706 } 5707 nc.Flush() 5708 select { 5709 case err := <-errChan: 5710 if !test.errExpected { 5711 t.Fatalf("Expected no error, got %v", err) 5712 } 5713 if !strings.Contains(err.Error(), `Permissions Violation for Subscription to "foo.bar"`) { 5714 t.Fatalf("error %v", err) 5715 } 5716 case <-time.After(150 * time.Millisecond): 5717 if test.errExpected { 5718 t.Fatal("Expected an error") 5719 } 5720 } 5721 }) 5722 5723 } 5724 } 5725 5726 func TestJWScopedSigningKeys(t *testing.T) { 5727 sysKp, syspub := createKey(t) 5728 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 5729 sysCreds := newUser(t, sysKp) 5730 5731 _, aExpPub := createKey(t) 5732 accClaim := jwt.NewAccountClaims(aExpPub) 5733 accClaim.Name = "acc" 5734 5735 aSignNonScopedKp, aSignNonScopedPub := createKey(t) 5736 accClaim.SigningKeys.Add(aSignNonScopedPub) 5737 5738 aSignScopedKp, aSignScopedPub := createKey(t) 5739 signer := jwt.NewUserScope() 5740 signer.Key = aSignScopedPub 5741 signer.Template.Pub.Deny.Add("denied") 5742 signer.Template.Payload = 5 5743 accClaim.SigningKeys.AddScopedSigner(signer) 5744 accJwt := encodeClaim(t, accClaim, aExpPub) 5745 5746 aNonScopedCreds := newUserEx(t, aSignNonScopedKp, false, aExpPub) 5747 aBadScopedCreds := newUserEx(t, aSignScopedKp, false, aExpPub) 5748 aScopedCreds := newUserEx(t, aSignScopedKp, true, aExpPub) 5749 5750 dirSrv := t.TempDir() 5751 cf := createConfFile(t, []byte(fmt.Sprintf(` 5752 listen: 127.0.0.1:-1 5753 operator: %s 5754 system_account: %s 5755 resolver: { 5756 type: full 5757 dir: '%s' 5758 } 5759 `, ojwt, syspub, dirSrv))) 5760 s, opts := RunServerWithConfig(cf) 5761 defer s.Shutdown() 5762 5763 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 5764 errChan := make(chan error, 1) 5765 defer close(errChan) 5766 awaitError := func(expected bool) { 5767 t.Helper() 5768 select { 5769 case err := <-errChan: 5770 if !expected { 5771 t.Fatalf("Expected no error, got %v", err) 5772 } 5773 case <-time.After(150 * time.Millisecond): 5774 if expected { 5775 t.Fatal("Expected an error") 5776 } 5777 } 5778 } 5779 errHdlr := nats.ErrorHandler(func(conn *nats.Conn, s *nats.Subscription, err error) { 5780 errChan <- err 5781 }) 5782 if updateJwt(t, url, sysCreds, sysJwt, 1) != 1 { 5783 t.Error("Expected update to pass") 5784 } else if updateJwt(t, url, sysCreds, accJwt, 1) != 1 { 5785 t.Error("Expected update to pass") 5786 } 5787 t.Run("bad-scoped-signing-key", func(t *testing.T) { 5788 _, err := nats.Connect(url, nats.UserCredentials(aBadScopedCreds)) 5789 require_Error(t, err) 5790 }) 5791 t.Run("regular-signing-key", func(t *testing.T) { 5792 nc := natsConnect(t, url, nats.UserCredentials(aNonScopedCreds), errHdlr) 5793 defer nc.Close() 5794 nc.Flush() 5795 err := nc.Publish("denied", nil) 5796 require_NoError(t, err) 5797 nc.Flush() 5798 awaitError(false) 5799 }) 5800 t.Run("scoped-signing-key-client-side", func(t *testing.T) { 5801 nc := natsConnect(t, url, nats.UserCredentials(aScopedCreds), errHdlr) 5802 defer nc.Close() 5803 nc.Flush() 5804 err := nc.Publish("too-long", []byte("way.too.long.for.payload.limit")) 5805 require_Error(t, err) 5806 require_True(t, strings.Contains(err.Error(), ErrMaxPayload.Error())) 5807 }) 5808 t.Run("scoped-signing-key-server-side", func(t *testing.T) { 5809 nc := natsConnect(t, url, nats.UserCredentials(aScopedCreds), errHdlr) 5810 defer nc.Close() 5811 nc.Flush() 5812 err := nc.Publish("denied", nil) 5813 require_NoError(t, err) 5814 nc.Flush() 5815 awaitError(true) 5816 }) 5817 t.Run("scoped-signing-key-reload", func(t *testing.T) { 5818 reconChan := make(chan struct{}, 1) 5819 defer close(reconChan) 5820 msgChan := make(chan *nats.Msg, 2) 5821 defer close(msgChan) 5822 nc := natsConnect(t, url, nats.UserCredentials(aScopedCreds), errHdlr, 5823 nats.DisconnectErrHandler(func(conn *nats.Conn, err error) { 5824 if err != nil { 5825 errChan <- err 5826 } 5827 }), 5828 nats.ReconnectHandler(func(conn *nats.Conn) { 5829 reconChan <- struct{}{} 5830 }), 5831 ) 5832 defer nc.Close() 5833 _, err := nc.ChanSubscribe("denied", msgChan) 5834 require_NoError(t, err) 5835 nc.Flush() 5836 err = nc.Publish("denied", nil) 5837 require_NoError(t, err) 5838 awaitError(true) 5839 require_Len(t, len(msgChan), 0) 5840 // Alter scoped permissions and update 5841 signer.Template.Payload = -1 5842 signer.Template.Pub.Deny.Remove("denied") 5843 accClaim.SigningKeys.AddScopedSigner(signer) 5844 accUpdatedJwt := encodeClaim(t, accClaim, aExpPub) 5845 if updateJwt(t, url, sysCreds, accUpdatedJwt, 1) != 1 { 5846 t.Error("Expected update to pass") 5847 } 5848 // disconnect triggered by update 5849 awaitError(true) 5850 <-reconChan 5851 nc.Flush() 5852 err = nc.Publish("denied", []byte("way.too.long.for.old.payload.limit")) 5853 require_NoError(t, err) 5854 awaitError(false) 5855 msg := <-msgChan 5856 require_Equal(t, string(msg.Data), "way.too.long.for.old.payload.limit") 5857 require_Len(t, len(msgChan), 0) 5858 }) 5859 require_Len(t, len(errChan), 0) 5860 } 5861 5862 func TestJWTStrictSigningKeys(t *testing.T) { 5863 newAccount := func(opKp nkeys.KeyPair) (nkeys.KeyPair, nkeys.KeyPair, string, *jwt.AccountClaims, string) { 5864 accId, err := nkeys.CreateAccount() 5865 require_NoError(t, err) 5866 accIdPub, err := accId.PublicKey() 5867 require_NoError(t, err) 5868 5869 accSig, err := nkeys.CreateAccount() 5870 require_NoError(t, err) 5871 accSigPub, err := accSig.PublicKey() 5872 require_NoError(t, err) 5873 5874 aClaim := jwt.NewAccountClaims(accIdPub) 5875 aClaim.SigningKeys.Add(accSigPub) 5876 theJwt, err := aClaim.Encode(opKp) 5877 require_NoError(t, err) 5878 return accId, accSig, accIdPub, aClaim, theJwt 5879 } 5880 5881 opId, err := nkeys.CreateOperator() 5882 require_NoError(t, err) 5883 opIdPub, err := opId.PublicKey() 5884 require_NoError(t, err) 5885 5886 opSig, err := nkeys.CreateOperator() 5887 require_NoError(t, err) 5888 opSigPub, err := opSig.PublicKey() 5889 require_NoError(t, err) 5890 5891 aBadBadKp, aBadGoodKp, aBadPub, _, aBadJwt := newAccount(opId) 5892 aGoodBadKp, aGoodGoodKp, aGoodPub, _, aGoodJwt := newAccount(opSig) 5893 _, aSysKp, aSysPub, _, aSysJwt := newAccount(opSig) 5894 5895 oClaim := jwt.NewOperatorClaims(opIdPub) 5896 oClaim.StrictSigningKeyUsage = true 5897 oClaim.SigningKeys.Add(opSigPub) 5898 oClaim.SystemAccount = aSysPub 5899 oJwt, err := oClaim.Encode(opId) 5900 require_NoError(t, err) 5901 5902 uBadBadCreds := newUserEx(t, aBadBadKp, false, aBadPub) 5903 uBadGoodCreds := newUserEx(t, aBadGoodKp, false, aBadPub) 5904 uGoodBadCreds := newUserEx(t, aGoodBadKp, false, aGoodPub) 5905 uGoodGoodCreds := newUserEx(t, aGoodGoodKp, false, aGoodPub) 5906 uSysCreds := newUserEx(t, aSysKp, false, aSysPub) 5907 5908 connectTest := func(url string) { 5909 for _, test := range []struct { 5910 creds string 5911 fail bool 5912 }{ 5913 {uBadBadCreds, true}, 5914 {uBadGoodCreds, true}, 5915 {uGoodBadCreds, true}, 5916 {uGoodGoodCreds, false}, 5917 } { 5918 nc, err := nats.Connect(url, nats.UserCredentials(test.creds)) 5919 nc.Close() 5920 if test.fail { 5921 require_Error(t, err) 5922 } else { 5923 require_NoError(t, err) 5924 } 5925 } 5926 } 5927 5928 t.Run("resolver", func(t *testing.T) { 5929 dirSrv := t.TempDir() 5930 cf := createConfFile(t, []byte(fmt.Sprintf(` 5931 port: -1 5932 operator = %s 5933 resolver: { 5934 type: full 5935 dir: '%s' 5936 } 5937 resolver_preload = { 5938 %s : "%s" 5939 } 5940 `, oJwt, dirSrv, aSysPub, aSysJwt))) 5941 s, _ := RunServerWithConfig(cf) 5942 defer s.Shutdown() 5943 url := s.ClientURL() 5944 if updateJwt(t, url, uSysCreds, aBadJwt, 1) != 0 { 5945 t.Fatal("Expected negative response") 5946 } 5947 if updateJwt(t, url, uSysCreds, aGoodJwt, 1) != 1 { 5948 t.Fatal("Expected positive response") 5949 } 5950 connectTest(url) 5951 }) 5952 5953 t.Run("mem-resolver", func(t *testing.T) { 5954 cf := createConfFile(t, []byte(fmt.Sprintf(` 5955 port: -1 5956 operator = %s 5957 resolver: MEMORY 5958 resolver_preload = { 5959 %s : "%s" 5960 %s : "%s" 5961 %s : "%s" 5962 } 5963 `, oJwt, aSysPub, aSysJwt, aBadPub, aBadJwt, aGoodPub, aGoodJwt))) 5964 s, _ := RunServerWithConfig(cf) 5965 defer s.Shutdown() 5966 connectTest(s.ClientURL()) 5967 }) 5968 } 5969 5970 func TestJWTAccountProtectedImport(t *testing.T) { 5971 srvFmt := ` 5972 port: -1 5973 operator = %s 5974 resolver: MEMORY 5975 resolver_preload = { 5976 %s : "%s" 5977 %s : "%s" 5978 } ` 5979 setupAccounts := func(pass bool) (nkeys.KeyPair, string, string, string, nkeys.KeyPair, string, string, string, string) { 5980 // Create accounts and imports/exports. 5981 exportKP, _ := nkeys.CreateAccount() 5982 exportPub, _ := exportKP.PublicKey() 5983 exportAC := jwt.NewAccountClaims(exportPub) 5984 exportAC.Exports.Add(&jwt.Export{Subject: "service.*", Type: jwt.Service, AccountTokenPosition: 2}) 5985 exportAC.Exports.Add(&jwt.Export{Subject: "stream.*", Type: jwt.Stream, AccountTokenPosition: 2}) 5986 exportJWT, err := exportAC.Encode(oKp) 5987 require_NoError(t, err) 5988 // create alternative exporter jwt without account token pos set 5989 exportAC.Exports = jwt.Exports{} 5990 exportAC.Exports.Add(&jwt.Export{Subject: "service.*", Type: jwt.Service}) 5991 exportAC.Exports.Add(&jwt.Export{Subject: "stream.*", Type: jwt.Stream}) 5992 exportJWTNoPos, err := exportAC.Encode(oKp) 5993 require_NoError(t, err) 5994 5995 importKP, _ := nkeys.CreateAccount() 5996 importPub, _ := importKP.PublicKey() 5997 importAc := jwt.NewAccountClaims(importPub) 5998 srvcSub, strmSub := "service.foo", "stream.foo" 5999 if pass { 6000 srvcSub = fmt.Sprintf("service.%s", importPub) 6001 strmSub = fmt.Sprintf("stream.%s", importPub) 6002 } 6003 importAc.Imports.Add(&jwt.Import{Account: exportPub, Subject: jwt.Subject(srvcSub), Type: jwt.Service}) 6004 importAc.Imports.Add(&jwt.Import{Account: exportPub, Subject: jwt.Subject(strmSub), Type: jwt.Stream}) 6005 importJWT, err := importAc.Encode(oKp) 6006 require_NoError(t, err) 6007 6008 return exportKP, exportPub, exportJWT, exportJWTNoPos, importKP, importPub, importJWT, srvcSub, strmSub 6009 } 6010 t.Run("pass", func(t *testing.T) { 6011 exportKp, exportPub, exportJWT, _, importKp, importPub, importJWT, srvcSub, strmSub := setupAccounts(true) 6012 cf := createConfFile(t, []byte(fmt.Sprintf(srvFmt, ojwt, exportPub, exportJWT, importPub, importJWT))) 6013 s, _ := RunServerWithConfig(cf) 6014 defer s.Shutdown() 6015 ncExp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, exportKp)) 6016 defer ncExp.Close() 6017 ncImp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, importKp)) 6018 defer ncImp.Close() 6019 t.Run("service", func(t *testing.T) { 6020 sub, err := ncExp.Subscribe("service.*", func(msg *nats.Msg) { 6021 msg.Respond([]byte("world")) 6022 }) 6023 defer sub.Unsubscribe() 6024 require_NoError(t, err) 6025 ncExp.Flush() 6026 msg, err := ncImp.Request(srvcSub, []byte("hello"), time.Second) 6027 require_NoError(t, err) 6028 require_Equal(t, string(msg.Data), "world") 6029 }) 6030 t.Run("stream", func(t *testing.T) { 6031 msgChan := make(chan *nats.Msg, 4) 6032 defer close(msgChan) 6033 sub, err := ncImp.ChanSubscribe(strmSub, msgChan) 6034 defer sub.Unsubscribe() 6035 require_NoError(t, err) 6036 ncImp.Flush() 6037 err = ncExp.Publish("stream.foo", []byte("hello")) 6038 require_NoError(t, err) 6039 err = ncExp.Publish(strmSub, []byte("hello")) 6040 require_NoError(t, err) 6041 msg := <-msgChan 6042 require_Equal(t, string(msg.Data), "hello") 6043 require_True(t, len(msgChan) == 0) 6044 }) 6045 }) 6046 t.Run("fail", func(t *testing.T) { 6047 exportKp, exportPub, exportJWT, _, importKp, importPub, importJWT, srvcSub, strmSub := setupAccounts(false) 6048 cf := createConfFile(t, []byte(fmt.Sprintf(srvFmt, ojwt, exportPub, exportJWT, importPub, importJWT))) 6049 s, _ := RunServerWithConfig(cf) 6050 defer s.Shutdown() 6051 ncExp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, exportKp)) 6052 defer ncExp.Close() 6053 ncImp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, importKp)) 6054 defer ncImp.Close() 6055 t.Run("service", func(t *testing.T) { 6056 sub, err := ncExp.Subscribe("service.*", func(msg *nats.Msg) { 6057 msg.Respond([]byte("world")) 6058 }) 6059 defer sub.Unsubscribe() 6060 require_NoError(t, err) 6061 ncExp.Flush() 6062 _, err = ncImp.Request(srvcSub, []byte("hello"), time.Second) 6063 require_Error(t, err) 6064 require_Contains(t, err.Error(), "no responders available for request") 6065 }) 6066 t.Run("stream", func(t *testing.T) { 6067 msgChan := make(chan *nats.Msg, 4) 6068 defer close(msgChan) 6069 _, err := ncImp.ChanSubscribe(strmSub, msgChan) 6070 require_NoError(t, err) 6071 ncImp.Flush() 6072 err = ncExp.Publish("stream.foo", []byte("hello")) 6073 require_NoError(t, err) 6074 err = ncExp.Publish(strmSub, []byte("hello")) 6075 require_NoError(t, err) 6076 select { 6077 case <-msgChan: 6078 t.Fatal("did not expect a message") 6079 case <-time.After(250 * time.Millisecond): 6080 } 6081 require_True(t, len(msgChan) == 0) 6082 }) 6083 }) 6084 t.Run("reload-off-2-on", func(t *testing.T) { 6085 exportKp, exportPub, exportJWTOn, exportJWTOff, importKp, _, importJWT, srvcSub, strmSub := setupAccounts(false) 6086 dirSrv := t.TempDir() 6087 // set up system account. Relying bootstrapping system account to not create JWT 6088 sysAcc, err := nkeys.CreateAccount() 6089 require_NoError(t, err) 6090 sysPub, err := sysAcc.PublicKey() 6091 require_NoError(t, err) 6092 sysUsrCreds := newUserEx(t, sysAcc, false, sysPub) 6093 cf := createConfFile(t, []byte(fmt.Sprintf(` 6094 port: -1 6095 operator = %s 6096 system_account = %s 6097 resolver: { 6098 type: full 6099 dir: '%s' 6100 }`, ojwt, sysPub, dirSrv))) 6101 s, _ := RunServerWithConfig(cf) 6102 defer s.Shutdown() 6103 updateJwt(t, s.ClientURL(), sysUsrCreds, importJWT, 1) 6104 updateJwt(t, s.ClientURL(), sysUsrCreds, exportJWTOff, 1) 6105 ncExp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, exportKp)) 6106 defer ncExp.Close() 6107 ncImp := natsConnect(t, s.ClientURL(), createUserCreds(t, s, importKp)) 6108 defer ncImp.Close() 6109 msgChan := make(chan *nats.Msg, 4) 6110 defer close(msgChan) 6111 // ensure service passes 6112 subSrvc, err := ncExp.Subscribe("service.*", func(msg *nats.Msg) { 6113 msg.Respond([]byte("world")) 6114 }) 6115 defer subSrvc.Unsubscribe() 6116 require_NoError(t, err) 6117 ncExp.Flush() 6118 respMst, err := ncImp.Request(srvcSub, []byte("hello"), time.Second) 6119 require_NoError(t, err) 6120 require_Equal(t, string(respMst.Data), "world") 6121 // ensure stream passes 6122 subStrm, err := ncImp.ChanSubscribe(strmSub, msgChan) 6123 defer subStrm.Unsubscribe() 6124 require_NoError(t, err) 6125 ncImp.Flush() 6126 err = ncExp.Publish(strmSub, []byte("hello")) 6127 require_NoError(t, err) 6128 msg := <-msgChan 6129 require_Equal(t, string(msg.Data), "hello") 6130 require_True(t, len(msgChan) == 0) 6131 6132 updateJwt(t, s.ClientURL(), sysUsrCreds, exportJWTOn, 1) 6133 6134 // ensure service fails 6135 _, err = ncImp.Request(srvcSub, []byte("hello"), time.Second) 6136 require_Error(t, err) 6137 require_Contains(t, err.Error(), "timeout") 6138 s.AccountResolver().Store(exportPub, exportJWTOn) 6139 // ensure stream fails 6140 err = ncExp.Publish(strmSub, []byte("hello")) 6141 require_NoError(t, err) 6142 select { 6143 case <-msgChan: 6144 t.Fatal("did not expect a message") 6145 case <-time.After(250 * time.Millisecond): 6146 } 6147 require_True(t, len(msgChan) == 0) 6148 }) 6149 } 6150 6151 // Headers are ignored in claims update, but passing them should not cause error. 6152 func TestJWTClaimsUpdateWithHeaders(t *testing.T) { 6153 skp, spub := createKey(t) 6154 newUser(t, skp) 6155 6156 sclaim := jwt.NewAccountClaims(spub) 6157 encodeClaim(t, sclaim, spub) 6158 6159 akp, apub := createKey(t) 6160 newUser(t, akp) 6161 claim := jwt.NewAccountClaims(apub) 6162 jwtClaim := encodeClaim(t, claim, apub) 6163 6164 dirSrv := t.TempDir() 6165 6166 conf := createConfFile(t, []byte(fmt.Sprintf(` 6167 listen: 127.0.0.1:-1 6168 operator: %s 6169 system_account: %s 6170 resolver: { 6171 type: full 6172 dir: '%s' 6173 } 6174 `, ojwt, spub, dirSrv))) 6175 6176 s, _ := RunServerWithConfig(conf) 6177 defer s.Shutdown() 6178 6179 type zapi struct { 6180 Server *ServerInfo 6181 Data *Connz 6182 Error *ApiError 6183 } 6184 6185 sc := natsConnect(t, s.ClientURL(), createUserCreds(t, s, skp)) 6186 defer sc.Close() 6187 // Pass claims update with headers. 6188 msg := &nats.Msg{ 6189 Subject: "$SYS.REQ.CLAIMS.UPDATE", 6190 Data: []byte(jwtClaim), 6191 Header: map[string][]string{"key": {"value"}}, 6192 } 6193 resp, err := sc.RequestMsg(msg, time.Second) 6194 if err != nil { 6195 t.Fatalf("Unexpected error: %v", err) 6196 } 6197 var cz zapi 6198 if err := json.Unmarshal(resp.Data, &cz); err != nil { 6199 t.Fatalf("Unexpected error: %v", err) 6200 } 6201 if cz.Error != nil { 6202 t.Fatalf("Unexpected error: %+v", cz.Error) 6203 } 6204 } 6205 6206 func TestJWTMappings(t *testing.T) { 6207 sysKp, syspub := createKey(t) 6208 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 6209 sysCreds := newUser(t, sysKp) 6210 6211 // create two jwt, one with and one without mapping 6212 aKp, aPub := createKey(t) 6213 aClaim := jwt.NewAccountClaims(aPub) 6214 aJwtNoM := encodeClaim(t, aClaim, aPub) 6215 aClaim.AddMapping("foo1", jwt.WeightedMapping{Subject: "bar1"}) 6216 aJwtMap1 := encodeClaim(t, aClaim, aPub) 6217 6218 aClaim.Mappings = map[jwt.Subject][]jwt.WeightedMapping{} 6219 aClaim.AddMapping("foo2", jwt.WeightedMapping{Subject: "bar2"}) 6220 aJwtMap2 := encodeClaim(t, aClaim, aPub) 6221 6222 dirSrv := t.TempDir() 6223 conf := createConfFile(t, []byte(fmt.Sprintf(` 6224 listen: 127.0.0.1:-1 6225 operator: %s 6226 system_account: %s 6227 resolver: { 6228 type: full 6229 dir: '%s' 6230 } 6231 `, ojwt, syspub, dirSrv))) 6232 srv, _ := RunServerWithConfig(conf) 6233 defer srv.Shutdown() 6234 updateJwt(t, srv.ClientURL(), sysCreds, sysJwt, 1) // update system account jwt 6235 6236 test := func(pub, sub string, fail bool) { 6237 t.Helper() 6238 nc := natsConnect(t, srv.ClientURL(), createUserCreds(t, srv, aKp)) 6239 defer nc.Close() 6240 s, err := nc.SubscribeSync(sub) 6241 require_NoError(t, err) 6242 nc.Flush() 6243 err = nc.Publish(pub, nil) 6244 require_NoError(t, err) 6245 _, err = s.NextMsg(500 * time.Millisecond) 6246 switch { 6247 case fail && err == nil: 6248 t.Fatal("expected error, got none") 6249 case !fail && err != nil: 6250 t.Fatalf("expected no error, got %v", err) 6251 } 6252 } 6253 6254 // turn mappings on 6255 require_Len(t, 1, updateJwt(t, srv.ClientURL(), sysCreds, aJwtMap1, 1)) 6256 test("foo1", "bar1", false) 6257 // alter mappings 6258 require_Len(t, 1, updateJwt(t, srv.ClientURL(), sysCreds, aJwtMap2, 1)) 6259 test("foo1", "bar1", true) 6260 test("foo2", "bar2", false) 6261 // turn mappings off 6262 require_Len(t, 1, updateJwt(t, srv.ClientURL(), sysCreds, aJwtNoM, 1)) 6263 test("foo2", "bar2", true) 6264 } 6265 6266 func TestJWTOperatorPinnedAccounts(t *testing.T) { 6267 kps, pubs, jwts := [4]nkeys.KeyPair{}, [4]string{}, [4]string{} 6268 for i := 0; i < 4; i++ { 6269 kps[i], pubs[i] = createKey(t) 6270 jwts[i] = encodeClaim(t, jwt.NewAccountClaims(pubs[i]), pubs[i]) 6271 } 6272 // create system account user credentials, index 0 is handled as system account 6273 newUser(t, kps[0]) 6274 6275 cfgCommon := fmt.Sprintf(` 6276 listen: 127.0.0.1:-1 6277 operator: %s 6278 system_account: %s 6279 resolver: MEM 6280 resolver_preload: { 6281 %s:%s 6282 %s:%s 6283 %s:%s 6284 %s:%s 6285 }`, ojwt, pubs[0], pubs[0], jwts[0], pubs[1], jwts[1], pubs[2], jwts[2], pubs[3], jwts[3]) 6286 cfgFmt := cfgCommon + ` 6287 resolver_pinned_accounts: [%s, %s] 6288 ` 6289 conf := createConfFile(t, []byte(fmt.Sprintf(cfgFmt, pubs[1], pubs[2]))) 6290 srv, _ := RunServerWithConfig(conf) 6291 defer srv.Shutdown() 6292 6293 connectPass := func(keys ...nkeys.KeyPair) { 6294 for _, kp := range keys { 6295 nc, err := nats.Connect(srv.ClientURL(), createUserCreds(t, srv, kp)) 6296 require_NoError(t, err) 6297 defer nc.Close() 6298 } 6299 } 6300 var pinnedFail uint64 6301 connectFail := func(key nkeys.KeyPair) { 6302 _, err := nats.Connect(srv.ClientURL(), createUserCreds(t, srv, key)) 6303 require_Error(t, err) 6304 require_Contains(t, err.Error(), "Authorization Violation") 6305 v, err := srv.Varz(&VarzOptions{}) 6306 require_NoError(t, err) 6307 require_True(t, pinnedFail+1 == v.PinnedAccountFail) 6308 pinnedFail = v.PinnedAccountFail 6309 } 6310 6311 connectPass(kps[0], kps[1], kps[2]) // make sure user from accounts listed and system account (index 0) work 6312 connectFail(kps[3]) // make sure the other user does not work 6313 // reload and test again 6314 reloadUpdateConfig(t, srv, conf, fmt.Sprintf(cfgFmt, pubs[2], pubs[3])) 6315 connectPass(kps[0], kps[2], kps[3]) // make sure user from accounts listed and system account (index 0) work 6316 connectFail(kps[1]) // make sure the other user does not work 6317 // completely disable and test again 6318 reloadUpdateConfig(t, srv, conf, cfgCommon) 6319 connectPass(kps[0], kps[1], kps[2], kps[3]) // make sure every account and system account (index 0) can connect 6320 // re-enable and test again 6321 reloadUpdateConfig(t, srv, conf, fmt.Sprintf(cfgFmt, pubs[2], pubs[3])) 6322 connectPass(kps[0], kps[2], kps[3]) // make sure user from accounts listed and system account (index 0) work 6323 connectFail(kps[1]) // make sure the other user does not work 6324 } 6325 6326 func TestJWTNoSystemAccountButNatsResolver(t *testing.T) { 6327 dirSrv := t.TempDir() 6328 for _, resType := range []string{"full", "cache"} { 6329 t.Run(resType, func(t *testing.T) { 6330 conf := createConfFile(t, []byte(fmt.Sprintf(` 6331 listen: 127.0.0.1:-1 6332 operator: %s 6333 resolver: { 6334 type: %s 6335 dir: '%s' 6336 }`, ojwt, resType, dirSrv))) 6337 opts := LoadConfig(conf) 6338 s, err := NewServer(opts) 6339 // Since the server cannot be stopped, since it did not start, 6340 // let's manually close the account resolver to avoid leaking go routines. 6341 opts.AccountResolver.Close() 6342 s.Shutdown() 6343 require_Error(t, err) 6344 require_Contains(t, err.Error(), "the system account needs to be specified in configuration or the operator jwt") 6345 }) 6346 } 6347 } 6348 6349 func TestJWTAccountConnzAccessAfterClaimUpdate(t *testing.T) { 6350 skp, spub := createKey(t) 6351 newUser(t, skp) 6352 6353 sclaim := jwt.NewAccountClaims(spub) 6354 sclaim.AddMapping("foo.bar", jwt.WeightedMapping{Subject: "foo.baz"}) 6355 sjwt := encodeClaim(t, sclaim, spub) 6356 6357 // create two jwt, one with and one without mapping 6358 akp, apub := createKey(t) 6359 newUser(t, akp) 6360 claim := jwt.NewAccountClaims(apub) 6361 jwt1 := encodeClaim(t, claim, apub) 6362 claim.AddMapping("foo.bar", jwt.WeightedMapping{Subject: "foo.baz"}) 6363 jwt2 := encodeClaim(t, claim, apub) 6364 6365 dirSrv := t.TempDir() 6366 6367 conf := createConfFile(t, []byte(fmt.Sprintf(` 6368 listen: 127.0.0.1:-1 6369 operator: %s 6370 system_account: %s 6371 resolver: { 6372 type: full 6373 dir: '%s' 6374 } 6375 `, ojwt, spub, dirSrv))) 6376 6377 s, _ := RunServerWithConfig(conf) 6378 defer s.Shutdown() 6379 6380 type zapi struct { 6381 Server *ServerInfo 6382 Data *Connz 6383 Error *ApiError 6384 } 6385 6386 updateJWT := func(jwt string) { 6387 t.Helper() 6388 sc := natsConnect(t, s.ClientURL(), createUserCreds(t, s, skp)) 6389 defer sc.Close() 6390 resp, err := sc.Request("$SYS.REQ.CLAIMS.UPDATE", []byte(jwt), time.Second) 6391 if err != nil { 6392 t.Fatalf("Unexpected error: %v", err) 6393 } 6394 var cz zapi 6395 if err := json.Unmarshal(resp.Data, &cz); err != nil { 6396 t.Fatalf("Unexpected error: %v", err) 6397 } 6398 if cz.Error != nil { 6399 t.Fatalf("Unexpected error: %+v", cz.Error) 6400 } 6401 } 6402 6403 updateJWT(jwt1) 6404 6405 nc := natsConnect(t, s.ClientURL(), createUserCreds(t, s, akp)) 6406 defer nc.Close() 6407 6408 doRequest := func() { 6409 t.Helper() 6410 resp, err := nc.Request("$SYS.REQ.SERVER.PING.CONNZ", nil, time.Second) 6411 if err != nil { 6412 t.Fatalf("Unexpected error: %v", err) 6413 } 6414 var cz zapi 6415 if err := json.Unmarshal(resp.Data, &cz); err != nil { 6416 t.Fatalf("Unexpected error: %v", err) 6417 } 6418 if cz.Error != nil { 6419 t.Fatalf("Unexpected error: %+v", cz.Error) 6420 } 6421 } 6422 6423 doRequest() 6424 updateJWT(jwt2) 6425 // If we accidentally wipe the system import this will fail with no responders. 6426 doRequest() 6427 // Now test updating system account. 6428 updateJWT(sjwt) 6429 // If export was wiped this would fail with timeout. 6430 doRequest() 6431 } 6432 6433 func TestAccountWeightedMappingInSuperCluster(t *testing.T) { 6434 skp, spub := createKey(t) 6435 sysClaim := jwt.NewAccountClaims(spub) 6436 sysClaim.Name = "SYS" 6437 sysCreds := newUser(t, skp) 6438 6439 akp, apub := createKey(t) 6440 aUsr := createUserCreds(t, nil, akp) 6441 claim := jwt.NewAccountClaims(apub) 6442 aJwtMap := encodeClaim(t, claim, apub) 6443 6444 // We are using the createJetStreamSuperClusterWithTemplateAndModHook() 6445 // helper, but this test is not about JetStream... 6446 tmpl := ` 6447 listen: 127.0.0.1:-1 6448 server_name: %s 6449 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 6450 cluster { 6451 name: %s 6452 listen: 127.0.0.1:%d 6453 routes = [%s] 6454 } 6455 ` 6456 6457 sc := createJetStreamSuperClusterWithTemplateAndModHook(t, tmpl, 3, 3, 6458 func(serverName, clusterName, storeDir, conf string) string { 6459 dirSrv := t.TempDir() 6460 return fmt.Sprintf(`%s 6461 operator: %s 6462 system_account: %s 6463 resolver: { 6464 type: full 6465 dir: '%s' 6466 } 6467 `, conf, ojwt, spub, dirSrv) 6468 }, nil) 6469 defer sc.shutdown() 6470 6471 // Update from C2 6472 require_Len(t, 1, updateJwt(t, sc.clusterForName("C2").randomServer().ClientURL(), sysCreds, aJwtMap, 1)) 6473 6474 // We will connect our services in the C3 cluster. 6475 nc1 := natsConnect(t, sc.clusterForName("C3").randomServer().ClientURL(), aUsr) 6476 defer nc1.Close() 6477 nc2 := natsConnect(t, sc.clusterForName("C3").randomServer().ClientURL(), aUsr) 6478 defer nc2.Close() 6479 6480 natsSub(t, nc1, "foo", func(m *nats.Msg) { 6481 m.Respond([]byte("foo")) 6482 }) 6483 natsSub(t, nc1, "bar.v1", func(m *nats.Msg) { 6484 m.Respond([]byte("v1")) 6485 }) 6486 natsSub(t, nc2, "bar.v2", func(m *nats.Msg) { 6487 m.Respond([]byte("v2")) 6488 }) 6489 natsFlush(t, nc1) 6490 natsFlush(t, nc2) 6491 6492 // Now we will update the account to add weighted subject mapping 6493 claim.Mappings = map[jwt.Subject][]jwt.WeightedMapping{} 6494 // Start with foo->bar.v2 at 40%, the server will auto-add foo->foo at 60%. 6495 wm := []jwt.WeightedMapping{{Subject: "bar.v2", Weight: 40}} 6496 claim.AddMapping("foo", wm...) 6497 aJwtMap = encodeClaim(t, claim, apub) 6498 6499 // We will update from C2 6500 require_Len(t, 1, updateJwt(t, sc.clusterForName("C2").randomServer().ClientURL(), sysCreds, aJwtMap, 1)) 6501 6502 time.Sleep(time.Second) 6503 6504 // And we will publish from C1 6505 nc := natsConnect(t, sc.clusterForName("C1").randomServer().ClientURL(), aUsr) 6506 defer nc.Close() 6507 6508 var foo, v1, v2 int 6509 pubAndCount := func() { 6510 for i := 0; i < 1000; i++ { 6511 msg, err := nc.Request("foo", []byte("req"), 500*time.Millisecond) 6512 if err != nil { 6513 continue 6514 } 6515 switch string(msg.Data) { 6516 case "foo": 6517 foo++ 6518 case "v1": 6519 v1++ 6520 case "v2": 6521 v2++ 6522 } 6523 } 6524 } 6525 pubAndCount() 6526 if foo < 550 || foo > 650 { 6527 t.Fatalf("Expected foo to receive 60%%, got %v/1000", foo) 6528 } 6529 if v1 != 0 { 6530 t.Fatalf("Expected v1 to receive no message, got %v/1000", v1) 6531 } 6532 if v2 < 350 || v2 > 450 { 6533 t.Fatalf("Expected v2 to receive 40%%, got %v/1000", v2) 6534 } 6535 6536 // Now send a new update with foo-> bar.v2(40) and bar.v1(60). 6537 // The auto-add of "foo" should no longer be used by the server. 6538 wm = []jwt.WeightedMapping{ 6539 {Subject: "bar.v2", Weight: 40}, 6540 {Subject: "bar.v1", Weight: 60}, 6541 } 6542 claim.AddMapping("foo", wm...) 6543 aJwtMap = encodeClaim(t, claim, apub) 6544 6545 // We will update from C2 6546 require_Len(t, 1, updateJwt(t, sc.clusterForName("C2").randomServer().ClientURL(), sysCreds, aJwtMap, 1)) 6547 6548 time.Sleep(time.Second) 6549 6550 foo, v1, v2 = 0, 0, 0 6551 pubAndCount() 6552 if foo != 0 { 6553 t.Fatalf("Expected foo to receive no message, got %v/1000", foo) 6554 } 6555 if v1 < 550 || v1 > 650 { 6556 t.Fatalf("Expected v1 to receive 60%%, got %v/1000", v1) 6557 } 6558 if v2 < 350 || v2 > 450 { 6559 t.Fatalf("Expected v2 to receive 40%%, got %v/1000", v2) 6560 } 6561 } 6562 6563 func TestServerOperatorModeNoAuthRequired(t *testing.T) { 6564 _, spub := createKey(t) 6565 sysClaim := jwt.NewAccountClaims(spub) 6566 sysClaim.Name = "$SYS" 6567 sysJwt, err := sysClaim.Encode(oKp) 6568 require_NoError(t, err) 6569 6570 akp, apub := createKey(t) 6571 accClaim := jwt.NewAccountClaims(apub) 6572 accClaim.Name = "TEST" 6573 accJwt, err := accClaim.Encode(oKp) 6574 require_NoError(t, err) 6575 6576 ukp, _ := nkeys.CreateUser() 6577 seed, _ := ukp.Seed() 6578 upub, _ := ukp.PublicKey() 6579 nuc := jwt.NewUserClaims(upub) 6580 ujwt, err := nuc.Encode(akp) 6581 require_NoError(t, err) 6582 creds := genCredsFile(t, ujwt, seed) 6583 6584 dirSrv := t.TempDir() 6585 6586 conf := createConfFile(t, []byte(fmt.Sprintf(` 6587 listen: 127.0.0.1:-1 6588 server_name: srv-A 6589 operator: %s 6590 system_account: %s 6591 resolver: { 6592 type: full 6593 dir: '%s' 6594 interval: "200ms" 6595 limit: 4 6596 } 6597 resolver_preload: { 6598 %s: %s 6599 %s: %s 6600 } 6601 `, ojwt, spub, dirSrv, spub, sysJwt, apub, accJwt))) 6602 6603 s, _ := RunServerWithConfig(conf) 6604 defer s.Shutdown() 6605 6606 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(creds)) 6607 defer nc.Close() 6608 6609 require_True(t, nc.AuthRequired()) 6610 } 6611 6612 func TestServerOperatorModeUserInfoExpiration(t *testing.T) { 6613 _, spub := createKey(t) 6614 sysClaim := jwt.NewAccountClaims(spub) 6615 sysClaim.Name = "$SYS" 6616 sysJwt, err := sysClaim.Encode(oKp) 6617 require_NoError(t, err) 6618 6619 akp, apub := createKey(t) 6620 accClaim := jwt.NewAccountClaims(apub) 6621 accClaim.Name = "TEST" 6622 accJwt, err := accClaim.Encode(oKp) 6623 require_NoError(t, err) 6624 6625 conf := createConfFile(t, []byte(fmt.Sprintf(` 6626 listen: 127.0.0.1:-1 6627 operator: %s 6628 system_account: %s 6629 resolver: MEM 6630 resolver_preload: { 6631 %s: %s 6632 %s: %s 6633 } 6634 `, ojwt, spub, apub, accJwt, spub, sysJwt))) 6635 defer removeFile(t, conf) 6636 6637 s, _ := RunServerWithConfig(conf) 6638 defer s.Shutdown() 6639 6640 expires := time.Now().Add(time.Minute) 6641 creds := createUserWithLimit(t, akp, expires, func(j *jwt.UserPermissionLimits) {}) 6642 6643 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(creds)) 6644 defer nc.Close() 6645 6646 resp, err := nc.Request("$SYS.REQ.USER.INFO", nil, time.Second) 6647 require_NoError(t, err) 6648 now := time.Now() 6649 6650 response := ServerAPIResponse{Data: &UserInfo{}} 6651 err = json.Unmarshal(resp.Data, &response) 6652 require_NoError(t, err) 6653 6654 userInfo := response.Data.(*UserInfo) 6655 require_True(t, userInfo.Expires != 0) 6656 6657 // We need to round the expiration time to the second because the server 6658 // will truncate the expiration time to the second. 6659 expiresDurRounded := expires.Sub(now).Truncate(time.Second) 6660 6661 // Checking range to avoid flaky tests where the expiration time is 6662 // off by a couple of seconds. 6663 require_True(t, expiresDurRounded >= userInfo.Expires-2*time.Second && expiresDurRounded <= userInfo.Expires+2*time.Second) 6664 } 6665 6666 func TestJWTAccountNATSResolverWrongCreds(t *testing.T) { 6667 require_NoLocalOrRemoteConnections := func(account string, srvs ...*Server) { 6668 t.Helper() 6669 for _, srv := range srvs { 6670 if acc, ok := srv.accounts.Load(account); ok { 6671 checkAccClientsCount(t, acc.(*Account), 0) 6672 } 6673 } 6674 } 6675 connect := func(url string, credsfile string, acc string, srvs ...*Server) { 6676 t.Helper() 6677 nc := natsConnect(t, url, nats.UserCredentials(credsfile), nats.Timeout(5*time.Second)) 6678 nc.Close() 6679 require_NoLocalOrRemoteConnections(acc, srvs...) 6680 } 6681 createAccountAndUser := func(limit bool, done chan struct{}, pubKey, jwt1, jwt2, creds *string) { 6682 t.Helper() 6683 kp, _ := nkeys.CreateAccount() 6684 *pubKey, _ = kp.PublicKey() 6685 claim := jwt.NewAccountClaims(*pubKey) 6686 var err error 6687 *jwt1, err = claim.Encode(oKp) 6688 require_NoError(t, err) 6689 *jwt2, err = claim.Encode(oKp) 6690 require_NoError(t, err) 6691 ukp, _ := nkeys.CreateUser() 6692 seed, _ := ukp.Seed() 6693 upub, _ := ukp.PublicKey() 6694 uclaim := newJWTTestUserClaims() 6695 uclaim.Subject = upub 6696 ujwt, err := uclaim.Encode(kp) 6697 require_NoError(t, err) 6698 *creds = genCredsFile(t, ujwt, seed) 6699 done <- struct{}{} 6700 } 6701 // Create Accounts and corresponding user creds. 6702 doneChan := make(chan struct{}, 4) 6703 defer close(doneChan) 6704 var syspub, sysjwt, dummy1, sysCreds string 6705 createAccountAndUser(false, doneChan, &syspub, &sysjwt, &dummy1, &sysCreds) 6706 6707 var apub, ajwt1, ajwt2, aCreds string 6708 createAccountAndUser(true, doneChan, &apub, &ajwt1, &ajwt2, &aCreds) 6709 6710 var bpub, bjwt1, bjwt2, bCreds string 6711 createAccountAndUser(true, doneChan, &bpub, &bjwt1, &bjwt2, &bCreds) 6712 6713 // The one that is going to be missing. 6714 var cpub, cjwt1, cjwt2, cCreds string 6715 createAccountAndUser(true, doneChan, &cpub, &cjwt1, &cjwt2, &cCreds) 6716 for i := 0; i < cap(doneChan); i++ { 6717 <-doneChan 6718 } 6719 // Create one directory for each server 6720 dirA := t.TempDir() 6721 dirB := t.TempDir() 6722 dirC := t.TempDir() 6723 6724 // Store accounts on servers A and B, then let C sync on its own. 6725 writeJWT(t, dirA, apub, ajwt1) 6726 writeJWT(t, dirB, bpub, bjwt1) 6727 6728 ///////////////////////////////////////// 6729 // // 6730 // Server A: has creds from client A // 6731 // // 6732 ///////////////////////////////////////// 6733 confA := createConfFile(t, []byte(fmt.Sprintf(` 6734 listen: 127.0.0.1:-1 6735 server_name: srv-A 6736 operator: %s 6737 system_account: %s 6738 debug: true 6739 resolver: { 6740 type: full 6741 dir: '%s' 6742 allow_delete: true 6743 timeout: "1.5s" 6744 interval: "200ms" 6745 } 6746 resolver_preload: { 6747 %s: %s 6748 } 6749 cluster { 6750 name: clust 6751 listen: 127.0.0.1:-1 6752 no_advertise: true 6753 } 6754 `, ojwt, syspub, dirA, apub, ajwt1))) 6755 sA, _ := RunServerWithConfig(confA) 6756 defer sA.Shutdown() 6757 require_JWTPresent(t, dirA, apub) 6758 6759 ///////////////////////////////////////// 6760 // // 6761 // Server B: has creds from client B // 6762 // // 6763 ///////////////////////////////////////// 6764 confB := createConfFile(t, []byte(fmt.Sprintf(` 6765 listen: 127.0.0.1:-1 6766 server_name: srv-B 6767 operator: %s 6768 system_account: %s 6769 resolver: { 6770 type: full 6771 dir: '%s' 6772 allow_delete: true 6773 timeout: "1.5s" 6774 interval: "200ms" 6775 } 6776 cluster { 6777 name: clust 6778 listen: 127.0.0.1:-1 6779 no_advertise: true 6780 routes [ 6781 nats-route://127.0.0.1:%d 6782 ] 6783 } 6784 `, ojwt, syspub, dirB, sA.opts.Cluster.Port))) 6785 sB, _ := RunServerWithConfig(confB) 6786 defer sB.Shutdown() 6787 6788 ///////////////////////////////////////// 6789 // // 6790 // Server C: has no creds // 6791 // // 6792 ///////////////////////////////////////// 6793 fmtC := ` 6794 listen: 127.0.0.1:-1 6795 server_name: srv-C 6796 operator: %s 6797 system_account: %s 6798 resolver: { 6799 type: full 6800 dir: '%s' 6801 allow_delete: true 6802 timeout: "1.5s" 6803 interval: "200ms" 6804 } 6805 cluster { 6806 name: clust 6807 listen: 127.0.0.1:-1 6808 no_advertise: true 6809 routes [ 6810 nats-route://127.0.0.1:%d 6811 ] 6812 } 6813 ` 6814 confClongTTL := createConfFile(t, []byte(fmt.Sprintf(fmtC, ojwt, syspub, dirC, sA.opts.Cluster.Port))) 6815 sC, _ := RunServerWithConfig(confClongTTL) // use long ttl to assure it is not kicking 6816 defer sC.Shutdown() 6817 6818 // startup cluster 6819 checkClusterFormed(t, sA, sB, sC) 6820 time.Sleep(1 * time.Second) // wait for the protocol to converge 6821 // // Check all accounts 6822 require_JWTPresent(t, dirA, apub) // was already present on startup 6823 require_JWTPresent(t, dirB, apub) // was copied from server A 6824 require_JWTPresent(t, dirA, bpub) // was copied from server B 6825 require_JWTPresent(t, dirB, bpub) // was already present on startup 6826 6827 // There should be no state about the missing account. 6828 require_JWTAbsent(t, dirA, cpub) 6829 require_JWTAbsent(t, dirB, cpub) 6830 require_JWTAbsent(t, dirC, cpub) 6831 6832 // system account client can connect to every server 6833 connect(sA.ClientURL(), sysCreds, "") 6834 connect(sB.ClientURL(), sysCreds, "") 6835 connect(sC.ClientURL(), sysCreds, "") 6836 6837 // A and B clients can connect to any server. 6838 connect(sA.ClientURL(), aCreds, "") 6839 connect(sB.ClientURL(), aCreds, "") 6840 connect(sC.ClientURL(), aCreds, "") 6841 connect(sA.ClientURL(), bCreds, "") 6842 connect(sB.ClientURL(), bCreds, "") 6843 connect(sC.ClientURL(), bCreds, "") 6844 6845 // Check that trying to connect with bad credentials should not hang until the fetch timeout 6846 // and instead return a faster response when an account is not found. 6847 _, err := nats.Connect(sC.ClientURL(), nats.UserCredentials(cCreds), nats.Timeout(500*time.Second)) 6848 if err != nil && !errors.Is(err, nats.ErrAuthorization) { 6849 t.Fatalf("Expected auth error: %v", err) 6850 } 6851 }