github.com/nats-io/jwt/v2@v2.5.6/account_claims_test.go (about) 1 /* 2 * Copyright 2018-2023 The NATS Authors 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package jwt 17 18 import ( 19 "fmt" 20 "strings" 21 "testing" 22 "time" 23 24 "github.com/nats-io/nkeys" 25 ) 26 27 func TestNewAccountClaims(t *testing.T) { 28 akp := createAccountNKey(t) 29 akp2 := createAccountNKey(t) 30 apk := publicKey(akp, t) 31 apk2 := publicKey(akp2, t) 32 33 activation := NewActivationClaims(apk) 34 activation.Expires = time.Now().Add(time.Hour).UTC().Unix() 35 activation.ImportSubject = "test" 36 activation.ImportType = Stream 37 actJWT := encode(activation, akp2, t) 38 39 account := NewAccountClaims(apk) 40 if !account.Limits.NatsLimits.IsUnlimited() { 41 t.Fatalf("Expected unlimited nats operator limits") 42 } 43 if !account.Limits.AccountLimits.IsUnlimited() { 44 t.Fatalf("Expected unlimited account operator limits") 45 } 46 if account.Limits.JetStreamLimits.DiskStorage != 0 || 47 account.Limits.JetStreamLimits.MemoryStorage != 0 || 48 account.Limits.JetStreamLimits.Consumer != 0 || 49 account.Limits.JetStreamLimits.Streams != 0 { 50 t.Fatalf("Expected unlimited operator limits") 51 } 52 53 account.Expires = time.Now().Add(time.Hour * 24 * 365).UTC().Unix() 54 55 account.InfoURL = "http://localhost/my-account/doc" 56 account.Description = "my account" 57 account.Imports = Imports{} 58 account.Imports.Add(&Import{Subject: "test", Name: "test import", Account: apk2, Token: actJWT, LocalSubject: "my", Type: Stream}) 59 60 vr := CreateValidationResults() 61 account.Validate(vr) 62 63 if !vr.IsEmpty() { 64 t.Fatal("Valid account will have no validation results") 65 } 66 67 actJwt := encode(account, akp, t) 68 69 account2, err := DecodeAccountClaims(actJwt) 70 if err != nil { 71 t.Fatal("error decoding account jwt", err) 72 } 73 74 AssertEquals(account.String(), account2.String(), t) 75 AssertEquals(account2.IsSelfSigned(), true, t) 76 77 AssertEquals(account2.Claims() != nil, true, t) 78 AssertEquals(account2.Payload() != nil, true, t) 79 AssertEquals(account.InfoURL, account2.InfoURL, t) 80 AssertEquals(account.Description, account2.Description, t) 81 } 82 83 func TestAccountCanSignOperatorLimits(t *testing.T) { // don't block encoding!!! 84 akp := createAccountNKey(t) 85 apk := publicKey(akp, t) 86 87 account := NewAccountClaims(apk) 88 account.Expires = time.Now().Add(time.Hour * 24 * 365).Unix() 89 account.Limits.Conn = 10 90 account.Limits.LeafNodeConn = 2 91 92 _, err := account.Encode(akp) 93 if err != nil { 94 t.Fatal("account should not be able to encode operator limits", err) 95 } 96 } 97 98 func TestOperatorCanSignClaims(t *testing.T) { 99 akp := createAccountNKey(t) 100 okp := createOperatorNKey(t) 101 apk := publicKey(akp, t) 102 103 account := NewAccountClaims(apk) 104 account.Expires = time.Now().Add(time.Hour * 24 * 365).Unix() 105 account.Limits.Conn = 1 106 account.Limits.LeafNodeConn = 4 107 108 actJwt := encode(account, okp, t) 109 110 account2, err := DecodeAccountClaims(actJwt) 111 if err != nil { 112 t.Fatal("error decoding account jwt", err) 113 } 114 115 AssertEquals(account.String(), account2.String(), t) 116 AssertEquals(account2.IsSelfSigned(), false, t) 117 118 if account2.Limits.Conn != 1 { 119 t.Fatalf("Expected Limits.Conn == 1, got %d", account2.Limits.Conn) 120 } 121 if account2.Limits.LeafNodeConn != 4 { 122 t.Fatalf("Expected Limits.Conn == 4, got %d", account2.Limits.LeafNodeConn) 123 } 124 } 125 126 func TestInvalidAccountClaimIssuer(t *testing.T) { 127 akp := createAccountNKey(t) 128 ac := NewAccountClaims(publicKey(akp, t)) 129 ac.Expires = time.Now().Add(time.Hour).Unix() 130 aJwt := encode(ac, akp, t) 131 132 temp, err := DecodeGeneric(aJwt) 133 if err != nil { 134 t.Fatal("failed to decode", err) 135 } 136 137 type kpInputs struct { 138 name string 139 kp nkeys.KeyPair 140 ok bool 141 } 142 143 inputs := []kpInputs{ 144 {"account", createAccountNKey(t), true}, 145 {"user", createUserNKey(t), false}, 146 {"operator", createOperatorNKey(t), true}, 147 {"server", createServerNKey(t), false}, 148 {"cluster", createClusterNKey(t), false}, 149 } 150 151 for _, i := range inputs { 152 bad := encode(temp, i.kp, t) 153 _, err = DecodeAccountClaims(bad) 154 if i.ok && err != nil { 155 t.Fatalf("unexpected error for %q: %v", i.name, err) 156 } 157 if !i.ok && err == nil { 158 t.Logf("should have failed to decode account signed by %q", i.name) 159 t.Fail() 160 } 161 } 162 } 163 164 func TestInvalidAccountSubjects(t *testing.T) { 165 type kpInputs struct { 166 name string 167 kp nkeys.KeyPair 168 ok bool 169 } 170 171 inputs := []kpInputs{ 172 {"account", createAccountNKey(t), true}, 173 {"user", createUserNKey(t), false}, 174 {"operator", createOperatorNKey(t), false}, 175 {"server", createServerNKey(t), false}, 176 {"cluster", createClusterNKey(t), false}, 177 } 178 179 for _, i := range inputs { 180 pk := publicKey(i.kp, t) 181 var err error 182 183 c := NewAccountClaims(pk) 184 _, err = c.Encode(i.kp) 185 if i.ok && err != nil { 186 t.Fatalf("unexpected error for %q: %v", i.name, err) 187 } 188 if !i.ok && err == nil { 189 t.Logf("should have failed to encode account with with %q subject", i.name) 190 t.Fail() 191 } 192 } 193 } 194 195 func TestAccountImports(t *testing.T) { 196 akp := createAccountNKey(t) 197 apk := publicKey(akp, t) 198 199 account := NewAccountClaims(apk) 200 account.Expires = time.Now().Add(time.Hour * 24 * 365).Unix() 201 202 actJwt := encode(account, akp, t) 203 204 account2, err := DecodeAccountClaims(actJwt) 205 if err != nil { 206 t.Fatal("error decoding account jwt", err) 207 } 208 209 AssertEquals(account.String(), account2.String(), t) 210 } 211 212 func TestNewNilAccountClaim(t *testing.T) { 213 v := NewAccountClaims("") 214 if v != nil { 215 t.Fatal("expected nil account claim") 216 } 217 } 218 219 func TestLimitValidationInAccount(t *testing.T) { 220 akp := createAccountNKey(t) 221 apk := publicKey(akp, t) 222 223 account := NewAccountClaims(apk) 224 account.Expires = time.Now().Add(time.Hour * 24 * 365).Unix() 225 account.Limits.Conn = 10 226 account.Limits.Imports = 10 227 account.Limits.Exports = 10 228 account.Limits.Data = 1024 229 account.Limits.Payload = 1024 230 account.Limits.Subs = 10 231 account.Limits.WildcardExports = true 232 233 vr := CreateValidationResults() 234 account.Validate(vr) 235 236 if len(vr.Issues) != 0 { 237 t.Fatal("valid account should have no validation issues") 238 } 239 240 account.Limits.Conn = -1 241 account.Limits.Imports = -1 242 account.Limits.Exports = -1 243 account.Limits.Subs = -1 244 account.Limits.Data = -1 245 account.Limits.Payload = -1 246 vr = CreateValidationResults() 247 account.Validate(vr) 248 249 if len(vr.Issues) != 0 { 250 t.Fatal("valid account should have no validation issues") 251 } 252 253 op := createOperatorNKey(t) 254 opk := publicKey(op, t) 255 account.Issuer = opk 256 257 vr = CreateValidationResults() 258 account.Validate(vr) 259 260 if !vr.IsEmpty() || vr.IsBlocking(true) { 261 t.Fatal("operator can encode limits and identity") 262 } 263 264 account.Issuer = apk 265 vr = CreateValidationResults() 266 account.Validate(vr) 267 268 if vr.IsEmpty() || vr.IsBlocking(true) { 269 t.Fatal("bad issuer for limits should have non-blocking validation results") 270 } 271 } 272 273 func TestWildcardExportLimit(t *testing.T) { 274 akp := createAccountNKey(t) 275 apk := publicKey(akp, t) 276 277 account := NewAccountClaims(apk) 278 account.Expires = time.Now().Add(time.Hour * 24 * 365).Unix() 279 account.Limits.Conn = 10 280 account.Limits.Imports = 10 281 account.Limits.Exports = 10 282 account.Limits.WildcardExports = true 283 account.Exports = Exports{ 284 &Export{Subject: "foo", Type: Stream}, 285 &Export{Subject: "bar.*", Type: Stream}, 286 } 287 288 vr := CreateValidationResults() 289 account.Validate(vr) 290 291 if !vr.IsEmpty() { 292 t.Fatal("valid account should have no validation issues") 293 } 294 295 account.Limits.WildcardExports = false 296 vr = CreateValidationResults() 297 account.Validate(vr) 298 299 if vr.IsEmpty() || !vr.IsBlocking(true) { 300 t.Fatal("invalid account should have validation issues") 301 } 302 303 account.Limits.WildcardExports = true 304 account.Limits.Exports = 1 305 vr = CreateValidationResults() 306 account.Validate(vr) 307 308 if vr.IsEmpty() || !vr.IsBlocking(true) { 309 t.Fatal("invalid account should have validation issues") 310 } 311 } 312 313 func TestJetstreamLimits(t *testing.T) { 314 akp := createAccountNKey(t) 315 apk := publicKey(akp, t) 316 acc1 := NewAccountClaims(apk) 317 if acc1.Limits.JetStreamLimits.DiskStorage != 0 || 318 acc1.Limits.JetStreamLimits.MemoryStorage != 0 || 319 acc1.Limits.JetStreamLimits.Consumer != 0 || 320 acc1.Limits.JetStreamLimits.Streams != 0 || 321 acc1.Limits.JetStreamLimits.MaxBytesRequired != false || 322 acc1.Limits.JetStreamLimits.MemoryMaxStreamBytes != 0 || 323 acc1.Limits.JetStreamLimits.DiskMaxStreamBytes != 0 || 324 acc1.Limits.JetStreamLimits.MaxAckPending != 0 { 325 t.Fatalf("Expected unlimited operator limits") 326 } 327 acc1.Limits.Consumer = 1 328 acc1.Limits.Streams = 2 329 acc1.Limits.MemoryStorage = 3 330 acc1.Limits.DiskStorage = 4 331 acc1.Limits.MemoryMaxStreamBytes = 1000 332 acc1.Limits.DiskMaxStreamBytes = 1000 333 acc1.Limits.MaxBytesRequired = true 334 acc1.Limits.MaxAckPending = 200 335 vr := CreateValidationResults() 336 acc1.Validate(vr) 337 if !vr.IsEmpty() { 338 t.Fatal("valid account should have no validation issues") 339 } 340 if token, err := acc1.Encode(akp); err != nil { 341 t.Fatal("valid account should have no validation issues") 342 } else if acc2, err := DecodeAccountClaims(token); err != nil { 343 t.Fatal("valid account should have no validation issues") 344 } else if acc1.Limits.JetStreamLimits != acc2.Limits.JetStreamLimits { 345 t.Fatal("account should have same properties") 346 } 347 } 348 349 func TestTieredLimits(t *testing.T) { 350 akp := createAccountNKey(t) 351 apk := publicKey(akp, t) 352 acc1 := NewAccountClaims(apk) 353 l := JetStreamLimits{ 354 MemoryStorage: 1024, 355 DiskStorage: 1024, 356 Streams: 1, 357 Consumer: 1, 358 MaxBytesRequired: true, 359 } 360 acc1.Limits.JetStreamTieredLimits["R1"] = l 361 l.Streams = 2 // minor change so both tiers differ 362 acc1.Limits.JetStreamTieredLimits["R3"] = l 363 364 vr := CreateValidationResults() 365 acc1.Validate(vr) 366 if !vr.IsEmpty() { 367 t.Fatal("valid account should have validation issues") 368 } 369 370 if token, err := acc1.Encode(akp); err != nil { 371 t.Fatal("valid account should have no validation issues") 372 } else if acc2, err := DecodeAccountClaims(token); err != nil { 373 t.Fatal("valid account should have no validation issues") 374 } else if acc1.Limits.JetStreamTieredLimits["R1"] != acc2.Limits.JetStreamTieredLimits["R1"] { 375 t.Fatal("tier R1 should have same limits") 376 } else if acc1.Limits.JetStreamTieredLimits["R3"] != acc2.Limits.JetStreamTieredLimits["R3"] { 377 t.Fatal("tier R2 should have same limits") 378 } 379 // test tiers and js limits being mutual exclusive 380 acc1.Limits.JetStreamLimits = l 381 acc1.Validate(vr) 382 if vr.IsEmpty() { 383 t.Fatal("valid account should have validation issues") 384 } 385 } 386 387 func TestJetstreamLimitsDeEnCode(t *testing.T) { 388 // token (generated without this change) with js disabled 389 c1, err := DecodeAccountClaims(`eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiI3V0NYQkZKS0lIN1Y0SkdPR0FVTEtTS05aQUxVTUZMVExZWVgyNTdDSzZORk5OWTdGRVdBIiwiaWF0IjoxNjQ0Mjc5NDY3LCJpc3MiOiJPQk5UUVJFSEVJUFJFVE1BVlBWUVVDSUdFUktHWkIzRVJBVjVTNUdNM0lPRVFOSFJFQkpPVUFSRiIsIm5hbWUiOiJ0ZXN0Iiwic3ViIjoiQUM2SFFJMlVBTVVQREVQN1dTWVFZV1JDTEVZQkxZVlNQTDZBSExDVVBKVEdVMzJUNEtRQktZU0ciLCJuYXRzIjp7ImxpbWl0cyI6eyJzdWJzIjotMSwiZGF0YSI6LTEsInBheWxvYWQiOi0xLCJpbXBvcnRzIjotMSwiZXhwb3J0cyI6LTEsIndpbGRjYXJkcyI6dHJ1ZSwiY29ubiI6LTEsImxlYWYiOi0xfSwiZGVmYXVsdF9wZXJtaXNzaW9ucyI6eyJwdWIiOnt9LCJzdWIiOnt9fSwidHlwZSI6ImFjY291bnQiLCJ2ZXJzaW9uIjoyfX0.73vDu9osNeLKwQ-g1Uu1fAtszMNz_QRZXRJLp0kzZh-0eMBmt0nb2mMwBwg-fufJs1FqYe9WbWKeXAYStnVnBg`) 390 if err != nil { 391 t.Fatal(err) 392 } else if c1.Limits.IsJSEnabled() { 393 t.Fatal("JetStream expected to be disabled") 394 } 395 // token (generated without this change) with js enabled 396 c2, err := DecodeAccountClaims(`eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJPVFFXVEQyVkFMWkRQQTZYU1hLS09GRVFZR1VaVFBDNEtKV1BYMlAyWU1XMjVTMzRTVjNRIiwiaWF0IjoxNjQ0Mjc5MzM0LCJpc3MiOiJPQk5UUVJFSEVJUFJFVE1BVlBWUVVDSUdFUktHWkIzRVJBVjVTNUdNM0lPRVFOSFJFQkpPVUFSRiIsIm5hbWUiOiJ0ZXN0Iiwic3ViIjoiQUM2SFFJMlVBTVVQREVQN1dTWVFZV1JDTEVZQkxZVlNQTDZBSExDVVBKVEdVMzJUNEtRQktZU0ciLCJuYXRzIjp7ImxpbWl0cyI6eyJzdWJzIjotMSwiZGF0YSI6LTEsInBheWxvYWQiOi0xLCJpbXBvcnRzIjotMSwiZXhwb3J0cyI6LTEsIndpbGRjYXJkcyI6dHJ1ZSwiY29ubiI6LTEsImxlYWYiOi0xLCJkaXNrX3N0b3JhZ2UiOjEwMDAwMDB9LCJkZWZhdWx0X3Blcm1pc3Npb25zIjp7InB1YiI6e30sInN1YiI6e319LCJ0eXBlIjoiYWNjb3VudCIsInZlcnNpb24iOjJ9fQ.Xt5azhxOkC7nywz9Q8xVtzX8lZIqdOhpfGyQI30aNdd-nbVGX2O13OOfouIaTLyajZiS4bcJFXa29q6QCFRUDA`) 397 if err != nil { 398 t.Fatal(err) 399 } else if !c2.Limits.IsJSEnabled() { 400 t.Fatal("JetStream expected to be enabled") 401 } 402 } 403 404 func TestAccountSigningKeyValidation(t *testing.T) { 405 okp := createOperatorNKey(t) 406 407 akp1 := createAccountNKey(t) 408 apk1 := publicKey(akp1, t) 409 akp2 := createAccountNKey(t) 410 apk2 := publicKey(akp2, t) 411 412 ac := NewAccountClaims(apk1) 413 ac.SigningKeys.Add(apk2) 414 415 var vr ValidationResults 416 ac.Validate(&vr) 417 if len(vr.Issues) != 0 { 418 t.Fatal("expected no validation issues") 419 } 420 421 // try encoding/decoding 422 token, err := ac.Encode(okp) 423 if err != nil { 424 t.Fatal(err) 425 } 426 427 ac2, err := DecodeAccountClaims(token) 428 if err != nil { 429 t.Fatal(err) 430 } 431 if len(ac2.SigningKeys) != 1 { 432 t.Fatal("expected claim to have a signing key") 433 } 434 if !ac.SigningKeys.Contains(apk2) { 435 t.Fatalf("expected signing key %s", apk2) 436 } 437 438 bkp := createUserNKey(t) 439 ac.SigningKeys.Add(publicKey(bkp, t)) 440 ac.Validate(&vr) 441 if len(vr.Issues) != 1 { 442 t.Fatal("expected 1 validation issue") 443 } 444 } 445 446 func TestAccountSignedBy(t *testing.T) { 447 okp := createOperatorNKey(t) 448 449 akp1 := createAccountNKey(t) 450 apk1 := publicKey(akp1, t) 451 akp2 := createAccountNKey(t) 452 apk2 := publicKey(akp2, t) 453 454 ac := NewAccountClaims(apk1) 455 ac.SigningKeys.Add(apk2) 456 457 token, err := ac.Encode(okp) 458 if err != nil { 459 t.Fatal(err) 460 } 461 ac2, err := DecodeAccountClaims(token) 462 if err != nil { 463 t.Fatal(err) 464 } 465 if len(ac2.SigningKeys) != 1 { 466 t.Fatal("expected claim to have a signing key") 467 } 468 if !ac.SigningKeys.Contains(apk2) { 469 t.Fatalf("expected signing key %s", apk2) 470 } 471 472 ukp := createUserNKey(t) 473 upk := publicKey(ukp, t) 474 475 // claim signed by alternate key 476 uc := NewUserClaims(upk) 477 uc.IssuerAccount = apk1 478 utoken, err := uc.Encode(akp2) 479 if err != nil { 480 t.Fatal(err) 481 } 482 483 uc2, err := DecodeUserClaims(utoken) 484 if err != nil { 485 t.Fatal(err) 486 } 487 if !ac2.DidSign(uc2) { 488 t.Fatal("failed to verify user claim") 489 } 490 491 // claim signed by the account pk 492 uc3 := NewUserClaims(upk) 493 utoken2, err := uc3.Encode(akp1) 494 if err != nil { 495 t.Fatal(err) 496 } 497 uc4, err := DecodeUserClaims(utoken2) 498 if err != nil { 499 t.Fatal(err) 500 } 501 if !ac2.DidSign(uc4) { 502 t.Fatal("failed to verify user claim") 503 } 504 } 505 506 func TestAddRemoveSigningKey(t *testing.T) { 507 akp1 := createAccountNKey(t) 508 apk1 := publicKey(akp1, t) 509 akp2 := createAccountNKey(t) 510 apk2 := publicKey(akp2, t) 511 akp3 := createAccountNKey(t) 512 apk3 := publicKey(akp3, t) 513 514 ac := NewAccountClaims(apk1) 515 ac.SigningKeys.Add(apk2, apk3) 516 517 if len(ac.SigningKeys) != 2 { 518 t.Fatal("expected 2 signing keys") 519 } 520 521 ac.SigningKeys.Remove(publicKey(createAccountNKey(t), t)) 522 if len(ac.SigningKeys) != 2 { 523 t.Fatal("expected 2 signing keys") 524 } 525 526 ac.SigningKeys.Remove(apk2) 527 if len(ac.SigningKeys) != 1 { 528 t.Fatal("expected single signing keys") 529 } 530 } 531 532 func TestUserRevocation(t *testing.T) { 533 akp := createAccountNKey(t) 534 apk := publicKey(akp, t) 535 account := NewAccountClaims(apk) 536 537 ukp := createUserNKey(t) 538 pubKey := publicKey(ukp, t) 539 uc := NewUserClaims(pubKey) 540 uJwt, _ := uc.Encode(akp) 541 uc, err := DecodeUserClaims(uJwt) 542 if err != nil { 543 t.Errorf("Failed to decode user claim: %v", err) 544 } 545 now := time.Now() 546 547 // test that clear is safe before we add any 548 account.ClearRevocation(pubKey) 549 550 if account.isRevoked(pubKey, now) { 551 t.Errorf("no revocation was added so is revoked should be false") 552 } 553 554 account.RevokeAt(pubKey, now.Add(time.Second*100)) 555 556 if !account.isRevoked(pubKey, now) { 557 t.Errorf("revocation should hold when timestamp is in the future") 558 } 559 560 if account.isRevoked(pubKey, now.Add(time.Second*150)) { 561 t.Errorf("revocation should time out") 562 } 563 564 account.RevokeAt(pubKey, now.Add(time.Second*50)) // shouldn't change the revocation, you can't move it in 565 566 if !account.isRevoked(pubKey, now.Add(time.Second*60)) { 567 t.Errorf("revocation should hold, 100 > 50") 568 } 569 570 encoded, _ := account.Encode(akp) 571 decoded, _ := DecodeAccountClaims(encoded) 572 573 if !decoded.isRevoked(pubKey, now.Add(time.Second*60)) { 574 t.Errorf("revocation should last across encoding") 575 } 576 577 account.ClearRevocation(pubKey) 578 579 if account.IsClaimRevoked(uc) { 580 t.Errorf("revocations should be cleared") 581 } 582 583 account.RevokeAt(pubKey, now.Add(time.Second*1000)) 584 585 if !account.IsClaimRevoked(uc) { 586 t.Errorf("revocation be true we revoked in the future") 587 } 588 } 589 590 func TestAccountDefaultPermissions(t *testing.T) { 591 akp := createAccountNKey(t) 592 apk := publicKey(akp, t) 593 594 account := NewAccountClaims(apk) 595 account.DefaultPermissions.Sub = Permission{ 596 Allow: []string{"foo.1", "bar.*"}, 597 Deny: []string{"foo.2", "baz.>"}, 598 } 599 account.DefaultPermissions.Pub = Permission{ 600 Allow: []string{"foo.4", "bar.>"}, 601 Deny: []string{"foo.4", "baz.*"}, 602 } 603 account.DefaultPermissions.Resp = &ResponsePermission{ 604 5, 605 5 * time.Second} 606 607 actJwt := encode(account, akp, t) 608 609 account2, err := DecodeAccountClaims(actJwt) 610 if err != nil { 611 t.Fatal("error decoding account jwt", err) 612 } 613 614 AssertEquals(account.String(), account2.String(), t) 615 } 616 617 func TestUserRevocationAll(t *testing.T) { 618 akp := createAccountNKey(t) 619 ukp := createUserNKey(t) 620 upk := publicKey(ukp, t) 621 user := NewUserClaims(upk) 622 token, err := user.Encode(akp) 623 if err != nil { 624 t.Fatal(err) 625 } 626 627 ud, err := DecodeUserClaims(token) 628 if err != nil { 629 t.Fatal(err) 630 } 631 632 apk := publicKey(akp, t) 633 account := NewAccountClaims(apk) 634 account.RevokeAt(All, time.Now().Add(time.Second)) 635 if !account.IsClaimRevoked(ud) { 636 t.Fatal("user should have been revoked") 637 } 638 639 account.RevokeAt(All, time.Now().Add(time.Second*-10)) 640 if !account.IsClaimRevoked(ud) { 641 t.Fatal("user should have not been revoked") 642 } 643 } 644 645 func TestInvalidAccountInfo(t *testing.T) { 646 a := NewAccountClaims(publicKey(createAccountNKey(t), t)) 647 a.InfoURL = "/bad" 648 vr := CreateValidationResults() 649 a.Validate(vr) 650 if vr.IsEmpty() { 651 t.Errorf("export info should not validate cleanly") 652 } 653 if !vr.IsBlocking(true) { 654 t.Errorf("invalid info needs to be blocking") 655 } 656 } 657 658 func TestAccountMapping(t *testing.T) { // don't block encoding!!! 659 akp := createAccountNKey(t) 660 apk := publicKey(akp, t) 661 662 account := NewAccountClaims(apk) 663 vr := &ValidationResults{} 664 665 account.AddMapping("foo1", WeightedMapping{Subject: "to"}) 666 account.Validate(vr) 667 if !vr.IsEmpty() { 668 t.Fatal("Expected no errors") 669 } 670 account.AddMapping("foo2", 671 WeightedMapping{Subject: "to1", Weight: 50}, 672 WeightedMapping{Subject: "to2", Weight: 50}) 673 account.Validate(vr) 674 if !vr.IsEmpty() { 675 t.Fatal("Expected no errors") 676 } 677 account.AddMapping("foo3", 678 WeightedMapping{Subject: "to1", Weight: 50}, 679 WeightedMapping{Subject: "to2", Weight: 51}) 680 account.Validate(vr) 681 if !vr.IsBlocking(false) { 682 t.Fatal("Expected blocking error as sum of weights is > 100") 683 } 684 685 vr = &ValidationResults{} 686 account.Mappings = Mapping{} 687 account.AddMapping("foo4", 688 WeightedMapping{Subject: "to1"}, // no weight means 100 689 WeightedMapping{Subject: "to2", Weight: 1}) 690 account.Validate(vr) 691 if !vr.IsBlocking(false) { 692 t.Fatal("Expected blocking error as sum of weights is > 100") 693 } 694 695 vr = &ValidationResults{} 696 account.Mappings = Mapping{} 697 account.AddMapping("foo5.>", WeightedMapping{Subject: "to.*.>"}) 698 account.Validate(vr) 699 if !vr.IsEmpty() { 700 t.Fatal("Expected no errors") 701 } 702 703 vr = &ValidationResults{} 704 account.Mappings = Mapping{} 705 account.AddMapping("foo6.>", WeightedMapping{Subject: "to.boo.>"}) 706 account.Validate(vr) 707 if !vr.IsEmpty() { 708 t.Fatal("Expected no errors") 709 } 710 } 711 712 func TestAccountExternalAuthorization(t *testing.T) { 713 akp := createAccountNKey(t) 714 apk := publicKey(akp, t) 715 716 account := NewAccountClaims(apk) 717 vr := &ValidationResults{} 718 719 ukp := createUserNKey(t) 720 account.EnableExternalAuthorization(publicKey(ukp, t)) 721 account.Validate(vr) 722 if !vr.IsEmpty() { 723 t.Fatal("Expected no errors") 724 } 725 726 akp2 := createAccountNKey(t) 727 account.Authorization.AllowedAccounts.Add(publicKey(akp2, t)) 728 account.Validate(vr) 729 if !vr.IsEmpty() { 730 t.Fatal("Expected no errors") 731 } 732 733 if !account.HasExternalAuthorization() { 734 t.Fatalf("Expected to have authorization enabled") 735 } 736 737 vr = &ValidationResults{} 738 account.Authorization = ExternalAuthorization{} 739 740 account.Authorization.AuthUsers.Add("Z") 741 account.Validate(vr) 742 if vr.IsEmpty() || !vr.IsBlocking(false) { 743 t.Fatalf("Expected blocking error on bad auth user") 744 } 745 746 vr = &ValidationResults{} 747 account.Authorization = ExternalAuthorization{} 748 account.Authorization.AllowedAccounts.Add("Z") 749 account.Validate(vr) 750 if vr.IsEmpty() || !vr.IsBlocking(false) { 751 t.Fatalf("Expected blocking error on bad allowed account") 752 } 753 754 account.Authorization = ExternalAuthorization{} 755 if account.Authorization.IsEnabled() { 756 t.Fatalf("Expected not to have authorization enabled") 757 } 758 } 759 760 func TestAccountExternalAuthorizationRequiresOneUser(t *testing.T) { 761 akp := createAccountNKey(t) 762 apk := publicKey(akp, t) 763 764 account := NewAccountClaims(apk) 765 account.Authorization.AllowedAccounts.Add(publicKey(createAccountNKey(t), t)) 766 767 vr := &ValidationResults{} 768 account.Validate(vr) 769 770 AssertEquals(len(vr.Errors()), 1, t) 771 AssertEquals("External authorization cannot have accounts without users specified", 772 vr.Errors()[0].Error(), 773 t) 774 } 775 776 func TestAccountExternalAuthorizationAnyAccount(t *testing.T) { 777 akp := createAccountNKey(t) 778 apk := publicKey(akp, t) 779 ukp := createUserNKey(t) 780 upk := publicKey(ukp, t) 781 782 account := NewAccountClaims(apk) 783 account.Authorization.AllowedAccounts.Add("*") 784 account.Authorization.AuthUsers.Add(upk) 785 786 vr := &ValidationResults{} 787 account.Validate(vr) 788 AssertEquals(len(vr.Errors()), 0, t) 789 } 790 791 func TestAccountExternalAuthorizationAnyAccountAndSpecificFails(t *testing.T) { 792 akp := createAccountNKey(t) 793 apk := publicKey(akp, t) 794 ukp := createUserNKey(t) 795 upk := publicKey(ukp, t) 796 797 account := NewAccountClaims(apk) 798 account.Authorization.AllowedAccounts.Add("*", apk) 799 account.Authorization.AuthUsers.Add(upk) 800 801 vr := &ValidationResults{} 802 account.Validate(vr) 803 AssertEquals(len(vr.Errors()), 1, t) 804 AssertEquals(vr.Errors()[0].Error(), fmt.Sprintf("AllowedAccounts can only be a list of accounts or %q", AnyAccount), t) 805 } 806 807 func TestAccountClaims_DidSign(t *testing.T) { 808 akp := createAccountNKey(t) 809 apk := publicKey(akp, t) 810 skp := createAccountNKey(t) 811 spk := publicKey(skp, t) 812 813 ac := NewAccountClaims(apk) 814 ac.SigningKeys.Add(spk) 815 816 upk := publicKey(createUserNKey(t), t) 817 uc := NewUserClaims(upk) 818 tok, err := uc.Encode(akp) 819 if err != nil { 820 t.Fatal("error encoding") 821 } 822 uc, err = DecodeUserClaims(tok) 823 if err != nil { 824 t.Fatal("error decoding") 825 } 826 if !ac.DidSign(uc) { 827 t.Fatal("expected account to have been issued") 828 } 829 uc = NewUserClaims(upk) 830 uc.IssuerAccount = publicKey(createAccountNKey(t), t) 831 tok, err = uc.Encode(skp) 832 if err != nil { 833 t.Fatalf("encode failed %v", err) 834 } 835 uc, err = DecodeUserClaims(tok) 836 if err != nil { 837 t.Fatalf("decode failed %v", err) 838 } 839 if ac.DidSign(uc) { 840 t.Fatal("this is not issued by account A") 841 } 842 } 843 844 func TestAccountClaims_GetTags(t *testing.T) { 845 akp := createAccountNKey(t) 846 apk := publicKey(akp, t) 847 848 ac := NewAccountClaims(apk) 849 ac.Account.Tags.Add("foo", "bar") 850 tags := ac.GetTags() 851 if len(tags) != 2 { 852 t.Fatal("expected 2 tags") 853 } 854 if tags[0] != "foo" { 855 t.Fatal("expected tag foo") 856 } 857 if tags[1] != "bar" { 858 t.Fatal("expected tag bar") 859 } 860 861 token, err := ac.Encode(akp) 862 if err != nil { 863 t.Fatal("error encoding") 864 } 865 ac, err = DecodeAccountClaims(token) 866 if err != nil { 867 t.Fatal("error decoding") 868 } 869 tags = ac.GetTags() 870 if len(tags) != 2 { 871 t.Fatal("expected 2 tags") 872 } 873 if tags[0] != "foo" { 874 t.Fatal("expected tag foo") 875 } 876 if tags[1] != "bar" { 877 t.Fatal("expected tag bar") 878 } 879 } 880 881 func TestAccountClaimsTraceDest(t *testing.T) { 882 akp := createAccountNKey(t) 883 apk := publicKey(akp, t) 884 885 account := NewAccountClaims(apk) 886 for i, test := range []struct { 887 name string 888 invalidSubj Subject 889 expectErr bool 890 }{ 891 {"trace not specified", "", false}, 892 {"trace created but with empty destination", "", true}, 893 {"trace dest has spaces", "invalid dest", true}, 894 {"trace dest start with a dot", ".invalid.dest", true}, 895 {"trace dest ends with a dot", "invalid.dest.", true}, 896 {"trace dest has consecutive dots", "invalid..dest", true}, 897 {"trace dest invalid publish dest", "invalid.publish.*.dest", true}, 898 } { 899 t.Run(test.name, func(t *testing.T) { 900 if i > 0 { 901 account.Trace = &MsgTrace{Destination: test.invalidSubj} 902 } 903 vr := CreateValidationResults() 904 account.Validate(vr) 905 906 if test.expectErr && vr.IsEmpty() { 907 t.Fatal("account validation should have failed") 908 } else if !test.expectErr && !vr.IsEmpty() { 909 t.Fatalf("account validation should not have failed, got %+v", vr.Issues) 910 } 911 }) 912 } 913 } 914 915 func TestAccountClaimsTraceDestSampling(t *testing.T) { 916 akp := createAccountNKey(t) 917 apk := publicKey(akp, t) 918 919 account := NewAccountClaims(apk) 920 for _, test := range []struct { 921 name string 922 dest string 923 sampling int 924 expectErr string 925 }{ 926 {"sampling without destination", "", 10, "subject cannot be empty"}, 927 {"sampling negative", "dest", -1, "should be in the range [1..100]"}, 928 {"sampling above 100", "dest", 101, "should be in the range [1..100]"}, 929 {"sampling at 50", "dest", 50, ""}, 930 {"sampling at zero sets to 100", "dest", 0, ""}, 931 } { 932 t.Run(test.name, func(t *testing.T) { 933 account.Trace = &MsgTrace{Destination: Subject(test.dest), Sampling: test.sampling} 934 vr := CreateValidationResults() 935 account.Validate(vr) 936 937 if test.expectErr == "" { 938 if !vr.IsEmpty() { 939 t.Fatalf("account validation should not have failed, got %+v", vr.Issues) 940 } 941 if test.sampling == 0 { 942 if account.Trace.Sampling != 100 { 943 t.Fatalf("account sampling should have been set to 100 got %d", account.Trace.Sampling) 944 } 945 } else if test.sampling != account.Trace.Sampling { 946 t.Fatalf("account sampling should be %d, got %d", test.sampling, account.Trace.Sampling) 947 } 948 } else { 949 if vr.IsEmpty() { 950 t.Fatal("account validation should have failed") 951 } 952 if !strings.Contains(vr.Issues[0].Description, test.expectErr) { 953 t.Fatalf("account validation should have failed with error %q, got %q", test.expectErr, vr.Issues[0].Description) 954 } 955 } 956 }) 957 } 958 }