github.com/nats-io/jwt/v2@v2.5.6/v1compat/operator_claims_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 "testing" 21 "time" 22 23 "github.com/nats-io/nkeys" 24 ) 25 26 func TestNewOperatorClaims(t *testing.T) { 27 ckp := createOperatorNKey(t) 28 29 uc := NewOperatorClaims(publicKey(ckp, t)) 30 uc.Expires = time.Now().Add(time.Duration(time.Hour)).Unix() 31 uJwt := encode(uc, ckp, t) 32 33 uc2, err := DecodeOperatorClaims(uJwt) 34 if err != nil { 35 t.Fatal("failed to decode", err) 36 } 37 38 AssertEquals(uc.String(), uc2.String(), t) 39 40 AssertEquals(uc.Claims() != nil, true, t) 41 AssertEquals(uc.Payload() != nil, true, t) 42 } 43 44 func TestOperatorSubjects(t *testing.T) { 45 type kpInputs struct { 46 name string 47 kp nkeys.KeyPair 48 ok bool 49 } 50 51 inputs := []kpInputs{ 52 {"account", createAccountNKey(t), false}, 53 {"cluster", createClusterNKey(t), false}, 54 {"operator", createOperatorNKey(t), true}, 55 {"server", createServerNKey(t), false}, 56 {"user", createUserNKey(t), false}, 57 } 58 59 for _, i := range inputs { 60 c := NewOperatorClaims(publicKey(i.kp, t)) 61 _, err := c.Encode(createOperatorNKey(t)) 62 if i.ok && err != nil { 63 t.Fatalf("unexpected error for %q: %v", i.name, err) 64 } 65 if !i.ok && err == nil { 66 t.Logf("should have failed to encode server with with %q subject", i.name) 67 t.Fail() 68 } 69 } 70 } 71 72 func TestInvalidOperatorClaimIssuer(t *testing.T) { 73 akp := createOperatorNKey(t) 74 ac := NewOperatorClaims(publicKey(akp, t)) 75 ac.Expires = time.Now().Add(time.Duration(time.Hour)).Unix() 76 aJwt := encode(ac, akp, t) 77 78 temp, err := DecodeGeneric(aJwt) 79 if err != nil { 80 t.Fatal("failed to decode", err) 81 } 82 83 type kpInputs struct { 84 name string 85 kp nkeys.KeyPair 86 ok bool 87 } 88 89 inputs := []kpInputs{ 90 {"account", createAccountNKey(t), false}, 91 {"user", createUserNKey(t), false}, 92 {"operator", createOperatorNKey(t), true}, 93 {"server", createServerNKey(t), false}, 94 {"cluster", createClusterNKey(t), false}, 95 } 96 97 for _, i := range inputs { 98 bad := encode(temp, i.kp, t) 99 _, err = DecodeOperatorClaims(bad) 100 if i.ok && err != nil { 101 t.Fatalf("unexpected error for %q: %v", i.name, err) 102 } 103 if !i.ok && err == nil { 104 t.Logf("should have failed to decode account signed by %q", i.name) 105 t.Fail() 106 } 107 } 108 } 109 110 func TestNewNilOperatorClaims(t *testing.T) { 111 v := NewOperatorClaims("") 112 if v != nil { 113 t.Fatal("expected nil user claim") 114 } 115 } 116 117 func TestOperatorType(t *testing.T) { 118 c := NewOperatorClaims(publicKey(createOperatorNKey(t), t)) 119 s := encode(c, createOperatorNKey(t), t) 120 u, err := DecodeOperatorClaims(s) 121 if err != nil { 122 t.Fatalf("failed to decode operator claim: %v", err) 123 } 124 125 if OperatorClaim != u.Type { 126 t.Fatalf("type is unexpected %q (wanted operator)", u.Type) 127 } 128 129 } 130 131 func TestSigningKeyValidation(t *testing.T) { 132 ckp := createOperatorNKey(t) 133 ckp2 := createOperatorNKey(t) 134 135 uc := NewOperatorClaims(publicKey(ckp, t)) 136 uc.Expires = time.Now().Add(time.Duration(time.Hour)).Unix() 137 uc.AddSigningKey(publicKey(ckp2, t)) 138 uJwt := encode(uc, ckp, t) 139 140 uc2, err := DecodeOperatorClaims(uJwt) 141 if err != nil { 142 t.Fatal("failed to decode", err) 143 } 144 145 AssertEquals(len(uc2.SigningKeys), 1, t) 146 AssertEquals(uc2.SigningKeys[0] == publicKey(ckp2, t), true, t) 147 148 vr := &ValidationResults{} 149 uc.Validate(vr) 150 151 if len(vr.Issues) != 0 { 152 t.Fatal("valid operator key should have no validation issues") 153 } 154 155 uc.AddSigningKey("") // add an invalid one 156 157 vr = &ValidationResults{} 158 uc.Validate(vr) 159 if len(vr.Issues) != 0 { 160 t.Fatal("should not be able to add empty values") 161 } 162 } 163 164 func TestSignedBy(t *testing.T) { 165 ckp := createOperatorNKey(t) 166 ckp2 := createOperatorNKey(t) 167 168 uc := NewOperatorClaims(publicKey(ckp, t)) 169 uc2 := NewOperatorClaims(publicKey(ckp2, t)) 170 171 akp := createAccountNKey(t) 172 ac := NewAccountClaims(publicKey(akp, t)) 173 enc, err := ac.Encode(ckp) // sign with the operator key 174 if err != nil { 175 t.Fatal("failed to encode", err) 176 } 177 ac, err = DecodeAccountClaims(enc) 178 if err != nil { 179 t.Fatal("failed to decode", err) 180 } 181 182 AssertEquals(uc.DidSign(ac), true, t) 183 AssertEquals(uc2.DidSign(ac), false, t) 184 185 enc, err = ac.Encode(ckp2) // sign with the other operator key 186 if err != nil { 187 t.Fatal("failed to encode", err) 188 } 189 ac, err = DecodeAccountClaims(enc) 190 if err != nil { 191 t.Fatal("failed to decode", err) 192 } 193 194 AssertEquals(uc.DidSign(ac), false, t) // no signing key 195 AssertEquals(uc2.DidSign(ac), true, t) // actual key 196 uc.AddSigningKey(publicKey(ckp2, t)) 197 AssertEquals(uc.DidSign(ac), true, t) // signing key 198 199 clusterKey := createClusterNKey(t) 200 clusterClaims := NewClusterClaims(publicKey(clusterKey, t)) 201 enc, err = clusterClaims.Encode(ckp2) // sign with the operator key 202 if err != nil { 203 t.Fatal("failed to encode", err) 204 } 205 clusterClaims, err = DecodeClusterClaims(enc) 206 if err != nil { 207 t.Fatal("failed to decode", err) 208 } 209 210 AssertEquals(uc.DidSign(clusterClaims), true, t) // signing key 211 AssertEquals(uc2.DidSign(clusterClaims), true, t) // actual key 212 } 213 214 func testAccountWithAccountServerURL(t *testing.T, u string) error { 215 kp := createOperatorNKey(t) 216 pk := publicKey(kp, t) 217 oc := NewOperatorClaims(pk) 218 oc.AccountServerURL = u 219 220 s, err := oc.Encode(kp) 221 if err != nil { 222 return err 223 } 224 oc, err = DecodeOperatorClaims(s) 225 if err != nil { 226 t.Fatal(err) 227 } 228 AssertEquals(oc.AccountServerURL, u, t) 229 vr := ValidationResults{} 230 oc.Validate(&vr) 231 if !vr.IsEmpty() { 232 errs := vr.Errors() 233 return errs[0] 234 } 235 return nil 236 } 237 238 func Test_SystemAccount(t *testing.T) { 239 operatorWithSystemAcc := func(t *testing.T, u string) error { 240 kp := createOperatorNKey(t) 241 pk := publicKey(kp, t) 242 oc := NewOperatorClaims(pk) 243 oc.SystemAccount = u 244 s, err := oc.Encode(kp) 245 if err != nil { 246 return err 247 } 248 oc, err = DecodeOperatorClaims(s) 249 if err != nil { 250 t.Fatal(err) 251 } 252 AssertEquals(oc.SystemAccount, u, t) 253 vr := ValidationResults{} 254 oc.Validate(&vr) 255 if !vr.IsEmpty() { 256 return fmt.Errorf("%s", vr.Errors()[0]) 257 } 258 return nil 259 } 260 var asuTests = []struct { 261 accKey string 262 shouldFail bool 263 }{ 264 {"", false}, 265 {"x", true}, 266 {"ADZ547B24WHPLWOK7TMLNBSA7FQFXR6UM2NZ4HHNIB7RDFVZQFOZ4GQQ", false}, 267 {"ADZ547B24WHPLWOK7TMLNBSA7FQFXR6UM2NZ4HHNIB7RDFVZQFOZ4777", true}, 268 } 269 for i, tt := range asuTests { 270 err := operatorWithSystemAcc(t, tt.accKey) 271 if err != nil && tt.shouldFail == false { 272 t.Fatalf("expected not to fail: %v", err) 273 } else if err == nil && tt.shouldFail { 274 t.Fatalf("test %s expected to fail but didn't", asuTests[i].accKey) 275 } 276 } 277 } 278 279 func Test_AccountServerURL(t *testing.T) { 280 var asuTests = []struct { 281 u string 282 shouldFail bool 283 }{ 284 {"", false}, 285 {"HTTP://foo.bar.com", false}, 286 {"http://foo.bar.com/foo/bar", false}, 287 {"http://user:pass@foo.bar.com/foo/bar", false}, 288 {"https://foo.bar.com", false}, 289 {"nats://foo.bar.com", false}, 290 {"/hello", true}, 291 } 292 293 for i, tt := range asuTests { 294 err := testAccountWithAccountServerURL(t, tt.u) 295 if err != nil && tt.shouldFail == false { 296 t.Fatalf("expected not to fail: %v", err) 297 } else if err == nil && tt.shouldFail { 298 t.Fatalf("test %s expected to fail but didn't", asuTests[i].u) 299 } 300 } 301 } 302 303 func testOperatorWithOperatorServiceURL(t *testing.T, u string) error { 304 kp := createOperatorNKey(t) 305 pk := publicKey(kp, t) 306 oc := NewOperatorClaims(pk) 307 oc.OperatorServiceURLs.Add(u) 308 309 s, err := oc.Encode(kp) 310 if err != nil { 311 return err 312 } 313 oc, err = DecodeOperatorClaims(s) 314 if err != nil { 315 t.Fatal(err) 316 } 317 if u != "" { 318 AssertEquals(oc.OperatorServiceURLs[0], u, t) 319 } 320 vr := ValidationResults{} 321 oc.Validate(&vr) 322 if !vr.IsEmpty() { 323 errs := vr.Errors() 324 return errs[0] 325 } 326 return nil 327 } 328 329 func Test_OperatorServiceURL(t *testing.T) { 330 var asuTests = []struct { 331 u string 332 shouldFail bool 333 }{ 334 {"", false}, 335 {"HTTP://foo.bar.com", true}, 336 {"http://foo.bar.com/foo/bar", true}, 337 {"nats://user:pass@foo.bar.com", true}, 338 {"NATS://user:pass@foo.bar.com", true}, 339 {"NATS://user@foo.bar.com", true}, 340 {"nats://foo.bar.com/path", true}, 341 {"tls://foo.bar.com/path", true}, 342 {"/hello", true}, 343 {"NATS://foo.bar.com", false}, 344 {"TLS://foo.bar.com", false}, 345 {"nats://foo.bar.com", false}, 346 {"tls://foo.bar.com", false}, 347 } 348 349 for i, tt := range asuTests { 350 err := testOperatorWithOperatorServiceURL(t, tt.u) 351 if err != nil && tt.shouldFail == false { 352 t.Fatalf("expected not to fail: %v", err) 353 } else if err == nil && tt.shouldFail { 354 t.Fatalf("test %s expected to fail but didn't", asuTests[i].u) 355 } 356 } 357 358 // now test all of them in a single jwt 359 kp := createOperatorNKey(t) 360 pk := publicKey(kp, t) 361 oc := NewOperatorClaims(pk) 362 363 encoded := 0 364 shouldFail := 0 365 for _, v := range asuTests { 366 oc.OperatorServiceURLs.Add(v.u) 367 // list won't encode empty strings 368 if v.u != "" { 369 encoded++ 370 } 371 if v.shouldFail { 372 shouldFail++ 373 } 374 } 375 376 s, err := oc.Encode(kp) 377 if err != nil { 378 t.Fatal(err) 379 } 380 oc, err = DecodeOperatorClaims(s) 381 if err != nil { 382 t.Fatal(err) 383 } 384 385 AssertEquals(len(oc.OperatorServiceURLs), encoded, t) 386 387 vr := ValidationResults{} 388 oc.Validate(&vr) 389 if vr.IsEmpty() { 390 t.Fatal("should have had errors") 391 } 392 393 errs := vr.Errors() 394 AssertEquals(len(errs), shouldFail, t) 395 } 396 397 func Test_ForwardCompatibility(t *testing.T) { 398 newOp := `eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJTSUYyR0ZRSEhWWUtDQlZYRklYUURYV1FCQUcyWEw3SVZLVVJZT0ZTWlhVT0tTRUpLWDdBIiwiaWF0IjoxNTkwNTI0NTAwLCJpc3MiOiJPQlQ2REtGSzQ2STM3TjdCUkwyUkpMVVJLWUdSQTZBWVJQREFISFFFQUFBR05ZWExNR1JEUEtMQyIsInN1YiI6Ik9CVDZES0ZLNDZJMzdON0JSTDJSSkxVUktZR1JBNkFZUlBEQUhIUUVBQUFHTllYTE1HUkRQS0xDIiwibmF0cyI6eyJ0YWdzIjpbIm9uZSIsInR3byIsInRocmVlIl0sInR5cGUiOiJvcGVyYXRvciIsInZlcnNpb24iOjJ9fQ.u6JFiISIh2o-CWxktfEw3binmCLhLaFVMyuIa2HNo_x_6EGWVPVICVWc_MOLFS-6Nm17Cj4SmOh3zUtlTRkfDA` 399 if _, err := DecodeOperatorClaims(newOp); err == nil { 400 t.Fatal("Expected error") 401 } else if err.Error() != `more recent jwt version` { 402 t.Fatal("Expected different error, got: ", err) 403 } 404 }