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  }