github.com/nats-io/jwt/v2@v2.5.6/v1compat/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 "testing" 20 "time" 21 22 "github.com/nats-io/nkeys" 23 ) 24 25 func TestNewAccountClaims(t *testing.T) { 26 akp := createAccountNKey(t) 27 akp2 := createAccountNKey(t) 28 apk := publicKey(akp, t) 29 apk2 := publicKey(akp2, t) 30 31 activation := NewActivationClaims(apk) 32 activation.Max = 1024 * 1024 33 activation.Expires = time.Now().Add(time.Duration(time.Hour)).UTC().Unix() 34 activation.ImportSubject = "test" 35 activation.ImportType = Stream 36 actJWT := encode(activation, akp2, t) 37 38 account := NewAccountClaims(apk) 39 if !account.Limits.IsUnlimited() { 40 t.Fatalf("Expected unlimited operator limits") 41 } 42 43 account.Expires = time.Now().Add(time.Duration(time.Hour * 24 * 365)).UTC().Unix() 44 45 account.Imports = Imports{} 46 account.Imports.Add(&Import{Subject: "test", Name: "test import", Account: apk2, Token: actJWT, To: "my", Type: Stream}) 47 48 vr := CreateValidationResults() 49 account.Validate(vr) 50 51 if !vr.IsEmpty() { 52 t.Fatal("Valid account will have no validation results") 53 } 54 55 actJwt := encode(account, akp, t) 56 57 account2, err := DecodeAccountClaims(actJwt) 58 if err != nil { 59 t.Fatal("error decoding account jwt", err) 60 } 61 62 AssertEquals(account.String(), account2.String(), t) 63 AssertEquals(account2.IsSelfSigned(), true, t) 64 65 AssertEquals(account2.Claims() != nil, true, t) 66 AssertEquals(account2.Payload() != nil, true, t) 67 } 68 69 func TestAccountCanSignOperatorLimits(t *testing.T) { // don't block encoding!!! 70 akp := createAccountNKey(t) 71 apk := publicKey(akp, t) 72 73 account := NewAccountClaims(apk) 74 account.Expires = time.Now().Add(time.Duration(time.Hour * 24 * 365)).Unix() 75 account.Limits.Conn = 10 76 account.Limits.LeafNodeConn = 2 77 78 _, err := account.Encode(akp) 79 if err != nil { 80 t.Fatal("account should not be able to encode operator limits", err) 81 } 82 } 83 84 func TestAccountCanSignIdentities(t *testing.T) { // don't block encoding!!! 85 akp := createAccountNKey(t) 86 apk := publicKey(akp, t) 87 88 account := NewAccountClaims(apk) 89 account.Expires = time.Now().Add(time.Duration(time.Hour * 24 * 365)).Unix() 90 account.Identities = []Identity{ 91 { 92 ID: "stephen", 93 Proof: "yougotit", 94 }, 95 } 96 97 _, err := account.Encode(akp) 98 if err != nil { 99 t.Fatal("account should not be able to encode identities", err) 100 } 101 } 102 103 func TestOperatorCanSignClaims(t *testing.T) { 104 akp := createAccountNKey(t) 105 okp := createOperatorNKey(t) 106 apk := publicKey(akp, t) 107 108 account := NewAccountClaims(apk) 109 account.Expires = time.Now().Add(time.Duration(time.Hour * 24 * 365)).Unix() 110 account.Limits.Conn = 1 111 account.Limits.LeafNodeConn = 4 112 113 account.Identities = []Identity{ 114 { 115 ID: "stephen", 116 Proof: "yougotit", 117 }, 118 } 119 120 actJwt := encode(account, okp, t) 121 122 account2, err := DecodeAccountClaims(actJwt) 123 if err != nil { 124 t.Fatal("error decoding account jwt", err) 125 } 126 127 AssertEquals(account.String(), account2.String(), t) 128 AssertEquals(account2.IsSelfSigned(), false, t) 129 130 if account2.Limits.Conn != 1 { 131 t.Fatalf("Expected Limits.Conn == 1, got %d", account2.Limits.Conn) 132 } 133 if account2.Limits.LeafNodeConn != 4 { 134 t.Fatalf("Expected Limits.Conn == 4, got %d", account2.Limits.LeafNodeConn) 135 } 136 } 137 138 func TestInvalidAccountClaimIssuer(t *testing.T) { 139 akp := createAccountNKey(t) 140 ac := NewAccountClaims(publicKey(akp, t)) 141 ac.Expires = time.Now().Add(time.Duration(time.Hour)).Unix() 142 aJwt := encode(ac, akp, t) 143 144 temp, err := DecodeGeneric(aJwt) 145 if err != nil { 146 t.Fatal("failed to decode", err) 147 } 148 149 type kpInputs struct { 150 name string 151 kp nkeys.KeyPair 152 ok bool 153 } 154 155 inputs := []kpInputs{ 156 {"account", createAccountNKey(t), true}, 157 {"user", createUserNKey(t), false}, 158 {"operator", createOperatorNKey(t), true}, 159 {"server", createServerNKey(t), false}, 160 {"cluster", createClusterNKey(t), false}, 161 } 162 163 for _, i := range inputs { 164 bad := encode(temp, i.kp, t) 165 _, err = DecodeAccountClaims(bad) 166 if i.ok && err != nil { 167 t.Fatalf("unexpected error for %q: %v", i.name, err) 168 } 169 if !i.ok && err == nil { 170 t.Logf("should have failed to decode account signed by %q", i.name) 171 t.Fail() 172 } 173 } 174 } 175 176 func TestInvalidAccountSubjects(t *testing.T) { 177 type kpInputs struct { 178 name string 179 kp nkeys.KeyPair 180 ok bool 181 } 182 183 inputs := []kpInputs{ 184 {"account", createAccountNKey(t), true}, 185 {"user", createUserNKey(t), false}, 186 {"operator", createOperatorNKey(t), false}, 187 {"server", createServerNKey(t), false}, 188 {"cluster", createClusterNKey(t), false}, 189 } 190 191 for _, i := range inputs { 192 pk := publicKey(i.kp, t) 193 var err error 194 195 c := NewAccountClaims(pk) 196 if i.ok && err != nil { 197 t.Fatalf("error encoding activation: %v", err) 198 } 199 _, err = c.Encode(i.kp) 200 if i.ok && err != nil { 201 t.Fatalf("unexpected error for %q: %v", i.name, err) 202 } 203 if !i.ok && err == nil { 204 t.Logf("should have failed to encode account with with %q subject", i.name) 205 t.Fail() 206 } 207 } 208 } 209 210 func TestAccountImports(t *testing.T) { 211 akp := createAccountNKey(t) 212 apk := publicKey(akp, t) 213 214 account := NewAccountClaims(apk) 215 account.Expires = time.Now().Add(time.Duration(time.Hour * 24 * 365)).Unix() 216 217 actJwt := encode(account, akp, t) 218 219 account2, err := DecodeAccountClaims(actJwt) 220 if err != nil { 221 t.Fatal("error decoding account jwt", err) 222 } 223 224 AssertEquals(account.String(), account2.String(), t) 225 } 226 227 func TestNewNilAccountClaim(t *testing.T) { 228 v := NewAccountClaims("") 229 if v != nil { 230 t.Fatal("expected nil account claim") 231 } 232 } 233 234 func TestLimitValidationInAccount(t *testing.T) { 235 akp := createAccountNKey(t) 236 apk := publicKey(akp, t) 237 238 account := NewAccountClaims(apk) 239 account.Expires = time.Now().Add(time.Duration(time.Hour * 24 * 365)).Unix() 240 account.Limits.Conn = 10 241 account.Limits.Imports = 10 242 account.Limits.Exports = 10 243 account.Limits.Data = 1024 244 account.Limits.Payload = 1024 245 account.Limits.Subs = 10 246 account.Limits.WildcardExports = true 247 account.Identities = []Identity{ 248 { 249 ID: "stephen", 250 Proof: "yougotit", 251 }, 252 } 253 254 vr := CreateValidationResults() 255 account.Validate(vr) 256 257 if len(vr.Issues) != 0 { 258 t.Fatal("valid account should have no validation issues") 259 } 260 261 account.Limits.Conn = -1 262 account.Limits.Imports = -1 263 account.Limits.Exports = -1 264 account.Limits.Subs = -1 265 account.Limits.Data = -1 266 account.Limits.Payload = -1 267 vr = CreateValidationResults() 268 account.Validate(vr) 269 270 if len(vr.Issues) != 0 { 271 t.Fatal("valid account should have no validation issues") 272 } 273 274 op := createOperatorNKey(t) 275 opk := publicKey(op, t) 276 account.Issuer = opk 277 278 vr = CreateValidationResults() 279 account.Validate(vr) 280 281 if !vr.IsEmpty() || vr.IsBlocking(true) { 282 t.Fatal("operator can encode limits and identity") 283 } 284 285 account.Identities = nil 286 account.Issuer = apk 287 vr = CreateValidationResults() 288 account.Validate(vr) 289 290 if vr.IsEmpty() || vr.IsBlocking(true) { 291 t.Fatal("bad issuer for limits should have non-blocking validation results") 292 } 293 294 account.Identities = []Identity{ 295 { 296 ID: "stephen", 297 Proof: "yougotit", 298 }, 299 } 300 account.Limits = OperatorLimits{} 301 account.Issuer = apk 302 vr = CreateValidationResults() 303 account.Validate(vr) 304 305 if vr.IsEmpty() || vr.IsBlocking(true) { 306 t.Fatal("bad issuer for identities should have non-blocking validation results") 307 } 308 309 account.Identities = nil 310 account.Issuer = apk 311 vr = CreateValidationResults() 312 account.Validate(vr) 313 314 if !vr.IsEmpty() || vr.IsBlocking(true) { 315 t.Fatal("account can encode without limits and identity") 316 } 317 } 318 319 func TestWildcardExportLimit(t *testing.T) { 320 akp := createAccountNKey(t) 321 apk := publicKey(akp, t) 322 323 account := NewAccountClaims(apk) 324 account.Expires = time.Now().Add(time.Duration(time.Hour * 24 * 365)).Unix() 325 account.Limits.Conn = 10 326 account.Limits.Imports = 10 327 account.Limits.Exports = 10 328 account.Limits.WildcardExports = true 329 account.Exports = Exports{ 330 &Export{Subject: "foo", Type: Stream}, 331 &Export{Subject: "bar.*", Type: Stream}, 332 } 333 334 vr := CreateValidationResults() 335 account.Validate(vr) 336 337 if !vr.IsEmpty() { 338 t.Fatal("valid account should have no validation issues") 339 } 340 341 account.Limits.WildcardExports = false 342 vr = CreateValidationResults() 343 account.Validate(vr) 344 345 if vr.IsEmpty() || !vr.IsBlocking(true) { 346 t.Fatal("invalid account should have validation issues") 347 } 348 349 account.Limits.WildcardExports = true 350 account.Limits.Exports = 1 351 vr = CreateValidationResults() 352 account.Validate(vr) 353 354 if vr.IsEmpty() || !vr.IsBlocking(true) { 355 t.Fatal("invalid account should have validation issues") 356 } 357 } 358 359 func TestAccountSigningKeyValidation(t *testing.T) { 360 okp := createOperatorNKey(t) 361 362 akp1 := createAccountNKey(t) 363 apk1 := publicKey(akp1, t) 364 akp2 := createAccountNKey(t) 365 apk2 := publicKey(akp2, t) 366 367 ac := NewAccountClaims(apk1) 368 ac.SigningKeys.Add(apk2) 369 370 var vr ValidationResults 371 ac.Validate(&vr) 372 if len(vr.Issues) != 0 { 373 t.Fatal("expected no validation issues") 374 } 375 376 // try encoding/decoding 377 token, err := ac.Encode(okp) 378 if err != nil { 379 t.Fatal(err) 380 } 381 ac2, err := DecodeAccountClaims(token) 382 if err != nil { 383 t.Fatal(err) 384 } 385 if len(ac2.SigningKeys) != 1 { 386 t.Fatal("expected claim to have a signing key") 387 } 388 if ac.SigningKeys[0] != apk2 { 389 t.Fatalf("expected signing key to be %s - got %s", apk2, ac.SigningKeys[0]) 390 } 391 392 bkp := createUserNKey(t) 393 ac.SigningKeys.Add(publicKey(bkp, t)) 394 ac.Validate(&vr) 395 if len(vr.Issues) != 1 { 396 t.Fatal("expected 1 validation issue") 397 } 398 } 399 400 func TestAccountSignedBy(t *testing.T) { 401 okp := createOperatorNKey(t) 402 403 akp1 := createAccountNKey(t) 404 apk1 := publicKey(akp1, t) 405 akp2 := createAccountNKey(t) 406 apk2 := publicKey(akp2, t) 407 408 ac := NewAccountClaims(apk1) 409 ac.SigningKeys.Add(apk2) 410 411 token, err := ac.Encode(okp) 412 if err != nil { 413 t.Fatal(err) 414 } 415 ac2, err := DecodeAccountClaims(token) 416 if err != nil { 417 t.Fatal(err) 418 } 419 if len(ac2.SigningKeys) != 1 { 420 t.Fatal("expected claim to have a signing key") 421 } 422 if ac.SigningKeys[0] != apk2 { 423 t.Fatalf("expected signing key to be %s - got %s", apk2, ac.SigningKeys[0]) 424 } 425 426 ukp := createUserNKey(t) 427 upk := publicKey(ukp, t) 428 429 // claim signed by alternate key 430 uc := NewUserClaims(upk) 431 uc.IssuerAccount = apk1 432 utoken, err := uc.Encode(akp2) 433 if err != nil { 434 t.Fatal(err) 435 } 436 437 uc2, err := DecodeUserClaims(utoken) 438 if err != nil { 439 t.Fatal(err) 440 } 441 if !ac2.DidSign(uc2) { 442 t.Fatal("failed to verify user claim") 443 } 444 445 // claim signed by the account pk 446 uc3 := NewUserClaims(upk) 447 utoken2, err := uc3.Encode(akp1) 448 if err != nil { 449 t.Fatal(err) 450 } 451 uc4, err := DecodeUserClaims(utoken2) 452 if err != nil { 453 t.Fatal(err) 454 } 455 if !ac2.DidSign(uc4) { 456 t.Fatal("failed to verify user claim") 457 } 458 } 459 460 func TestAddRemoveSigningKey(t *testing.T) { 461 akp1 := createAccountNKey(t) 462 apk1 := publicKey(akp1, t) 463 akp2 := createAccountNKey(t) 464 apk2 := publicKey(akp2, t) 465 akp3 := createAccountNKey(t) 466 apk3 := publicKey(akp3, t) 467 468 ac := NewAccountClaims(apk1) 469 ac.SigningKeys.Add(apk2, apk3) 470 471 if len(ac.SigningKeys) != 2 { 472 t.Fatal("expected 2 signing keys") 473 } 474 475 ac.SigningKeys.Remove(publicKey(createAccountNKey(t), t)) 476 if len(ac.SigningKeys) != 2 { 477 t.Fatal("expected 2 signing keys") 478 } 479 480 ac.SigningKeys.Remove(apk2) 481 if len(ac.SigningKeys) != 1 { 482 t.Fatal("expected single signing keys") 483 } 484 } 485 486 func TestUserRevocation(t *testing.T) { 487 akp := createAccountNKey(t) 488 apk := publicKey(akp, t) 489 account := NewAccountClaims(apk) 490 491 ukp := createUserNKey(t) 492 pubKey := publicKey(ukp, t) 493 uc := NewUserClaims(pubKey) 494 uJwt, _ := uc.Encode(akp) 495 uc, err := DecodeUserClaims(uJwt) 496 if err != nil { 497 t.Errorf("Failed to decode user claim: %v", err) 498 } 499 now := time.Now() 500 501 // test that clear is safe before we add any 502 account.ClearRevocation(pubKey) 503 504 if account.IsRevokedAt(pubKey, now) { 505 t.Errorf("no revocation was added so is revoked should be false") 506 } 507 508 account.RevokeAt(pubKey, now.Add(time.Second*100)) 509 510 if !account.IsRevokedAt(pubKey, now) { 511 t.Errorf("revocation should hold when timestamp is in the future") 512 } 513 514 if account.IsRevokedAt(pubKey, now.Add(time.Second*150)) { 515 t.Errorf("revocation should time out") 516 } 517 518 account.RevokeAt(pubKey, now.Add(time.Second*50)) // shouldn't change the revocation, you can't move it in 519 520 if !account.IsRevokedAt(pubKey, now.Add(time.Second*60)) { 521 t.Errorf("revocation should hold, 100 > 50") 522 } 523 524 encoded, _ := account.Encode(akp) 525 decoded, _ := DecodeAccountClaims(encoded) 526 527 if !decoded.IsRevokedAt(pubKey, now.Add(time.Second*60)) { 528 t.Errorf("revocation should last across encoding") 529 } 530 531 account.ClearRevocation(pubKey) 532 533 if account.IsClaimRevoked(uc) { 534 t.Errorf("revocations should be cleared") 535 } 536 537 account.RevokeAt(pubKey, now.Add(time.Second*1000)) 538 539 if !account.IsClaimRevoked(uc) { 540 t.Errorf("revocation be true we revoked in the future") 541 } 542 } 543 544 func TestUserRevocationAll(t *testing.T) { 545 akp := createAccountNKey(t) 546 apk := publicKey(akp, t) 547 account := NewAccountClaims(apk) 548 549 now := time.Now().Add(time.Second * -10) 550 account.RevokeAt(All, now) 551 552 before := now.Add(time.Second * -1) 553 if !account.IsRevokedAt("foo", before) { 554 t.Error("foo should have been revoked (before)") 555 } 556 if !account.IsRevokedAt("foo", now) { 557 t.Error("foo should have been revoked (now)") 558 } 559 if account.IsRevokedAt("foo", now.Add(time.Second)) { 560 t.Error("foo should have not been revoked") 561 } 562 } 563 564 func TestAccountClaims_DidSign(t *testing.T) { 565 akp := createAccountNKey(t) 566 apk := publicKey(akp, t) 567 skp := createAccountNKey(t) 568 spk := publicKey(skp, t) 569 570 ac := NewAccountClaims(apk) 571 ac.SigningKeys.Add(spk) 572 573 upk := publicKey(createUserNKey(t), t) 574 uc := NewUserClaims(upk) 575 tok, err := uc.Encode(akp) 576 if err != nil { 577 t.Fatal("error encoding") 578 } 579 uc, err = DecodeUserClaims(tok) 580 if err != nil { 581 t.Fatal("error decoding") 582 } 583 if !ac.DidSign(uc) { 584 t.Fatal("expected account to have been issued") 585 } 586 uc = NewUserClaims(upk) 587 uc.IssuerAccount = publicKey(createAccountNKey(t), t) 588 tok, err = uc.Encode(skp) 589 if err != nil { 590 t.Fatalf("encode failed %v", err) 591 } 592 uc, err = DecodeUserClaims(tok) 593 if err != nil { 594 t.Fatalf("decode failed %v", err) 595 } 596 if ac.DidSign(uc) { 597 t.Fatal("this is not issued by account A") 598 } 599 }