github.com/nats-io/nats-server/v2@v2.11.0-preview.2/server/events_test.go (about) 1 // Copyright 2018-2023 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 "bytes" 18 "crypto/sha256" 19 "encoding/json" 20 "errors" 21 "fmt" 22 "math/rand" 23 "net/http" 24 "net/http/httptest" 25 "os" 26 "reflect" 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 "github.com/nats-io/nuid" 37 ) 38 39 func createAccount(s *Server) (*Account, nkeys.KeyPair) { 40 okp, _ := nkeys.FromSeed(oSeed) 41 akp, _ := nkeys.CreateAccount() 42 pub, _ := akp.PublicKey() 43 nac := jwt.NewAccountClaims(pub) 44 jwt, _ := nac.Encode(okp) 45 addAccountToMemResolver(s, pub, jwt) 46 acc, err := s.LookupAccount(pub) 47 if err != nil { 48 panic(err) 49 } 50 return acc, akp 51 } 52 53 func createUserCredsEx(t *testing.T, nuc *jwt.UserClaims, akp nkeys.KeyPair) nats.Option { 54 t.Helper() 55 kp, _ := nkeys.CreateUser() 56 nuc.Subject, _ = kp.PublicKey() 57 ujwt, err := nuc.Encode(akp) 58 if err != nil { 59 t.Fatalf("Error generating user JWT: %v", err) 60 } 61 userCB := func() (string, error) { 62 return ujwt, nil 63 } 64 sigCB := func(nonce []byte) ([]byte, error) { 65 sig, _ := kp.Sign(nonce) 66 return sig, nil 67 } 68 return nats.UserJWT(userCB, sigCB) 69 } 70 71 func createUserCreds(t *testing.T, _ *Server, akp nkeys.KeyPair) nats.Option { 72 return createUserCredsEx(t, jwt.NewUserClaims("test"), akp) 73 } 74 75 func runTrustedServer(t *testing.T) (*Server, *Options) { 76 t.Helper() 77 opts := DefaultOptions() 78 kp, _ := nkeys.FromSeed(oSeed) 79 pub, _ := kp.PublicKey() 80 opts.TrustedKeys = []string{pub} 81 opts.AccountResolver = &MemAccResolver{} 82 s := RunServer(opts) 83 return s, opts 84 } 85 86 func runTrustedCluster(t *testing.T) (*Server, *Options, *Server, *Options, nkeys.KeyPair) { 87 t.Helper() 88 89 kp, _ := nkeys.FromSeed(oSeed) 90 pub, _ := kp.PublicKey() 91 92 mr := &MemAccResolver{} 93 94 // Now create a system account. 95 // NOTE: This can NOT be shared directly between servers. 96 // Set via server options. 97 okp, _ := nkeys.FromSeed(oSeed) 98 akp, _ := nkeys.CreateAccount() 99 apub, _ := akp.PublicKey() 100 nac := jwt.NewAccountClaims(apub) 101 jwt, _ := nac.Encode(okp) 102 103 mr.Store(apub, jwt) 104 105 optsA := DefaultOptions() 106 optsA.Cluster.Name = "TEST CLUSTER 22" 107 optsA.Cluster.Host = "127.0.0.1" 108 optsA.TrustedKeys = []string{pub} 109 optsA.AccountResolver = mr 110 optsA.SystemAccount = apub 111 optsA.ServerName = "A_SRV" 112 // Add in dummy gateway 113 optsA.Gateway.Name = "TEST CLUSTER 22" 114 optsA.Gateway.Host = "127.0.0.1" 115 optsA.Gateway.Port = -1 116 optsA.gatewaysSolicitDelay = 30 * time.Second 117 118 sa := RunServer(optsA) 119 120 optsB := nextServerOpts(optsA) 121 optsB.ServerName = "B_SRV" 122 optsB.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", optsA.Cluster.Host, optsA.Cluster.Port)) 123 sb := RunServer(optsB) 124 125 checkClusterFormed(t, sa, sb) 126 127 return sa, optsA, sb, optsB, akp 128 } 129 130 func runTrustedGateways(t *testing.T) (*Server, *Options, *Server, *Options, nkeys.KeyPair) { 131 t.Helper() 132 133 kp, _ := nkeys.FromSeed(oSeed) 134 pub, _ := kp.PublicKey() 135 136 mr := &MemAccResolver{} 137 138 // Now create a system account. 139 // NOTE: This can NOT be shared directly between servers. 140 // Set via server options. 141 okp, _ := nkeys.FromSeed(oSeed) 142 akp, _ := nkeys.CreateAccount() 143 apub, _ := akp.PublicKey() 144 nac := jwt.NewAccountClaims(apub) 145 jwt, _ := nac.Encode(okp) 146 147 mr.Store(apub, jwt) 148 149 optsA := testDefaultOptionsForGateway("A") 150 optsA.Cluster.Name = "A" 151 optsA.Cluster.Host = "127.0.0.1" 152 optsA.TrustedKeys = []string{pub} 153 optsA.AccountResolver = mr 154 optsA.SystemAccount = apub 155 156 sa := RunServer(optsA) 157 158 optsB := testGatewayOptionsFromToWithServers(t, "B", "A", sa) 159 optsB.Cluster.Name = "B" 160 optsB.TrustedKeys = []string{pub} 161 optsB.AccountResolver = mr 162 optsB.SystemAccount = apub 163 164 sb := RunServer(optsB) 165 166 waitForInboundGateways(t, sa, 1, time.Second) 167 waitForOutboundGateways(t, sa, 1, time.Second) 168 waitForInboundGateways(t, sb, 1, time.Second) 169 waitForOutboundGateways(t, sb, 1, time.Second) 170 171 return sa, optsA, sb, optsB, akp 172 } 173 174 func TestSystemAccount(t *testing.T) { 175 s, _ := runTrustedServer(t) 176 defer s.Shutdown() 177 178 acc, _ := createAccount(s) 179 s.setSystemAccount(acc) 180 181 s.mu.Lock() 182 defer s.mu.Unlock() 183 184 if s.sys == nil || s.sys.account == nil { 185 t.Fatalf("Expected sys.account to be non-nil") 186 } 187 if s.sys.client == nil { 188 t.Fatalf("Expected sys.client to be non-nil") 189 } 190 191 s.sys.client.mu.Lock() 192 defer s.sys.client.mu.Unlock() 193 if s.sys.client.echo { 194 t.Fatalf("Internal clients should always have echo false") 195 } 196 } 197 198 func TestSystemAccountNewConnection(t *testing.T) { 199 s, opts := runTrustedServer(t) 200 defer s.Shutdown() 201 202 acc, akp := createAccount(s) 203 s.setSystemAccount(acc) 204 205 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 206 ncs, err := nats.Connect(url, createUserCreds(t, s, akp)) 207 if err != nil { 208 t.Fatalf("Error on connect: %v", err) 209 } 210 defer ncs.Close() 211 212 // We may not be able to hear ourselves (if the event is processed 213 // before we create the sub), so we need to create a second client to 214 // trigger the connect/disconnect events. 215 acc2, akp2 := createAccount(s) 216 217 // Be explicit to only receive the event for acc2. 218 sub, _ := ncs.SubscribeSync(fmt.Sprintf("$SYS.ACCOUNT.%s.>", acc2.Name)) 219 defer sub.Unsubscribe() 220 ncs.Flush() 221 222 nc, err := nats.Connect(url, createUserCreds(t, s, akp2), nats.Name("TEST EVENTS")) 223 if err != nil { 224 t.Fatalf("Error on connect: %v", err) 225 } 226 defer nc.Close() 227 228 msg, err := sub.NextMsg(time.Second) 229 if err != nil { 230 t.Fatalf("Error receiving msg: %v", err) 231 } 232 connsMsg, err := sub.NextMsg(time.Second) 233 if err != nil { 234 t.Fatalf("Error receiving msg: %v", err) 235 } 236 if strings.HasPrefix(msg.Subject, fmt.Sprintf("$SYS.ACCOUNT.%s.SERVER.CONNS", acc2.Name)) { 237 msg, connsMsg = connsMsg, msg 238 } 239 if !strings.HasPrefix(connsMsg.Subject, fmt.Sprintf("$SYS.ACCOUNT.%s.SERVER.CONNS", acc2.Name)) { 240 t.Fatalf("Expected subject to start with %q, got %q", "$SYS.ACCOUNT.<account>.CONNECT", msg.Subject) 241 } 242 conns := AccountNumConns{} 243 if err := json.Unmarshal(connsMsg.Data, &conns); err != nil { 244 t.Fatalf("Error unmarshalling conns event message: %v", err) 245 } else if conns.Account != acc2.Name { 246 t.Fatalf("Wrong account in conns message: %v", conns) 247 } else if conns.Conns != 1 || conns.TotalConns != 1 || conns.LeafNodes != 0 { 248 t.Fatalf("Wrong counts in conns message: %v", conns) 249 } 250 if !strings.HasPrefix(msg.Subject, fmt.Sprintf("$SYS.ACCOUNT.%s.CONNECT", acc2.Name)) { 251 t.Fatalf("Expected subject to start with %q, got %q", "$SYS.ACCOUNT.<account>.CONNECT", msg.Subject) 252 } 253 tokens := strings.Split(msg.Subject, ".") 254 if len(tokens) < 4 { 255 t.Fatalf("Expected 4 tokens, got %d", len(tokens)) 256 } 257 account := tokens[2] 258 if account != acc2.Name { 259 t.Fatalf("Expected %q for account, got %q", acc2.Name, account) 260 } 261 262 cem := ConnectEventMsg{} 263 if err := json.Unmarshal(msg.Data, &cem); err != nil { 264 t.Fatalf("Error unmarshalling connect event message: %v", err) 265 } 266 if cem.Type != ConnectEventMsgType { 267 t.Fatalf("Incorrect schema in connect event: %s", cem.Type) 268 } 269 if cem.Time.IsZero() { 270 t.Fatalf("Event time is not set") 271 } 272 if len(cem.ID) != 22 { 273 t.Fatalf("Event ID is incorrectly set to len %d", len(cem.ID)) 274 } 275 if cem.Server.ID != s.ID() { 276 t.Fatalf("Expected server to be %q, got %q", s.ID(), cem.Server.ID) 277 } 278 if cem.Server.Seq == 0 { 279 t.Fatalf("Expected sequence to be non-zero") 280 } 281 if cem.Client.Name != "TEST EVENTS" { 282 t.Fatalf("Expected client name to be %q, got %q", "TEST EVENTS", cem.Client.Name) 283 } 284 if cem.Client.Lang != "go" { 285 t.Fatalf("Expected client lang to be \"go\", got %q", cem.Client.Lang) 286 } 287 288 // Now close the other client. Should fire a disconnect event. 289 // First send and receive some messages. 290 sub2, _ := nc.SubscribeSync("foo") 291 defer sub2.Unsubscribe() 292 sub3, _ := nc.SubscribeSync("*") 293 defer sub3.Unsubscribe() 294 295 for i := 0; i < 10; i++ { 296 nc.Publish("foo", []byte("HELLO WORLD")) 297 } 298 nc.Flush() 299 nc.Close() 300 301 msg, err = sub.NextMsg(time.Second) 302 if err != nil { 303 t.Fatalf("Error receiving msg: %v", err) 304 } 305 connsMsg, err = sub.NextMsg(time.Second) 306 if err != nil { 307 t.Fatalf("Error receiving msg: %v", err) 308 } 309 if strings.HasPrefix(msg.Subject, fmt.Sprintf("$SYS.ACCOUNT.%s.SERVER.CONNS", acc2.Name)) { 310 msg, connsMsg = connsMsg, msg 311 } 312 if !strings.HasPrefix(connsMsg.Subject, fmt.Sprintf("$SYS.ACCOUNT.%s.SERVER.CONNS", acc2.Name)) { 313 t.Fatalf("Expected subject to start with %q, got %q", "$SYS.ACCOUNT.<account>.CONNECT", msg.Subject) 314 } else if !strings.Contains(string(connsMsg.Data), `"total_conns":0`) { 315 t.Fatalf("Expected event to reflect created connection, got: %s", string(connsMsg.Data)) 316 } 317 conns = AccountNumConns{} 318 if err := json.Unmarshal(connsMsg.Data, &conns); err != nil { 319 t.Fatalf("Error unmarshalling conns event message: %v", err) 320 } else if conns.Account != acc2.Name { 321 t.Fatalf("Wrong account in conns message: %v", conns) 322 } else if conns.Conns != 0 || conns.TotalConns != 0 || conns.LeafNodes != 0 { 323 t.Fatalf("Wrong counts in conns message: %v", conns) 324 } 325 if !strings.HasPrefix(msg.Subject, fmt.Sprintf("$SYS.ACCOUNT.%s.DISCONNECT", acc2.Name)) { 326 t.Fatalf("Expected subject to start with %q, got %q", "$SYS.ACCOUNT.<account>.DISCONNECT", msg.Subject) 327 } 328 tokens = strings.Split(msg.Subject, ".") 329 if len(tokens) < 4 { 330 t.Fatalf("Expected 4 tokens, got %d", len(tokens)) 331 } 332 account = tokens[2] 333 if account != acc2.Name { 334 t.Fatalf("Expected %q for account, got %q", acc2.Name, account) 335 } 336 337 dem := DisconnectEventMsg{} 338 if err := json.Unmarshal(msg.Data, &dem); err != nil { 339 t.Fatalf("Error unmarshalling disconnect event message: %v", err) 340 } 341 if dem.Type != DisconnectEventMsgType { 342 t.Fatalf("Incorrect schema in connect event: %s", cem.Type) 343 } 344 if dem.Time.IsZero() { 345 t.Fatalf("Event time is not set") 346 } 347 if len(dem.ID) != 22 { 348 t.Fatalf("Event ID is incorrectly set to len %d", len(cem.ID)) 349 } 350 if dem.Server.ID != s.ID() { 351 t.Fatalf("Expected server to be %q, got %q", s.ID(), dem.Server.ID) 352 } 353 if dem.Server.Seq == 0 { 354 t.Fatalf("Expected sequence to be non-zero") 355 } 356 if dem.Server.Seq <= cem.Server.Seq { 357 t.Fatalf("Expected sequence to be increasing") 358 } 359 360 if cem.Client.Name != "TEST EVENTS" { 361 t.Fatalf("Expected client name to be %q, got %q", "TEST EVENTS", dem.Client.Name) 362 } 363 if dem.Client.Lang != "go" { 364 t.Fatalf("Expected client lang to be \"go\", got %q", dem.Client.Lang) 365 } 366 367 if dem.Sent.Msgs != 10 { 368 t.Fatalf("Expected 10 msgs sent, got %d", dem.Sent.Msgs) 369 } 370 if dem.Sent.Bytes != 110 { 371 t.Fatalf("Expected 110 bytes sent, got %d", dem.Sent.Bytes) 372 } 373 if dem.Received.Msgs != 20 { 374 t.Fatalf("Expected 20 msgs received, got %d", dem.Sent.Msgs) 375 } 376 if dem.Received.Bytes != 220 { 377 t.Fatalf("Expected 220 bytes sent, got %d", dem.Sent.Bytes) 378 } 379 } 380 381 func runTrustedLeafServer(t *testing.T) (*Server, *Options) { 382 t.Helper() 383 opts := DefaultOptions() 384 kp, _ := nkeys.FromSeed(oSeed) 385 pub, _ := kp.PublicKey() 386 opts.TrustedKeys = []string{pub} 387 opts.AccountResolver = &MemAccResolver{} 388 opts.LeafNode.Port = -1 389 s := RunServer(opts) 390 return s, opts 391 } 392 393 func genCredsFile(t *testing.T, jwt string, seed []byte) string { 394 creds := ` 395 -----BEGIN NATS USER JWT----- 396 %s 397 ------END NATS USER JWT------ 398 399 ************************* IMPORTANT ************************* 400 NKEY Seed printed below can be used to sign and prove identity. 401 NKEYs are sensitive and should be treated as secrets. 402 403 -----BEGIN USER NKEY SEED----- 404 %s 405 ------END USER NKEY SEED------ 406 407 ************************************************************* 408 ` 409 return createConfFile(t, []byte(strings.Replace(fmt.Sprintf(creds, jwt, seed), "\t\t", "", -1))) 410 } 411 412 func runSolicitWithCredentials(t *testing.T, opts *Options, creds string) (*Server, *Options, string) { 413 content := ` 414 port: -1 415 leafnodes { 416 remotes = [ 417 { 418 url: nats-leaf://127.0.0.1:%d 419 credentials: '%s' 420 } 421 ] 422 } 423 ` 424 config := fmt.Sprintf(content, opts.LeafNode.Port, creds) 425 conf := createConfFile(t, []byte(config)) 426 s, opts := RunServerWithConfig(conf) 427 return s, opts, conf 428 } 429 430 // Helper function to check that a leaf node has connected to our server. 431 func checkLeafNodeConnected(t testing.TB, s *Server) { 432 t.Helper() 433 checkLeafNodeConnectedCount(t, s, 1) 434 } 435 436 // Helper function to check that a leaf node has connected to n server. 437 func checkLeafNodeConnectedCount(t testing.TB, s *Server, lnCons int) { 438 t.Helper() 439 checkFor(t, 5*time.Second, 15*time.Millisecond, func() error { 440 if nln := s.NumLeafNodes(); nln != lnCons { 441 return fmt.Errorf("Expected %d connected leafnode(s) for server %v, got %d", 442 lnCons, s, nln) 443 } 444 return nil 445 }) 446 } 447 448 func TestSystemAccountingWithLeafNodes(t *testing.T) { 449 s, opts := runTrustedLeafServer(t) 450 defer s.Shutdown() 451 452 acc, akp := createAccount(s) 453 s.setSystemAccount(acc) 454 455 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 456 ncs, err := nats.Connect(url, createUserCreds(t, s, akp)) 457 if err != nil { 458 t.Fatalf("Error on connect: %v", err) 459 } 460 defer ncs.Close() 461 462 acc2, akp2 := createAccount(s) 463 464 // Be explicit to only receive the event for acc2 account. 465 sub, _ := ncs.SubscribeSync(fmt.Sprintf("$SYS.ACCOUNT.%s.DISCONNECT", acc2.Name)) 466 defer sub.Unsubscribe() 467 ncs.Flush() 468 469 kp, _ := nkeys.CreateUser() 470 pub, _ := kp.PublicKey() 471 nuc := jwt.NewUserClaims(pub) 472 ujwt, err := nuc.Encode(akp2) 473 if err != nil { 474 t.Fatalf("Error generating user JWT: %v", err) 475 } 476 seed, _ := kp.Seed() 477 mycreds := genCredsFile(t, ujwt, seed) 478 479 // Create a server that solicits a leafnode connection. 480 sl, slopts, _ := runSolicitWithCredentials(t, opts, mycreds) 481 defer sl.Shutdown() 482 483 checkLeafNodeConnected(t, s) 484 485 // Compute the expected number of subs on "sl" based on number 486 // of existing subs before creating the sub on "s". 487 expected := int(sl.NumSubscriptions() + 1) 488 489 nc, err := nats.Connect(url, createUserCreds(t, s, akp2), nats.Name("TEST LEAFNODE EVENTS")) 490 if err != nil { 491 t.Fatalf("Error on connect: %v", err) 492 } 493 defer nc.Close() 494 fooSub := natsSubSync(t, nc, "foo") 495 natsFlush(t, nc) 496 497 checkExpectedSubs(t, expected, sl) 498 499 surl := fmt.Sprintf("nats://%s:%d", slopts.Host, slopts.Port) 500 nc2, err := nats.Connect(surl, nats.Name("TEST LEAFNODE EVENTS")) 501 if err != nil { 502 t.Fatalf("Error on connect: %v", err) 503 } 504 defer nc2.Close() 505 506 // Compute the expected number of subs on "s" based on number 507 // of existing subs before creating the sub on "sl". 508 expected = int(s.NumSubscriptions() + 1) 509 510 m := []byte("HELLO WORLD") 511 512 // Now generate some traffic 513 starSub := natsSubSync(t, nc2, "*") 514 for i := 0; i < 10; i++ { 515 nc2.Publish("foo", m) 516 nc2.Publish("bar", m) 517 } 518 natsFlush(t, nc2) 519 520 checkExpectedSubs(t, expected, s) 521 522 // Now send some from the cluster side too. 523 for i := 0; i < 10; i++ { 524 nc.Publish("foo", m) 525 nc.Publish("bar", m) 526 } 527 nc.Flush() 528 529 // Make sure all messages are received 530 for i := 0; i < 20; i++ { 531 if _, err := fooSub.NextMsg(time.Second); err != nil { 532 t.Fatalf("Did not get message: %v", err) 533 } 534 } 535 for i := 0; i < 40; i++ { 536 if _, err := starSub.NextMsg(time.Second); err != nil { 537 t.Fatalf("Did not get message: %v", err) 538 } 539 } 540 541 // Now shutdown the leafnode server since this is where the event tracking should 542 // happen. Right now we do not track local clients to the leafnode server that 543 // solicited to the cluster, but we should track usage once the leafnode connection stops. 544 sl.Shutdown() 545 546 // Make sure we get disconnect event and that tracking is correct. 547 msg, err := sub.NextMsg(time.Second) 548 if err != nil { 549 t.Fatalf("Error receiving msg: %v", err) 550 } 551 552 dem := DisconnectEventMsg{} 553 if err := json.Unmarshal(msg.Data, &dem); err != nil { 554 t.Fatalf("Error unmarshalling disconnect event message: %v", err) 555 } 556 if dem.Sent.Msgs != 10 { 557 t.Fatalf("Expected 10 msgs sent, got %d", dem.Sent.Msgs) 558 } 559 if dem.Sent.Bytes != 110 { 560 t.Fatalf("Expected 110 bytes sent, got %d", dem.Sent.Bytes) 561 } 562 if dem.Received.Msgs != 20 { 563 t.Fatalf("Expected 20 msgs received, got %d", dem.Received.Msgs) 564 } 565 if dem.Received.Bytes != 220 { 566 t.Fatalf("Expected 220 bytes sent, got %d", dem.Received.Bytes) 567 } 568 } 569 570 func TestSystemAccountDisconnectBadLogin(t *testing.T) { 571 s, opts := runTrustedServer(t) 572 defer s.Shutdown() 573 574 acc, akp := createAccount(s) 575 s.setSystemAccount(acc) 576 577 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 578 ncs, err := nats.Connect(url, createUserCreds(t, s, akp)) 579 if err != nil { 580 t.Fatalf("Error on connect: %v", err) 581 } 582 defer ncs.Close() 583 584 // We should never hear $G account events for bad logins. 585 sub, _ := ncs.SubscribeSync("$SYS.ACCOUNT.$G.*") 586 defer sub.Unsubscribe() 587 588 // Listen for auth error events though. 589 asub, _ := ncs.SubscribeSync("$SYS.SERVER.*.CLIENT.AUTH.ERR") 590 defer asub.Unsubscribe() 591 592 ncs.Flush() 593 594 nats.Connect(url, nats.Name("TEST BAD LOGIN")) 595 596 // Should not hear these. 597 if _, err := sub.NextMsg(100 * time.Millisecond); err == nil { 598 t.Fatalf("Received a disconnect message from bad login, expected none") 599 } 600 601 m, err := asub.NextMsg(100 * time.Millisecond) 602 if err != nil { 603 t.Fatalf("Should have heard an auth error event") 604 } 605 dem := DisconnectEventMsg{} 606 if err := json.Unmarshal(m.Data, &dem); err != nil { 607 t.Fatalf("Error unmarshalling disconnect event message: %v", err) 608 } 609 if dem.Reason != "Authentication Failure" { 610 t.Fatalf("Expected auth error, got %q", dem.Reason) 611 } 612 } 613 614 func TestSysSubscribeRace(t *testing.T) { 615 s, opts := runTrustedServer(t) 616 defer s.Shutdown() 617 618 acc, akp := createAccount(s) 619 s.setSystemAccount(acc) 620 621 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 622 623 nc, err := nats.Connect(url, createUserCreds(t, s, akp)) 624 if err != nil { 625 t.Fatalf("Error on connect: %v", err) 626 } 627 defer nc.Close() 628 629 done := make(chan struct{}) 630 wg := sync.WaitGroup{} 631 wg.Add(1) 632 go func() { 633 defer wg.Done() 634 for { 635 nc.Publish("foo", []byte("hello")) 636 select { 637 case <-done: 638 return 639 default: 640 } 641 } 642 }() 643 644 time.Sleep(10 * time.Millisecond) 645 646 received := make(chan struct{}) 647 // Create message callback handler. 648 cb := func(sub *subscription, producer *client, _ *Account, subject, reply string, msg []byte) { 649 select { 650 case received <- struct{}{}: 651 default: 652 } 653 } 654 // Now create an internal subscription 655 sub, err := s.sysSubscribe("foo", cb) 656 if sub == nil || err != nil { 657 t.Fatalf("Expected to subscribe, got %v", err) 658 } 659 select { 660 case <-received: 661 close(done) 662 case <-time.After(time.Second): 663 t.Fatalf("Did not receive the message") 664 } 665 wg.Wait() 666 } 667 668 func TestSystemAccountInternalSubscriptions(t *testing.T) { 669 s, opts := runTrustedServer(t) 670 defer s.Shutdown() 671 672 sub, err := s.sysSubscribe("foo", nil) 673 if sub != nil || err != ErrNoSysAccount { 674 t.Fatalf("Expected to get proper error, got %v", err) 675 } 676 677 acc, akp := createAccount(s) 678 s.setSystemAccount(acc) 679 680 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 681 682 nc, err := nats.Connect(url, createUserCreds(t, s, akp)) 683 if err != nil { 684 t.Fatalf("Error on connect: %v", err) 685 } 686 defer nc.Close() 687 688 sub, err = s.sysSubscribe("foo", nil) 689 if sub != nil || err == nil { 690 t.Fatalf("Expected to get error for no handler, got %v", err) 691 } 692 693 received := make(chan *nats.Msg) 694 // Create message callback handler. 695 cb := func(sub *subscription, _ *client, _ *Account, subject, reply string, msg []byte) { 696 copy := append([]byte(nil), msg...) 697 received <- &nats.Msg{Subject: subject, Reply: reply, Data: copy} 698 } 699 700 // Now create an internal subscription 701 sub, err = s.sysSubscribe("foo", cb) 702 if sub == nil || err != nil { 703 t.Fatalf("Expected to subscribe, got %v", err) 704 } 705 // Now send out a message from our normal client. 706 nc.Publish("foo", []byte("HELLO WORLD")) 707 708 var msg *nats.Msg 709 710 select { 711 case msg = <-received: 712 if msg.Subject != "foo" { 713 t.Fatalf("Expected \"foo\" as subject, got %q", msg.Subject) 714 } 715 if msg.Reply != "" { 716 t.Fatalf("Expected no reply, got %q", msg.Reply) 717 } 718 if !bytes.Equal(msg.Data, []byte("HELLO WORLD")) { 719 t.Fatalf("Got the wrong msg payload: %q", msg.Data) 720 } 721 break 722 case <-time.After(time.Second): 723 t.Fatalf("Did not receive the message") 724 } 725 s.sysUnsubscribe(sub) 726 727 // Now send out a message from our normal client. 728 // We should not see this one. 729 nc.Publish("foo", []byte("You There?")) 730 731 select { 732 case <-received: 733 t.Fatalf("Received a message when we should not have") 734 case <-time.After(100 * time.Millisecond): 735 break 736 } 737 738 // Now make sure we do not hear ourselves. We optimize this for internally 739 // generated messages. 740 s.mu.Lock() 741 s.sendInternalMsg("foo", "", nil, msg.Data) 742 s.mu.Unlock() 743 744 select { 745 case <-received: 746 t.Fatalf("Received a message when we should not have") 747 case <-time.After(100 * time.Millisecond): 748 break 749 } 750 } 751 752 func TestSystemAccountConnectionUpdatesStopAfterNoLocal(t *testing.T) { 753 sa, _, sb, optsB, _ := runTrustedCluster(t) 754 defer sa.Shutdown() 755 defer sb.Shutdown() 756 757 // Normal Account 758 okp, _ := nkeys.FromSeed(oSeed) 759 akp, _ := nkeys.CreateAccount() 760 pub, _ := akp.PublicKey() 761 nac := jwt.NewAccountClaims(pub) 762 nac.Limits.Conn = 4 // Limit to 4 connections. 763 jwt, _ := nac.Encode(okp) 764 765 addAccountToMemResolver(sa, pub, jwt) 766 767 // Listen for updates to the new account connection activity. 768 received := make(chan *nats.Msg, 10) 769 cb := func(sub *subscription, _ *client, _ *Account, subject, reply string, msg []byte) { 770 copy := append([]byte(nil), msg...) 771 received <- &nats.Msg{Subject: subject, Reply: reply, Data: copy} 772 } 773 subj := fmt.Sprintf(accConnsEventSubjNew, pub) 774 sub, err := sa.sysSubscribe(subj, cb) 775 if sub == nil || err != nil { 776 t.Fatalf("Expected to subscribe, got %v", err) 777 } 778 defer sa.sysUnsubscribe(sub) 779 780 // Create a few users on the new account. 781 clients := []*nats.Conn{} 782 783 url := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 784 for i := 0; i < 4; i++ { 785 nc, err := nats.Connect(url, createUserCreds(t, sb, akp)) 786 if err != nil { 787 t.Fatalf("Error on connect: %v", err) 788 } 789 defer nc.Close() 790 clients = append(clients, nc) 791 } 792 793 // Wait for all 4 notifications. 794 checkFor(t, time.Second, 50*time.Millisecond, func() error { 795 if len(received) == 4 { 796 return nil 797 } 798 return fmt.Errorf("Not enough messages, %d vs 4", len(received)) 799 }) 800 801 // Now lookup the account doing the events on sb. 802 acc, _ := sb.LookupAccount(pub) 803 // Make sure we have the timer running. 804 acc.mu.RLock() 805 ctmr := acc.ctmr 806 acc.mu.RUnlock() 807 if ctmr == nil { 808 t.Fatalf("Expected event timer for acc conns to be running") 809 } 810 811 // Now close all of the connections. 812 for _, nc := range clients { 813 nc.Close() 814 } 815 816 // Wait for the 4 new notifications, 8 total (4 for connect, 4 for disconnect) 817 checkFor(t, time.Second, 50*time.Millisecond, func() error { 818 if len(received) == 8 { 819 return nil 820 } 821 return fmt.Errorf("Not enough messages, %d vs 4", len(received)) 822 }) 823 // Drain the messages. 824 for i := 0; i < 7; i++ { 825 <-received 826 } 827 // Check last one. 828 msg := <-received 829 m := AccountNumConns{} 830 if err := json.Unmarshal(msg.Data, &m); err != nil { 831 t.Fatalf("Error unmarshalling account connections request message: %v", err) 832 } 833 if m.Conns != 0 { 834 t.Fatalf("Expected Conns to be 0, got %d", m.Conns) 835 } 836 837 // Should not receive any more messages.. 838 select { 839 case <-received: 840 t.Fatalf("Did not expect a message here") 841 case <-time.After(50 * time.Millisecond): 842 break 843 } 844 845 // Make sure we have the timer is NOT running. 846 acc.mu.RLock() 847 ctmr = acc.ctmr 848 acc.mu.RUnlock() 849 if ctmr != nil { 850 t.Fatalf("Expected event timer for acc conns to NOT be running after reaching zero local clients") 851 } 852 } 853 854 func TestSystemAccountConnectionLimits(t *testing.T) { 855 sa, optsA, sb, optsB, _ := runTrustedCluster(t) 856 defer sa.Shutdown() 857 defer sb.Shutdown() 858 859 // We want to test that we are limited to a certain number of active connections 860 // across multiple servers. 861 862 // Let's create a user account. 863 okp, _ := nkeys.FromSeed(oSeed) 864 akp, _ := nkeys.CreateAccount() 865 pub, _ := akp.PublicKey() 866 nac := jwt.NewAccountClaims(pub) 867 nac.Limits.Conn = 4 // Limit to 4 connections. 868 jwt, _ := nac.Encode(okp) 869 870 addAccountToMemResolver(sa, pub, jwt) 871 872 urlA := fmt.Sprintf("nats://%s:%d", optsA.Host, optsA.Port) 873 urlB := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 874 875 // Create a user on each server. Break on first failure. 876 for { 877 nca1, err := nats.Connect(urlA, createUserCreds(t, sa, akp)) 878 if err != nil { 879 break 880 } 881 defer nca1.Close() 882 ncb1, err := nats.Connect(urlB, createUserCreds(t, sb, akp)) 883 if err != nil { 884 break 885 } 886 defer ncb1.Close() 887 } 888 889 checkFor(t, 5*time.Second, 50*time.Millisecond, func() error { 890 total := sa.NumClients() + sb.NumClients() 891 if total > int(nac.Limits.Conn) { 892 return fmt.Errorf("Expected only %d connections, was allowed to connect %d", nac.Limits.Conn, total) 893 } 894 return nil 895 }) 896 } 897 898 func TestBadAccountUpdate(t *testing.T) { 899 sa, _ := runTrustedServer(t) 900 defer sa.Shutdown() 901 akp1, _ := nkeys.CreateAccount() 902 pub, _ := akp1.PublicKey() 903 nac := jwt.NewAccountClaims(pub) 904 ajwt1, err := nac.Encode(oKp) 905 require_NoError(t, err) 906 addAccountToMemResolver(sa, pub, ajwt1) 907 akp2, _ := nkeys.CreateAccount() 908 pub2, _ := akp2.PublicKey() 909 nac.Subject = pub2 // maliciously use a different subject but pretend to remain pub 910 ajwt2, err := nac.Encode(oKp) 911 require_NoError(t, err) 912 acc, err := sa.fetchAccount(pub) 913 require_NoError(t, err) 914 if err := sa.updateAccountWithClaimJWT(acc, ajwt2); err != ErrAccountValidation { 915 t.Fatalf("expected %v but got %v", ErrAccountValidation, err) 916 } 917 } 918 919 // Make sure connection limits apply to the system account itself. 920 func TestSystemAccountSystemConnectionLimitsHonored(t *testing.T) { 921 sa, optsA, sb, optsB, sakp := runTrustedCluster(t) 922 defer sa.Shutdown() 923 defer sb.Shutdown() 924 925 okp, _ := nkeys.FromSeed(oSeed) 926 // Update system account to have 10 connections 927 pub, _ := sakp.PublicKey() 928 nac := jwt.NewAccountClaims(pub) 929 nac.Limits.Conn = 10 930 ajwt, _ := nac.Encode(okp) 931 932 addAccountToMemResolver(sa, pub, ajwt) 933 addAccountToMemResolver(sb, pub, ajwt) 934 935 // Update the accounts on each server with new claims to force update. 936 sysAccA := sa.SystemAccount() 937 sa.updateAccountWithClaimJWT(sysAccA, ajwt) 938 sysAccB := sb.SystemAccount() 939 sb.updateAccountWithClaimJWT(sysAccB, ajwt) 940 941 // Check system here first, with no external it should be zero. 942 sacc := sa.SystemAccount() 943 if nlc := sacc.NumLocalConnections(); nlc != 0 { 944 t.Fatalf("Expected no local connections, got %d", nlc) 945 } 946 947 urlA := fmt.Sprintf("nats://%s:%d", optsA.Host, optsA.Port) 948 urlB := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 949 950 // Create a user on each server. Break on first failure. 951 tc := 0 952 for { 953 nca1, err := nats.Connect(urlA, createUserCreds(t, sa, sakp)) 954 if err != nil { 955 break 956 } 957 defer nca1.Close() 958 tc++ 959 960 ncb1, err := nats.Connect(urlB, createUserCreds(t, sb, sakp)) 961 if err != nil { 962 break 963 } 964 defer ncb1.Close() 965 tc++ 966 967 // The account's connection count is exchanged between servers 968 // so that the local count on each server reflects the total count. 969 // Pause a bit to give a chance to each server to process the update. 970 time.Sleep(15 * time.Millisecond) 971 } 972 if tc != 10 { 973 t.Fatalf("Expected to get 10 external connections, got %d", tc) 974 } 975 976 checkFor(t, 1*time.Second, 50*time.Millisecond, func() error { 977 total := sa.NumClients() + sb.NumClients() 978 if total > int(nac.Limits.Conn) { 979 return fmt.Errorf("Expected only %d connections, was allowed to connect %d", nac.Limits.Conn, total) 980 } 981 return nil 982 }) 983 } 984 985 // Test that the remote accounting works when a server is started some time later. 986 func TestSystemAccountConnectionLimitsServersStaggered(t *testing.T) { 987 sa, optsA, sb, optsB, _ := runTrustedCluster(t) 988 defer sa.Shutdown() 989 sb.Shutdown() 990 991 // Let's create a user account. 992 okp, _ := nkeys.FromSeed(oSeed) 993 akp, _ := nkeys.CreateAccount() 994 pub, _ := akp.PublicKey() 995 nac := jwt.NewAccountClaims(pub) 996 nac.Limits.Conn = 4 // Limit to 4 connections. 997 jwt, _ := nac.Encode(okp) 998 999 addAccountToMemResolver(sa, pub, jwt) 1000 1001 urlA := fmt.Sprintf("nats://%s:%d", optsA.Host, optsA.Port) 1002 // Create max connections on sa. 1003 for i := 0; i < int(nac.Limits.Conn); i++ { 1004 nc, err := nats.Connect(urlA, createUserCreds(t, sa, akp)) 1005 if err != nil { 1006 t.Fatalf("Unexpected error on #%d try: %v", i+1, err) 1007 } 1008 defer nc.Close() 1009 } 1010 1011 // Restart server B. 1012 optsB.AccountResolver = sa.AccountResolver() 1013 optsB.SystemAccount = sa.SystemAccount().Name 1014 sb = RunServer(optsB) 1015 defer sb.Shutdown() 1016 checkClusterFormed(t, sa, sb) 1017 1018 // Trigger a load of the user account on the new server 1019 // NOTE: If we do not load the user, the user can be the first 1020 // to request this account, hence the connection will succeed. 1021 checkFor(t, time.Second, 15*time.Millisecond, func() error { 1022 if acc, err := sb.LookupAccount(pub); acc == nil || err != nil { 1023 return fmt.Errorf("LookupAccount did not return account or failed, err=%v", err) 1024 } 1025 return nil 1026 }) 1027 1028 // Expect this to fail. 1029 urlB := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 1030 if _, err := nats.Connect(urlB, createUserCreds(t, sb, akp)); err == nil { 1031 t.Fatalf("Expected connection to fail due to max limit") 1032 } 1033 } 1034 1035 // Test that the remote accounting works when a server is shutdown. 1036 func TestSystemAccountConnectionLimitsServerShutdownGraceful(t *testing.T) { 1037 sa, optsA, sb, optsB, _ := runTrustedCluster(t) 1038 defer sa.Shutdown() 1039 defer sb.Shutdown() 1040 1041 // Let's create a user account. 1042 okp, _ := nkeys.FromSeed(oSeed) 1043 akp, _ := nkeys.CreateAccount() 1044 pub, _ := akp.PublicKey() 1045 nac := jwt.NewAccountClaims(pub) 1046 nac.Limits.Conn = 10 // Limit to 10 connections. 1047 jwt, _ := nac.Encode(okp) 1048 1049 addAccountToMemResolver(sa, pub, jwt) 1050 addAccountToMemResolver(sb, pub, jwt) 1051 1052 urlA := fmt.Sprintf("nats://%s:%d", optsA.Host, optsA.Port) 1053 urlB := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 1054 1055 for i := 0; i < 5; i++ { 1056 nc, err := nats.Connect(urlA, nats.NoReconnect(), createUserCreds(t, sa, akp)) 1057 if err != nil { 1058 t.Fatalf("Expected to connect, got %v", err) 1059 } 1060 defer nc.Close() 1061 nc, err = nats.Connect(urlB, nats.NoReconnect(), createUserCreds(t, sb, akp)) 1062 if err != nil { 1063 t.Fatalf("Expected to connect, got %v", err) 1064 } 1065 defer nc.Close() 1066 } 1067 1068 // We are at capacity so both of these should fail. 1069 if _, err := nats.Connect(urlA, createUserCreds(t, sa, akp)); err == nil { 1070 t.Fatalf("Expected connection to fail due to max limit") 1071 } 1072 if _, err := nats.Connect(urlB, createUserCreds(t, sb, akp)); err == nil { 1073 t.Fatalf("Expected connection to fail due to max limit") 1074 } 1075 1076 // Now shutdown Server B. 1077 sb.Shutdown() 1078 1079 // Now we should be able to create more on A now. 1080 for i := 0; i < 5; i++ { 1081 nc, err := nats.Connect(urlA, createUserCreds(t, sa, akp)) 1082 if err != nil { 1083 t.Fatalf("Expected to connect on %d, got %v", i, err) 1084 } 1085 defer nc.Close() 1086 } 1087 } 1088 1089 // Test that the remote accounting works when a server goes away. 1090 func TestSystemAccountConnectionLimitsServerShutdownForced(t *testing.T) { 1091 sa, optsA, sb, optsB, _ := runTrustedCluster(t) 1092 defer sa.Shutdown() 1093 1094 // Let's create a user account. 1095 okp, _ := nkeys.FromSeed(oSeed) 1096 akp, _ := nkeys.CreateAccount() 1097 pub, _ := akp.PublicKey() 1098 nac := jwt.NewAccountClaims(pub) 1099 nac.Limits.Conn = 20 // Limit to 20 connections. 1100 jwt, _ := nac.Encode(okp) 1101 1102 addAccountToMemResolver(sa, pub, jwt) 1103 addAccountToMemResolver(sb, pub, jwt) 1104 1105 urlA := fmt.Sprintf("nats://%s:%d", optsA.Host, optsA.Port) 1106 urlB := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 1107 1108 for i := 0; i < 10; i++ { 1109 c, err := nats.Connect(urlA, nats.NoReconnect(), createUserCreds(t, sa, akp)) 1110 if err != nil { 1111 t.Fatalf("Expected to connect, got %v", err) 1112 } 1113 defer c.Close() 1114 c, err = nats.Connect(urlB, nats.NoReconnect(), createUserCreds(t, sb, akp)) 1115 if err != nil { 1116 t.Fatalf("Expected to connect, got %v", err) 1117 } 1118 defer c.Close() 1119 } 1120 1121 // Now shutdown Server B. Do so such that no communications go out. 1122 sb.mu.Lock() 1123 sb.sys = nil 1124 sb.mu.Unlock() 1125 sb.Shutdown() 1126 1127 if _, err := nats.Connect(urlA, createUserCreds(t, sa, akp)); err == nil { 1128 t.Fatalf("Expected connection to fail due to max limit") 1129 } 1130 1131 // Let's speed up the checking process. 1132 sa.mu.Lock() 1133 sa.sys.chkOrph = 10 * time.Millisecond 1134 sa.sys.orphMax = 30 * time.Millisecond 1135 sa.sys.sweeper.Reset(sa.sys.chkOrph) 1136 sa.mu.Unlock() 1137 1138 // We should eventually be able to connect. 1139 checkFor(t, 2*time.Second, 50*time.Millisecond, func() error { 1140 if c, err := nats.Connect(urlA, createUserCreds(t, sa, akp)); err != nil { 1141 return err 1142 } else { 1143 c.Close() 1144 } 1145 return nil 1146 }) 1147 } 1148 1149 func TestSystemAccountFromConfig(t *testing.T) { 1150 kp, _ := nkeys.FromSeed(oSeed) 1151 opub, _ := kp.PublicKey() 1152 akp, _ := nkeys.CreateAccount() 1153 apub, _ := akp.PublicKey() 1154 nac := jwt.NewAccountClaims(apub) 1155 ajwt, err := nac.Encode(kp) 1156 if err != nil { 1157 t.Fatalf("Error generating account JWT: %v", err) 1158 } 1159 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1160 w.Write([]byte(ajwt)) 1161 })) 1162 defer ts.Close() 1163 1164 confTemplate := ` 1165 listen: -1 1166 trusted: %s 1167 system_account: %s 1168 resolver: URL("%s/jwt/v1/accounts/") 1169 ` 1170 1171 conf := createConfFile(t, []byte(fmt.Sprintf(confTemplate, opub, apub, ts.URL))) 1172 1173 s, _ := RunServerWithConfig(conf) 1174 defer s.Shutdown() 1175 1176 if acc := s.SystemAccount(); acc == nil || acc.Name != apub { 1177 t.Fatalf("System Account not properly set") 1178 } 1179 } 1180 1181 func TestAccountClaimsUpdates(t *testing.T) { 1182 test := func(subj string) { 1183 s, opts := runTrustedServer(t) 1184 defer s.Shutdown() 1185 1186 sacc, sakp := createAccount(s) 1187 s.setSystemAccount(sacc) 1188 1189 // Let's create a normal account with limits we can update. 1190 okp, _ := nkeys.FromSeed(oSeed) 1191 akp, _ := nkeys.CreateAccount() 1192 pub, _ := akp.PublicKey() 1193 nac := jwt.NewAccountClaims(pub) 1194 nac.Limits.Conn = 4 1195 ajwt, _ := nac.Encode(okp) 1196 1197 addAccountToMemResolver(s, pub, ajwt) 1198 1199 acc, _ := s.LookupAccount(pub) 1200 if acc.MaxActiveConnections() != 4 { 1201 t.Fatalf("Expected to see a limit of 4 connections") 1202 } 1203 1204 // Simulate a systems publisher so we can do an account claims update. 1205 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 1206 nc, err := nats.Connect(url, createUserCreds(t, s, sakp)) 1207 if err != nil { 1208 t.Fatalf("Error on connect: %v", err) 1209 } 1210 defer nc.Close() 1211 1212 // Update the account 1213 nac = jwt.NewAccountClaims(pub) 1214 nac.Limits.Conn = 8 1215 issAt := time.Now().Add(-30 * time.Second).Unix() 1216 nac.IssuedAt = issAt 1217 expires := time.Now().Add(2 * time.Second).Unix() 1218 nac.Expires = expires 1219 ajwt, _ = nac.Encode(okp) 1220 1221 // Publish to the system update subject. 1222 claimUpdateSubj := fmt.Sprintf(subj, pub) 1223 nc.Publish(claimUpdateSubj, []byte(ajwt)) 1224 nc.Flush() 1225 time.Sleep(200 * time.Millisecond) 1226 1227 acc, _ = s.LookupAccount(pub) 1228 if acc.MaxActiveConnections() != 8 { 1229 t.Fatalf("Account was not updated") 1230 } 1231 } 1232 t.Run("new", func(t *testing.T) { 1233 test(accUpdateEventSubjNew) 1234 }) 1235 t.Run("old", func(t *testing.T) { 1236 test(accUpdateEventSubjOld) 1237 }) 1238 } 1239 1240 func TestAccountReqMonitoring(t *testing.T) { 1241 s, opts := runTrustedServer(t) 1242 defer s.Shutdown() 1243 sacc, sakp := createAccount(s) 1244 s.setSystemAccount(sacc) 1245 s.EnableJetStream(&JetStreamConfig{StoreDir: t.TempDir()}) 1246 unusedAcc, _ := createAccount(s) 1247 acc, akp := createAccount(s) 1248 acc.EnableJetStream(nil) 1249 subsz := fmt.Sprintf(accDirectReqSubj, acc.Name, "SUBSZ") 1250 connz := fmt.Sprintf(accDirectReqSubj, acc.Name, "CONNZ") 1251 jsz := fmt.Sprintf(accDirectReqSubj, acc.Name, "JSZ") 1252 1253 pStatz := fmt.Sprintf(accPingReqSubj, "STATZ") 1254 statz := func(name string) string { return fmt.Sprintf(accDirectReqSubj, name, "STATZ") } 1255 // Create system account connection to query 1256 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 1257 ncSys, err := nats.Connect(url, createUserCreds(t, s, sakp)) 1258 if err != nil { 1259 t.Fatalf("Error on connect: %v", err) 1260 } 1261 defer ncSys.Close() 1262 // Create a connection that we can query 1263 nc, err := nats.Connect(url, createUserCreds(t, s, akp)) 1264 if err != nil { 1265 t.Fatalf("Error on connect: %v", err) 1266 } 1267 defer nc.Close() 1268 // query SUBSZ for account 1269 resp, err := ncSys.Request(subsz, nil, time.Second) 1270 require_NoError(t, err) 1271 require_Contains(t, string(resp.Data), `"num_subscriptions":5,`) 1272 // create a subscription 1273 sub, err := nc.Subscribe("foo", func(msg *nats.Msg) {}) 1274 require_NoError(t, err) 1275 defer sub.Unsubscribe() 1276 1277 require_NoError(t, nc.Flush()) 1278 // query SUBSZ for account 1279 resp, err = ncSys.Request(subsz, nil, time.Second) 1280 require_NoError(t, err) 1281 require_Contains(t, string(resp.Data), `"num_subscriptions":6,`, `"subject":"foo"`) 1282 // query connections for account 1283 resp, err = ncSys.Request(connz, nil, time.Second) 1284 require_NoError(t, err) 1285 require_Contains(t, string(resp.Data), `"num_connections":1,`, `"total":1,`) 1286 // query connections for js account 1287 resp, err = ncSys.Request(jsz, nil, time.Second) 1288 require_NoError(t, err) 1289 require_Contains(t, string(resp.Data), `"memory":0,`, `"storage":0,`) 1290 // query statz/conns for account 1291 resp, err = ncSys.Request(statz(acc.Name), nil, time.Second) 1292 require_NoError(t, err) 1293 respContentAcc := []string{`"conns":1,`, `"total_conns":1`, `"slow_consumers":0`, `"sent":{"msgs":0,"bytes":0}`, 1294 `"received":{"msgs":0,"bytes":0}`, `"num_subscriptions":`, fmt.Sprintf(`"acc":"%s"`, acc.Name)} 1295 require_Contains(t, string(resp.Data), respContentAcc...) 1296 1297 rIb := ncSys.NewRespInbox() 1298 rSub, err := ncSys.SubscribeSync(rIb) 1299 require_NoError(t, err) 1300 require_NoError(t, ncSys.PublishRequest(pStatz, rIb, nil)) 1301 minRespContentForBothAcc := []string{`"conns":1,`, `"total_conns":1`, `"slow_consumers":0`, `"acc":"`, `"num_subscriptions":`} 1302 resp, err = rSub.NextMsg(time.Second) 1303 require_NoError(t, err) 1304 require_Contains(t, string(resp.Data), minRespContentForBothAcc...) 1305 // expect one entry per account 1306 require_Contains(t, string(resp.Data), fmt.Sprintf(`"acc":"%s"`, acc.Name), fmt.Sprintf(`"acc":"%s"`, sacc.Name)) 1307 1308 // Test ping with filter by account name 1309 require_NoError(t, ncSys.PublishRequest(pStatz, rIb, []byte(fmt.Sprintf(`{"accounts":["%s"]}`, sacc.Name)))) 1310 m, err := rSub.NextMsg(time.Second) 1311 require_NoError(t, err) 1312 require_Contains(t, string(m.Data), minRespContentForBothAcc...) 1313 1314 require_NoError(t, ncSys.PublishRequest(pStatz, rIb, []byte(fmt.Sprintf(`{"accounts":["%s"]}`, acc.Name)))) 1315 m, err = rSub.NextMsg(time.Second) 1316 require_NoError(t, err) 1317 require_Contains(t, string(m.Data), respContentAcc...) 1318 1319 // Test include unused for statz and ping of statz 1320 unusedContent := []string{`"conns":0,`, `"total_conns":0`, `"slow_consumers":0`, 1321 fmt.Sprintf(`"acc":"%s"`, unusedAcc.Name)} 1322 1323 resp, err = ncSys.Request(statz(unusedAcc.Name), 1324 []byte(fmt.Sprintf(`{"accounts":["%s"], "include_unused":true}`, unusedAcc.Name)), 1325 time.Second) 1326 require_NoError(t, err) 1327 require_Contains(t, string(resp.Data), unusedContent...) 1328 1329 require_NoError(t, ncSys.PublishRequest(pStatz, rIb, 1330 []byte(fmt.Sprintf(`{"accounts":["%s"], "include_unused":true}`, unusedAcc.Name)))) 1331 resp, err = rSub.NextMsg(time.Second) 1332 require_NoError(t, err) 1333 require_Contains(t, string(resp.Data), unusedContent...) 1334 1335 require_NoError(t, ncSys.PublishRequest(pStatz, rIb, []byte(fmt.Sprintf(`{"accounts":["%s"]}`, unusedAcc.Name)))) 1336 _, err = rSub.NextMsg(200 * time.Millisecond) 1337 require_Error(t, err) 1338 1339 // Test ping from within account, send extra message to check counters. 1340 require_NoError(t, nc.Publish("foo", nil)) 1341 ib := nc.NewRespInbox() 1342 rSub, err = nc.SubscribeSync(ib) 1343 require_NoError(t, err) 1344 require_NoError(t, nc.PublishRequest(pStatz, ib, nil)) 1345 require_NoError(t, nc.Flush()) 1346 resp, err = rSub.NextMsg(time.Second) 1347 require_NoError(t, err) 1348 1349 // Since we now have processed our own message, sent msgs will be at least 1. 1350 payload := string(resp.Data) 1351 respContentAcc = []string{`"conns":1,`, `"total_conns":1`, `"slow_consumers":0`, `"sent":{"msgs":1,"bytes":0}`, fmt.Sprintf(`"acc":"%s"`, acc.Name)} 1352 require_Contains(t, payload, respContentAcc...) 1353 1354 // Depending on timing, statz message could be accounted too. 1355 receivedOK := strings.Contains(payload, `"received":{"msgs":1,"bytes":0}`) || strings.Contains(payload, `"received":{"msgs":2,"bytes":0}`) 1356 require_True(t, receivedOK) 1357 _, err = rSub.NextMsg(200 * time.Millisecond) 1358 require_Error(t, err) 1359 } 1360 1361 func TestAccountReqInfo(t *testing.T) { 1362 s, opts := runTrustedServer(t) 1363 defer s.Shutdown() 1364 sacc, sakp := createAccount(s) 1365 s.setSystemAccount(sacc) 1366 // Let's create an account with service export. 1367 akp, _ := nkeys.CreateAccount() 1368 pub1, _ := akp.PublicKey() 1369 nac1 := jwt.NewAccountClaims(pub1) 1370 nac1.Exports.Add(&jwt.Export{Subject: "req.*", Type: jwt.Service}) 1371 ajwt1, _ := nac1.Encode(oKp) 1372 addAccountToMemResolver(s, pub1, ajwt1) 1373 s.LookupAccount(pub1) 1374 info1 := fmt.Sprintf(accDirectReqSubj, pub1, "INFO") 1375 // Now add an account with service imports. 1376 akp2, _ := nkeys.CreateAccount() 1377 pub2, _ := akp2.PublicKey() 1378 nac2 := jwt.NewAccountClaims(pub2) 1379 nac2.Imports.Add(&jwt.Import{Account: pub1, Subject: "req.1", Type: jwt.Service}) 1380 ajwt2, _ := nac2.Encode(oKp) 1381 addAccountToMemResolver(s, pub2, ajwt2) 1382 s.LookupAccount(pub2) 1383 info2 := fmt.Sprintf(accDirectReqSubj, pub2, "INFO") 1384 // Create system account connection to query 1385 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 1386 ncSys, err := nats.Connect(url, createUserCreds(t, s, sakp)) 1387 if err != nil { 1388 t.Fatalf("Error on connect: %v", err) 1389 } 1390 defer ncSys.Close() 1391 checkCommon := func(info *AccountInfo, srv *ServerInfo, pub, jwt string) { 1392 if info.Complete != true { 1393 t.Fatalf("Unexpected value: %v", info.Complete) 1394 } else if info.Expired != false { 1395 t.Fatalf("Unexpected value: %v", info.Expired) 1396 } else if info.JetStream != false { 1397 t.Fatalf("Unexpected value: %v", info.JetStream) 1398 } else if info.ClientCnt != 0 { 1399 t.Fatalf("Unexpected value: %v", info.ClientCnt) 1400 } else if info.AccountName != pub { 1401 t.Fatalf("Unexpected value: %v", info.AccountName) 1402 } else if info.LeafCnt != 0 { 1403 t.Fatalf("Unexpected value: %v", info.LeafCnt) 1404 } else if info.Jwt != jwt { 1405 t.Fatalf("Unexpected value: %v", info.Jwt) 1406 } else if srv.Cluster != "abc" { 1407 t.Fatalf("Unexpected value: %v", srv.Cluster) 1408 } else if srv.Name != s.Name() { 1409 t.Fatalf("Unexpected value: %v", srv.Name) 1410 } else if srv.Host != opts.Host { 1411 t.Fatalf("Unexpected value: %v", srv.Host) 1412 } else if srv.Seq < 1 { 1413 t.Fatalf("Unexpected value: %v", srv.Seq) 1414 } 1415 } 1416 info := AccountInfo{} 1417 srv := ServerInfo{} 1418 msg := struct { 1419 Data *AccountInfo `json:"data"` 1420 Srv *ServerInfo `json:"server"` 1421 }{ 1422 &info, 1423 &srv, 1424 } 1425 if resp, err := ncSys.Request(info1, nil, time.Second); err != nil { 1426 t.Fatalf("Error on request: %v", err) 1427 } else if err := json.Unmarshal(resp.Data, &msg); err != nil { 1428 t.Fatalf("Unmarshalling failed: %v", err) 1429 } else if len(info.Exports) != 1 { 1430 t.Fatalf("Unexpected value: %v", info.Exports) 1431 } else if len(info.Imports) != 4 { 1432 t.Fatalf("Unexpected value: %+v", info.Imports) 1433 } else if info.Exports[0].Subject != "req.*" { 1434 t.Fatalf("Unexpected value: %v", info.Exports) 1435 } else if info.Exports[0].Type != jwt.Service { 1436 t.Fatalf("Unexpected value: %v", info.Exports) 1437 } else if info.Exports[0].ResponseType != jwt.ResponseTypeSingleton { 1438 t.Fatalf("Unexpected value: %v", info.Exports) 1439 } else if info.SubCnt != 4 { 1440 t.Fatalf("Unexpected value: %v", info.SubCnt) 1441 } else { 1442 checkCommon(&info, &srv, pub1, ajwt1) 1443 } 1444 info = AccountInfo{} 1445 srv = ServerInfo{} 1446 if resp, err := ncSys.Request(info2, nil, time.Second); err != nil { 1447 t.Fatalf("Error on request: %v", err) 1448 } else if err := json.Unmarshal(resp.Data, &msg); err != nil { 1449 t.Fatalf("Unmarshalling failed: %v", err) 1450 } else if len(info.Exports) != 0 { 1451 t.Fatalf("Unexpected value: %v", info.Exports) 1452 } else if len(info.Imports) != 5 { 1453 t.Fatalf("Unexpected value: %+v", info.Imports) 1454 } 1455 // Here we need to find our import 1456 var si *ExtImport 1457 for _, im := range info.Imports { 1458 if im.Subject == "req.1" { 1459 si = &im 1460 break 1461 } 1462 } 1463 if si == nil { 1464 t.Fatalf("Could not find our import") 1465 } 1466 if si.Type != jwt.Service { 1467 t.Fatalf("Unexpected value: %+v", si) 1468 } else if si.Account != pub1 { 1469 t.Fatalf("Unexpected value: %+v", si) 1470 } else if info.SubCnt != 5 { 1471 t.Fatalf("Unexpected value: %+v", si) 1472 } else { 1473 checkCommon(&info, &srv, pub2, ajwt2) 1474 } 1475 } 1476 1477 func TestAccountClaimsUpdatesWithServiceImports(t *testing.T) { 1478 s, opts := runTrustedServer(t) 1479 defer s.Shutdown() 1480 1481 sacc, sakp := createAccount(s) 1482 s.setSystemAccount(sacc) 1483 1484 okp, _ := nkeys.FromSeed(oSeed) 1485 1486 // Let's create an account with service export. 1487 akp, _ := nkeys.CreateAccount() 1488 pub, _ := akp.PublicKey() 1489 nac := jwt.NewAccountClaims(pub) 1490 nac.Exports.Add(&jwt.Export{Subject: "req.*", Type: jwt.Service}) 1491 ajwt, _ := nac.Encode(okp) 1492 addAccountToMemResolver(s, pub, ajwt) 1493 s.LookupAccount(pub) 1494 1495 // Now add an account with multiple service imports. 1496 akp2, _ := nkeys.CreateAccount() 1497 pub2, _ := akp2.PublicKey() 1498 nac2 := jwt.NewAccountClaims(pub2) 1499 nac2.Imports.Add(&jwt.Import{Account: pub, Subject: "req.1", Type: jwt.Service}) 1500 ajwt2, _ := nac2.Encode(okp) 1501 1502 addAccountToMemResolver(s, pub2, ajwt2) 1503 s.LookupAccount(pub2) 1504 1505 startSubs := s.NumSubscriptions() 1506 1507 // Simulate a systems publisher so we can do an account claims update. 1508 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 1509 nc, err := nats.Connect(url, createUserCreds(t, s, sakp)) 1510 if err != nil { 1511 t.Fatalf("Error on connect: %v", err) 1512 } 1513 defer nc.Close() 1514 1515 // Update the account several times 1516 for i := 1; i <= 10; i++ { 1517 nac2 = jwt.NewAccountClaims(pub2) 1518 nac2.Limits.Conn = int64(i) 1519 nac2.Imports.Add(&jwt.Import{Account: pub, Subject: "req.1", Type: jwt.Service}) 1520 ajwt2, _ = nac2.Encode(okp) 1521 1522 // Publish to the system update subject. 1523 claimUpdateSubj := fmt.Sprintf(accUpdateEventSubjNew, pub2) 1524 nc.Publish(claimUpdateSubj, []byte(ajwt2)) 1525 } 1526 nc.Flush() 1527 time.Sleep(50 * time.Millisecond) 1528 1529 if startSubs < s.NumSubscriptions() { 1530 t.Fatalf("Subscriptions leaked: %d vs %d", startSubs, s.NumSubscriptions()) 1531 } 1532 } 1533 1534 func TestAccountConnsLimitExceededAfterUpdate(t *testing.T) { 1535 s, opts := runTrustedServer(t) 1536 defer s.Shutdown() 1537 1538 sacc, _ := createAccount(s) 1539 s.setSystemAccount(sacc) 1540 1541 // Let's create a normal account with limits we can update. 1542 okp, _ := nkeys.FromSeed(oSeed) 1543 akp, _ := nkeys.CreateAccount() 1544 pub, _ := akp.PublicKey() 1545 nac := jwt.NewAccountClaims(pub) 1546 nac.Limits.Conn = 10 1547 ajwt, _ := nac.Encode(okp) 1548 1549 addAccountToMemResolver(s, pub, ajwt) 1550 acc, _ := s.LookupAccount(pub) 1551 1552 // Now create the max connections. 1553 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 1554 for { 1555 nc, err := nats.Connect(url, createUserCreds(t, s, akp)) 1556 if err != nil { 1557 break 1558 } 1559 defer nc.Close() 1560 } 1561 1562 // We should have max here. 1563 checkFor(t, 2*time.Second, 50*time.Millisecond, func() error { 1564 if total := s.NumClients(); total != acc.MaxActiveConnections() { 1565 return fmt.Errorf("Expected %d connections, got %d", acc.MaxActiveConnections(), total) 1566 } 1567 return nil 1568 }) 1569 1570 // Now change limits to make current connections over the limit. 1571 nac = jwt.NewAccountClaims(pub) 1572 nac.Limits.Conn = 2 1573 ajwt, _ = nac.Encode(okp) 1574 1575 s.updateAccountWithClaimJWT(acc, ajwt) 1576 if acc.MaxActiveConnections() != 2 { 1577 t.Fatalf("Expected max connections to be set to 2, got %d", acc.MaxActiveConnections()) 1578 } 1579 // We should have closed the excess connections. 1580 checkClientsCount(t, s, acc.MaxActiveConnections()) 1581 } 1582 1583 func TestAccountConnsLimitExceededAfterUpdateDisconnectNewOnly(t *testing.T) { 1584 s, opts := runTrustedServer(t) 1585 defer s.Shutdown() 1586 1587 sacc, _ := createAccount(s) 1588 s.setSystemAccount(sacc) 1589 1590 // Let's create a normal account with limits we can update. 1591 okp, _ := nkeys.FromSeed(oSeed) 1592 akp, _ := nkeys.CreateAccount() 1593 pub, _ := akp.PublicKey() 1594 nac := jwt.NewAccountClaims(pub) 1595 nac.Limits.Conn = 10 1596 ajwt, _ := nac.Encode(okp) 1597 1598 addAccountToMemResolver(s, pub, ajwt) 1599 acc, _ := s.LookupAccount(pub) 1600 1601 // Now create the max connections. 1602 // We create half then we will wait and then create the rest. 1603 // Will test that we disconnect the newest ones. 1604 newConns := make([]*nats.Conn, 0, 5) 1605 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 1606 for i := 0; i < 5; i++ { 1607 nc, err := nats.Connect(url, nats.NoReconnect(), createUserCreds(t, s, akp)) 1608 require_NoError(t, err) 1609 defer nc.Close() 1610 } 1611 time.Sleep(500 * time.Millisecond) 1612 for i := 0; i < 5; i++ { 1613 nc, err := nats.Connect(url, nats.NoReconnect(), createUserCreds(t, s, akp)) 1614 require_NoError(t, err) 1615 defer nc.Close() 1616 newConns = append(newConns, nc) 1617 } 1618 1619 // We should have max here. 1620 checkClientsCount(t, s, acc.MaxActiveConnections()) 1621 1622 // Now change limits to make current connections over the limit. 1623 nac = jwt.NewAccountClaims(pub) 1624 nac.Limits.Conn = 5 1625 ajwt, _ = nac.Encode(okp) 1626 1627 s.updateAccountWithClaimJWT(acc, ajwt) 1628 if acc.MaxActiveConnections() != 5 { 1629 t.Fatalf("Expected max connections to be set to 2, got %d", acc.MaxActiveConnections()) 1630 } 1631 // We should have closed the excess connections. 1632 checkClientsCount(t, s, acc.MaxActiveConnections()) 1633 1634 // Now make sure that only the new ones were closed. 1635 var closed int 1636 for _, nc := range newConns { 1637 if !nc.IsClosed() { 1638 closed++ 1639 } 1640 } 1641 if closed != 5 { 1642 t.Fatalf("Expected all new clients to be closed, only got %d of 5", closed) 1643 } 1644 } 1645 1646 func TestSystemAccountWithBadRemoteLatencyUpdate(t *testing.T) { 1647 s, _ := runTrustedServer(t) 1648 defer s.Shutdown() 1649 1650 acc, _ := createAccount(s) 1651 s.setSystemAccount(acc) 1652 1653 rl := remoteLatency{ 1654 Account: "NONSENSE", 1655 ReqId: "_INBOX.22", 1656 } 1657 b, _ := json.Marshal(&rl) 1658 s.remoteLatencyUpdate(nil, nil, nil, "foo", _EMPTY_, nil, b) 1659 } 1660 1661 func TestSystemAccountWithGateways(t *testing.T) { 1662 sa, oa, sb, ob, akp := runTrustedGateways(t) 1663 defer sa.Shutdown() 1664 defer sb.Shutdown() 1665 1666 // Create a client on A that will subscribe on $SYS.ACCOUNT.> 1667 urla := fmt.Sprintf("nats://%s:%d", oa.Host, oa.Port) 1668 nca := natsConnect(t, urla, createUserCreds(t, sa, akp), nats.Name("SYS")) 1669 defer nca.Close() 1670 nca.Flush() 1671 1672 sub, _ := nca.SubscribeSync("$SYS.ACCOUNT.>") 1673 defer sub.Unsubscribe() 1674 nca.Flush() 1675 1676 // If this tests fails with wrong number after 10 seconds we may have 1677 // added a new inititial subscription for the eventing system. 1678 checkExpectedSubs(t, 56, sa) 1679 1680 // Create a client on B and see if we receive the event 1681 urlb := fmt.Sprintf("nats://%s:%d", ob.Host, ob.Port) 1682 ncb := natsConnect(t, urlb, createUserCreds(t, sb, akp), nats.Name("TEST EVENTS")) 1683 defer ncb.Close() 1684 1685 // space for .CONNECT and .CONNS from SYS and $G as well as one extra message 1686 msgs := [4]*nats.Msg{} 1687 var err error 1688 msgs[0], err = sub.NextMsg(time.Second) 1689 require_NoError(t, err) 1690 msgs[1], err = sub.NextMsg(time.Second) 1691 require_NoError(t, err) 1692 // TODO: There is a race currently that can cause the server to process the 1693 // system event *after* the subscription on "A" has been registered, and so 1694 // the "nca" client would receive its own CONNECT message. 1695 msgs[2], _ = sub.NextMsg(250 * time.Millisecond) 1696 1697 findMsgs := func(sub string) []*nats.Msg { 1698 rMsgs := []*nats.Msg{} 1699 for _, m := range msgs { 1700 if m == nil { 1701 continue 1702 } 1703 if m.Subject == sub { 1704 rMsgs = append(rMsgs, m) 1705 } 1706 } 1707 return rMsgs 1708 } 1709 1710 msg := findMsgs(fmt.Sprintf("$SYS.ACCOUNT.%s.CONNECT", sa.SystemAccount().Name)) 1711 var bMsg *nats.Msg 1712 if len(msg) < 1 { 1713 t.Fatal("Expected at least one message") 1714 } 1715 bMsg = msg[len(msg)-1] 1716 1717 require_Contains(t, string(bMsg.Data), sb.ID()) 1718 require_Contains(t, string(bMsg.Data), `"cluster":"B"`) 1719 require_Contains(t, string(bMsg.Data), `"name":"TEST EVENTS"`) 1720 1721 connsMsgA := findMsgs(fmt.Sprintf("$SYS.ACCOUNT.%s.SERVER.CONNS", sa.SystemAccount().Name)) 1722 if len(connsMsgA) != 1 { 1723 t.Fatal("Expected a message") 1724 } 1725 } 1726 1727 func TestSystemAccountNoAuthUser(t *testing.T) { 1728 conf := createConfFile(t, []byte(` 1729 listen: "127.0.0.1:-1" 1730 accounts { 1731 $SYS { 1732 users [{user: "admin", password: "pwd"}] 1733 } 1734 } 1735 `)) 1736 defer os.Remove(conf) 1737 s, o := RunServerWithConfig(conf) 1738 defer s.Shutdown() 1739 1740 for _, test := range []struct { 1741 name string 1742 usrInfo string 1743 ok bool 1744 account string 1745 }{ 1746 {"valid user/pwd", "admin:pwd@", true, "$SYS"}, 1747 {"invalid pwd", "admin:wrong@", false, _EMPTY_}, 1748 {"some token", "sometoken@", false, _EMPTY_}, 1749 {"user used without pwd", "admin@", false, _EMPTY_}, // will be treated as a token 1750 {"user with empty password", "admin:@", false, _EMPTY_}, 1751 {"no user means global account", _EMPTY_, true, globalAccountName}, 1752 } { 1753 t.Run(test.name, func(t *testing.T) { 1754 url := fmt.Sprintf("nats://%s127.0.0.1:%d", test.usrInfo, o.Port) 1755 nc, err := nats.Connect(url) 1756 if err != nil { 1757 if test.ok { 1758 t.Fatalf("Unexpected error: %v", err) 1759 } 1760 return 1761 } else if !test.ok { 1762 nc.Close() 1763 t.Fatalf("Should have failed, did not") 1764 } 1765 var accName string 1766 s.mu.Lock() 1767 for _, c := range s.clients { 1768 c.mu.Lock() 1769 if c.acc != nil { 1770 accName = c.acc.Name 1771 } 1772 c.mu.Unlock() 1773 break 1774 } 1775 s.mu.Unlock() 1776 nc.Close() 1777 checkClientsCount(t, s, 0) 1778 if accName != test.account { 1779 t.Fatalf("The account should have been %q, got %q", test.account, accName) 1780 } 1781 }) 1782 } 1783 } 1784 1785 func TestServerAccountConns(t *testing.T) { 1786 // speed up hb 1787 orgHBInterval := eventsHBInterval 1788 eventsHBInterval = time.Millisecond * 100 1789 defer func() { eventsHBInterval = orgHBInterval }() 1790 conf := createConfFile(t, []byte(` 1791 host: 127.0.0.1 1792 port: -1 1793 system_account: SYS 1794 accounts: { 1795 SYS: {users: [{user: s, password: s}]} 1796 ACC: {users: [{user: a, password: a}]} 1797 }`)) 1798 s, _ := RunServerWithConfig(conf) 1799 defer s.Shutdown() 1800 1801 nc := natsConnect(t, s.ClientURL(), nats.UserInfo("a", "a")) 1802 defer nc.Close() 1803 1804 subOut, err := nc.SubscribeSync("foo") 1805 require_NoError(t, err) 1806 hw := "HELLO WORLD" 1807 nc.Publish("foo", []byte(hw)) 1808 nc.Publish("bar", []byte(hw)) // will only count towards received 1809 nc.Flush() 1810 m, err := subOut.NextMsg(time.Second) 1811 require_NoError(t, err) 1812 require_Equal(t, string(m.Data), hw) 1813 1814 ncs := natsConnect(t, s.ClientURL(), nats.UserInfo("s", "s")) 1815 defer ncs.Close() 1816 subs, err := ncs.SubscribeSync("$SYS.ACCOUNT.ACC.SERVER.CONNS") 1817 require_NoError(t, err) 1818 1819 m, err = subs.NextMsg(time.Second) 1820 require_NoError(t, err) 1821 accConns := &AccountNumConns{} 1822 err = json.Unmarshal(m.Data, accConns) 1823 require_NoError(t, err) 1824 1825 require_True(t, accConns.Received.Msgs == 2) 1826 require_True(t, accConns.Received.Bytes == 2*int64(len(hw))) 1827 require_True(t, accConns.Sent.Msgs == 1) 1828 require_True(t, accConns.Sent.Bytes == int64(len(hw))) 1829 } 1830 1831 func TestServerEventsStatsZ(t *testing.T) { 1832 serverStatsReqSubj := "$SYS.REQ.SERVER.%s.STATSZ" 1833 preStart := time.Now().UTC() 1834 // Add little bit of delay to make sure that time check 1835 // between pre-start and actual start does not fail. 1836 time.Sleep(5 * time.Millisecond) 1837 sa, optsA, sb, _, akp := runTrustedCluster(t) 1838 defer sa.Shutdown() 1839 defer sb.Shutdown() 1840 // Same between actual start and post start. 1841 time.Sleep(5 * time.Millisecond) 1842 postStart := time.Now().UTC() 1843 1844 url := fmt.Sprintf("nats://%s:%d", optsA.Host, optsA.Port) 1845 ncs, err := nats.Connect(url, createUserCreds(t, sa, akp)) 1846 if err != nil { 1847 t.Fatalf("Error on connect: %v", err) 1848 } 1849 defer ncs.Close() 1850 1851 subj := fmt.Sprintf(serverStatsSubj, sa.ID()) 1852 sub, _ := ncs.SubscribeSync(subj) 1853 defer sub.Unsubscribe() 1854 ncs.Publish("foo", []byte("HELLO WORLD")) 1855 ncs.Flush() 1856 1857 // Let's speed up the checking process. 1858 sa.mu.Lock() 1859 sa.sys.statsz = 10 * time.Millisecond 1860 sa.sys.stmr.Reset(sa.sys.statsz) 1861 sa.mu.Unlock() 1862 1863 _, err = sub.NextMsg(time.Second) 1864 if err != nil { 1865 t.Fatalf("Error receiving msg: %v", err) 1866 } 1867 // Get it the second time so we can check some stats 1868 msg, err := sub.NextMsg(time.Second) 1869 if err != nil { 1870 t.Fatalf("Error receiving msg: %v", err) 1871 } 1872 m := ServerStatsMsg{} 1873 if err := json.Unmarshal(msg.Data, &m); err != nil { 1874 t.Fatalf("Error unmarshalling the statz json: %v", err) 1875 } 1876 if m.Server.ID != sa.ID() { 1877 t.Fatalf("Did not match IDs") 1878 } 1879 if m.Server.Cluster != "TEST CLUSTER 22" { 1880 t.Fatalf("Did not match cluster name") 1881 } 1882 if m.Server.Version != VERSION { 1883 t.Fatalf("Did not match server version") 1884 } 1885 if !m.Stats.Start.After(preStart) && m.Stats.Start.Before(postStart) { 1886 t.Fatalf("Got a wrong start time for the server %v", m.Stats.Start) 1887 } 1888 if m.Stats.Connections != 1 { 1889 t.Fatalf("Did not match connections of 1, got %d", m.Stats.Connections) 1890 } 1891 if m.Stats.ActiveAccounts != 1 { 1892 t.Fatalf("Did not match active accounts of 1, got %d", m.Stats.ActiveAccounts) 1893 } 1894 if m.Stats.Sent.Msgs < 1 { 1895 t.Fatalf("Did not match sent msgs of >=1, got %d", m.Stats.Sent.Msgs) 1896 } 1897 if m.Stats.Received.Msgs < 1 { 1898 t.Fatalf("Did not match received msgs of >=1, got %d", m.Stats.Received.Msgs) 1899 } 1900 // Default pool size + 1 for system account 1901 expectedRoutes := DEFAULT_ROUTE_POOL_SIZE + 1 1902 if lr := len(m.Stats.Routes); lr != expectedRoutes { 1903 t.Fatalf("Expected %d routes, but got %d", expectedRoutes, lr) 1904 } 1905 1906 // Now let's prompt this server to send us the statsz 1907 subj = fmt.Sprintf(serverStatsReqSubj, sa.ID()) 1908 msg, err = ncs.Request(subj, nil, time.Second) 1909 if err != nil { 1910 t.Fatalf("Error trying to request statsz: %v", err) 1911 } 1912 m2 := ServerStatsMsg{} 1913 if err := json.Unmarshal(msg.Data, &m2); err != nil { 1914 t.Fatalf("Error unmarshalling the statz json: %v", err) 1915 } 1916 if m2.Server.ID != sa.ID() { 1917 t.Fatalf("Did not match IDs") 1918 } 1919 if m2.Stats.Connections != 1 { 1920 t.Fatalf("Did not match connections of 1, got %d", m2.Stats.Connections) 1921 } 1922 if m2.Stats.ActiveAccounts != 1 { 1923 t.Fatalf("Did not match active accounts of 1, got %d", m2.Stats.ActiveAccounts) 1924 } 1925 if m2.Stats.Sent.Msgs < 3 { 1926 t.Fatalf("Did not match sent msgs of >= 3, got %d", m2.Stats.Sent.Msgs) 1927 } 1928 if m2.Stats.Received.Msgs < 1 { 1929 t.Fatalf("Did not match received msgs of >= 1, got %d", m2.Stats.Received.Msgs) 1930 } 1931 if lr := len(m2.Stats.Routes); lr != expectedRoutes { 1932 t.Fatalf("Expected %d routes, but got %d", expectedRoutes, lr) 1933 } 1934 1935 msg, err = ncs.Request(subj, nil, time.Second) 1936 if err != nil { 1937 t.Fatalf("Error trying to request statsz: %v", err) 1938 } 1939 m3 := ServerStatsMsg{} 1940 if err := json.Unmarshal(msg.Data, &m3); err != nil { 1941 t.Fatalf("Error unmarshalling the statz json: %v", err) 1942 } 1943 if m3.Server.ID != sa.ID() { 1944 t.Fatalf("Did not match IDs") 1945 } 1946 if m3.Stats.Connections != 1 { 1947 t.Fatalf("Did not match connections of 1, got %d", m3.Stats.Connections) 1948 } 1949 if m3.Stats.ActiveAccounts != 1 { 1950 t.Fatalf("Did not match active accounts of 1, got %d", m3.Stats.ActiveAccounts) 1951 } 1952 if m3.Stats.Sent.Msgs < 4 { 1953 t.Fatalf("Did not match sent msgs of >= 4, got %d", m3.Stats.Sent.Msgs) 1954 } 1955 if m3.Stats.Received.Msgs < 2 { 1956 t.Fatalf("Did not match received msgs of >= 2, got %d", m3.Stats.Received.Msgs) 1957 } 1958 if lr := len(m3.Stats.Routes); lr != expectedRoutes { 1959 t.Fatalf("Expected %d routes, but got %d", expectedRoutes, lr) 1960 } 1961 for _, sr := range m3.Stats.Routes { 1962 if sr.Name != "B_SRV" { 1963 t.Fatalf("Expected server A's route to B to have Name set to %q, got %q", "B", sr.Name) 1964 } 1965 } 1966 1967 // Now query B and check that route's name is "A" 1968 subj = fmt.Sprintf(serverStatsReqSubj, sb.ID()) 1969 ncs.SubscribeSync(subj) 1970 msg, err = ncs.Request(subj, nil, time.Second) 1971 if err != nil { 1972 t.Fatalf("Error trying to request statsz: %v", err) 1973 } 1974 m = ServerStatsMsg{} 1975 if err := json.Unmarshal(msg.Data, &m); err != nil { 1976 t.Fatalf("Error unmarshalling the statz json: %v", err) 1977 } 1978 if lr := len(m.Stats.Routes); lr != expectedRoutes { 1979 t.Fatalf("Expected %d routes, but got %d", expectedRoutes, lr) 1980 } 1981 for _, sr := range m.Stats.Routes { 1982 if sr.Name != "A_SRV" { 1983 t.Fatalf("Expected server B's route to A to have Name set to %q, got %q", "A_SRV", sr.Name) 1984 } 1985 } 1986 } 1987 1988 func TestServerEventsHealthZSingleServer(t *testing.T) { 1989 type healthzResp struct { 1990 Healthz HealthStatus `json:"data"` 1991 Server ServerInfo `json:"server"` 1992 } 1993 cfg := fmt.Sprintf(`listen: 127.0.0.1:-1 1994 1995 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 1996 1997 no_auth_user: one 1998 1999 accounts { 2000 ONE { users = [ { user: "one", pass: "p" } ]; jetstream: enabled } 2001 $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } 2002 }`, t.TempDir()) 2003 2004 serverHealthzReqSubj := "$SYS.REQ.SERVER.%s.HEALTHZ" 2005 s, _ := RunServerWithConfig(createConfFile(t, []byte(cfg))) 2006 defer s.Shutdown() 2007 2008 ncs, err := nats.Connect(s.ClientURL(), nats.UserInfo("admin", "s3cr3t!")) 2009 if err != nil { 2010 t.Fatalf("Error connecting to cluster: %v", err) 2011 } 2012 2013 defer ncs.Close() 2014 ncAcc, err := nats.Connect(s.ClientURL()) 2015 if err != nil { 2016 t.Fatalf("Error on connect: %v", err) 2017 } 2018 defer ncAcc.Close() 2019 js, err := ncAcc.JetStream() 2020 if err != nil { 2021 t.Fatalf("Error creating JetStream context: %v", err) 2022 } 2023 _, err = js.AddStream(&nats.StreamConfig{ 2024 Name: "test", 2025 Subjects: []string{"foo"}, 2026 }) 2027 if err != nil { 2028 t.Fatalf("Error creating stream: %v", err) 2029 } 2030 _, err = js.AddConsumer("test", &nats.ConsumerConfig{ 2031 Name: "cons", 2032 }) 2033 if err != nil { 2034 t.Fatalf("Error creating consumer: %v", err) 2035 } 2036 2037 subj := fmt.Sprintf(serverHealthzReqSubj, s.ID()) 2038 2039 tests := []struct { 2040 name string 2041 req *HealthzEventOptions 2042 expected HealthStatus 2043 }{ 2044 { 2045 name: "no parameters", 2046 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2047 }, 2048 { 2049 name: "with js enabled only", 2050 req: &HealthzEventOptions{ 2051 HealthzOptions: HealthzOptions{ 2052 JSEnabledOnly: true, 2053 }, 2054 }, 2055 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2056 }, 2057 { 2058 name: "with server only", 2059 req: &HealthzEventOptions{ 2060 HealthzOptions: HealthzOptions{ 2061 JSServerOnly: true, 2062 }, 2063 }, 2064 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2065 }, 2066 { 2067 name: "with account name", 2068 req: &HealthzEventOptions{ 2069 HealthzOptions: HealthzOptions{ 2070 Account: "ONE", 2071 }, 2072 }, 2073 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2074 }, 2075 { 2076 name: "with account name and stream", 2077 req: &HealthzEventOptions{ 2078 HealthzOptions: HealthzOptions{ 2079 Account: "ONE", 2080 Stream: "test", 2081 }, 2082 }, 2083 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2084 }, 2085 { 2086 name: "with account name, stream and consumer", 2087 req: &HealthzEventOptions{ 2088 HealthzOptions: HealthzOptions{ 2089 Account: "ONE", 2090 Stream: "test", 2091 Consumer: "cons", 2092 }, 2093 }, 2094 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2095 }, 2096 { 2097 name: "with stream only", 2098 req: &HealthzEventOptions{ 2099 HealthzOptions: HealthzOptions{ 2100 Stream: "test", 2101 }, 2102 }, 2103 expected: HealthStatus{ 2104 Status: "error", 2105 StatusCode: 400, 2106 Error: `"account" must not be empty when checking stream health`, 2107 }, 2108 }, 2109 { 2110 name: "with stream only, detailed", 2111 req: &HealthzEventOptions{ 2112 HealthzOptions: HealthzOptions{ 2113 Details: true, 2114 Stream: "test", 2115 }, 2116 }, 2117 expected: HealthStatus{ 2118 Status: "error", 2119 StatusCode: 400, 2120 Errors: []HealthzError{ 2121 { 2122 Type: HealthzErrorBadRequest, 2123 Error: `"account" must not be empty when checking stream health`, 2124 }, 2125 }, 2126 }, 2127 }, 2128 { 2129 name: "with account and consumer", 2130 req: &HealthzEventOptions{ 2131 HealthzOptions: HealthzOptions{ 2132 Account: "ONE", 2133 Consumer: "cons", 2134 }, 2135 }, 2136 expected: HealthStatus{ 2137 Status: "error", 2138 StatusCode: 400, 2139 Error: `"stream" must not be empty when checking consumer health`, 2140 }, 2141 }, 2142 { 2143 name: "with account and consumer, detailed", 2144 req: &HealthzEventOptions{ 2145 HealthzOptions: HealthzOptions{ 2146 Account: "ONE", 2147 Consumer: "cons", 2148 Details: true, 2149 }, 2150 }, 2151 expected: HealthStatus{ 2152 Status: "error", 2153 StatusCode: 400, 2154 Errors: []HealthzError{ 2155 { 2156 Type: HealthzErrorBadRequest, 2157 Error: `"stream" must not be empty when checking consumer health`, 2158 }, 2159 }, 2160 }, 2161 }, 2162 { 2163 name: "account not found", 2164 req: &HealthzEventOptions{ 2165 HealthzOptions: HealthzOptions{ 2166 Account: "abc", 2167 }, 2168 }, 2169 expected: HealthStatus{ 2170 Status: "unavailable", 2171 StatusCode: 404, 2172 Error: `JetStream account "abc" not found`, 2173 }, 2174 }, 2175 { 2176 name: "account not found, detailed", 2177 req: &HealthzEventOptions{ 2178 HealthzOptions: HealthzOptions{ 2179 Account: "abc", 2180 Details: true, 2181 }, 2182 }, 2183 expected: HealthStatus{ 2184 Status: "error", 2185 StatusCode: 404, 2186 Errors: []HealthzError{ 2187 { 2188 Type: HealthzErrorAccount, 2189 Account: "abc", 2190 Error: `JetStream account "abc" not found`, 2191 }, 2192 }, 2193 }, 2194 }, 2195 { 2196 name: "stream not found", 2197 req: &HealthzEventOptions{ 2198 HealthzOptions: HealthzOptions{ 2199 Account: "ONE", 2200 Stream: "abc", 2201 }, 2202 }, 2203 expected: HealthStatus{ 2204 Status: "unavailable", 2205 StatusCode: 404, 2206 Error: `JetStream stream "abc" not found on account "ONE"`, 2207 }, 2208 }, 2209 { 2210 name: "stream not found, detailed", 2211 req: &HealthzEventOptions{ 2212 HealthzOptions: HealthzOptions{ 2213 Account: "ONE", 2214 Stream: "abc", 2215 Details: true, 2216 }, 2217 }, 2218 expected: HealthStatus{ 2219 Status: "error", 2220 StatusCode: 404, 2221 Errors: []HealthzError{ 2222 { 2223 Type: HealthzErrorStream, 2224 Account: "ONE", 2225 Stream: "abc", 2226 Error: `JetStream stream "abc" not found on account "ONE"`, 2227 }, 2228 }, 2229 }, 2230 }, 2231 { 2232 name: "consumer not found", 2233 req: &HealthzEventOptions{ 2234 HealthzOptions: HealthzOptions{ 2235 Account: "ONE", 2236 Stream: "test", 2237 Consumer: "abc", 2238 }, 2239 }, 2240 expected: HealthStatus{ 2241 Status: "unavailable", 2242 StatusCode: 404, 2243 Error: `JetStream consumer "abc" not found for stream "test" on account "ONE"`, 2244 }, 2245 }, 2246 { 2247 name: "consumer not found, detailed", 2248 req: &HealthzEventOptions{ 2249 HealthzOptions: HealthzOptions{ 2250 Account: "ONE", 2251 Stream: "test", 2252 Consumer: "abc", 2253 Details: true, 2254 }, 2255 }, 2256 expected: HealthStatus{ 2257 Status: "error", 2258 StatusCode: 404, 2259 Errors: []HealthzError{ 2260 { 2261 Type: HealthzErrorConsumer, 2262 Account: "ONE", 2263 Stream: "test", 2264 Consumer: "abc", 2265 Error: `JetStream consumer "abc" not found for stream "test" on account "ONE"`, 2266 }, 2267 }, 2268 }, 2269 }, 2270 } 2271 for _, test := range tests { 2272 t.Run(test.name, func(t *testing.T) { 2273 var body []byte 2274 var err error 2275 if test.req != nil { 2276 body, err = json.Marshal(test.req) 2277 if err != nil { 2278 t.Fatalf("Error marshaling request body: %v", err) 2279 } 2280 } 2281 msg, err := ncs.Request(subj, body, 1*time.Second) 2282 if err != nil { 2283 t.Fatalf("Error trying to request healthz: %v", err) 2284 } 2285 var health healthzResp 2286 if err := json.Unmarshal(msg.Data, &health); err != nil { 2287 t.Fatalf("Error unmarshalling the statz json: %v", err) 2288 } 2289 if !reflect.DeepEqual(health.Healthz, test.expected) { 2290 t.Errorf("Invalid healthz status; want: %+v; got: %+v", test.expected, health.Healthz) 2291 } 2292 }) 2293 } 2294 } 2295 2296 func TestServerEventsHealthZClustered(t *testing.T) { 2297 type healthzResp struct { 2298 Healthz HealthStatus `json:"data"` 2299 Server ServerInfo `json:"server"` 2300 } 2301 serverHealthzReqSubj := "$SYS.REQ.SERVER.%s.HEALTHZ" 2302 c := createJetStreamClusterWithTemplate(t, jsClusterAccountsTempl, "JSC", 3) 2303 defer c.shutdown() 2304 2305 ncs, err := nats.Connect(c.randomServer().ClientURL(), nats.UserInfo("admin", "s3cr3t!")) 2306 if err != nil { 2307 t.Fatalf("Error connecting to cluster: %v", err) 2308 } 2309 2310 defer ncs.Close() 2311 ncAcc, err := nats.Connect(c.randomServer().ClientURL()) 2312 if err != nil { 2313 t.Fatalf("Error on connect: %v", err) 2314 } 2315 defer ncAcc.Close() 2316 js, err := ncAcc.JetStream() 2317 if err != nil { 2318 t.Fatalf("Error creating JetStream context: %v", err) 2319 } 2320 _, err = js.AddStream(&nats.StreamConfig{ 2321 Name: "test", 2322 Subjects: []string{"foo"}, 2323 Replicas: 3, 2324 }) 2325 if err != nil { 2326 t.Fatalf("Error creating stream: %v", err) 2327 } 2328 _, err = js.AddConsumer("test", &nats.ConsumerConfig{ 2329 Name: "cons", 2330 Replicas: 3, 2331 }) 2332 if err != nil { 2333 t.Fatalf("Error creating consumer: %v", err) 2334 } 2335 2336 subj := fmt.Sprintf(serverHealthzReqSubj, c.servers[0].ID()) 2337 pingSubj := fmt.Sprintf(serverHealthzReqSubj, "PING") 2338 2339 tests := []struct { 2340 name string 2341 req *HealthzEventOptions 2342 expected HealthStatus 2343 expectedError string 2344 }{ 2345 { 2346 name: "no parameters", 2347 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2348 }, 2349 { 2350 name: "with js enabled only", 2351 req: &HealthzEventOptions{ 2352 HealthzOptions: HealthzOptions{ 2353 JSEnabledOnly: true, 2354 }, 2355 }, 2356 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2357 }, 2358 { 2359 name: "with server only", 2360 req: &HealthzEventOptions{ 2361 HealthzOptions: HealthzOptions{ 2362 JSServerOnly: true, 2363 }, 2364 }, 2365 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2366 }, 2367 { 2368 name: "with account name", 2369 req: &HealthzEventOptions{ 2370 HealthzOptions: HealthzOptions{ 2371 Account: "ONE", 2372 }, 2373 }, 2374 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2375 }, 2376 { 2377 name: "with account name and stream", 2378 req: &HealthzEventOptions{ 2379 HealthzOptions: HealthzOptions{ 2380 Account: "ONE", 2381 Stream: "test", 2382 }, 2383 }, 2384 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2385 }, 2386 { 2387 name: "with account name, stream and consumer", 2388 req: &HealthzEventOptions{ 2389 HealthzOptions: HealthzOptions{ 2390 Account: "ONE", 2391 Stream: "test", 2392 Consumer: "cons", 2393 }, 2394 }, 2395 expected: HealthStatus{Status: "ok", StatusCode: 200}, 2396 }, 2397 { 2398 name: "with stream only", 2399 req: &HealthzEventOptions{ 2400 HealthzOptions: HealthzOptions{ 2401 Stream: "test", 2402 }, 2403 }, 2404 expected: HealthStatus{ 2405 Status: "error", 2406 StatusCode: 400, 2407 Error: `"account" must not be empty when checking stream health`, 2408 }, 2409 expectedError: "Bad request:", 2410 }, 2411 { 2412 name: "with stream only, detailed", 2413 req: &HealthzEventOptions{ 2414 HealthzOptions: HealthzOptions{ 2415 Details: true, 2416 Stream: "test", 2417 }, 2418 }, 2419 expected: HealthStatus{ 2420 Status: "error", 2421 StatusCode: 400, 2422 Errors: []HealthzError{ 2423 { 2424 Type: HealthzErrorBadRequest, 2425 Error: `"account" must not be empty when checking stream health`, 2426 }, 2427 }, 2428 }, 2429 }, 2430 { 2431 name: "account not found", 2432 req: &HealthzEventOptions{ 2433 HealthzOptions: HealthzOptions{ 2434 Account: "abc", 2435 }, 2436 }, 2437 expected: HealthStatus{ 2438 Status: "unavailable", 2439 StatusCode: 404, 2440 Error: `JetStream account "abc" not found`, 2441 }, 2442 expectedError: `account "abc" not found`, 2443 }, 2444 { 2445 name: "account not found, detailed", 2446 req: &HealthzEventOptions{ 2447 HealthzOptions: HealthzOptions{ 2448 Account: "abc", 2449 Details: true, 2450 }, 2451 }, 2452 expected: HealthStatus{ 2453 Status: "error", 2454 StatusCode: 404, 2455 Errors: []HealthzError{ 2456 { 2457 Type: HealthzErrorAccount, 2458 Account: "abc", 2459 Error: `JetStream account "abc" not found`, 2460 }, 2461 }, 2462 }, 2463 }, 2464 { 2465 name: "stream not found", 2466 req: &HealthzEventOptions{ 2467 HealthzOptions: HealthzOptions{ 2468 Account: "ONE", 2469 Stream: "abc", 2470 }, 2471 }, 2472 expected: HealthStatus{ 2473 Status: "unavailable", 2474 StatusCode: 404, 2475 Error: `JetStream stream "abc" not found on account "ONE"`, 2476 }, 2477 expectedError: `stream "abc" not found`, 2478 }, 2479 { 2480 name: "stream not found, detailed", 2481 req: &HealthzEventOptions{ 2482 HealthzOptions: HealthzOptions{ 2483 Account: "ONE", 2484 Stream: "abc", 2485 Details: true, 2486 }, 2487 }, 2488 expected: HealthStatus{ 2489 Status: "error", 2490 StatusCode: 404, 2491 Errors: []HealthzError{ 2492 { 2493 Type: HealthzErrorStream, 2494 Account: "ONE", 2495 Stream: "abc", 2496 Error: `JetStream stream "abc" not found on account "ONE"`, 2497 }, 2498 }, 2499 }, 2500 }, 2501 { 2502 name: "consumer not found", 2503 req: &HealthzEventOptions{ 2504 HealthzOptions: HealthzOptions{ 2505 Account: "ONE", 2506 Stream: "test", 2507 Consumer: "abc", 2508 }, 2509 }, 2510 expected: HealthStatus{ 2511 Status: "unavailable", 2512 StatusCode: 404, 2513 Error: `JetStream consumer "abc" not found for stream "test" on account "ONE"`, 2514 }, 2515 expectedError: `consumer "abc" not found for stream "test"`, 2516 }, 2517 { 2518 name: "consumer not found, detailed", 2519 req: &HealthzEventOptions{ 2520 HealthzOptions: HealthzOptions{ 2521 Account: "ONE", 2522 Stream: "test", 2523 Consumer: "abc", 2524 Details: true, 2525 }, 2526 }, 2527 expected: HealthStatus{ 2528 Status: "error", 2529 StatusCode: 404, 2530 Errors: []HealthzError{ 2531 { 2532 Type: HealthzErrorConsumer, 2533 Account: "ONE", 2534 Stream: "test", 2535 Consumer: "abc", 2536 Error: `JetStream consumer "abc" not found for stream "test" on account "ONE"`, 2537 }, 2538 }, 2539 }, 2540 }, 2541 } 2542 for _, test := range tests { 2543 t.Run(test.name, func(t *testing.T) { 2544 var body []byte 2545 var err error 2546 if test.req != nil { 2547 body, err = json.Marshal(test.req) 2548 if err != nil { 2549 t.Fatalf("Error marshaling request body: %v", err) 2550 } 2551 } 2552 msg, err := ncs.Request(subj, body, 1*time.Second) 2553 if err != nil { 2554 t.Fatalf("Error trying to request healthz: %v", err) 2555 } 2556 var health healthzResp 2557 if err := json.Unmarshal(msg.Data, &health); err != nil { 2558 t.Fatalf("Error unmarshalling the statz json: %v", err) 2559 } 2560 if !reflect.DeepEqual(health.Healthz, test.expected) { 2561 t.Errorf("Invalid healthz status; want: %+v; got: %+v", test.expected, health.Healthz) 2562 } 2563 2564 reply := ncs.NewRespInbox() 2565 sub, err := ncs.SubscribeSync(reply) 2566 if err != nil { 2567 t.Fatalf("Error creating subscription: %v", err) 2568 } 2569 defer sub.Unsubscribe() 2570 2571 // now PING all servers 2572 if err := ncs.PublishRequest(pingSubj, reply, body); err != nil { 2573 t.Fatalf("Publish error: %v", err) 2574 } 2575 for i := 0; i < 3; i++ { 2576 msg, err := sub.NextMsg(1 * time.Second) 2577 if err != nil { 2578 t.Fatalf("Error fetching healthz PING response: %v", err) 2579 } 2580 var health healthzResp 2581 if err := json.Unmarshal(msg.Data, &health); err != nil { 2582 t.Fatalf("Error unmarshalling the statz json: %v", err) 2583 } 2584 if !reflect.DeepEqual(health.Healthz, test.expected) { 2585 t.Errorf("Invalid healthz status; want: %+v; got: %+v", test.expected, health.Healthz) 2586 } 2587 } 2588 if _, err := sub.NextMsg(50 * time.Millisecond); !errors.Is(err, nats.ErrTimeout) { 2589 t.Fatalf("Expected timeout error; got: %v", err) 2590 } 2591 }) 2592 } 2593 } 2594 2595 func TestServerEventsHealthZClustered_NoReplicas(t *testing.T) { 2596 type healthzResp struct { 2597 Healthz HealthStatus `json:"data"` 2598 Server ServerInfo `json:"server"` 2599 } 2600 serverHealthzReqSubj := "$SYS.REQ.SERVER.%s.HEALTHZ" 2601 c := createJetStreamClusterWithTemplate(t, jsClusterAccountsTempl, "JSC", 3) 2602 defer c.shutdown() 2603 2604 ncs, err := nats.Connect(c.randomServer().ClientURL(), nats.UserInfo("admin", "s3cr3t!")) 2605 if err != nil { 2606 t.Fatalf("Error connecting to cluster: %v", err) 2607 } 2608 2609 defer ncs.Close() 2610 ncAcc, err := nats.Connect(c.randomServer().ClientURL()) 2611 if err != nil { 2612 t.Fatalf("Error on connect: %v", err) 2613 } 2614 defer ncAcc.Close() 2615 js, err := ncAcc.JetStream() 2616 if err != nil { 2617 t.Fatalf("Error creating JetStream context: %v", err) 2618 } 2619 2620 pingSubj := fmt.Sprintf(serverHealthzReqSubj, "PING") 2621 2622 t.Run("non-replicated stream", func(t *testing.T) { 2623 _, err = js.AddStream(&nats.StreamConfig{ 2624 Name: "test", 2625 Subjects: []string{"foo"}, 2626 }) 2627 if err != nil { 2628 t.Fatalf("Error creating stream: %v", err) 2629 } 2630 _, err = js.AddConsumer("test", &nats.ConsumerConfig{ 2631 Name: "cons", 2632 }) 2633 if err != nil { 2634 t.Fatalf("Error creating consumer: %v", err) 2635 } 2636 body, err := json.Marshal(HealthzEventOptions{ 2637 HealthzOptions: HealthzOptions{ 2638 Account: "ONE", 2639 Stream: "test", 2640 }, 2641 }) 2642 if err != nil { 2643 t.Fatalf("Error marshaling request body: %v", err) 2644 } 2645 2646 reply := ncs.NewRespInbox() 2647 sub, err := ncs.SubscribeSync(reply) 2648 if err != nil { 2649 t.Fatalf("Error creating subscription: %v", err) 2650 } 2651 defer sub.Unsubscribe() 2652 2653 // now PING all servers 2654 if err := ncs.PublishRequest(pingSubj, reply, body); err != nil { 2655 t.Fatalf("Publish error: %v", err) 2656 } 2657 var healthy int 2658 for i := 0; i < 3; i++ { 2659 msg, err := sub.NextMsg(1 * time.Second) 2660 if err != nil { 2661 t.Fatalf("Error fetching healthz PING response: %v", err) 2662 } 2663 var health healthzResp 2664 if err := json.Unmarshal(msg.Data, &health); err != nil { 2665 t.Fatalf("Error unmarshalling the statz json: %v", err) 2666 } 2667 if health.Healthz.Status == "ok" { 2668 healthy++ 2669 continue 2670 } 2671 if !strings.Contains(health.Healthz.Error, `stream "test" not found`) { 2672 t.Errorf("Expected error to contain: %q, got: %s", `stream "test" not found`, health.Healthz.Error) 2673 } 2674 } 2675 if healthy != 1 { 2676 t.Fatalf("Expected 1 healthy server; got: %d", healthy) 2677 } 2678 if _, err := sub.NextMsg(50 * time.Millisecond); !errors.Is(err, nats.ErrTimeout) { 2679 t.Fatalf("Expected timeout error; got: %v", err) 2680 } 2681 }) 2682 2683 t.Run("non-replicated consumer", func(t *testing.T) { 2684 _, err = js.AddStream(&nats.StreamConfig{ 2685 Name: "test-repl", 2686 Subjects: []string{"bar"}, 2687 Replicas: 3, 2688 }) 2689 if err != nil { 2690 t.Fatalf("Error creating stream: %v", err) 2691 } 2692 _, err = js.AddConsumer("test-repl", &nats.ConsumerConfig{ 2693 Name: "cons-single", 2694 }) 2695 if err != nil { 2696 t.Fatalf("Error creating consumer: %v", err) 2697 } 2698 body, err := json.Marshal(HealthzEventOptions{ 2699 HealthzOptions: HealthzOptions{ 2700 Account: "ONE", 2701 Stream: "test-repl", 2702 Consumer: "cons-single", 2703 }, 2704 }) 2705 if err != nil { 2706 t.Fatalf("Error marshaling request body: %v", err) 2707 } 2708 2709 reply := ncs.NewRespInbox() 2710 sub, err := ncs.SubscribeSync(reply) 2711 if err != nil { 2712 t.Fatalf("Error creating subscription: %v", err) 2713 } 2714 defer sub.Unsubscribe() 2715 2716 // now PING all servers 2717 if err := ncs.PublishRequest(pingSubj, reply, body); err != nil { 2718 t.Fatalf("Publish error: %v", err) 2719 } 2720 var healthy int 2721 for i := 0; i < 3; i++ { 2722 msg, err := sub.NextMsg(1 * time.Second) 2723 if err != nil { 2724 t.Fatalf("Error fetching healthz PING response: %v", err) 2725 } 2726 var health healthzResp 2727 if err := json.Unmarshal(msg.Data, &health); err != nil { 2728 t.Fatalf("Error unmarshalling the statz json: %v", err) 2729 } 2730 if health.Healthz.Status == "ok" { 2731 healthy++ 2732 continue 2733 } 2734 if !strings.Contains(health.Healthz.Error, `consumer "cons-single" not found`) { 2735 t.Errorf("Expected error to contain: %q, got: %s", `consumer "cons-single" not found`, health.Healthz.Error) 2736 } 2737 } 2738 if healthy != 1 { 2739 t.Fatalf("Expected 1 healthy server; got: %d", healthy) 2740 } 2741 if _, err := sub.NextMsg(50 * time.Millisecond); !errors.Is(err, nats.ErrTimeout) { 2742 t.Fatalf("Expected timeout error; got: %v", err) 2743 } 2744 }) 2745 2746 } 2747 2748 func TestServerEventsHealthZJetStreamNotEnabled(t *testing.T) { 2749 type healthzResp struct { 2750 Healthz HealthStatus `json:"data"` 2751 Server ServerInfo `json:"server"` 2752 } 2753 cfg := `listen: 127.0.0.1:-1 2754 2755 accounts { 2756 $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } 2757 }` 2758 2759 serverHealthzReqSubj := "$SYS.REQ.SERVER.%s.HEALTHZ" 2760 s, _ := RunServerWithConfig(createConfFile(t, []byte(cfg))) 2761 defer s.Shutdown() 2762 2763 ncs, err := nats.Connect(s.ClientURL(), nats.UserInfo("admin", "s3cr3t!")) 2764 if err != nil { 2765 t.Fatalf("Error connecting to cluster: %v", err) 2766 } 2767 2768 defer ncs.Close() 2769 2770 subj := fmt.Sprintf(serverHealthzReqSubj, s.ID()) 2771 2772 msg, err := ncs.Request(subj, nil, 1*time.Second) 2773 if err != nil { 2774 t.Fatalf("Error trying to request healthz: %v", err) 2775 } 2776 var health healthzResp 2777 if err := json.Unmarshal(msg.Data, &health); err != nil { 2778 t.Fatalf("Error unmarshalling the statz json: %v", err) 2779 } 2780 if health.Healthz.Status != "ok" { 2781 t.Errorf("Invalid healthz status; want: %q; got: %q", "ok", health.Healthz.Status) 2782 } 2783 if health.Healthz.Error != "" { 2784 t.Errorf("HealthZ error: %s", health.Healthz.Error) 2785 } 2786 } 2787 2788 func TestServerEventsPingStatsZ(t *testing.T) { 2789 sa, _, sb, optsB, akp := runTrustedCluster(t) 2790 defer sa.Shutdown() 2791 defer sb.Shutdown() 2792 url := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 2793 nc, err := nats.Connect(url, createUserCreds(t, sb, akp)) 2794 if err != nil { 2795 t.Fatalf("Error on connect: %v", err) 2796 } 2797 defer nc.Close() 2798 test := func(req []byte) { 2799 reply := nc.NewRespInbox() 2800 sub, _ := nc.SubscribeSync(reply) 2801 nc.PublishRequest(serverStatsPingReqSubj, reply, req) 2802 // Make sure its a statsz 2803 m := ServerStatsMsg{} 2804 // Receive both manually. 2805 msg, err := sub.NextMsg(time.Second) 2806 if err != nil { 2807 t.Fatalf("Error receiving msg: %v", err) 2808 } 2809 if err := json.Unmarshal(msg.Data, &m); err != nil { 2810 t.Fatalf("Error unmarshalling the statz json: %v", err) 2811 } 2812 msg, err = sub.NextMsg(time.Second) 2813 if err != nil { 2814 t.Fatalf("Error receiving msg: %v", err) 2815 } 2816 if err := json.Unmarshal(msg.Data, &m); err != nil { 2817 t.Fatalf("Error unmarshalling the statz json: %v", err) 2818 } 2819 } 2820 strRequestTbl := []string{ 2821 `{"cluster":"TEST"}`, 2822 `{"cluster":"CLUSTER"}`, 2823 `{"server_name":"SRV"}`, 2824 `{"server_name":"_"}`, 2825 fmt.Sprintf(`{"host":"%s"}`, optsB.Host), 2826 fmt.Sprintf(`{"host":"%s", "cluster":"CLUSTER", "name":"SRV"}`, optsB.Host), 2827 } 2828 for i, opt := range strRequestTbl { 2829 t.Run(fmt.Sprintf("%s-%d", t.Name(), i), func(t *testing.T) { 2830 test([]byte(opt)) 2831 }) 2832 } 2833 requestTbl := []StatszEventOptions{ 2834 {EventFilterOptions: EventFilterOptions{Cluster: "TEST"}}, 2835 {EventFilterOptions: EventFilterOptions{Cluster: "CLUSTER"}}, 2836 {EventFilterOptions: EventFilterOptions{Name: "SRV"}}, 2837 {EventFilterOptions: EventFilterOptions{Name: "_"}}, 2838 {EventFilterOptions: EventFilterOptions{Host: optsB.Host}}, 2839 {EventFilterOptions: EventFilterOptions{Host: optsB.Host, Cluster: "CLUSTER", Name: "SRV"}}, 2840 } 2841 for i, opt := range requestTbl { 2842 t.Run(fmt.Sprintf("%s-%d", t.Name(), i), func(t *testing.T) { 2843 msg, _ := json.MarshalIndent(&opt, "", " ") 2844 test(msg) 2845 }) 2846 } 2847 } 2848 2849 func TestServerEventsPingStatsZFilter(t *testing.T) { 2850 sa, _, sb, optsB, akp := runTrustedCluster(t) 2851 defer sa.Shutdown() 2852 defer sb.Shutdown() 2853 2854 url := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 2855 nc, err := nats.Connect(url, createUserCreds(t, sb, akp)) 2856 if err != nil { 2857 t.Fatalf("Error on connect: %v", err) 2858 } 2859 defer nc.Close() 2860 2861 requestTbl := []string{ 2862 `{"cluster":"DOESNOTEXIST"}`, 2863 `{"host":"DOESNOTEXIST"}`, 2864 `{"server_name":"DOESNOTEXIST"}`, 2865 } 2866 for i, msg := range requestTbl { 2867 t.Run(fmt.Sprintf("%s-%d", t.Name(), i), func(t *testing.T) { 2868 // Receive both manually. 2869 if _, err := nc.Request(serverStatsPingReqSubj, []byte(msg), time.Second/4); err != nats.ErrTimeout { 2870 t.Fatalf("Error, expected timeout: %v", err) 2871 } 2872 }) 2873 } 2874 requestObjTbl := []EventFilterOptions{ 2875 {Cluster: "DOESNOTEXIST"}, 2876 {Host: "DOESNOTEXIST"}, 2877 {Name: "DOESNOTEXIST"}, 2878 } 2879 for i, opt := range requestObjTbl { 2880 t.Run(fmt.Sprintf("%s-%d", t.Name(), i), func(t *testing.T) { 2881 msg, _ := json.MarshalIndent(&opt, "", " ") 2882 // Receive both manually. 2883 if _, err := nc.Request(serverStatsPingReqSubj, []byte(msg), time.Second/4); err != nats.ErrTimeout { 2884 t.Fatalf("Error, expected timeout: %v", err) 2885 } 2886 }) 2887 } 2888 } 2889 2890 func TestServerEventsPingStatsZFailFilter(t *testing.T) { 2891 sa, _, sb, optsB, akp := runTrustedCluster(t) 2892 defer sa.Shutdown() 2893 defer sb.Shutdown() 2894 2895 url := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 2896 nc, err := nats.Connect(url, createUserCreds(t, sb, akp)) 2897 if err != nil { 2898 t.Fatalf("Error on connect: %v", err) 2899 } 2900 defer nc.Close() 2901 2902 // Receive both manually. 2903 if msg, err := nc.Request(serverStatsPingReqSubj, []byte(`{MALFORMEDJSON`), time.Second/4); err != nil { 2904 t.Fatalf("Error: %v", err) 2905 } else { 2906 resp := make(map[string]map[string]any) 2907 if err := json.Unmarshal(msg.Data, &resp); err != nil { 2908 t.Fatalf("Error unmarshalling the response json: %v", err) 2909 } 2910 if resp["error"]["code"].(float64) != http.StatusBadRequest { 2911 t.Fatal("bad error code") 2912 } 2913 } 2914 } 2915 2916 func TestServerEventsPingMonitorz(t *testing.T) { 2917 sa, _, sb, optsB, akp := runTrustedCluster(t) 2918 defer sa.Shutdown() 2919 defer sb.Shutdown() 2920 sysAcc, _ := akp.PublicKey() 2921 url := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 2922 nc, err := nats.Connect(url, createUserCreds(t, sb, akp)) 2923 if err != nil { 2924 t.Fatalf("Error on connect: %v", err) 2925 } 2926 defer nc.Close() 2927 2928 nc.Flush() 2929 2930 tests := []struct { 2931 endpoint string 2932 opt any 2933 resp any 2934 respField []string 2935 }{ 2936 {"VARZ", nil, &Varz{}, 2937 []string{"now", "cpu", "system_account"}}, 2938 {"SUBSZ", nil, &Subsz{}, 2939 []string{"num_subscriptions", "num_cache"}}, 2940 {"CONNZ", nil, &Connz{}, 2941 []string{"now", "connections"}}, 2942 {"ROUTEZ", nil, &Routez{}, 2943 []string{"now", "routes"}}, 2944 {"GATEWAYZ", nil, &Gatewayz{}, 2945 []string{"now", "outbound_gateways", "inbound_gateways"}}, 2946 {"LEAFZ", nil, &Leafz{}, 2947 []string{"now", "leafs"}}, 2948 2949 {"SUBSZ", &SubszOptions{}, &Subsz{}, 2950 []string{"num_subscriptions", "num_cache"}}, 2951 {"CONNZ", &ConnzOptions{}, &Connz{}, 2952 []string{"now", "connections"}}, 2953 {"ROUTEZ", &RoutezOptions{}, &Routez{}, 2954 []string{"now", "routes"}}, 2955 {"GATEWAYZ", &GatewayzOptions{}, &Gatewayz{}, 2956 []string{"now", "outbound_gateways", "inbound_gateways"}}, 2957 {"LEAFZ", &LeafzOptions{}, &Leafz{}, 2958 []string{"now", "leafs"}}, 2959 {"ACCOUNTZ", &AccountzOptions{}, &Accountz{}, 2960 []string{"now", "accounts"}}, 2961 2962 {"SUBSZ", &SubszOptions{Limit: 5}, &Subsz{}, 2963 []string{"num_subscriptions", "num_cache"}}, 2964 {"CONNZ", &ConnzOptions{Limit: 5}, &Connz{}, 2965 []string{"now", "connections"}}, 2966 {"ROUTEZ", &RoutezOptions{SubscriptionsDetail: true}, &Routez{}, 2967 []string{"now", "routes"}}, 2968 {"GATEWAYZ", &GatewayzOptions{Accounts: true}, &Gatewayz{}, 2969 []string{"now", "outbound_gateways", "inbound_gateways"}}, 2970 {"LEAFZ", &LeafzOptions{Subscriptions: true}, &Leafz{}, 2971 []string{"now", "leafs"}}, 2972 {"ACCOUNTZ", &AccountzOptions{Account: sysAcc}, &Accountz{}, 2973 []string{"now", "account_detail"}}, 2974 {"LEAFZ", &LeafzOptions{Account: sysAcc}, &Leafz{}, 2975 []string{"now", "leafs"}}, 2976 2977 {"ROUTEZ", json.RawMessage(`{"cluster":""}`), &Routez{}, 2978 []string{"now", "routes"}}, 2979 {"ROUTEZ", json.RawMessage(`{"name":""}`), &Routez{}, 2980 []string{"now", "routes"}}, 2981 {"ROUTEZ", json.RawMessage(`{"cluster":"TEST CLUSTER 22"}`), &Routez{}, 2982 []string{"now", "routes"}}, 2983 {"ROUTEZ", json.RawMessage(`{"cluster":"CLUSTER"}`), &Routez{}, 2984 []string{"now", "routes"}}, 2985 {"ROUTEZ", json.RawMessage(`{"cluster":"TEST CLUSTER 22", "subscriptions":true}`), &Routez{}, 2986 []string{"now", "routes"}}, 2987 2988 {"JSZ", nil, &JSzOptions{}, []string{"now", "disabled"}}, 2989 2990 {"HEALTHZ", nil, &JSzOptions{}, []string{"status"}}, 2991 {"HEALTHZ", &HealthzOptions{JSEnabledOnly: true}, &JSzOptions{}, []string{"status"}}, 2992 {"HEALTHZ", &HealthzOptions{JSServerOnly: true}, &JSzOptions{}, []string{"status"}}, 2993 } 2994 2995 for i, test := range tests { 2996 t.Run(fmt.Sprintf("%s-%d", test.endpoint, i), func(t *testing.T) { 2997 var opt []byte 2998 if test.opt != nil { 2999 opt, err = json.Marshal(test.opt) 3000 if err != nil { 3001 t.Fatalf("Error marshaling opts: %v", err) 3002 } 3003 } 3004 reply := nc.NewRespInbox() 3005 replySubj, _ := nc.SubscribeSync(reply) 3006 3007 // set a header to make sure request parsing knows to ignore them 3008 nc.PublishMsg(&nats.Msg{ 3009 Subject: fmt.Sprintf("%s.%s", serverStatsPingReqSubj, test.endpoint), 3010 Reply: reply, 3011 Header: nats.Header{"header": []string{"for header sake"}}, 3012 Data: opt, 3013 }) 3014 3015 // Receive both manually. 3016 msg, err := replySubj.NextMsg(time.Second) 3017 if err != nil { 3018 t.Fatalf("Error receiving msg: %v", err) 3019 } 3020 response1 := make(map[string]map[string]any) 3021 3022 if err := json.Unmarshal(msg.Data, &response1); err != nil { 3023 t.Fatalf("Error unmarshalling response1 json: %v", err) 3024 } 3025 3026 serverName := "" 3027 if response1["server"]["name"] == "A_SRV" { 3028 serverName = "B_SRV" 3029 } else if response1["server"]["name"] == "B_SRV" { 3030 serverName = "A_SRV" 3031 } else { 3032 t.Fatalf("Error finding server in %s", string(msg.Data)) 3033 } 3034 if resp, ok := response1["data"]; !ok { 3035 t.Fatalf("Error finding: %s in %s", 3036 strings.ToLower(test.endpoint), string(msg.Data)) 3037 } else { 3038 for _, respField := range test.respField { 3039 if _, ok := resp[respField]; !ok { 3040 t.Fatalf("Error finding: %s in %s", respField, resp) 3041 } 3042 } 3043 } 3044 3045 msg, err = replySubj.NextMsg(time.Second) 3046 if err != nil { 3047 t.Fatalf("Error receiving msg: %v", err) 3048 } 3049 response2 := make(map[string]map[string]any) 3050 if err := json.Unmarshal(msg.Data, &response2); err != nil { 3051 t.Fatalf("Error unmarshalling the response2 json: %v", err) 3052 } 3053 if response2["server"]["name"] != serverName { 3054 t.Fatalf("Error finding server %s in %s", serverName, string(msg.Data)) 3055 } 3056 if resp, ok := response2["data"]; !ok { 3057 t.Fatalf("Error finding: %s in %s", 3058 strings.ToLower(test.endpoint), string(msg.Data)) 3059 } else { 3060 for _, respField := range test.respField { 3061 if _, ok := resp[respField]; !ok { 3062 t.Fatalf("Error finding: %s in %s", respField, resp) 3063 } 3064 } 3065 } 3066 }) 3067 } 3068 } 3069 3070 func TestGatewayNameClientInfo(t *testing.T) { 3071 sa, _, sb, _, _ := runTrustedCluster(t) 3072 defer sa.Shutdown() 3073 defer sb.Shutdown() 3074 3075 c, _, l := newClientForServer(sa) 3076 defer c.close() 3077 3078 var info Info 3079 err := json.Unmarshal([]byte(l[5:]), &info) 3080 if err != nil { 3081 t.Fatalf("Could not parse INFO json: %v\n", err) 3082 } 3083 if info.Cluster != "TEST CLUSTER 22" { 3084 t.Fatalf("Expected a cluster name of 'TEST CLUSTER 22', got %q", info.Cluster) 3085 } 3086 } 3087 3088 type slowAccResolver struct { 3089 sync.Mutex 3090 AccountResolver 3091 acc string 3092 } 3093 3094 func (sr *slowAccResolver) Fetch(name string) (string, error) { 3095 sr.Lock() 3096 delay := sr.acc == name 3097 sr.Unlock() 3098 if delay { 3099 time.Sleep(200 * time.Millisecond) 3100 } 3101 return sr.AccountResolver.Fetch(name) 3102 } 3103 3104 func TestConnectionUpdatesTimerProperlySet(t *testing.T) { 3105 origEventsHBInterval := eventsHBInterval 3106 eventsHBInterval = 50 * time.Millisecond 3107 defer func() { eventsHBInterval = origEventsHBInterval }() 3108 3109 sa, _, sb, optsB, _ := runTrustedCluster(t) 3110 defer sa.Shutdown() 3111 defer sb.Shutdown() 3112 3113 // Normal Account 3114 okp, _ := nkeys.FromSeed(oSeed) 3115 akp, _ := nkeys.CreateAccount() 3116 pub, _ := akp.PublicKey() 3117 nac := jwt.NewAccountClaims(pub) 3118 nac.Limits.Conn = 10 // set any limit... 3119 jwt, _ := nac.Encode(okp) 3120 3121 addAccountToMemResolver(sa, pub, jwt) 3122 3123 // Listen for HB updates... 3124 count := int32(0) 3125 cb := func(sub *subscription, _ *client, _ *Account, subject, reply string, msg []byte) { 3126 atomic.AddInt32(&count, 1) 3127 } 3128 subj := fmt.Sprintf(accConnsEventSubjNew, pub) 3129 sub, err := sa.sysSubscribe(subj, cb) 3130 if sub == nil || err != nil { 3131 t.Fatalf("Expected to subscribe, got %v", err) 3132 } 3133 defer sa.sysUnsubscribe(sub) 3134 3135 url := fmt.Sprintf("nats://%s:%d", optsB.Host, optsB.Port) 3136 nc := natsConnect(t, url, createUserCreds(t, sb, akp)) 3137 defer nc.Close() 3138 3139 time.Sleep(500 * time.Millisecond) 3140 // After waiting 500ms with HB interval of 50ms, we should get 3141 // about 10 updates, no much more 3142 if n := atomic.LoadInt32(&count); n > 15 { 3143 t.Fatalf("Expected about 10 updates, got %v", n) 3144 } 3145 3146 // Now lookup the account doing the events on sb. 3147 acc, _ := sb.LookupAccount(pub) 3148 // Make sure we have the timer running. 3149 acc.mu.RLock() 3150 ctmr := acc.ctmr 3151 acc.mu.RUnlock() 3152 if ctmr == nil { 3153 t.Fatalf("Expected event timer for acc conns to be running") 3154 } 3155 3156 nc.Close() 3157 3158 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 3159 // Make sure we have the timer is NOT running. 3160 acc.mu.RLock() 3161 ctmr = acc.ctmr 3162 acc.mu.RUnlock() 3163 if ctmr != nil { 3164 return fmt.Errorf("Expected event timer for acc conns to NOT be running after reaching zero local clients") 3165 } 3166 return nil 3167 }) 3168 } 3169 3170 func TestServerEventsReceivedByQSubs(t *testing.T) { 3171 s, opts := runTrustedServer(t) 3172 defer s.Shutdown() 3173 3174 acc, akp := createAccount(s) 3175 s.setSystemAccount(acc) 3176 3177 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 3178 ncs, err := nats.Connect(url, createUserCreds(t, s, akp)) 3179 if err != nil { 3180 t.Fatalf("Error on connect: %v", err) 3181 } 3182 defer ncs.Close() 3183 3184 // Listen for auth error events. 3185 qsub, _ := ncs.QueueSubscribeSync("$SYS.SERVER.*.CLIENT.AUTH.ERR", "queue") 3186 defer qsub.Unsubscribe() 3187 3188 ncs.Flush() 3189 3190 nats.Connect(url, nats.Name("TEST BAD LOGIN")) 3191 3192 m, err := qsub.NextMsg(time.Second) 3193 if err != nil { 3194 t.Fatalf("Should have heard an auth error event") 3195 } 3196 dem := DisconnectEventMsg{} 3197 if err := json.Unmarshal(m.Data, &dem); err != nil { 3198 t.Fatalf("Error unmarshalling disconnect event message: %v", err) 3199 } 3200 if dem.Reason != "Authentication Failure" { 3201 t.Fatalf("Expected auth error, got %q", dem.Reason) 3202 } 3203 } 3204 3205 func TestServerEventsFilteredByTag(t *testing.T) { 3206 confA := createConfFile(t, []byte(` 3207 listen: -1 3208 server_name: srv-A 3209 server_tags: ["foo", "bar"] 3210 cluster { 3211 name: clust 3212 listen: -1 3213 no_advertise: true 3214 } 3215 system_account: SYS 3216 accounts: { 3217 SYS: { 3218 users: [ 3219 {user: b, password: b} 3220 ] 3221 } 3222 } 3223 no_auth_user: b 3224 `)) 3225 sA, _ := RunServerWithConfig(confA) 3226 defer sA.Shutdown() 3227 confB := createConfFile(t, []byte(fmt.Sprintf(` 3228 listen: -1 3229 server_name: srv-B 3230 server_tags: ["bar", "baz"] 3231 cluster { 3232 name: clust 3233 listen: -1 3234 no_advertise: true 3235 routes [ 3236 nats-route://127.0.0.1:%d 3237 ] 3238 } 3239 system_account: SYS 3240 accounts: { 3241 SYS: { 3242 users: [ 3243 {user: b, password: b} 3244 ] 3245 } 3246 } 3247 no_auth_user: b 3248 `, sA.opts.Cluster.Port))) 3249 sB, _ := RunServerWithConfig(confB) 3250 defer sB.Shutdown() 3251 checkClusterFormed(t, sA, sB) 3252 nc := natsConnect(t, sA.ClientURL()) 3253 defer nc.Close() 3254 3255 ib := nats.NewInbox() 3256 req := func(tags ...string) { 3257 t.Helper() 3258 r, err := json.Marshal(VarzEventOptions{EventFilterOptions: EventFilterOptions{Tags: tags}}) 3259 require_NoError(t, err) 3260 err = nc.PublishRequest(fmt.Sprintf(serverPingReqSubj, "VARZ"), ib, r) 3261 require_NoError(t, err) 3262 } 3263 3264 msgs := make(chan *nats.Msg, 10) 3265 defer close(msgs) 3266 _, err := nc.ChanSubscribe(ib, msgs) 3267 require_NoError(t, err) 3268 req("none") 3269 select { 3270 case <-msgs: 3271 t.Fatalf("no message expected") 3272 case <-time.After(200 * time.Millisecond): 3273 } 3274 req("foo") 3275 m := <-msgs 3276 require_Contains(t, string(m.Data), "srv-A", "foo", "bar") 3277 req("foo", "bar") 3278 m = <-msgs 3279 require_Contains(t, string(m.Data), "srv-A", "foo", "bar") 3280 req("baz") 3281 m = <-msgs 3282 require_Contains(t, string(m.Data), "srv-B", "bar", "baz") 3283 req("bar") 3284 m1 := <-msgs 3285 m2 := <-msgs 3286 require_Contains(t, string(m1.Data)+string(m2.Data), "srv-A", "srv-B", "foo", "bar", "baz") 3287 require_Len(t, len(msgs), 0) 3288 } 3289 3290 // https://github.com/nats-io/nats-server/issues/3177 3291 func TestServerEventsAndDQSubscribers(t *testing.T) { 3292 c := createJetStreamClusterWithTemplate(t, jsClusterAccountsTempl, "DDQ", 3) 3293 defer c.shutdown() 3294 3295 nc, err := nats.Connect(c.randomServer().ClientURL(), nats.UserInfo("admin", "s3cr3t!")) 3296 require_NoError(t, err) 3297 defer nc.Close() 3298 3299 sub, err := nc.QueueSubscribeSync("$SYS.ACCOUNT.*.DISCONNECT", "qq") 3300 require_NoError(t, err) 3301 nc.Flush() 3302 3303 // Create and disconnect 10 random connections. 3304 for i := 0; i < 10; i++ { 3305 nc, err := nats.Connect(c.randomServer().ClientURL()) 3306 require_NoError(t, err) 3307 nc.Close() 3308 } 3309 3310 checkSubsPending(t, sub, 10) 3311 } 3312 3313 func TestServerEventsStatszSingleServer(t *testing.T) { 3314 conf := createConfFile(t, []byte(` 3315 listen: "127.0.0.1:-1" 3316 accounts { $SYS { users [{user: "admin", password: "p1d"}]} } 3317 `)) 3318 s, _ := RunServerWithConfig(conf) 3319 defer s.Shutdown() 3320 3321 // Grab internal system client. 3322 s.mu.RLock() 3323 sysc := s.sys.client 3324 wait := s.sys.cstatsz + 25*time.Millisecond 3325 s.mu.RUnlock() 3326 3327 // Wait for when first statsz would have gone out.. 3328 time.Sleep(wait) 3329 3330 sysc.mu.Lock() 3331 outMsgs := sysc.stats.outMsgs 3332 sysc.mu.Unlock() 3333 3334 require_True(t, outMsgs == 0) 3335 3336 // Connect as a system user and make sure if there is 3337 // subscription interest that we will receive updates. 3338 nc, _ := jsClientConnect(t, s, nats.UserInfo("admin", "p1d")) 3339 defer nc.Close() 3340 3341 sub, err := nc.SubscribeSync(fmt.Sprintf(serverStatsSubj, "*")) 3342 require_NoError(t, err) 3343 3344 checkSubsPending(t, sub, 1) 3345 } 3346 3347 func TestServerEventsReload(t *testing.T) { 3348 conf := createConfFile(t, []byte(` 3349 listen: "127.0.0.1:-1" 3350 accounts: { 3351 $SYS { users [{user: "admin", password: "p1d"}]} 3352 test { users [{user: "foo", password: "bar"}]} 3353 } 3354 ping_interval: "100ms" 3355 `)) 3356 opts := LoadConfig(conf) 3357 s := RunServer(opts) 3358 defer s.Shutdown() 3359 subject := fmt.Sprintf(serverReloadReqSubj, s.info.ID) 3360 3361 // Connect as a test user and make sure the reload endpoint is not 3362 // accessible. 3363 ncTest, _ := jsClientConnect(t, s, nats.UserInfo("foo", "bar")) 3364 defer ncTest.Close() 3365 testReply := ncTest.NewRespInbox() 3366 sub, err := ncTest.SubscribeSync(testReply) 3367 require_NoError(t, err) 3368 err = ncTest.PublishRequest(subject, testReply, nil) 3369 require_NoError(t, err) 3370 _, err = sub.NextMsg(time.Second) 3371 require_Error(t, err) 3372 3373 require_True(t, s.getOpts().PingInterval == 100*time.Millisecond) 3374 3375 // Connect as a system user. 3376 nc, _ := jsClientConnect(t, s, nats.UserInfo("admin", "p1d")) 3377 defer nc.Close() 3378 3379 // rewrite the config file with a different ping interval 3380 err = os.WriteFile(conf, []byte(` 3381 listen: "127.0.0.1:-1" 3382 accounts: { 3383 $SYS { users [{user: "admin", password: "p1d"}]} 3384 test { users [{user: "foo", password: "bar"}]} 3385 } 3386 ping_interval: "200ms" 3387 `), 0666) 3388 require_NoError(t, err) 3389 3390 msg, err := nc.Request(subject, nil, time.Second) 3391 require_NoError(t, err) 3392 3393 var apiResp = ServerAPIResponse{} 3394 err = json.Unmarshal(msg.Data, &apiResp) 3395 require_NoError(t, err) 3396 3397 require_True(t, apiResp.Data == nil) 3398 require_True(t, apiResp.Error == nil) 3399 3400 // See that the ping interval has changed. 3401 require_True(t, s.getOpts().PingInterval == 200*time.Millisecond) 3402 3403 // rewrite the config file with a different ping interval 3404 err = os.WriteFile(conf, []byte(`garbage and nonsense`), 0666) 3405 require_NoError(t, err) 3406 3407 // Request the server to reload and wait for the response. 3408 msg, err = nc.Request(subject, nil, time.Second) 3409 require_NoError(t, err) 3410 3411 apiResp = ServerAPIResponse{} 3412 err = json.Unmarshal(msg.Data, &apiResp) 3413 require_NoError(t, err) 3414 3415 require_True(t, apiResp.Data == nil) 3416 require_Error(t, apiResp.Error, fmt.Errorf("Parse error on line 1: 'Expected a top-level value to end with a new line, comment or EOF, but got 'n' instead.'")) 3417 3418 // See that the ping interval has not changed. 3419 require_True(t, s.getOpts().PingInterval == 200*time.Millisecond) 3420 } 3421 3422 func TestServerEventsLDMKick(t *testing.T) { 3423 ldmed := make(chan bool, 1) 3424 disconnected := make(chan bool, 1) 3425 3426 s, opts := runTrustedServer(t) 3427 defer s.Shutdown() 3428 3429 acc, akp := createAccount(s) 3430 s.setSystemAccount(acc) 3431 3432 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 3433 ncs, err := nats.Connect(url, createUserCreds(t, s, akp)) 3434 if err != nil { 3435 t.Fatalf("Error on connect: %v", err) 3436 } 3437 defer ncs.Close() 3438 3439 _, akp2 := createAccount(s) 3440 3441 nc, err := nats.Connect(url, createUserCreds(t, s, akp2), nats.Name("TEST EVENTS LDM+KICK"), nats.LameDuckModeHandler(func(_ *nats.Conn) { ldmed <- true })) 3442 if err != nil { 3443 t.Fatalf("Error on connect: %v", err) 3444 } 3445 defer nc.Close() 3446 3447 nc.SetDisconnectErrHandler(func(_ *nats.Conn, err error) { disconnected <- true }) 3448 3449 cid, err := nc.GetClientID() 3450 if err != nil { 3451 t.Fatalf("Error on getting the CID: %v", err) 3452 } 3453 3454 reqldm := LDMClientReq{CID: cid} 3455 reqldmpayload, _ := json.Marshal(reqldm) 3456 reqkick := KickClientReq{CID: cid} 3457 reqkickpayload, _ := json.Marshal(reqkick) 3458 3459 _, err = ncs.Request(fmt.Sprintf("$SYS.REQ.SERVER.%s.LDM", s.ID()), reqldmpayload, time.Second) 3460 if err != nil { 3461 t.Fatalf("Error trying to publish the LDM request: %v", err) 3462 } 3463 3464 select { 3465 case <-ldmed: 3466 case <-time.After(time.Second): 3467 t.Fatalf("timeout waiting for the connection to receive the LDM signal") 3468 } 3469 3470 _, err = ncs.Request(fmt.Sprintf("$SYS.REQ.SERVER.%s.KICK", s.ID()), reqkickpayload, time.Second) 3471 if err != nil { 3472 t.Fatalf("Error trying to publish the KICK request: %v", err) 3473 } 3474 3475 select { 3476 case <-disconnected: 3477 case <-time.After(time.Second): 3478 t.Fatalf("timeout waiting for the client to get disconnected") 3479 } 3480 } 3481 3482 func Benchmark_GetHash(b *testing.B) { 3483 b.StopTimer() 3484 // Get 100 random names 3485 names := make([]string, 0, 100) 3486 for i := 0; i < 100; i++ { 3487 names = append(names, nuid.Next()) 3488 } 3489 hashes := make([]string, 0, 100) 3490 for j := 0; j < 100; j++ { 3491 sha := sha256.New() 3492 sha.Write([]byte(names[j])) 3493 b := sha.Sum(nil) 3494 for i := 0; i < 8; i++ { 3495 b[i] = digits[int(b[i]%base)] 3496 } 3497 hashes = append(hashes, string(b[:8])) 3498 } 3499 wg := sync.WaitGroup{} 3500 wg.Add(8) 3501 errCh := make(chan error, 8) 3502 b.StartTimer() 3503 for i := 0; i < 8; i++ { 3504 go func() { 3505 defer wg.Done() 3506 for i := 0; i < b.N; i++ { 3507 idx := rand.Intn(100) 3508 if h := getHash(names[idx]); h != hashes[idx] { 3509 errCh <- fmt.Errorf("Hash for name %q was %q, but should be %q", names[idx], h, hashes[idx]) 3510 return 3511 } 3512 } 3513 }() 3514 } 3515 wg.Wait() 3516 select { 3517 case err := <-errCh: 3518 b.Fatal(err.Error()) 3519 default: 3520 } 3521 }