github.com/kbehouse/nsc@v0.0.6/cmd/adduser_test.go (about) 1 /* 2 * Copyright 2018-2020 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 cmd 17 18 import ( 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 "testing" 23 "time" 24 25 "github.com/nats-io/nkeys" 26 27 "github.com/stretchr/testify/require" 28 ) 29 30 func Test_AddUser(t *testing.T) { 31 ts := NewTestStore(t, "add_server") 32 defer ts.Done(t) 33 34 _, _, err := ExecuteCmd(CreateAddAccountCmd(), "--name", "c") 35 require.NoError(t, err) 36 37 _, bar, _ := CreateUserKey(t) 38 _, badBar, _ := CreateAccountKey(t) 39 40 tests := CmdTests{ 41 {CreateAddUserCmd(), []string{"add", "user"}, nil, []string{"user name is required"}, true}, 42 {CreateAddUserCmd(), []string{"add", "user", "--name", "foo"}, nil, []string{"generated and stored user key", "added user"}, false}, 43 {CreateAddUserCmd(), []string{"add", "user", "--name", "foo"}, nil, []string{"the user \"foo\" already exists"}, true}, 44 {CreateAddUserCmd(), []string{"add", "user", "--name", "foo"}, nil, []string{"the user \"foo\" already exists"}, true}, 45 {CreateAddUserCmd(), []string{"add", "user", "--name", "*"}, nil, []string{"generated and stored user key", "added user"}, false}, 46 {CreateAddUserCmd(), []string{"add", "user", "--name", "*"}, nil, []string{"generated and stored user key", "added user"}, false}, // should make a new name 47 {CreateAddUserCmd(), []string{"add", "user", "--name", "bar", "--public-key", bar}, nil, nil, false}, 48 {CreateAddUserCmd(), []string{"add", "user", "--name", "badbar", "--public-key", badBar}, nil, []string{"invalid user key"}, true}, 49 {CreateAddUserCmd(), []string{"add", "user", "--name", "badexp", "--expiry", "30d"}, nil, nil, false}, 50 {CreateAddUserCmd(), []string{"add", "user", "--name", "usra", "--deny-sub", "foo queue"}, nil, []string{"added user"}, false}, 51 {CreateAddUserCmd(), []string{"add", "user", "--name", "usrb", "--allow-sub", "foo queue"}, nil, []string{"added user"}, false}, 52 {CreateAddUserCmd(), []string{"add", "user", "--name", "usrc", "--deny-pub", "foo queue"}, nil, []string{"contains illegal space"}, true}, 53 {CreateAddUserCmd(), []string{"add", "user", "--name", "usrd", "--allow-pub", "foo queue"}, nil, []string{"contains illegal space"}, true}, 54 {CreateAddUserCmd(), []string{"add", "user", "--name", "usre", "--deny-pubsub", "foo queue"}, nil, []string{"contains illegal space"}, true}, 55 {CreateAddUserCmd(), []string{"add", "user", "--name", "usrf", "--allow-pubsub", "foo queue"}, nil, []string{"contains illegal space"}, true}, 56 {CreateAddUserCmd(), []string{"add", "user", "--name", "usrg", "--deny-sub", "foo queue doo"}, nil, []string{"can at most contain one space"}, true}, 57 {CreateAddUserCmd(), []string{"add", "user", "--name", "usrh", "--allow-sub", "foo queue doo"}, nil, []string{"can at most contain one space"}, true}, 58 } 59 60 tests.Run(t, "root", "add") 61 } 62 63 func Test_AddUserNoStore(t *testing.T) { 64 // reset the store 65 require.NoError(t, ForceStoreRoot(t, "")) 66 _, _, err := ExecuteCmd(CreateAddUserCmd()) 67 require.Error(t, err) 68 require.Equal(t, "no stores available", err.Error()) 69 } 70 71 func Test_AddUserOutput(t *testing.T) { 72 ts := NewTestStore(t, "test") 73 defer ts.Done(t) 74 75 _, _, err := ExecuteCmd(CreateAddAccountCmd(), "--name", "A") 76 require.NoError(t, err, "account creation") 77 78 _, _, err = ExecuteCmd(CreateAddUserCmd(), "--name", "U", "--start", "2018-01-01", "--expiry", "2050-01-01") 79 require.NoError(t, err) 80 validateAddUserClaims(t, ts) 81 } 82 83 func Test_AddUserInteractive(t *testing.T) { 84 ts := NewTestStore(t, "test") 85 defer ts.Done(t) 86 87 _, _, err := ExecuteCmd(CreateAddAccountCmd(), "--name", "A") 88 require.NoError(t, err, "account creation") 89 90 inputs := []interface{}{"U", true, "2018-01-01", "2050-01-01", 0} 91 92 cmd := CreateAddUserCmd() 93 HoistRootFlags(cmd) 94 _, _, err = ExecuteInteractiveCmd(cmd, inputs) 95 require.NoError(t, err) 96 validateAddUserClaims(t, ts) 97 98 up, err := ts.Store.ReadUserClaim("A", "U") 99 require.NoError(t, err) 100 require.Nil(t, up.Resp) 101 } 102 103 func validateAddUserClaims(t *testing.T, ts *TestStore) { 104 skp := ts.GetUserKey(t, "A", "U") 105 _, err := skp.Seed() 106 require.NoError(t, err, "stored key should be a seed") 107 108 sc, err := ts.Store.ReadUserClaim("A", "U") 109 require.NoError(t, err, "reading user claim") 110 111 pub, err := skp.PublicKey() 112 require.NoError(t, err) 113 require.Equal(t, sc.Subject, pub, "public key is subject") 114 115 okp := ts.GetAccountKey(t, "A") 116 117 oppub, err := okp.PublicKey() 118 require.NoError(t, err, "getting public key for account") 119 require.Equal(t, sc.Issuer, oppub, "account signed it") 120 121 start, err := ParseExpiry("2018-01-01") 122 require.NoError(t, err) 123 require.Equal(t, start, sc.NotBefore) 124 125 expire, err := ParseExpiry("2050-01-01") 126 require.NoError(t, err) 127 require.Equal(t, expire, sc.Expires) 128 } 129 130 func Test_AddUserManagedStore(t *testing.T) { 131 as, m := RunTestAccountServer(t) 132 defer as.Close() 133 134 ts := NewTestStoreWithOperatorJWT(t, string(m["operator"])) 135 defer ts.Done(t) 136 137 _, _, err := ExecuteCmd(CreateAddAccountCmd(), "--name", "A", "--start", "2018-01-01", "--expiry", "2050-01-01") 138 require.NoError(t, err) 139 140 _, _, err = ExecuteCmd(CreateAddUserCmd(), "--name", "U", "--start", "2018-01-01", "--expiry", "2050-01-01") 141 require.NoError(t, err) 142 143 validateAddUserClaims(t, ts) 144 } 145 146 func Test_AddUser_Account(t *testing.T) { 147 ts := NewTestStore(t, "O") 148 defer ts.Done(t) 149 150 ts.AddAccount(t, "A") 151 ts.AddAccount(t, "B") 152 153 config := GetConfig() 154 err := config.SetAccount("A") 155 require.NoError(t, err) 156 157 _, _, err = ExecuteCmd(CreateAddUserCmd(), "--name", "bb", "--account", "B") 158 require.NoError(t, err) 159 160 u, err := ts.Store.ReadUserClaim("B", "bb") 161 require.NoError(t, err) 162 require.NotNil(t, u) 163 } 164 165 func Test_AddUser_WithSK(t *testing.T) { 166 ts := NewTestStore(t, "test") 167 defer ts.Done(t) 168 169 ts.AddAccount(t, "A") 170 171 sk, pk, _ := CreateAccountKey(t) 172 _, _, err := ExecuteCmd(createEditAccount(), "--sk", pk) 173 require.NoError(t, err) 174 175 _, _, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "bb", "--account", "A", "-K", string(sk)) 176 require.NoError(t, err) 177 178 ac, err := ts.Store.ReadAccountClaim("A") 179 require.NoError(t, err) 180 181 u, err := ts.Store.ReadUserClaim("A", "bb") 182 require.NoError(t, err) 183 require.NotNil(t, u) 184 require.Equal(t, u.Issuer, pk) 185 require.True(t, ac.DidSign(u)) 186 } 187 188 func Test_AddUser_InteractiveResp(t *testing.T) { 189 t.Skip("interactive resp permissions") 190 ts := NewTestStore(t, "test") 191 defer ts.Done(t) 192 193 _, _, err := ExecuteCmd(CreateAddAccountCmd(), "--name", "A") 194 require.NoError(t, err, "account creation") 195 196 inputs := []interface{}{"U", true, true, "100", "1000ms", "2018-01-01", "2050-01-01", 0} 197 cmd := CreateAddUserCmd() 198 HoistRootFlags(cmd) 199 _, _, err = ExecuteInteractiveCmd(cmd, inputs) 200 require.NoError(t, err) 201 validateAddUserClaims(t, ts) 202 203 up, err := ts.Store.ReadUserClaim("A", "U") 204 require.NoError(t, err) 205 require.NotNil(t, up.Resp) 206 require.Equal(t, 100, up.Resp.MaxMsgs) 207 require.Equal(t, time.Millisecond*1000, up.Resp.Expires) 208 } 209 210 func Test_AddUserNameArg(t *testing.T) { 211 ts := NewTestStore(t, "O") 212 defer ts.Done(t) 213 ts.AddAccount(t, "A") 214 215 _, _, err := ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "U") 216 require.NoError(t, err) 217 218 uc, err := ts.Store.ReadUserClaim("A", "U") 219 require.NoError(t, err) 220 require.Equal(t, "U", uc.Name) 221 } 222 223 func Test_AddUserWithResponsePerms(t *testing.T) { 224 ts := NewTestStore(t, "O") 225 defer ts.Done(t) 226 ts.AddAccount(t, "A") 227 228 _, _, err := ExecuteCmd(CreateAddUserCmd(), "U", "--max-responses", "100", "--response-ttl", "2ms") 229 require.NoError(t, err) 230 231 uc, err := ts.Store.ReadUserClaim("A", "U") 232 require.NoError(t, err) 233 require.NotNil(t, uc.Resp) 234 require.Equal(t, 100, uc.Resp.MaxMsgs) 235 d, _ := time.ParseDuration("2ms") 236 require.Equal(t, d, uc.Resp.Expires) 237 } 238 239 func Test_AddUserWithResponsePerms2(t *testing.T) { 240 ts := NewTestStore(t, "O") 241 defer ts.Done(t) 242 ts.AddAccount(t, "A") 243 244 _, _, err := ExecuteCmd(CreateAddUserCmd(), "U", "--allow-pub-response", "--response-ttl", "2ms") 245 require.NoError(t, err) 246 247 uc, err := ts.Store.ReadUserClaim("A", "U") 248 require.NoError(t, err) 249 require.NotNil(t, uc.Resp) 250 require.Equal(t, 1, uc.Resp.MaxMsgs) 251 d, _ := time.ParseDuration("2ms") 252 require.Equal(t, d, uc.Resp.Expires) 253 } 254 255 func Test_AddUserWithInteractiveAccountCtx(t *testing.T) { 256 ts := NewTestStore(t, "O") 257 defer ts.Done(t) 258 ts.AddAccount(t, "A") 259 ts.AddAccount(t, "B") 260 261 // adding to user bb to B 262 inputs := []interface{}{1, "bb", true, "0", "0", 0} 263 cmd := CreateAddUserCmd() 264 HoistRootFlags(cmd) 265 _, _, err := ExecuteInteractiveCmd(cmd, inputs) 266 require.NoError(t, err) 267 268 bpk := ts.GetAccountPublicKey(t, "B") 269 uc, err := ts.Store.ReadUserClaim("B", "bb") 270 require.NoError(t, err) 271 require.Equal(t, bpk, uc.Issuer) 272 require.Empty(t, uc.IssuerAccount) 273 274 // adding to user aa to A 275 inputs = []interface{}{0, "aa", true, "0", "0", 0} 276 _, _, err = ExecuteInteractiveCmd(cmd, inputs) 277 require.NoError(t, err) 278 apk := ts.GetAccountPublicKey(t, "A") 279 280 uc, err = ts.Store.ReadUserClaim("A", "aa") 281 require.NoError(t, err) 282 require.Equal(t, apk, uc.Issuer) 283 require.Empty(t, uc.IssuerAccount) 284 } 285 286 func Test_AddUserWithInteractiveCustomKey(t *testing.T) { 287 ts := NewTestStore(t, "O") 288 defer ts.Done(t) 289 ts.AddAccount(t, "A") 290 291 kp, err := nkeys.CreateUser() 292 require.NoError(t, err) 293 sk, err := kp.Seed() 294 require.NoError(t, err) 295 pk, err := kp.PublicKey() 296 require.NoError(t, err) 297 298 inputs := []interface{}{"aa", false, string(sk), "0", "0"} 299 cmd := CreateAddUserCmd() 300 HoistRootFlags(cmd) 301 _, _, err = ExecuteInteractiveCmd(cmd, inputs) 302 require.NoError(t, err) 303 304 uc, err := ts.Store.ReadUserClaim("A", "aa") 305 require.NoError(t, err) 306 require.Equal(t, pk, uc.Subject) 307 require.Empty(t, uc.IssuerAccount) 308 require.False(t, ts.KeyStore.HasPrivateKey(pk)) 309 310 inputs = []interface{}{"bb", false, pk, "0", "0"} 311 cmd = CreateAddUserCmd() 312 HoistRootFlags(cmd) 313 _, _, err = ExecuteInteractiveCmd(cmd, inputs) 314 require.NoError(t, err) 315 316 uc, err = ts.Store.ReadUserClaim("A", "bb") 317 require.NoError(t, err) 318 require.Equal(t, pk, uc.Subject) 319 require.Empty(t, uc.IssuerAccount) 320 require.False(t, ts.KeyStore.HasPrivateKey(pk)) 321 322 fp := filepath.Join(ts.Dir, "key") 323 err = ioutil.WriteFile(fp, sk, 0600) 324 require.NoError(t, err) 325 326 inputs = []interface{}{"cc", false, fp, "0", "0"} 327 cmd = CreateAddUserCmd() 328 HoistRootFlags(cmd) 329 _, _, err = ExecuteInteractiveCmd(cmd, inputs) 330 require.NoError(t, err) 331 332 uc, err = ts.Store.ReadUserClaim("A", "cc") 333 require.NoError(t, err) 334 require.Equal(t, pk, uc.Subject) 335 require.Empty(t, uc.IssuerAccount) 336 require.False(t, ts.KeyStore.HasPrivateKey(pk)) 337 } 338 339 func Test_AddUserWithExistingNkey(t *testing.T) { 340 ts := NewTestStore(t, "O") 341 defer ts.Done(t) 342 ts.AddAccount(t, "A") 343 344 kp, err := nkeys.CreateUser() 345 require.NoError(t, err) 346 _, err = ts.KeyStore.Store(kp) 347 require.NoError(t, err) 348 pk, err := kp.PublicKey() 349 require.NoError(t, err) 350 351 _, _, err = ExecuteCmd(CreateAddUserCmd(), "U", "--public-key", pk) 352 require.NoError(t, err) 353 } 354 355 func Test_AddUser_BearerToken(t *testing.T) { 356 ts := NewTestStore(t, "O") 357 defer ts.Done(t) 358 359 ts.AddAccount(t, "A") 360 _, _, err := ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UA") 361 require.NoError(t, err) 362 363 _, _, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UB", "--bearer") 364 require.NoError(t, err) 365 366 u, err := ts.Store.ReadUserClaim("A", "UA") 367 require.NoError(t, err) 368 require.False(t, u.BearerToken) 369 370 u, err = ts.Store.ReadUserClaim("A", "UB") 371 require.NoError(t, err) 372 require.True(t, u.BearerToken) 373 } 374 375 func Test_AddUserWithSigningKeyOnly(t *testing.T) { 376 ts := NewTestStore(t, "O") 377 defer ts.Done(t) 378 379 // create a signing key 380 kp, err := nkeys.CreateAccount() 381 require.NoError(t, err) 382 _, err = ts.KeyStore.Store(kp) 383 require.NoError(t, err) 384 pk, err := kp.PublicKey() 385 require.NoError(t, err) 386 require.True(t, ts.KeyStore.HasPrivateKey(pk)) 387 388 ts.AddAccount(t, "A") 389 _, _, err = ExecuteCmd(createEditAccount(), "--sk", pk) 390 require.NoError(t, err) 391 392 ac, err := ts.Store.ReadAccountClaim("A") 393 require.NoError(t, err) 394 require.NotNil(t, ac) 395 ts.KeyStore.Remove(ac.Subject) 396 require.False(t, ts.KeyStore.HasPrivateKey(ac.Subject)) 397 398 _, _, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "AAA") 399 require.NoError(t, err) 400 401 claim, err := ts.Store.ReadUserClaim("A", "AAA") 402 require.NoError(t, err) 403 require.NotEmpty(t, claim.IssuerAccount) 404 require.NotEqual(t, claim.Issuer, claim.IssuerAccount) 405 require.Equal(t, claim.Issuer, pk) 406 } 407 408 func Test_AddUserWithSigningKeyInteractive(t *testing.T) { 409 ts := NewTestStore(t, "O") 410 defer ts.Done(t) 411 412 // create a signing key 413 kp, err := nkeys.CreateAccount() 414 require.NoError(t, err) 415 _, err = ts.KeyStore.Store(kp) 416 require.NoError(t, err) 417 pk, err := kp.PublicKey() 418 require.NoError(t, err) 419 require.True(t, ts.KeyStore.HasPrivateKey(pk)) 420 421 ts.AddAccount(t, "A") 422 _, _, err = ExecuteCmd(createEditAccount(), "--sk", pk) 423 require.NoError(t, err) 424 425 ac, err := ts.Store.ReadAccountClaim("A") 426 require.NoError(t, err) 427 require.NotNil(t, ac) 428 require.True(t, ts.KeyStore.HasPrivateKey(ac.Subject)) 429 430 inputs := []interface{}{"AAA", true, "0", "0", 1} 431 cmd := CreateAddUserCmd() 432 HoistRootFlags(cmd) 433 _, _, err = ExecuteInteractiveCmd(cmd, inputs) 434 require.NoError(t, err) 435 436 claim, err := ts.Store.ReadUserClaim("A", "AAA") 437 require.NoError(t, err) 438 require.NotEmpty(t, claim.IssuerAccount) 439 require.NotEqual(t, claim.Issuer, claim.IssuerAccount) 440 require.Equal(t, claim.Issuer, pk) 441 } 442 443 func Test_AddUser_QueuePermissions(t *testing.T) { 444 ts := NewTestStore(t, "O") 445 defer ts.Done(t) 446 447 ts.AddAccount(t, "A") 448 449 _, _, err := ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UA", "--allow-sub", "foo queue", "--deny-sub", "bar queue") 450 require.NoError(t, err) 451 452 u, err := ts.Store.ReadUserClaim("A", "UA") 453 require.NoError(t, err) 454 require.True(t, u.Sub.Allow.Contains("foo queue")) 455 require.True(t, u.Sub.Deny.Contains("bar queue")) 456 } 457 458 func Test_AddUser_SrcPermissions(t *testing.T) { 459 ts := NewTestStore(t, "O") 460 defer ts.Done(t) 461 462 ts.AddAccount(t, "A") 463 464 _, _, err := ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UA", "--source-network", "1.2.1.1/29", "--source-network", "1.2.2.2/29,1.2.0.3/32") 465 require.NoError(t, err) 466 467 u, err := ts.Store.ReadUserClaim("A", "UA") 468 require.NoError(t, err) 469 require.True(t, u.Limits.Src.Contains("1.2.1.1/29")) 470 require.True(t, u.Limits.Src.Contains("1.2.2.2/29")) 471 require.True(t, u.Limits.Src.Contains("1.2.0.3/32")) 472 } 473 474 func Test_AddUser_Scoped(t *testing.T) { 475 ts := NewTestStore(t, "O") 476 defer ts.Done(t) 477 478 ts.AddAccount(t, "A") 479 s, pk, kp := CreateAccountKey(t) 480 481 // store seed in temporary file 482 f, err := ioutil.TempFile("", "") 483 defer os.Remove(f.Name()) 484 require.NoError(t, err) 485 f.Write(s) 486 f.Sync() 487 488 _, err = ts.KeyStore.Store(kp) 489 require.NoError(t, err) 490 491 _, _, err = ExecuteCmd(createEditAccount(), "--sk", pk) 492 require.NoError(t, err) 493 494 ac, err := ts.Store.ReadAccountClaim("A") 495 require.NoError(t, err) 496 require.Contains(t, ac.SigningKeys, pk) 497 498 _, _, err = ExecuteCmd(createEditSkopedSkCmd(), "--account", "A", "--sk", pk, "--subs", "5", "--role", "user-role") 499 require.NoError(t, err) 500 501 // fail using key outright 502 _, stderr, err := ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UA", "--tag", "foo", "--bearer", "-K", pk) 503 require.Error(t, err) 504 require.Contains(t, stderr, "[ERR ] scoped users require no permissions or limits set") 505 506 // fail using key via role name 507 _, stderr, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UB", "--tag", "foo", "--bearer", "-K", "user-role") 508 require.Error(t, err) 509 require.Contains(t, stderr, "[ERR ] scoped users require no permissions or limits set") 510 511 // pass as no permissions/limits are modified. 512 _, _, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UC", "--tag", "foo", "-K", "user-role") 513 require.NoError(t, err) 514 515 // pass as no permissions/limits are modified. 516 _, _, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UD", "--tag", "foo", "-K", pk) 517 require.NoError(t, err) 518 519 // pass as no permissions/limits are modified. 520 _, _, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UE", "--tag", "foo", "-K", string(s)) 521 require.NoError(t, err) 522 523 // pass as no permissions/limits are modified. 524 _, _, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "UF", "--tag", "foo", "-K", f.Name()) 525 require.NoError(t, err) 526 }