github.com/nats-io/nats-server/v2@v2.11.0-preview.2/server/jetstream_jwt_test.go (about) 1 // Copyright 2020-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 //go:build !skip_js_tests 15 // +build !skip_js_tests 16 17 package server 18 19 import ( 20 "encoding/json" 21 "errors" 22 "fmt" 23 "net/http" 24 "net/http/httptest" 25 "strings" 26 "sync/atomic" 27 "testing" 28 "time" 29 30 jwt "github.com/nats-io/jwt/v2" 31 "github.com/nats-io/nats.go" 32 "github.com/nats-io/nkeys" 33 ) 34 35 func TestJetStreamJWTLimits(t *testing.T) { 36 updateJwt := func(url string, creds string, pubKey string, jwt string) { 37 t.Helper() 38 c := natsConnect(t, url, nats.UserCredentials(creds)) 39 defer c.Close() 40 if msg, err := c.Request(fmt.Sprintf(accUpdateEventSubjNew, pubKey), []byte(jwt), time.Second); err != nil { 41 t.Fatal("error not expected in this test", err) 42 } else { 43 content := make(map[string]any) 44 if err := json.Unmarshal(msg.Data, &content); err != nil { 45 t.Fatalf("%v", err) 46 } else if _, ok := content["data"]; !ok { 47 t.Fatalf("did not get an ok response got: %v", content) 48 } 49 } 50 } 51 require_IdenticalLimits := func(infoLim JetStreamAccountLimits, lim jwt.JetStreamLimits) { 52 t.Helper() 53 if int64(infoLim.MaxConsumers) != lim.Consumer || int64(infoLim.MaxStreams) != lim.Streams || 54 infoLim.MaxMemory != lim.MemoryStorage || infoLim.MaxStore != lim.DiskStorage { 55 t.Fatalf("limits do not match %v != %v", infoLim, lim) 56 } 57 } 58 expect_JSDisabledForAccount := func(c *nats.Conn) { 59 t.Helper() 60 if _, err := c.Request("$JS.API.INFO", nil, time.Second); err != nats.ErrTimeout && err != nats.ErrNoResponders { 61 t.Fatalf("Unexpected error: %v", err) 62 } 63 } 64 expect_InfoError := func(c *nats.Conn) { 65 t.Helper() 66 var info JSApiAccountInfoResponse 67 if resp, err := c.Request("$JS.API.INFO", nil, time.Second); err != nil { 68 t.Fatalf("Unexpected error: %v", err) 69 } else if err = json.Unmarshal(resp.Data, &info); err != nil { 70 t.Fatalf("response1 %v got error %v", string(resp.Data), err) 71 } else if info.Error == nil { 72 t.Fatalf("expected error") 73 } 74 } 75 validate_limits := func(c *nats.Conn, expectedLimits jwt.JetStreamLimits) { 76 t.Helper() 77 var info JSApiAccountInfoResponse 78 if resp, err := c.Request("$JS.API.INFO", nil, time.Second); err != nil { 79 t.Fatalf("Unexpected error: %v", err) 80 } else if err = json.Unmarshal(resp.Data, &info); err != nil { 81 t.Fatalf("response1 %v got error %v", string(resp.Data), err) 82 } else { 83 require_IdenticalLimits(info.Limits, expectedLimits) 84 } 85 } 86 // create system account 87 sysKp, _ := nkeys.CreateAccount() 88 sysPub, _ := sysKp.PublicKey() 89 sysUKp, _ := nkeys.CreateUser() 90 sysUSeed, _ := sysUKp.Seed() 91 uclaim := newJWTTestUserClaims() 92 uclaim.Subject, _ = sysUKp.PublicKey() 93 sysUserJwt, err := uclaim.Encode(sysKp) 94 require_NoError(t, err) 95 sysKp.Seed() 96 sysCreds := genCredsFile(t, sysUserJwt, sysUSeed) 97 // limits to apply and check 98 limits1 := jwt.JetStreamLimits{MemoryStorage: 1024 * 1024, DiskStorage: 2048 * 1024, Streams: 1, Consumer: 2, MaxBytesRequired: true} 99 // has valid limits that would fail when incorrectly applied twice 100 limits2 := jwt.JetStreamLimits{MemoryStorage: 4096 * 1024, DiskStorage: 8192 * 1024, Streams: 3, Consumer: 4} 101 // limits exceeding actual configured value of DiskStorage 102 limitsExceeded := jwt.JetStreamLimits{MemoryStorage: 8192 * 1024, DiskStorage: 16384 * 1024, Streams: 5, Consumer: 6} 103 // create account using jetstream with both limits 104 akp, _ := nkeys.CreateAccount() 105 aPub, _ := akp.PublicKey() 106 claim := jwt.NewAccountClaims(aPub) 107 claim.Limits.JetStreamLimits = limits1 108 aJwt1, err := claim.Encode(oKp) 109 require_NoError(t, err) 110 claim.Limits.JetStreamLimits = limits2 111 aJwt2, err := claim.Encode(oKp) 112 require_NoError(t, err) 113 claim.Limits.JetStreamLimits = limitsExceeded 114 aJwtLimitsExceeded, err := claim.Encode(oKp) 115 require_NoError(t, err) 116 claim.Limits.JetStreamLimits = jwt.JetStreamLimits{} // disabled 117 aJwt4, err := claim.Encode(oKp) 118 require_NoError(t, err) 119 // account user 120 uKp, _ := nkeys.CreateUser() 121 uSeed, _ := uKp.Seed() 122 uclaim = newJWTTestUserClaims() 123 uclaim.Subject, _ = uKp.PublicKey() 124 userJwt, err := uclaim.Encode(akp) 125 require_NoError(t, err) 126 userCreds := genCredsFile(t, userJwt, uSeed) 127 dir := t.TempDir() 128 conf := createConfFile(t, []byte(fmt.Sprintf(` 129 listen: 127.0.0.1:-1 130 jetstream: {max_mem_store: 10Mb, max_file_store: 10Mb, store_dir: "%s"} 131 operator: %s 132 resolver: { 133 type: full 134 dir: '%s' 135 } 136 system_account: %s 137 `, dir, ojwt, dir, sysPub))) 138 s, opts := RunServerWithConfig(conf) 139 defer s.Shutdown() 140 port := opts.Port 141 updateJwt(s.ClientURL(), sysCreds, aPub, aJwt1) 142 c := natsConnect(t, s.ClientURL(), nats.UserCredentials(userCreds), nats.ReconnectWait(200*time.Millisecond)) 143 defer c.Close() 144 validate_limits(c, limits1) 145 // keep using the same connection 146 updateJwt(s.ClientURL(), sysCreds, aPub, aJwt2) 147 validate_limits(c, limits2) 148 // keep using the same connection but do NOT CHANGE anything. 149 // This tests if the jwt is applied a second time (would fail) 150 updateJwt(s.ClientURL(), sysCreds, aPub, aJwt2) 151 validate_limits(c, limits2) 152 // keep using the same connection. This update EXCEEDS LIMITS 153 updateJwt(s.ClientURL(), sysCreds, aPub, aJwtLimitsExceeded) 154 validate_limits(c, limits2) 155 // disable test after failure 156 updateJwt(s.ClientURL(), sysCreds, aPub, aJwt4) 157 expect_InfoError(c) 158 // re enable, again testing with a value that can't be applied twice 159 updateJwt(s.ClientURL(), sysCreds, aPub, aJwt2) 160 validate_limits(c, limits2) 161 // disable test no prior failure 162 updateJwt(s.ClientURL(), sysCreds, aPub, aJwt4) 163 expect_InfoError(c) 164 // Wrong limits form start 165 updateJwt(s.ClientURL(), sysCreds, aPub, aJwtLimitsExceeded) 166 expect_JSDisabledForAccount(c) 167 // enable js but exceed limits. Followed by fix via restart 168 updateJwt(s.ClientURL(), sysCreds, aPub, aJwt2) 169 validate_limits(c, limits2) 170 updateJwt(s.ClientURL(), sysCreds, aPub, aJwtLimitsExceeded) 171 validate_limits(c, limits2) 172 s.Shutdown() 173 conf = createConfFile(t, []byte(fmt.Sprintf(` 174 listen: 127.0.0.1:%d 175 jetstream: {max_mem_store: 20Mb, max_file_store: 20Mb, store_dir: "%s"} 176 operator: %s 177 resolver: { 178 type: full 179 dir: '%s' 180 } 181 system_account: %s 182 `, port, dir, ojwt, dir, sysPub))) 183 s, _ = RunServerWithConfig(conf) 184 defer s.Shutdown() 185 c.Flush() // force client to discover the disconnect 186 checkClientsCount(t, s, 1) 187 validate_limits(c, limitsExceeded) 188 s.Shutdown() 189 // disable jetstream test 190 conf = createConfFile(t, []byte(fmt.Sprintf(` 191 listen: 127.0.0.1:%d 192 operator: %s 193 resolver: { 194 type: full 195 dir: '%s' 196 } 197 system_account: %s 198 `, port, ojwt, dir, sysPub))) 199 s, _ = RunServerWithConfig(conf) 200 defer s.Shutdown() 201 c.Flush() // force client to discover the disconnect 202 checkClientsCount(t, s, 1) 203 expect_JSDisabledForAccount(c) 204 // test that it stays disabled 205 updateJwt(s.ClientURL(), sysCreds, aPub, aJwt2) 206 expect_JSDisabledForAccount(c) 207 c.Close() 208 } 209 210 func TestJetStreamJWTDisallowBearer(t *testing.T) { 211 sysKp, syspub := createKey(t) 212 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 213 sysCreds := newUser(t, sysKp) 214 215 accKp, err := nkeys.CreateAccount() 216 require_NoError(t, err) 217 accIdPub, err := accKp.PublicKey() 218 require_NoError(t, err) 219 aClaim := jwt.NewAccountClaims(accIdPub) 220 accJwt1, err := aClaim.Encode(oKp) 221 require_NoError(t, err) 222 aClaim.Limits.DisallowBearer = true 223 accJwt2, err := aClaim.Encode(oKp) 224 require_NoError(t, err) 225 226 uc := jwt.NewUserClaims("dummy") 227 uc.BearerToken = true 228 uOpt1 := createUserCredsEx(t, uc, accKp) 229 uc.BearerToken = false 230 uOpt2 := createUserCredsEx(t, uc, accKp) 231 232 dir := t.TempDir() 233 cf := createConfFile(t, []byte(fmt.Sprintf(` 234 port: -1 235 operator = %s 236 system_account: %s 237 resolver: { 238 type: full 239 dir: '%s/jwt' 240 } 241 resolver_preload = { 242 %s : "%s" 243 } 244 `, ojwt, syspub, dir, syspub, sysJwt))) 245 s, _ := RunServerWithConfig(cf) 246 defer s.Shutdown() 247 248 updateJwt(t, s.ClientURL(), sysCreds, accJwt1, 1) 249 disconnectErrCh := make(chan error, 10) 250 defer close(disconnectErrCh) 251 nc1, err := nats.Connect(s.ClientURL(), uOpt1, 252 nats.NoReconnect(), 253 nats.ErrorHandler(func(conn *nats.Conn, s *nats.Subscription, err error) { 254 disconnectErrCh <- err 255 })) 256 require_NoError(t, err) 257 defer nc1.Close() 258 259 // update jwt and observe bearer token get disconnected 260 updateJwt(t, s.ClientURL(), sysCreds, accJwt2, 1) 261 select { 262 case err := <-disconnectErrCh: 263 require_Contains(t, err.Error(), "authorization violation") 264 case <-time.After(time.Second): 265 t.Fatalf("expected error on disconnect") 266 } 267 268 // assure bearer token is not allowed to connect 269 _, err = nats.Connect(s.ClientURL(), uOpt1) 270 require_Error(t, err) 271 272 // assure non bearer token can connect 273 nc2, err := nats.Connect(s.ClientURL(), uOpt2) 274 require_NoError(t, err) 275 defer nc2.Close() 276 } 277 278 func TestJetStreamJWTMove(t *testing.T) { 279 sysKp, syspub := createKey(t) 280 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 281 sysCreds := newUser(t, sysKp) 282 283 accKp, aExpPub := createKey(t) 284 285 test := func(t *testing.T, replicas int, accClaim *jwt.AccountClaims) { 286 accClaim.Name = "acc" 287 accJwt := encodeClaim(t, accClaim, aExpPub) 288 accCreds := newUser(t, accKp) 289 290 tmlp := ` 291 listen: 127.0.0.1:-1 292 server_name: %s 293 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 294 leaf { 295 listen: 127.0.0.1:-1 296 } 297 cluster { 298 name: %s 299 listen: 127.0.0.1:%d 300 routes = [%s] 301 } 302 ` 303 sc := createJetStreamSuperClusterWithTemplateAndModHook(t, tmlp, 5, 2, 304 func(serverName, clustername, storeDir, conf string) string { 305 switch sname := serverName[strings.Index(serverName, "-")+1:]; sname { 306 case "S1", "S2": 307 conf = strings.ReplaceAll(conf, "jetstream", "#jetstream") 308 } 309 return conf + fmt.Sprintf(` 310 server_tags: [cloud:%s-tag] 311 operator: %s 312 system_account: %s 313 resolver: { 314 type: full 315 dir: '%s/jwt' 316 } 317 resolver_preload = { 318 %s : %s 319 } 320 `, clustername, ojwt, syspub, storeDir, syspub, sysJwt) 321 }, nil) 322 defer sc.shutdown() 323 324 s := sc.serverByName("C1-S1") 325 require_False(t, s.JetStreamEnabled()) 326 updateJwt(t, s.ClientURL(), sysCreds, accJwt, 10) 327 328 s = sc.serverByName("C2-S1") 329 require_False(t, s.JetStreamEnabled()) 330 331 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(accCreds)) 332 defer nc.Close() 333 334 js, err := nc.JetStream() 335 require_NoError(t, err) 336 337 ci, err := js.AddStream(&nats.StreamConfig{Name: "MOVE-ME", Replicas: replicas, 338 Placement: &nats.Placement{Tags: []string{"cloud:C1-tag"}}}) 339 require_NoError(t, err) 340 require_Equal(t, ci.Cluster.Name, "C1") 341 342 _, err = js.AddConsumer("MOVE-ME", &nats.ConsumerConfig{Durable: "dur", AckPolicy: nats.AckExplicitPolicy}) 343 require_NoError(t, err) 344 _, err = js.Publish("MOVE-ME", []byte("hello world")) 345 require_NoError(t, err) 346 347 // Perform actual move 348 ci, err = js.UpdateStream(&nats.StreamConfig{Name: "MOVE-ME", Replicas: replicas, 349 Placement: &nats.Placement{Tags: []string{"cloud:C2-tag"}}}) 350 require_NoError(t, err) 351 require_Equal(t, ci.Cluster.Name, "C1") 352 353 sc.clusterForName("C2").waitOnStreamLeader(aExpPub, "MOVE-ME") 354 355 checkFor(t, 30*time.Second, 250*time.Millisecond, func() error { 356 if si, err := js.StreamInfo("MOVE-ME"); err != nil { 357 return fmt.Errorf("stream: %v", err) 358 } else if si.Cluster.Name != "C2" { 359 return fmt.Errorf("Wrong cluster: %q", si.Cluster.Name) 360 } else if !strings.HasPrefix(si.Cluster.Leader, "C2-") { 361 return fmt.Errorf("Wrong leader: %q", si.Cluster.Leader) 362 } else if len(si.Cluster.Replicas) != replicas-1 { 363 return fmt.Errorf("Expected %d replicas, got %d", replicas-1, len(si.Cluster.Replicas)) 364 } else if si.State.Msgs != 1 { 365 return fmt.Errorf("expected one message") 366 } 367 // Now make sure consumer has leader etc.. 368 if ci, err := js.ConsumerInfo("MOVE-ME", "dur"); err != nil { 369 return fmt.Errorf("stream: %v", err) 370 } else if ci.Cluster.Name != "C2" { 371 return fmt.Errorf("Wrong cluster: %q", ci.Cluster.Name) 372 } else if ci.Cluster.Leader == _EMPTY_ { 373 return fmt.Errorf("No leader yet") 374 } 375 return nil 376 }) 377 378 sub, err := js.PullSubscribe("", "dur", nats.BindStream("MOVE-ME")) 379 require_NoError(t, err) 380 m, err := sub.Fetch(1) 381 require_NoError(t, err) 382 require_NoError(t, m[0].AckSync()) 383 } 384 385 t.Run("tiered", func(t *testing.T) { 386 accClaim := jwt.NewAccountClaims(aExpPub) 387 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 388 DiskStorage: 1100, Consumer: 1, Streams: 1} 389 accClaim.Limits.JetStreamTieredLimits["R3"] = jwt.JetStreamLimits{ 390 DiskStorage: 3300, Consumer: 1, Streams: 1} 391 392 t.Run("R3", func(t *testing.T) { 393 test(t, 3, accClaim) 394 }) 395 t.Run("R1", func(t *testing.T) { 396 test(t, 1, accClaim) 397 }) 398 }) 399 400 t.Run("non-tiered", func(t *testing.T) { 401 accClaim := jwt.NewAccountClaims(aExpPub) 402 accClaim.Limits.JetStreamLimits = jwt.JetStreamLimits{ 403 DiskStorage: 4400, Consumer: 2, Streams: 2} 404 405 t.Run("R3", func(t *testing.T) { 406 test(t, 3, accClaim) 407 }) 408 t.Run("R1", func(t *testing.T) { 409 test(t, 1, accClaim) 410 }) 411 }) 412 } 413 414 func TestJetStreamJWTClusteredTiers(t *testing.T) { 415 sysKp, syspub := createKey(t) 416 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 417 newUser(t, sysKp) 418 419 accKp, aExpPub := createKey(t) 420 accClaim := jwt.NewAccountClaims(aExpPub) 421 accClaim.Name = "acc" 422 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 423 DiskStorage: 1100, Consumer: 2, Streams: 2} 424 accClaim.Limits.JetStreamTieredLimits["R3"] = jwt.JetStreamLimits{ 425 DiskStorage: 1100, Consumer: 1, Streams: 1} 426 accJwt := encodeClaim(t, accClaim, aExpPub) 427 accCreds := newUser(t, accKp) 428 tmlp := ` 429 listen: 127.0.0.1:-1 430 server_name: %s 431 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 432 leaf { 433 listen: 127.0.0.1:-1 434 } 435 cluster { 436 name: %s 437 listen: 127.0.0.1:%d 438 routes = [%s] 439 } 440 ` + fmt.Sprintf(` 441 operator: %s 442 system_account: %s 443 resolver = MEMORY 444 resolver_preload = { 445 %s : %s 446 %s : %s 447 } 448 `, ojwt, syspub, syspub, sysJwt, aExpPub, accJwt) 449 450 c := createJetStreamClusterWithTemplate(t, tmlp, "cluster", 3) 451 defer c.shutdown() 452 453 nc := natsConnect(t, c.randomServer().ClientURL(), nats.UserCredentials(accCreds)) 454 defer nc.Close() 455 456 js, err := nc.JetStream() 457 require_NoError(t, err) 458 459 // Test absent tiers 460 _, err = js.AddStream(&nats.StreamConfig{Name: "testR2", Replicas: 2, Subjects: []string{"testR2"}}) 461 require_Error(t, err) 462 require_Equal(t, err.Error(), "nats: no JetStream default or applicable tiered limit present") 463 _, err = js.AddStream(&nats.StreamConfig{Name: "testR5", Replicas: 5, Subjects: []string{"testR5"}}) 464 require_Error(t, err) 465 require_Equal(t, err.Error(), "nats: no JetStream default or applicable tiered limit present") 466 467 // Test tiers up to stream limits 468 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-1", Replicas: 1, Subjects: []string{"testR1-1"}}) 469 require_NoError(t, err) 470 _, err = js.AddStream(&nats.StreamConfig{Name: "testR3-1", Replicas: 3, Subjects: []string{"testR3-1"}}) 471 require_NoError(t, err) 472 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-2", Replicas: 1, Subjects: []string{"testR1-2"}}) 473 require_NoError(t, err) 474 475 // Test exceeding tiered stream limit 476 _, err = js.AddStream(&nats.StreamConfig{Name: "testR1-3", Replicas: 1, Subjects: []string{"testR1-3"}}) 477 require_Error(t, err) 478 require_Equal(t, err.Error(), "nats: maximum number of streams reached") 479 _, err = js.AddStream(&nats.StreamConfig{Name: "testR3-3", Replicas: 3, Subjects: []string{"testR3-3"}}) 480 require_Error(t, err) 481 require_Equal(t, err.Error(), "nats: maximum number of streams reached") 482 483 // Test tiers up to consumer limits 484 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur1", AckPolicy: nats.AckExplicitPolicy}) 485 require_NoError(t, err) 486 _, err = js.AddConsumer("testR3-1", &nats.ConsumerConfig{Durable: "dur2", AckPolicy: nats.AckExplicitPolicy}) 487 require_NoError(t, err) 488 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur3", AckPolicy: nats.AckExplicitPolicy}) 489 require_NoError(t, err) 490 491 // test exceeding tiered consumer limits 492 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur4", AckPolicy: nats.AckExplicitPolicy}) 493 require_Error(t, err) 494 require_Equal(t, err.Error(), "nats: maximum consumers limit reached") 495 _, err = js.AddConsumer("testR1-1", &nats.ConsumerConfig{Durable: "dur5", AckPolicy: nats.AckExplicitPolicy}) 496 require_Error(t, err) 497 require_Equal(t, err.Error(), "nats: maximum consumers limit reached") 498 499 // test tiered storage limit 500 msg := [512]byte{} 501 _, err = js.Publish("testR1-1", msg[:]) 502 require_NoError(t, err) 503 _, err = js.Publish("testR3-1", msg[:]) 504 require_NoError(t, err) 505 _, err = js.Publish("testR3-1", msg[:]) 506 require_NoError(t, err) 507 _, err = js.Publish("testR1-2", msg[:]) 508 require_NoError(t, err) 509 510 time.Sleep(2000 * time.Millisecond) // wait for update timer to synchronize totals 511 512 // test exceeding tiered storage limit 513 _, err = js.Publish("testR1-1", []byte("1")) 514 require_Error(t, err) 515 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 516 _, err = js.Publish("testR3-1", []byte("fail this message!")) 517 require_Error(t, err) 518 require_Equal(t, err.Error(), "nats: resource limits exceeded for account") 519 520 // retrieve limits 521 var info JSApiAccountInfoResponse 522 m, err := nc.Request("$JS.API.INFO", nil, time.Second) 523 require_NoError(t, err) 524 err = json.Unmarshal(m.Data, &info) 525 require_NoError(t, err) 526 527 require_True(t, info.Memory == 0) 528 // R1 streams fail message with an add followed by remove, if the update was sent in between, the count is > limit 529 // Alternative to checking both values is, prior to the info request, wait for another update 530 require_True(t, info.Store == 4400 || info.Store == 4439) 531 require_True(t, info.Streams == 3) 532 require_True(t, info.Consumers == 3) 533 require_True(t, info.Limits == JetStreamAccountLimits{}) 534 r1 := info.Tiers["R1"] 535 require_True(t, r1.Streams == 2) 536 require_True(t, r1.Consumers == 2) 537 // R1 streams fail message with an add followed by remove, if the update was sent in between, the count is > limit 538 // Alternative to checking both values is, prior to the info request, wait for another update 539 require_True(t, r1.Store == 1100 || r1.Store == 1139) 540 require_True(t, r1.Memory == 0) 541 require_True(t, r1.Limits == JetStreamAccountLimits{ 542 MaxMemory: 0, 543 MaxStore: 1100, 544 MaxStreams: 2, 545 MaxConsumers: 2, 546 MaxAckPending: -1, 547 MemoryMaxStreamBytes: -1, 548 StoreMaxStreamBytes: -1, 549 MaxBytesRequired: false, 550 }) 551 r3 := info.Tiers["R3"] 552 require_True(t, r3.Streams == 1) 553 require_True(t, r3.Consumers == 1) 554 require_True(t, r3.Store == 3300) 555 require_True(t, r3.Memory == 0) 556 require_True(t, r3.Limits == JetStreamAccountLimits{ 557 MaxMemory: 0, 558 MaxStore: 1100, 559 MaxStreams: 1, 560 MaxConsumers: 1, 561 MaxAckPending: -1, 562 MemoryMaxStreamBytes: -1, 563 StoreMaxStreamBytes: -1, 564 MaxBytesRequired: false, 565 }) 566 } 567 568 func TestJetStreamJWTClusteredTiersChange(t *testing.T) { 569 sysKp, syspub := createKey(t) 570 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 571 sysCreds := newUser(t, sysKp) 572 573 accKp, aExpPub := createKey(t) 574 accClaim := jwt.NewAccountClaims(aExpPub) 575 accClaim.Name = "acc" 576 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 577 DiskStorage: 1000, MemoryStorage: 0, Consumer: 1, Streams: 1} 578 accClaim.Limits.JetStreamTieredLimits["R3"] = jwt.JetStreamLimits{ 579 DiskStorage: 500, MemoryStorage: 0, Consumer: 1, Streams: 1} 580 accJwt1 := encodeClaim(t, accClaim, aExpPub) 581 accCreds := newUser(t, accKp) 582 start := time.Now() 583 584 tmlp := ` 585 listen: 127.0.0.1:-1 586 server_name: %s 587 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 588 leaf { 589 listen: 127.0.0.1:-1 590 } 591 cluster { 592 name: %s 593 listen: 127.0.0.1:%d 594 routes = [%s] 595 } 596 ` 597 c := createJetStreamClusterWithTemplateAndModHook(t, tmlp, "cluster", 3, 598 func(serverName, clustername, storeDir, conf string) string { 599 return conf + fmt.Sprintf(` 600 operator: %s 601 system_account: %s 602 resolver: { 603 type: full 604 dir: '%s/jwt' 605 }`, ojwt, syspub, storeDir) 606 }) 607 defer c.shutdown() 608 609 updateJwt(t, c.randomServer().ClientURL(), sysCreds, sysJwt, 3) 610 updateJwt(t, c.randomServer().ClientURL(), sysCreds, accJwt1, 3) 611 612 nc := natsConnect(t, c.randomServer().ClientURL(), nats.UserCredentials(accCreds)) 613 defer nc.Close() 614 615 js, err := nc.JetStream() 616 require_NoError(t, err) 617 618 // Test tiers up to stream limits 619 cfg := &nats.StreamConfig{Name: "testR1-1", Replicas: 1, Subjects: []string{"testR1-1"}, MaxBytes: 1000} 620 _, err = js.AddStream(cfg) 621 require_NoError(t, err) 622 623 cfg.Replicas = 3 624 _, err = js.UpdateStream(cfg) 625 require_Error(t, err, errors.New("nats: insufficient storage resources available")) 626 627 time.Sleep(time.Second - time.Since(start)) // make sure the time stamp changes 628 accClaim.Limits.JetStreamTieredLimits["R3"] = jwt.JetStreamLimits{ 629 DiskStorage: 1000, MemoryStorage: 0, Consumer: 1, Streams: 1} 630 accJwt2 := encodeClaim(t, accClaim, aExpPub) 631 632 updateJwt(t, c.randomServer().ClientURL(), sysCreds, accJwt2, 3) 633 634 var rBefore, rAfter JSApiAccountInfoResponse 635 m, err := nc.Request("$JS.API.INFO", nil, time.Second) 636 require_NoError(t, err) 637 err = json.Unmarshal(m.Data, &rBefore) 638 require_NoError(t, err) 639 _, err = js.UpdateStream(cfg) 640 require_NoError(t, err) 641 642 m, err = nc.Request("$JS.API.INFO", nil, time.Second) 643 require_NoError(t, err) 644 err = json.Unmarshal(m.Data, &rAfter) 645 require_NoError(t, err) 646 require_True(t, rBefore.Tiers["R1"].Streams == 1) 647 require_True(t, rBefore.Tiers["R1"].Streams == rAfter.Tiers["R3"].Streams) 648 require_True(t, rBefore.Tiers["R3"].Streams == 0) 649 require_True(t, rAfter.Tiers["R1"].Streams == 0) 650 } 651 652 func TestJetStreamJWTClusteredDeleteTierWithStreamAndMove(t *testing.T) { 653 sysKp, syspub := createKey(t) 654 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 655 sysCreds := newUser(t, sysKp) 656 657 accKp, aExpPub := createKey(t) 658 accClaim := jwt.NewAccountClaims(aExpPub) 659 accClaim.Name = "acc" 660 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{ 661 DiskStorage: 1000, MemoryStorage: 0, Consumer: 1, Streams: 1} 662 accClaim.Limits.JetStreamTieredLimits["R3"] = jwt.JetStreamLimits{ 663 DiskStorage: 3000, MemoryStorage: 0, Consumer: 1, Streams: 1} 664 accJwt1 := encodeClaim(t, accClaim, aExpPub) 665 accCreds := newUser(t, accKp) 666 start := time.Now() 667 668 tmlp := ` 669 listen: 127.0.0.1:-1 670 server_name: %s 671 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 672 leaf { 673 listen: 127.0.0.1:-1 674 } 675 cluster { 676 name: %s 677 listen: 127.0.0.1:%d 678 routes = [%s] 679 } 680 ` 681 c := createJetStreamClusterWithTemplateAndModHook(t, tmlp, "cluster", 3, 682 func(serverName, clustername, storeDir, conf string) string { 683 return conf + fmt.Sprintf(` 684 operator: %s 685 system_account: %s 686 resolver: { 687 type: full 688 dir: '%s/jwt' 689 }`, ojwt, syspub, storeDir) 690 }) 691 defer c.shutdown() 692 693 updateJwt(t, c.randomServer().ClientURL(), sysCreds, sysJwt, 3) 694 updateJwt(t, c.randomServer().ClientURL(), sysCreds, accJwt1, 3) 695 696 nc := natsConnect(t, c.randomServer().ClientURL(), nats.UserCredentials(accCreds)) 697 defer nc.Close() 698 699 js, err := nc.JetStream() 700 require_NoError(t, err) 701 702 // Test tiers up to stream limits 703 cfg := &nats.StreamConfig{Name: "testR1-1", Replicas: 1, Subjects: []string{"testR1-1"}, MaxBytes: 1000} 704 _, err = js.AddStream(cfg) 705 require_NoError(t, err) 706 707 _, err = js.Publish("testR1-1", nil) 708 require_NoError(t, err) 709 710 time.Sleep(time.Second - time.Since(start)) // make sure the time stamp changes 711 delete(accClaim.Limits.JetStreamTieredLimits, "R1") 712 accJwt2 := encodeClaim(t, accClaim, aExpPub) 713 updateJwt(t, c.randomServer().ClientURL(), sysCreds, accJwt2, 3) 714 715 var respBefore JSApiAccountInfoResponse 716 m, err := nc.Request("$JS.API.INFO", nil, time.Second) 717 require_NoError(t, err) 718 err = json.Unmarshal(m.Data, &respBefore) 719 require_NoError(t, err) 720 721 require_True(t, respBefore.JetStreamAccountStats.Tiers["R3"].Streams == 0) 722 require_True(t, respBefore.JetStreamAccountStats.Tiers["R1"].Streams == 1) 723 724 _, err = js.Publish("testR1-1", nil) 725 require_Error(t, err) 726 require_Equal(t, err.Error(), "nats: no JetStream default or applicable tiered limit present") 727 728 cfg.Replicas = 3 729 _, err = js.UpdateStream(cfg) 730 require_NoError(t, err) 731 732 // I noticed this taking > 5 seconds 733 checkFor(t, 10*time.Second, 250*time.Millisecond, func() error { 734 _, err = js.Publish("testR1-1", nil) 735 return err 736 }) 737 738 var respAfter JSApiAccountInfoResponse 739 m, err = nc.Request("$JS.API.INFO", nil, time.Second) 740 require_NoError(t, err) 741 err = json.Unmarshal(m.Data, &respAfter) 742 require_NoError(t, err) 743 744 require_True(t, respAfter.JetStreamAccountStats.Tiers["R3"].Streams == 1) 745 require_True(t, respAfter.JetStreamAccountStats.Tiers["R3"].Store > 0) 746 747 _, ok := respAfter.JetStreamAccountStats.Tiers["R1"] 748 require_True(t, !ok) 749 } 750 751 func TestJetStreamJWTSysAccUpdateMixedMode(t *testing.T) { 752 skp, spub := createKey(t) 753 sUsr := createUserCreds(t, nil, skp) 754 sysClaim := jwt.NewAccountClaims(spub) 755 sysClaim.Name = "SYS" 756 sysJwt := encodeClaim(t, sysClaim, spub) 757 encodeJwt1Time := time.Now() 758 759 akp, apub := createKey(t) 760 aUsr := createUserCreds(t, nil, akp) 761 claim := jwt.NewAccountClaims(apub) 762 claim.Limits.JetStreamLimits.DiskStorage = 1024 * 1024 763 claim.Limits.JetStreamLimits.Streams = 1 764 jwt1 := encodeClaim(t, claim, apub) 765 766 basePath := "/ngs/v1/accounts/jwt/" 767 reqCount := int32(0) 768 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 769 if r.URL.Path == basePath { 770 w.Write([]byte("ok")) 771 } else if strings.HasSuffix(r.URL.Path, spub) { 772 w.Write([]byte(sysJwt)) 773 } else if strings.HasSuffix(r.URL.Path, apub) { 774 w.Write([]byte(jwt1)) 775 } else { 776 // only count requests that could be filled 777 return 778 } 779 atomic.AddInt32(&reqCount, 1) 780 })) 781 defer ts.Close() 782 783 tmpl := ` 784 listen: 127.0.0.1:-1 785 server_name: %s 786 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 787 cluster { 788 name: %s 789 listen: 127.0.0.1:%d 790 routes = [%s] 791 } 792 ` 793 794 sc := createJetStreamSuperClusterWithTemplateAndModHook(t, tmpl, 3, 2, 795 func(serverName, clusterName, storeDir, conf string) string { 796 // create an ngs like setup, with connection and non connection server 797 if clusterName == "C1" { 798 conf = strings.ReplaceAll(conf, "jetstream", "#jetstream") 799 } 800 return fmt.Sprintf(`%s 801 operator: %s 802 system_account: %s 803 resolver: URL("%s%s")`, conf, ojwt, spub, ts.URL, basePath) 804 }, nil) 805 defer sc.shutdown() 806 disconnectChan := make(chan struct{}, 100) 807 defer close(disconnectChan) 808 disconnectCb := nats.DisconnectErrHandler(func(conn *nats.Conn, err error) { 809 disconnectChan <- struct{}{} 810 }) 811 812 s := sc.clusterForName("C1").randomServer() 813 814 sysNc := natsConnect(t, s.ClientURL(), sUsr, disconnectCb, nats.NoCallbacksAfterClientClose()) 815 defer sysNc.Close() 816 aNc := natsConnect(t, s.ClientURL(), aUsr, disconnectCb, nats.NoCallbacksAfterClientClose()) 817 defer aNc.Close() 818 819 js, err := aNc.JetStream() 820 require_NoError(t, err) 821 822 si, err := js.AddStream(&nats.StreamConfig{Name: "bar", Subjects: []string{"bar"}, Replicas: 3}) 823 require_NoError(t, err) 824 require_Equal(t, si.Cluster.Name, "C2") 825 _, err = js.AccountInfo() 826 require_NoError(t, err) 827 828 r, err := sysNc.Request(fmt.Sprintf(serverPingReqSubj, "ACCOUNTZ"), 829 []byte(fmt.Sprintf(`{"account":"%s"}`, spub)), time.Second) 830 require_NoError(t, err) 831 respb := ServerAPIResponse{Data: &Accountz{}} 832 require_NoError(t, json.Unmarshal(r.Data, &respb)) 833 834 hasJSExp := func(resp *ServerAPIResponse) bool { 835 found := false 836 for _, e := range resp.Data.(*Accountz).Account.Exports { 837 if e.Subject == jsAllAPI { 838 found = true 839 break 840 } 841 } 842 return found 843 } 844 require_True(t, hasJSExp(&respb)) 845 846 // make sure jti increased 847 time.Sleep(time.Second - time.Since(encodeJwt1Time)) 848 sysJwt2 := encodeClaim(t, sysClaim, spub) 849 850 oldRcount := atomic.LoadInt32(&reqCount) 851 _, err = sysNc.Request(fmt.Sprintf(accUpdateEventSubjNew, spub), []byte(sysJwt2), time.Second) 852 require_NoError(t, err) 853 // test to make sure connected client (aNc) was not kicked 854 time.Sleep(200 * time.Millisecond) 855 require_True(t, len(disconnectChan) == 0) 856 857 // ensure nothing new has happened, lookup for account not found is skipped during inc 858 require_True(t, atomic.LoadInt32(&reqCount) == oldRcount) 859 // no responders 860 _, err = aNc.Request("foo", nil, time.Second) 861 require_Error(t, err) 862 require_Equal(t, err.Error(), "nats: no responders available for request") 863 864 nc2, js2 := jsClientConnect(t, sc.clusterForName("C2").randomServer(), aUsr) 865 defer nc2.Close() 866 _, err = js2.AccountInfo() 867 require_NoError(t, err) 868 869 r, err = sysNc.Request(fmt.Sprintf(serverPingReqSubj, "ACCOUNTZ"), 870 []byte(fmt.Sprintf(`{"account":"%s"}`, spub)), time.Second) 871 require_NoError(t, err) 872 respa := ServerAPIResponse{Data: &Accountz{}} 873 require_NoError(t, json.Unmarshal(r.Data, &respa)) 874 require_True(t, hasJSExp(&respa)) 875 876 _, err = js.AccountInfo() 877 require_NoError(t, err) 878 } 879 880 func TestJetStreamJWTExpiredAccountNotCountedTowardLimits(t *testing.T) { 881 op, _ := nkeys.CreateOperator() 882 opPk, _ := op.PublicKey() 883 sk, _ := nkeys.CreateOperator() 884 skPk, _ := sk.PublicKey() 885 opClaim := jwt.NewOperatorClaims(opPk) 886 opClaim.SigningKeys.Add(skPk) 887 opJwt, err := opClaim.Encode(op) 888 require_NoError(t, err) 889 createAccountAndUser := func(pubKey, jwt1, creds1 *string) { 890 t.Helper() 891 kp, _ := nkeys.CreateAccount() 892 *pubKey, _ = kp.PublicKey() 893 claim := jwt.NewAccountClaims(*pubKey) 894 claim.Limits.JetStreamLimits = jwt.JetStreamLimits{MemoryStorage: 7 * 1024 * 1024, DiskStorage: 7 * 1024 * 1024, Streams: 10} 895 var err error 896 *jwt1, err = claim.Encode(sk) 897 require_NoError(t, err) 898 899 ukp, _ := nkeys.CreateUser() 900 seed, _ := ukp.Seed() 901 upub, _ := ukp.PublicKey() 902 uclaim := newJWTTestUserClaims() 903 uclaim.Subject = upub 904 905 ujwt1, err := uclaim.Encode(kp) 906 require_NoError(t, err) 907 *creds1 = genCredsFile(t, ujwt1, seed) 908 } 909 generateRequest := func(accs []string, kp nkeys.KeyPair) []byte { 910 t.Helper() 911 opk, _ := kp.PublicKey() 912 c := jwt.NewGenericClaims(opk) 913 c.Data["accounts"] = accs 914 cJwt, err := c.Encode(kp) 915 if err != nil { 916 t.Fatalf("Expected no error %v", err) 917 } 918 return []byte(cJwt) 919 } 920 921 var syspub, sysjwt, sysCreds string 922 createAccountAndUser(&syspub, &sysjwt, &sysCreds) 923 924 dirSrv := t.TempDir() 925 conf := createConfFile(t, []byte(fmt.Sprintf(` 926 listen: 127.0.0.1:-1 927 operator: %s 928 jetstream: {max_mem_store: 10Mb, max_file_store: 10Mb, store_dir: "%s"} 929 system_account: %s 930 resolver: { 931 type: full 932 allow_delete: true 933 dir: '%s' 934 timeout: "500ms" 935 } 936 `, opJwt, dirSrv, syspub, dirSrv))) 937 938 s, _ := RunServerWithConfig(conf) 939 defer s.Shutdown() 940 941 // update system account jwt 942 updateJwt(t, s.ClientURL(), sysCreds, sysjwt, 1) 943 944 var apub, ajwt1, aCreds1 string 945 createAccountAndUser(&apub, &ajwt1, &aCreds1) 946 // push jwt (for full resolver) 947 updateJwt(t, s.ClientURL(), sysCreds, ajwt1, 1) 948 949 ncA, jsA := jsClientConnect(t, s, nats.UserCredentials(aCreds1)) 950 defer ncA.Close() 951 952 ai, err := jsA.AccountInfo() 953 require_NoError(t, err) 954 require_True(t, ai.Limits.MaxMemory == 7*1024*1024) 955 ncA.Close() 956 957 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(sysCreds)) 958 defer nc.Close() 959 resp, err := nc.Request(accDeleteReqSubj, generateRequest([]string{apub}, sk), time.Second) 960 require_NoError(t, err) 961 require_True(t, strings.Contains(string(resp.Data), `"message":"deleted 1 accounts"`)) 962 963 var apub2, ajwt2, aCreds2 string 964 createAccountAndUser(&apub2, &ajwt2, &aCreds2) 965 // push jwt (for full resolver) 966 updateJwt(t, s.ClientURL(), sysCreds, ajwt2, 1) 967 968 ncB, jsB := jsClientConnect(t, s, nats.UserCredentials(aCreds2)) 969 defer ncB.Close() 970 971 ai, err = jsB.AccountInfo() 972 require_NoError(t, err) 973 require_True(t, ai.Limits.MaxMemory == 7*1024*1024) 974 } 975 976 func TestJetStreamJWTDeletedAccountDoesNotLeakSubscriptions(t *testing.T) { 977 op, _ := nkeys.CreateOperator() 978 opPk, _ := op.PublicKey() 979 sk, _ := nkeys.CreateOperator() 980 skPk, _ := sk.PublicKey() 981 opClaim := jwt.NewOperatorClaims(opPk) 982 opClaim.SigningKeys.Add(skPk) 983 opJwt, err := opClaim.Encode(op) 984 require_NoError(t, err) 985 createAccountAndUser := func(pubKey, jwt1, creds1 *string) { 986 t.Helper() 987 kp, _ := nkeys.CreateAccount() 988 *pubKey, _ = kp.PublicKey() 989 claim := jwt.NewAccountClaims(*pubKey) 990 claim.Limits.JetStreamLimits = jwt.JetStreamLimits{MemoryStorage: 7 * 1024 * 1024, DiskStorage: 7 * 1024 * 1024, Streams: 10} 991 var err error 992 *jwt1, err = claim.Encode(sk) 993 require_NoError(t, err) 994 995 ukp, _ := nkeys.CreateUser() 996 seed, _ := ukp.Seed() 997 upub, _ := ukp.PublicKey() 998 uclaim := newJWTTestUserClaims() 999 uclaim.Subject = upub 1000 1001 ujwt1, err := uclaim.Encode(kp) 1002 require_NoError(t, err) 1003 *creds1 = genCredsFile(t, ujwt1, seed) 1004 } 1005 generateRequest := func(accs []string, kp nkeys.KeyPair) []byte { 1006 t.Helper() 1007 opk, _ := kp.PublicKey() 1008 c := jwt.NewGenericClaims(opk) 1009 c.Data["accounts"] = accs 1010 cJwt, err := c.Encode(kp) 1011 if err != nil { 1012 t.Fatalf("Expected no error %v", err) 1013 } 1014 return []byte(cJwt) 1015 } 1016 1017 var syspub, sysjwt, sysCreds string 1018 createAccountAndUser(&syspub, &sysjwt, &sysCreds) 1019 1020 dirSrv := t.TempDir() 1021 conf := createConfFile(t, []byte(fmt.Sprintf(` 1022 listen: 127.0.0.1:-1 1023 operator: %s 1024 jetstream: {max_mem_store: 10Mb, max_file_store: 10Mb, store_dir: %v} 1025 system_account: %s 1026 resolver: { 1027 type: full 1028 allow_delete: true 1029 dir: '%s' 1030 timeout: "500ms" 1031 } 1032 `, opJwt, dirSrv, syspub, dirSrv))) 1033 1034 s, _ := RunServerWithConfig(conf) 1035 defer s.Shutdown() 1036 1037 checkNumSubs := func(expected uint32) uint32 { 1038 t.Helper() 1039 // Wait a bit before capturing number of subs... 1040 time.Sleep(250 * time.Millisecond) 1041 1042 var ns uint32 1043 checkFor(t, time.Second, 50*time.Millisecond, func() error { 1044 subsz, err := s.Subsz(nil) 1045 if err != nil { 1046 return err 1047 } 1048 ns = subsz.NumSubs 1049 if expected > 0 && ns > expected { 1050 return fmt.Errorf("Expected num subs to be back at %v, got %v", 1051 expected, ns) 1052 } 1053 return nil 1054 }) 1055 return ns 1056 } 1057 beforeCreate := checkNumSubs(0) 1058 1059 // update system account jwt 1060 updateJwt(t, s.ClientURL(), sysCreds, sysjwt, 1) 1061 1062 createAndDelete := func() { 1063 t.Helper() 1064 1065 var apub, ajwt1, aCreds1 string 1066 createAccountAndUser(&apub, &ajwt1, &aCreds1) 1067 // push jwt (for full resolver) 1068 updateJwt(t, s.ClientURL(), sysCreds, ajwt1, 1) 1069 1070 ncA, jsA := jsClientConnect(t, s, nats.UserCredentials(aCreds1)) 1071 defer ncA.Close() 1072 1073 ai, err := jsA.AccountInfo() 1074 require_NoError(t, err) 1075 require_True(t, ai.Limits.MaxMemory == 7*1024*1024) 1076 ncA.Close() 1077 1078 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(sysCreds)) 1079 defer nc.Close() 1080 1081 resp, err := nc.Request(accDeleteReqSubj, generateRequest([]string{apub}, sk), time.Second) 1082 require_NoError(t, err) 1083 require_True(t, strings.Contains(string(resp.Data), `"message":"deleted 1 accounts"`)) 1084 } 1085 1086 // Create and delete multiple accounts 1087 for i := 0; i < 10; i++ { 1088 createAndDelete() 1089 } 1090 1091 // There is a subscription on `_R_.>` that is created on the system account 1092 // and that will not go away, so discount it. 1093 checkNumSubs(beforeCreate + 1) 1094 } 1095 1096 func TestJetStreamJWTDeletedAccountIsReEnabled(t *testing.T) { 1097 op, _ := nkeys.CreateOperator() 1098 opPk, _ := op.PublicKey() 1099 sk, _ := nkeys.CreateOperator() 1100 skPk, _ := sk.PublicKey() 1101 opClaim := jwt.NewOperatorClaims(opPk) 1102 opClaim.SigningKeys.Add(skPk) 1103 opJwt, err := opClaim.Encode(op) 1104 require_NoError(t, err) 1105 createAccountAndUser := func(pubKey, jwt1, creds1 *string) { 1106 t.Helper() 1107 kp, _ := nkeys.CreateAccount() 1108 *pubKey, _ = kp.PublicKey() 1109 claim := jwt.NewAccountClaims(*pubKey) 1110 claim.Limits.JetStreamLimits = jwt.JetStreamLimits{MemoryStorage: 7 * 1024 * 1024, DiskStorage: 7 * 1024 * 1024, Streams: 10} 1111 var err error 1112 *jwt1, err = claim.Encode(sk) 1113 require_NoError(t, err) 1114 1115 ukp, _ := nkeys.CreateUser() 1116 seed, _ := ukp.Seed() 1117 upub, _ := ukp.PublicKey() 1118 uclaim := newJWTTestUserClaims() 1119 uclaim.Subject = upub 1120 1121 ujwt1, err := uclaim.Encode(kp) 1122 require_NoError(t, err) 1123 *creds1 = genCredsFile(t, ujwt1, seed) 1124 } 1125 generateRequest := func(accs []string, kp nkeys.KeyPair) []byte { 1126 t.Helper() 1127 opk, _ := kp.PublicKey() 1128 c := jwt.NewGenericClaims(opk) 1129 c.Data["accounts"] = accs 1130 cJwt, err := c.Encode(kp) 1131 if err != nil { 1132 t.Fatalf("Expected no error %v", err) 1133 } 1134 return []byte(cJwt) 1135 } 1136 1137 // admin user 1138 var syspub, sysjwt, sysCreds string 1139 createAccountAndUser(&syspub, &sysjwt, &sysCreds) 1140 1141 dirSrv := t.TempDir() 1142 conf := createConfFile(t, []byte(fmt.Sprintf(` 1143 listen: 127.0.0.1:-1 1144 operator: %s 1145 jetstream: {max_mem_store: 10Mb, max_file_store: 10Mb, store_dir: "%s"} 1146 system_account: %s 1147 resolver: { 1148 type: full 1149 allow_delete: true 1150 dir: '%s' 1151 timeout: "500ms" 1152 } 1153 `, opJwt, dirSrv, syspub, dirSrv))) 1154 1155 s, _ := RunServerWithConfig(conf) 1156 defer s.Shutdown() 1157 1158 // update system account jwt 1159 updateJwt(t, s.ClientURL(), sysCreds, sysjwt, 1) 1160 1161 // create account 1162 var apub, ajwt1, aCreds1 string 1163 kp, _ := nkeys.CreateAccount() 1164 apub, _ = kp.PublicKey() 1165 claim := jwt.NewAccountClaims(apub) 1166 claim.Limits.JetStreamLimits = jwt.JetStreamLimits{ 1167 MemoryStorage: 7 * 1024 * 1024, 1168 DiskStorage: 7 * 1024 * 1024, 1169 Streams: 10, 1170 } 1171 ajwt1, err = claim.Encode(sk) 1172 require_NoError(t, err) 1173 1174 // user 1175 ukp, _ := nkeys.CreateUser() 1176 seed, _ := ukp.Seed() 1177 upub, _ := ukp.PublicKey() 1178 uclaim := newJWTTestUserClaims() 1179 uclaim.Subject = upub 1180 1181 ujwt1, err := uclaim.Encode(kp) 1182 require_NoError(t, err) 1183 aCreds1 = genCredsFile(t, ujwt1, seed) 1184 1185 // push user account 1186 updateJwt(t, s.ClientURL(), sysCreds, ajwt1, 1) 1187 1188 ncA, jsA := jsClientConnect(t, s, nats.UserCredentials(aCreds1)) 1189 defer ncA.Close() 1190 1191 jsA.AddStream(&nats.StreamConfig{Name: "foo"}) 1192 jsA.Publish("foo", []byte("Hello World")) 1193 jsA.Publish("foo", []byte("Hello Again")) 1194 1195 // JS should be working 1196 ai, err := jsA.AccountInfo() 1197 require_NoError(t, err) 1198 require_True(t, ai.Limits.MaxMemory == 7*1024*1024) 1199 require_True(t, ai.Limits.MaxStore == 7*1024*1024) 1200 require_True(t, ai.Tier.Streams == 1) 1201 1202 // connect with a different connection and delete the account. 1203 nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(sysCreds)) 1204 defer nc.Close() 1205 1206 // delete account 1207 resp, err := nc.Request(accDeleteReqSubj, generateRequest([]string{apub}, sk), time.Second) 1208 require_NoError(t, err) 1209 require_True(t, strings.Contains(string(resp.Data), `"message":"deleted 1 accounts"`)) 1210 1211 // account was disabled and now disconnected, this should get a connection is closed error. 1212 _, err = jsA.AccountInfo() 1213 if err == nil || !errors.Is(err, nats.ErrConnectionClosed) { 1214 t.Errorf("Expected connection closed error, got: %v", err) 1215 } 1216 ncA.Close() 1217 1218 // re-enable, same claims would be detected 1219 updateJwt(t, s.ClientURL(), sysCreds, ajwt1, 1) 1220 1221 // expected to get authorization timeout at this time 1222 _, err = nats.Connect(s.ClientURL(), nats.UserCredentials(aCreds1)) 1223 if !errors.Is(err, nats.ErrAuthorization) { 1224 t.Errorf("Expected authorization issue on connect, got: %v", err) 1225 } 1226 1227 // edit the account and push again with updated claims to same account 1228 claim = jwt.NewAccountClaims(apub) 1229 claim.Limits.JetStreamLimits = jwt.JetStreamLimits{ 1230 MemoryStorage: -1, 1231 DiskStorage: 10 * 1024 * 1024, 1232 Streams: 10, 1233 } 1234 ajwt1, err = claim.Encode(sk) 1235 require_NoError(t, err) 1236 updateJwt(t, s.ClientURL(), sysCreds, ajwt1, 1) 1237 1238 // reconnect with the updated account 1239 ncA, jsA = jsClientConnect(t, s, nats.UserCredentials(aCreds1)) 1240 defer ncA.Close() 1241 ai, err = jsA.AccountInfo() 1242 if err != nil { 1243 t.Fatal(err) 1244 } 1245 require_True(t, ai.Limits.MaxMemory == -1) 1246 require_True(t, ai.Limits.MaxStore == 10*1024*1024) 1247 require_True(t, ai.Tier.Streams == 1) 1248 1249 // should be possible to get stream info again 1250 si, err := jsA.StreamInfo("foo") 1251 if err != nil { 1252 t.Fatal(err) 1253 } 1254 if si.State.Msgs != 2 { 1255 t.Fatal("Unexpected number of messages from recovered stream") 1256 } 1257 msg, err := jsA.GetMsg("foo", 1) 1258 if err != nil { 1259 t.Fatal(err) 1260 } 1261 if string(msg.Data) != "Hello World" { 1262 t.Error("Unexpected message") 1263 } 1264 ncA.Close() 1265 } 1266 1267 // Make sure 100MB HA means 100MB of R3, not 33.3MB. 1268 func TestJetStreamJWTHAStorageLimitsAndAccounting(t *testing.T) { 1269 sysKp, syspub := createKey(t) 1270 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 1271 newUser(t, sysKp) 1272 1273 maxFileStorage := int64(100 * 1024 * 1024) 1274 maxMemStorage := int64(2 * 1024 * 1024) 1275 1276 accKp, aExpPub := createKey(t) 1277 accClaim := jwt.NewAccountClaims(aExpPub) 1278 accClaim.Name = "acc" 1279 accClaim.Limits.JetStreamTieredLimits["R3"] = jwt.JetStreamLimits{DiskStorage: maxFileStorage, MemoryStorage: maxMemStorage} 1280 accJwt := encodeClaim(t, accClaim, aExpPub) 1281 accCreds := newUser(t, accKp) 1282 tmlp := ` 1283 listen: 127.0.0.1:-1 1284 server_name: %s 1285 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 1286 leaf { listen: 127.0.0.1:-1 } 1287 cluster { 1288 name: %s 1289 listen: 127.0.0.1:%d 1290 routes = [%s] 1291 } 1292 ` + fmt.Sprintf(` 1293 operator: %s 1294 system_account: %s 1295 resolver = MEMORY 1296 resolver_preload = { 1297 %s : %s 1298 %s : %s 1299 } 1300 `, ojwt, syspub, syspub, sysJwt, aExpPub, accJwt) 1301 1302 c := createJetStreamClusterWithTemplate(t, tmlp, "cluster", 3) 1303 defer c.shutdown() 1304 1305 nc := natsConnect(t, c.randomServer().ClientURL(), nats.UserCredentials(accCreds)) 1306 defer nc.Close() 1307 1308 js, err := nc.JetStream() 1309 require_NoError(t, err) 1310 1311 // Test max bytes first. 1312 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST", Replicas: 3, MaxBytes: maxFileStorage, Subjects: []string{"foo"}}) 1313 require_NoError(t, err) 1314 1315 require_NoError(t, js.DeleteStream("TEST")) 1316 1317 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST", Replicas: 3, Subjects: []string{"foo"}}) 1318 require_NoError(t, err) 1319 1320 // Now test actual usage. 1321 // We should be able to send just over 200 of these. 1322 msg := [500 * 1024]byte{} 1323 for i := 0; i < 250; i++ { 1324 if _, err := js.Publish("foo", msg[:]); err != nil { 1325 require_Error(t, err, NewJSAccountResourcesExceededError()) 1326 require_True(t, i > 200) 1327 break 1328 } 1329 } 1330 1331 si, err := js.StreamInfo("TEST") 1332 require_NoError(t, err) 1333 // Make sure we are no more then 1 msg below our max in terms of size. 1334 delta := maxFileStorage - int64(si.State.Bytes) 1335 require_True(t, int(delta) < len(msg)) 1336 1337 // Now memory as well. 1338 require_NoError(t, js.DeleteStream("TEST")) 1339 1340 // Test max bytes first. 1341 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST", Replicas: 3, MaxBytes: maxMemStorage, Storage: nats.MemoryStorage, Subjects: []string{"foo"}}) 1342 require_NoError(t, err) 1343 1344 require_NoError(t, js.DeleteStream("TEST")) 1345 1346 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST", Replicas: 3, Storage: nats.MemoryStorage, Subjects: []string{"foo"}}) 1347 require_NoError(t, err) 1348 1349 // This is much smaller, so should only be able to send 4. 1350 for i := 0; i < 5; i++ { 1351 if _, err := js.Publish("foo", msg[:]); err != nil { 1352 require_Error(t, err, NewJSAccountResourcesExceededError()) 1353 require_Equal(t, i, 4) 1354 break 1355 } 1356 } 1357 1358 si, err = js.StreamInfo("TEST") 1359 require_NoError(t, err) 1360 // Make sure we are no more then 1 msg below our max in terms of size. 1361 delta = maxMemStorage - int64(si.State.Bytes) 1362 require_True(t, int(delta) < len(msg)) 1363 } 1364 1365 func TestJetStreamJWTHAStorageLimitsOnScaleAndUpdate(t *testing.T) { 1366 sysKp, syspub := createKey(t) 1367 sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub) 1368 newUser(t, sysKp) 1369 1370 maxFileStorage := int64(5 * 1024 * 1024) 1371 maxMemStorage := int64(1 * 1024 * 1024) 1372 1373 accKp, aExpPub := createKey(t) 1374 accClaim := jwt.NewAccountClaims(aExpPub) 1375 accClaim.Name = "acc" 1376 accClaim.Limits.JetStreamTieredLimits["R3"] = jwt.JetStreamLimits{DiskStorage: maxFileStorage, MemoryStorage: maxMemStorage} 1377 accClaim.Limits.JetStreamTieredLimits["R1"] = jwt.JetStreamLimits{DiskStorage: maxFileStorage, MemoryStorage: maxMemStorage} 1378 1379 accJwt := encodeClaim(t, accClaim, aExpPub) 1380 accCreds := newUser(t, accKp) 1381 tmlp := ` 1382 listen: 127.0.0.1:-1 1383 server_name: %s 1384 jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'} 1385 leaf { listen: 127.0.0.1:-1 } 1386 cluster { 1387 name: %s 1388 listen: 127.0.0.1:%d 1389 routes = [%s] 1390 } 1391 ` + fmt.Sprintf(` 1392 operator: %s 1393 system_account: %s 1394 resolver = MEMORY 1395 resolver_preload = { 1396 %s : %s 1397 %s : %s 1398 } 1399 `, ojwt, syspub, syspub, sysJwt, aExpPub, accJwt) 1400 1401 c := createJetStreamClusterWithTemplate(t, tmlp, "cluster", 3) 1402 defer c.shutdown() 1403 1404 nc := natsConnect(t, c.randomServer().ClientURL(), nats.UserCredentials(accCreds)) 1405 defer nc.Close() 1406 1407 js, err := nc.JetStream() 1408 require_NoError(t, err) 1409 1410 // Test max bytes first. 1411 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST", Replicas: 3, MaxBytes: maxFileStorage, Subjects: []string{"foo"}}) 1412 require_NoError(t, err) 1413 // Now delete 1414 require_NoError(t, js.DeleteStream("TEST")) 1415 // Now do 5 1MB streams. 1416 for i := 1; i <= 5; i++ { 1417 sname := fmt.Sprintf("TEST%d", i) 1418 _, err = js.AddStream(&nats.StreamConfig{Name: sname, Replicas: 3, MaxBytes: 1 * 1024 * 1024}) 1419 require_NoError(t, err) 1420 } 1421 // Should fail. 1422 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST6", Replicas: 3, MaxBytes: 1 * 1024 * 1024}) 1423 require_Error(t, err, errors.New("insufficient storage resources")) 1424 1425 // Update Test1 and Test2 to smaller reservations. 1426 _, err = js.UpdateStream(&nats.StreamConfig{Name: "TEST1", Replicas: 3, MaxBytes: 512 * 1024}) 1427 require_NoError(t, err) 1428 _, err = js.UpdateStream(&nats.StreamConfig{Name: "TEST2", Replicas: 3, MaxBytes: 512 * 1024}) 1429 require_NoError(t, err) 1430 // Now make sure TEST6 succeeds. 1431 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST6", Replicas: 3, MaxBytes: 1 * 1024 * 1024}) 1432 require_NoError(t, err) 1433 // Now delete the R3 version. 1434 require_NoError(t, js.DeleteStream("TEST6")) 1435 // Now do R1 version and then we will scale up. 1436 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST6", Replicas: 1, MaxBytes: 1 * 1024 * 1024}) 1437 require_NoError(t, err) 1438 // Now make sure scale up works. 1439 _, err = js.UpdateStream(&nats.StreamConfig{Name: "TEST6", Replicas: 3, MaxBytes: 1 * 1024 * 1024}) 1440 require_NoError(t, err) 1441 // Add in a few more streams to check reserved reporting in account info. 1442 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST7", Replicas: 1, MaxBytes: 2 * 1024 * 1024}) 1443 require_NoError(t, err) 1444 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST8", Replicas: 1, MaxBytes: 256 * 1024, Storage: nats.MemoryStorage}) 1445 require_NoError(t, err) 1446 _, err = js.AddStream(&nats.StreamConfig{Name: "TEST9", Replicas: 3, MaxBytes: 22 * 1024, Storage: nats.MemoryStorage}) 1447 require_NoError(t, err) 1448 1449 // Now make sure we report reserved correctly. 1450 // Do this direct to server since client does not support it yet. 1451 var info JSApiAccountInfoResponse 1452 resp, err := nc.Request("$JS.API.INFO", nil, time.Second) 1453 require_NoError(t, err) 1454 require_NoError(t, json.Unmarshal(resp.Data, &info)) 1455 stats := info.JetStreamAccountStats 1456 r1, r3 := stats.Tiers["R1"], stats.Tiers["R3"] 1457 1458 require_Equal(t, r1.ReservedMemory, 256*1024) // TEST8 1459 require_Equal(t, r1.ReservedStore, 2*1024*1024) // TEST7 1460 require_Equal(t, r3.ReservedMemory, 22*1024) // TEST9 1461 require_Equal(t, r3.ReservedStore, 5*1024*1024) // TEST1-TEST6 1462 }