github.com/nats-io/jwt/v2@v2.5.6/v1compat/imports_test.go (about)

     1  /*
     2   * Copyright 2018 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  	"net/http"
    21  	"net/http/httptest"
    22  	"sort"
    23  	"testing"
    24  	"time"
    25  )
    26  
    27  func TestImportValidation(t *testing.T) {
    28  	ak := createAccountNKey(t)
    29  	ak2 := createAccountNKey(t)
    30  	akp := publicKey(ak, t)
    31  	akp2 := publicKey(ak2, t)
    32  	i := &Import{Subject: "test", Account: akp2, To: "bar", Type: Stream}
    33  
    34  	vr := CreateValidationResults()
    35  	i.Validate("", vr)
    36  
    37  	if !vr.IsEmpty() {
    38  		t.Errorf("imports should not generate an issue")
    39  	}
    40  
    41  	vr = CreateValidationResults()
    42  	i.Validate("", vr)
    43  
    44  	if !vr.IsEmpty() {
    45  		t.Errorf("imports should not generate an issue")
    46  	}
    47  
    48  	activation := NewActivationClaims(akp)
    49  	activation.Expires = time.Now().Add(time.Hour).UTC().Unix()
    50  
    51  	activation.ImportSubject = "test"
    52  	activation.ImportType = Stream
    53  	actJWT := encode(activation, ak2, t)
    54  
    55  	i.Token = actJWT
    56  	vr = CreateValidationResults()
    57  	i.Validate(akp, vr)
    58  
    59  	if !vr.IsEmpty() {
    60  		t.Errorf("imports with token should be valid")
    61  	}
    62  }
    63  
    64  func TestInvalidImportType(t *testing.T) {
    65  	ak := createAccountNKey(t)
    66  	akp := publicKey(ak, t)
    67  	i := &Import{Subject: "foo", Account: akp, To: "bar", Type: Unknown}
    68  
    69  	vr := CreateValidationResults()
    70  	i.Validate("", vr)
    71  
    72  	if vr.IsEmpty() {
    73  		t.Errorf("imports without token or url should warn the caller")
    74  	}
    75  
    76  	if !vr.IsBlocking(true) {
    77  		t.Errorf("invalid type is blocking")
    78  	}
    79  }
    80  
    81  func TestInvalidImportToken(t *testing.T) {
    82  	ak := createAccountNKey(t)
    83  	akp := publicKey(ak, t)
    84  	i := &Import{Subject: "foo", Account: akp, Token: "bad token", To: "bar", Type: Stream}
    85  
    86  	vr := CreateValidationResults()
    87  	i.Validate("", vr)
    88  
    89  	if !vr.IsBlocking(true) {
    90  		t.Errorf("bad token should be blocking")
    91  	}
    92  }
    93  
    94  func TestInvalidImportURL(t *testing.T) {
    95  	ak := createAccountNKey(t)
    96  	akp := publicKey(ak, t)
    97  	i := &Import{Subject: "foo", Account: akp, Token: "foo://bad-token-url", To: "bar", Type: Stream}
    98  
    99  	vr := CreateValidationResults()
   100  	i.Validate("", vr)
   101  
   102  	if vr.IsEmpty() {
   103  		t.Errorf("imports with a bad token or url should warn the caller")
   104  	}
   105  
   106  	if !vr.IsBlocking(true) {
   107  		t.Errorf("invalid type should be blocking")
   108  	}
   109  }
   110  
   111  func TestInvalidImportTokenValuesValidation(t *testing.T) {
   112  	ak := createAccountNKey(t)
   113  	ak2 := createAccountNKey(t)
   114  	akp := publicKey(ak, t)
   115  	akp2 := publicKey(ak2, t)
   116  	i := &Import{Subject: "bar", Account: akp2, To: "test", Type: Service}
   117  
   118  	vr := CreateValidationResults()
   119  	i.Validate("", vr)
   120  
   121  	if vr.IsBlocking(true) {
   122  		t.Errorf("imports without token or url should not be blocking")
   123  	}
   124  
   125  	i.Type = Service
   126  	vr = CreateValidationResults()
   127  	i.Validate("", vr)
   128  
   129  	if vr.IsBlocking(true) {
   130  		t.Errorf("imports without token or url should not be blocking")
   131  	}
   132  
   133  	activation := NewActivationClaims(akp)
   134  	activation.Max = 1024 * 1024
   135  	activation.Expires = time.Now().Add(time.Duration(time.Hour)).UTC().Unix()
   136  
   137  	activation.ImportSubject = "test"
   138  	activation.ImportType = Service
   139  	actJWT := encode(activation, ak2, t)
   140  
   141  	i.Token = actJWT
   142  	vr = CreateValidationResults()
   143  	i.Validate(akp, vr)
   144  
   145  	if !vr.IsEmpty() {
   146  		t.Errorf("imports with token should be valid")
   147  	}
   148  
   149  	actJWT = encode(activation, ak, t) // wrong issuer
   150  	i.Token = actJWT
   151  	vr = CreateValidationResults()
   152  	i.Validate(akp, vr)
   153  
   154  	if vr.IsEmpty() {
   155  		t.Errorf("imports with wrong issuer")
   156  	}
   157  
   158  	activation.Subject = akp2           // wrong subject
   159  	actJWT = encode(activation, ak2, t) // right issuer
   160  	i.Token = actJWT
   161  	vr = CreateValidationResults()
   162  	i.Validate(akp, vr)
   163  
   164  	if vr.IsEmpty() {
   165  		t.Errorf("imports with wrong issuer")
   166  	}
   167  }
   168  
   169  func TestMissingAccountInImport(t *testing.T) {
   170  	i := &Import{Subject: "foo", To: "bar", Type: Stream}
   171  
   172  	vr := CreateValidationResults()
   173  	i.Validate("", vr)
   174  
   175  	if len(vr.Issues) != 1 {
   176  		t.Errorf("expected only one issue")
   177  	}
   178  
   179  	if !vr.IsBlocking(true) {
   180  		t.Errorf("Missing Account is blocking")
   181  	}
   182  }
   183  
   184  func TestServiceImportWithWildcard(t *testing.T) {
   185  	ak := createAccountNKey(t)
   186  	akp := publicKey(ak, t)
   187  	i := &Import{Subject: "foo.*", Account: akp, To: "bar", Type: Service}
   188  
   189  	vr := CreateValidationResults()
   190  	i.Validate("", vr)
   191  
   192  	if !vr.IsBlocking(true) {
   193  		t.Errorf("expected service import with a wildcard subject to be a blocking error")
   194  	}
   195  }
   196  
   197  func TestStreamImportWithWildcardPrefix(t *testing.T) {
   198  	i := &Import{Subject: "foo", To: "bar.>", Type: Stream}
   199  
   200  	vr := CreateValidationResults()
   201  	i.Validate("", vr)
   202  
   203  	if len(vr.Issues) != 2 {
   204  		t.Errorf("should have registered 2 issues with this import, got %d", len(vr.Issues))
   205  	}
   206  
   207  	if !vr.IsBlocking(true) {
   208  		t.Fatalf("expected stream import prefix with a wildcard to produce a blocking error")
   209  	}
   210  }
   211  
   212  func TestImportsValidation(t *testing.T) {
   213  	ak := createAccountNKey(t)
   214  	akp := publicKey(ak, t)
   215  	i := &Import{Subject: "foo", Account: akp, To: "bar", Type: Stream}
   216  	i2 := &Import{Subject: "foo.*", Account: akp, To: "bar", Type: Service}
   217  
   218  	imports := &Imports{}
   219  	imports.Add(i, i2)
   220  
   221  	vr := CreateValidationResults()
   222  	imports.Validate("", vr)
   223  
   224  	if len(vr.Issues) != 1 {
   225  		t.Errorf("warn about wildcard service")
   226  	}
   227  
   228  	if !vr.IsBlocking(true) {
   229  		t.Errorf("expected service import with a wildcard subject to be a blocking error")
   230  	}
   231  }
   232  
   233  func TestTokenURLImportValidation(t *testing.T) {
   234  	ak := createAccountNKey(t)
   235  	ak2 := createAccountNKey(t)
   236  	akp := publicKey(ak, t)
   237  	akp2 := publicKey(ak2, t)
   238  	i := &Import{Subject: "test", Account: akp2, To: "bar", Type: Stream}
   239  
   240  	activation := NewActivationClaims(akp)
   241  	activation.Max = 1024 * 1024
   242  	activation.Expires = time.Now().Add(time.Duration(time.Hour)).UTC().Unix()
   243  	activation.ImportSubject = "test"
   244  	activation.ImportType = Stream
   245  
   246  	actJWT := encode(activation, ak2, t)
   247  
   248  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   249  		w.Write([]byte(actJWT))
   250  	}))
   251  	defer ts.Close()
   252  
   253  	i.Token = ts.URL
   254  	vr := CreateValidationResults()
   255  	i.Validate(akp, vr)
   256  
   257  	if !vr.IsEmpty() {
   258  		fmt.Printf("vr is %+v\n", vr)
   259  		t.Errorf("imports with token url should be valid")
   260  	}
   261  
   262  	i.Token = "http://Bad URL"
   263  	vr = CreateValidationResults()
   264  	i.Validate(akp, vr)
   265  
   266  	if vr.IsEmpty() {
   267  		t.Errorf("imports with bad token url should be valid")
   268  	}
   269  
   270  	ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   271  		w.Write([]byte("bad jwt"))
   272  	}))
   273  	defer ts.Close()
   274  
   275  	i.Token = ts.URL
   276  	vr = CreateValidationResults()
   277  	i.Validate(akp, vr)
   278  
   279  	if vr.IsEmpty() {
   280  		t.Errorf("imports with token url pointing to bad JWT")
   281  	}
   282  
   283  	ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   284  		w.WriteHeader(http.StatusBadRequest)
   285  	}))
   286  	defer ts.Close()
   287  
   288  	i.Token = ts.URL
   289  	vr = CreateValidationResults()
   290  	i.Validate(akp, vr)
   291  
   292  	if vr.IsEmpty() {
   293  		t.Errorf("imports with token url pointing to bad url")
   294  	}
   295  }
   296  
   297  func TestImportSubjectValidation(t *testing.T) {
   298  	ak := createAccountNKey(t)
   299  	akp := publicKey(ak, t)
   300  	activation := NewActivationClaims(akp)
   301  	activation.Max = 1024 * 1024
   302  	activation.Expires = time.Now().Add(time.Duration(time.Hour)).UTC().Unix()
   303  	activation.ImportSubject = "one.*"
   304  	activation.ImportType = Stream
   305  
   306  	ak2 := createAccountNKey(t)
   307  	akp2 := publicKey(ak2, t)
   308  	i := &Import{Subject: "one.two", Account: akp2, To: "bar", Type: Stream}
   309  
   310  	actJWT := encode(activation, ak2, t)
   311  	i.Token = actJWT
   312  	vr := CreateValidationResults()
   313  	i.Validate(akp, vr)
   314  
   315  	if !vr.IsEmpty() {
   316  		t.Log(vr.Issues[0].Description)
   317  		t.Errorf("imports with valid contains subject should be valid")
   318  	}
   319  
   320  	activation.ImportSubject = "two"
   321  	activation.ImportType = Stream
   322  	actJWT = encode(activation, ak2, t)
   323  	i.Token = actJWT
   324  	vr = CreateValidationResults()
   325  	i.Validate(akp, vr)
   326  
   327  	if vr.IsEmpty() {
   328  		t.Errorf("imports with non-contains subject should be not valid")
   329  	}
   330  
   331  	activation.ImportSubject = ">"
   332  	activation.ImportType = Stream
   333  	actJWT = encode(activation, ak2, t)
   334  	i.Token = actJWT
   335  	vr = CreateValidationResults()
   336  	i.Validate(akp, vr)
   337  
   338  	if !vr.IsEmpty() {
   339  		t.Errorf("imports with valid contains subject should be valid")
   340  	}
   341  }
   342  
   343  func TestImportServiceDoubleToSubjectsValidation(t *testing.T) {
   344  	akp := createAccountNKey(t)
   345  	akp2 := createAccountNKey(t)
   346  	apk := publicKey(akp, t)
   347  	apk2 := publicKey(akp2, t)
   348  
   349  	account := NewAccountClaims(apk)
   350  
   351  	i := &Import{Subject: "one.two", Account: apk2, To: "foo.bar", Type: Service}
   352  	account.Imports.Add(i)
   353  
   354  	vr := CreateValidationResults()
   355  	account.Validate(vr)
   356  
   357  	if vr.IsBlocking(true) {
   358  		t.Fatalf("Expected no blocking validation errors")
   359  	}
   360  
   361  	i2 := &Import{Subject: "two.three", Account: apk2, To: "foo.bar", Type: Service}
   362  	account.Imports.Add(i2)
   363  
   364  	vr = CreateValidationResults()
   365  	account.Validate(vr)
   366  
   367  	if !vr.IsBlocking(true) {
   368  		t.Fatalf("Expected multiple import 'to' subjects to produce an error")
   369  	}
   370  }
   371  
   372  func TestImport_Sorting(t *testing.T) {
   373  	var imports Imports
   374  	pk := publicKey(createAccountNKey(t), t)
   375  	imports.Add(&Import{Subject: "x", Type: Service, Account: pk})
   376  	imports.Add(&Import{Subject: "z", Type: Service, Account: pk})
   377  	imports.Add(&Import{Subject: "y", Type: Service, Account: pk})
   378  	if imports[0].Subject != "x" {
   379  		t.Fatal("added import not in expected order")
   380  	}
   381  	sort.Sort(imports)
   382  	if imports[0].Subject != "x" && imports[1].Subject != "y" && imports[2].Subject != "z" {
   383  		t.Fatal("imports not sorted")
   384  	}
   385  }