github.com/kbehouse/nsc@v0.0.6/cmd/edituser_test.go (about) 1 /* 2 * Copyright 2018-2021 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 "testing" 20 "time" 21 22 "github.com/nats-io/nkeys" 23 24 cli "github.com/nats-io/cliprompts/v2" 25 "github.com/nats-io/jwt/v2" 26 "github.com/stretchr/testify/require" 27 ) 28 29 func Test_EditUser(t *testing.T) { 30 ts := NewTestStore(t, "edit user") 31 defer ts.Done(t) 32 33 ts.AddUser(t, "A", "a") 34 ts.AddUser(t, "B", "b") 35 ts.AddUser(t, "B", "bb") 36 37 tests := CmdTests{ 38 {CreateEditUserCmd(), []string{"edit", "user"}, nil, []string{"specify an edit option"}, true}, 39 {CreateEditUserCmd(), []string{"edit", "user", "--tag", "A", "--account", "A"}, nil, []string{"edited user \"a\""}, false}, 40 {CreateEditUserCmd(), []string{"edit", "user", "--conn-type", "MQTT", "--rm-conn-type", "LEAFNODE", "--account", "A"}, nil, []string{"added connection type MQTT", "added connection type MQTT"}, false}, 41 {CreateEditUserCmd(), []string{"edit", "user", "--tag", "B", "--account", "B"}, nil, []string{"user name is required"}, true}, 42 {CreateEditUserCmd(), []string{"edit", "user", "--tag", "B", "--account", "B", "--name", "bb"}, nil, []string{"edited user \"bb\""}, false}, 43 } 44 45 tests.Run(t, "root", "edit") 46 } 47 48 func Test_EditUserInteractive(t *testing.T) { 49 ts := NewTestStore(t, "O") 50 defer ts.Done(t) 51 ts.AddUser(t, "A", "U") 52 53 inputs := []interface{}{"-1", "2018-01-01", "2050-01-01", false} 54 cli.LogFn = t.Log 55 _, _, err := ExecuteInteractiveCmd(CreateEditUserCmd(), inputs) 56 require.NoError(t, err) 57 58 uc, err := ts.Store.ReadUserClaim("A", "U") 59 require.NoError(t, err) 60 61 start, err := ParseExpiry("2018-01-01") 62 require.NoError(t, err) 63 require.Equal(t, start, uc.NotBefore) 64 65 expire, err := ParseExpiry("2050-01-01") 66 require.NoError(t, err) 67 require.Equal(t, expire, uc.Expires) 68 require.Nil(t, uc.Resp) 69 } 70 71 func Test_EditUserEditResponsePermissions(t *testing.T) { 72 t.Skip("response permissions not interactive") 73 ts := NewTestStore(t, "O") 74 defer ts.Done(t) 75 ts.AddUser(t, "A", "U") 76 77 inputs := []interface{}{true, 100, "1000ms", -1, 0, 0, false} 78 _, _, err := ExecuteInteractiveCmd(CreateEditUserCmd(), inputs) 79 require.NoError(t, err) 80 81 uc, err := ts.Store.ReadUserClaim("A", "U") 82 require.NoError(t, err) 83 84 require.NotNil(t, uc.Resp) 85 require.Equal(t, 100, uc.Resp.MaxMsgs) 86 require.Equal(t, time.Millisecond*1000, uc.Resp.Expires) 87 } 88 89 func Test_EditUserAccountRequired(t *testing.T) { 90 ts := NewTestStore(t, "edit user") 91 defer ts.Done(t) 92 93 ts.AddUser(t, "A", "a") 94 ts.AddUser(t, "B", "b") 95 require.NoError(t, GetConfig().SetAccount("")) 96 _, _, err := ExecuteCmd(CreateEditUserCmd(), "--tag", "A") 97 require.Error(t, err) 98 require.Contains(t, err.Error(), "account is required") 99 } 100 101 func Test_EditUser_Tag(t *testing.T) { 102 ts := NewTestStore(t, "edit user") 103 defer ts.Done(t) 104 105 ts.AddUser(t, "A", "a") 106 _, _, err := ExecuteCmd(CreateEditUserCmd(), "--tag", "A,B,C") 107 require.NoError(t, err) 108 109 cc, err := ts.Store.ReadUserClaim("A", "a") 110 require.NoError(t, err) 111 require.NotNil(t, cc) 112 113 require.Len(t, cc.Tags, 3) 114 require.ElementsMatch(t, cc.Tags, []string{"a", "b", "c"}) 115 116 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--rm-tag", "A,B") 117 require.NoError(t, err) 118 119 cc, err = ts.Store.ReadUserClaim("A", "a") 120 require.NoError(t, err) 121 require.NotNil(t, cc) 122 123 require.Len(t, cc.Tags, 1) 124 require.ElementsMatch(t, cc.Tags, []string{"c"}) 125 126 } 127 128 func Test_EditUser_Pubs(t *testing.T) { 129 ts := NewTestStore(t, "edit user") 130 defer ts.Done(t) 131 132 ts.AddUser(t, "A", "a") 133 134 _, _, err := ExecuteCmd(CreateEditUserCmd(), "--allow-pub", "a,b", "--allow-pubsub", "c", "--deny-pub", "foo", "--deny-pubsub", "bar") 135 require.NoError(t, err) 136 137 cc, err := ts.Store.ReadUserClaim("A", "a") 138 require.NoError(t, err) 139 require.NotNil(t, cc) 140 require.ElementsMatch(t, cc.Pub.Allow, []string{"a", "b", "c"}) 141 require.ElementsMatch(t, cc.Sub.Allow, []string{"c"}) 142 require.ElementsMatch(t, cc.Pub.Deny, []string{"foo", "bar"}) 143 require.ElementsMatch(t, cc.Sub.Deny, []string{"bar"}) 144 145 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--rm", "c,bar") 146 require.NoError(t, err) 147 cc, err = ts.Store.ReadUserClaim("A", "a") 148 require.NoError(t, err) 149 require.NotNil(t, cc) 150 151 require.ElementsMatch(t, cc.Pub.Allow, []string{"a", "b"}) 152 require.Len(t, cc.Sub.Allow, 0) 153 require.ElementsMatch(t, cc.Pub.Deny, []string{"foo"}) 154 require.Len(t, cc.Sub.Deny, 0) 155 } 156 157 func Test_EditUser_Src(t *testing.T) { 158 ts := NewTestStore(t, "edit user") 159 defer ts.Done(t) 160 161 ts.AddUser(t, "A", "a") 162 163 _, _, err := ExecuteCmd(CreateEditUserCmd(), "--source-network", "192.0.2.0/24,192.0.1.0/8") 164 require.NoError(t, err) 165 166 cc, err := ts.Store.ReadUserClaim("A", "a") 167 require.NoError(t, err) 168 require.NotNil(t, cc) 169 require.ElementsMatch(t, cc.Src, []string{"192.0.2.0/24", "192.0.1.0/8"}) 170 171 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--rm-source-network", "192.0.2.0/24") 172 require.NoError(t, err) 173 174 cc, err = ts.Store.ReadUserClaim("A", "a") 175 require.NoError(t, err) 176 require.NotNil(t, cc) 177 require.ElementsMatch(t, cc.Src, []string{"192.0.1.0/8"}) 178 } 179 180 func Test_EditUser_Times(t *testing.T) { 181 ts := NewTestStore(t, "edit user") 182 defer ts.Done(t) 183 184 ts.AddUser(t, "A", "a") 185 186 _, _, err := ExecuteCmd(CreateEditUserCmd(), "--time", "16:04:05-17:04:09", "--time", "18:04:05-19:04:09", "--locale", "America/New_York") 187 require.NoError(t, err) 188 189 cc, err := ts.Store.ReadUserClaim("A", "a") 190 require.NoError(t, err) 191 require.NotNil(t, cc) 192 193 require.ElementsMatch(t, cc.Times, []jwt.TimeRange{ 194 {Start: "16:04:05", End: "17:04:09"}, 195 {Start: "18:04:05", End: "19:04:09"}}) 196 require.Equal(t, "America/New_York", cc.Locale) 197 198 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--rm-time", "16:04:05", "--locale", "") 199 require.NoError(t, err) 200 201 cc, err = ts.Store.ReadUserClaim("A", "a") 202 require.NoError(t, err) 203 require.NotNil(t, cc) 204 require.ElementsMatch(t, cc.Times, []jwt.TimeRange{ 205 {Start: "18:04:05", End: "19:04:09"}}) 206 require.Equal(t, "UTC", cc.Locale) 207 } 208 209 func Test_EditUserSK(t *testing.T) { 210 ts := NewTestStore(t, "O") 211 t.Log(ts.Dir) 212 213 s, p, _ := CreateAccountKey(t) 214 ts.AddAccount(t, "A") 215 _, _, err := ExecuteCmd(HoistRootFlags(createEditAccount()), "--name", "A", "--sk", p) 216 require.NoError(t, err) 217 218 ac, err := ts.Store.ReadAccountClaim("A") 219 require.NoError(t, err) 220 require.Contains(t, ac.SigningKeys, p) 221 222 ts.AddUser(t, "A", "U") 223 uc, err := ts.Store.ReadUserClaim("A", "U") 224 require.NoError(t, err) 225 require.Equal(t, uc.Issuer, ac.Subject) 226 require.Empty(t, uc.IssuerAccount) 227 228 _, _, err = ExecuteCmd(HoistRootFlags(CreateEditUserCmd()), "-n", "U", "--allow-pub", "foo", "-K", string(s)) 229 require.NoError(t, err) 230 uc, err = ts.Store.ReadUserClaim("A", "U") 231 require.NoError(t, err) 232 require.Equal(t, uc.Issuer, p) 233 require.Equal(t, uc.IssuerAccount, ac.Subject) 234 } 235 236 func Test_EditUserAddedWithSK(t *testing.T) { 237 ts := NewTestStore(t, "O") 238 t.Log(ts.Dir) 239 240 s, p, sk := CreateAccountKey(t) 241 ts.AddAccount(t, "A") 242 _, _, err := ExecuteCmd(HoistRootFlags(createEditAccount()), "--name", "A", "--sk", p) 243 require.NoError(t, err) 244 245 ac, err := ts.Store.ReadAccountClaim("A") 246 require.NoError(t, err) 247 require.Contains(t, ac.SigningKeys, p) 248 249 ts.AddUserWithSigner(t, "A", "U", sk) 250 uc, err := ts.Store.ReadUserClaim("A", "U") 251 require.NoError(t, err) 252 require.Equal(t, uc.Issuer, p) 253 require.Equal(t, uc.IssuerAccount, ac.Subject) 254 255 _, _, err = ExecuteCmd(HoistRootFlags(CreateEditUserCmd()), "-n", "U", "--allow-pub", "foo", "-K", string(s)) 256 require.NoError(t, err) 257 uc, err = ts.Store.ReadUserClaim("A", "U") 258 require.NoError(t, err) 259 require.Equal(t, uc.Issuer, p) 260 require.Equal(t, uc.IssuerAccount, ac.Subject) 261 } 262 263 func Test_EditUser_Payload(t *testing.T) { 264 ts := NewTestStore(t, "edit user") 265 defer ts.Done(t) 266 267 ts.AddUser(t, "A", "U") 268 269 _, _, err := ExecuteCmd(CreateEditUserCmd(), "--payload", "1000") 270 require.NoError(t, err) 271 272 cc, err := ts.Store.ReadUserClaim("A", "U") 273 require.NoError(t, err) 274 require.NotNil(t, cc) 275 require.Equal(t, int64(1000), cc.Limits.Payload) 276 277 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--payload", "-1") 278 require.NoError(t, err) 279 280 cc, err = ts.Store.ReadUserClaim("A", "U") 281 require.NoError(t, err) 282 require.NotNil(t, cc) 283 require.Equal(t, int64(jwt.NoLimit), cc.Limits.Payload) 284 } 285 286 func Test_EditUserResponsePermissions(t *testing.T) { 287 ts := NewTestStore(t, "O") 288 defer ts.Done(t) 289 ts.AddAccount(t, "A") 290 291 _, _, err := ExecuteCmd(CreateAddUserCmd(), "U", "--max-responses", "100", "--response-ttl", "2ms") 292 require.NoError(t, err) 293 294 uc, err := ts.Store.ReadUserClaim("A", "U") 295 require.NoError(t, err) 296 require.NotNil(t, uc.Resp) 297 298 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--max-responses", "1000", "--response-ttl", "4ms") 299 require.NoError(t, err) 300 301 uc, err = ts.Store.ReadUserClaim("A", "U") 302 require.NoError(t, err) 303 require.NotNil(t, uc.Resp) 304 require.Equal(t, 1000, uc.Resp.MaxMsgs) 305 d, _ := time.ParseDuration("4ms") 306 require.Equal(t, d, uc.Resp.Expires) 307 308 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--rm-response-perms") 309 require.NoError(t, err) 310 311 uc, err = ts.Store.ReadUserClaim("A", "U") 312 require.NoError(t, err) 313 require.Nil(t, uc.Resp) 314 } 315 316 func Test_EditUserResponsePermissions2(t *testing.T) { 317 ts := NewTestStore(t, "O") 318 defer ts.Done(t) 319 ts.AddAccount(t, "A") 320 321 _, _, err := ExecuteCmd(CreateAddUserCmd(), "U", "--allow-pub-response", "--response-ttl", "2ms") 322 require.NoError(t, err) 323 uc, err := ts.Store.ReadUserClaim("A", "U") 324 require.NoError(t, err) 325 require.NotNil(t, uc.Resp) 326 require.Equal(t, 1, uc.Resp.MaxMsgs) 327 328 _, _, err = ExecuteCmd(CreateEditUserCmd(), "U", "--allow-pub-response=100", "--response-ttl", "2ms") 329 require.NoError(t, err) 330 331 uc, err = ts.Store.ReadUserClaim("A", "U") 332 require.NoError(t, err) 333 require.NotNil(t, uc.Resp) 334 require.Equal(t, 100, uc.Resp.MaxMsgs) 335 336 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--rm-response-perms") 337 require.NoError(t, err) 338 339 uc, err = ts.Store.ReadUserClaim("A", "U") 340 require.NoError(t, err) 341 require.Nil(t, uc.Resp) 342 } 343 344 func Test_EditUserBearerToken(t *testing.T) { 345 ts := NewTestStore(t, "O") 346 defer ts.Done(t) 347 ts.AddAccount(t, "A") 348 349 _, _, err := ExecuteCmd(CreateAddUserCmd(), "U") 350 require.NoError(t, err) 351 352 u, err := ts.Store.ReadUserClaim("A", "U") 353 require.NoError(t, err) 354 require.False(t, u.BearerToken) 355 356 _, stderr, err := ExecuteCmd(CreateEditUserCmd(), "--name", "U", "--bearer") 357 require.NoError(t, err) 358 require.Contains(t, stderr, "changed bearer to true") 359 360 u, err = ts.Store.ReadUserClaim("A", "U") 361 require.NoError(t, err) 362 require.True(t, u.BearerToken) 363 364 _, stderr, err = ExecuteCmd(CreateEditUserCmd(), "--name", "U", "--bearer=false") 365 require.NoError(t, err) 366 require.Contains(t, stderr, "changed bearer to false") 367 368 u, err = ts.Store.ReadUserClaim("A", "U") 369 require.NoError(t, err) 370 require.False(t, u.BearerToken) 371 } 372 373 func Test_EditUserWithSigningKeyOnly(t *testing.T) { 374 ts := NewTestStore(t, "O") 375 defer ts.Done(t) 376 377 // create a signing key 378 kp, err := nkeys.CreateAccount() 379 require.NoError(t, err) 380 _, err = ts.KeyStore.Store(kp) 381 require.NoError(t, err) 382 pk, err := kp.PublicKey() 383 require.NoError(t, err) 384 require.True(t, ts.KeyStore.HasPrivateKey(pk)) 385 386 ts.AddAccount(t, "A") 387 _, _, err = ExecuteCmd(createEditAccount(), "--sk", pk) 388 require.NoError(t, err) 389 390 ac, err := ts.Store.ReadAccountClaim("A") 391 require.NoError(t, err) 392 require.NotNil(t, ac) 393 require.NoError(t, ts.KeyStore.Remove(ac.Subject)) 394 require.False(t, ts.KeyStore.HasPrivateKey(ac.Subject)) 395 396 _, _, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "AAA") 397 require.NoError(t, err) 398 _, _, err = ExecuteCmd(HoistRootFlags(CreateEditUserCmd()), "--name", "AAA", "--payload", "5") 399 require.NoError(t, err) 400 401 claim, err := ts.Store.ReadUserClaim("A", "AAA") 402 require.NoError(t, err) 403 require.Equal(t, claim.Limits.Payload, int64(5)) 404 require.NotEmpty(t, claim.IssuerAccount) 405 require.NotEqual(t, claim.Issuer, claim.IssuerAccount) 406 require.Equal(t, claim.Issuer, pk) 407 } 408 409 func Test_EditUserWithSigningKeyInteractive(t *testing.T) { 410 ts := NewTestStore(t, "O") 411 defer ts.Done(t) 412 413 // create a signing key 414 kp, err := nkeys.CreateAccount() 415 require.NoError(t, err) 416 _, err = ts.KeyStore.Store(kp) 417 require.NoError(t, err) 418 pk, err := kp.PublicKey() 419 require.NoError(t, err) 420 require.True(t, ts.KeyStore.HasPrivateKey(pk)) 421 422 ts.AddAccount(t, "A") 423 _, _, err = ExecuteCmd(createEditAccount(), "--sk", pk) 424 require.NoError(t, err) 425 426 ac, err := ts.Store.ReadAccountClaim("A") 427 require.NoError(t, err) 428 require.NotNil(t, ac) 429 require.True(t, ts.KeyStore.HasPrivateKey(ac.Subject)) 430 431 _, _, err = ExecuteCmd(HoistRootFlags(CreateAddUserCmd()), "--name", "AAA") 432 require.NoError(t, err) 433 434 inputs := []interface{}{1, "5", "0", "0", false} 435 cmd := CreateEditUserCmd() 436 HoistRootFlags(cmd) 437 _, _, err = ExecuteInteractiveCmd(cmd, inputs, "--name", "AAA") 438 require.NoError(t, err) 439 440 claim, err := ts.Store.ReadUserClaim("A", "AAA") 441 require.NoError(t, err) 442 require.Equal(t, claim.Limits.Payload, int64(5)) 443 require.NotEmpty(t, claim.IssuerAccount) 444 require.NotEqual(t, claim.Issuer, claim.IssuerAccount) 445 require.Equal(t, claim.Issuer, pk) 446 } 447 448 func Test_EditUserSk(t *testing.T) { 449 ts := NewTestStore(t, "O") 450 defer ts.Done(t) 451 ts.AddAccount(t, "A") 452 453 sk, err := nkeys.CreateAccount() 454 require.NoError(t, err) 455 _, err = ts.KeyStore.Store(sk) 456 require.NoError(t, err) 457 pSk, err := sk.PublicKey() 458 require.NoError(t, err) 459 460 _, _, err = ExecuteCmd(createEditAccount(), "--sk", pSk) 461 require.NoError(t, err) 462 463 ts.AddUserWithSigner(t, "A", "u", sk) 464 uc, err := ts.Store.ReadUserClaim("A", "u") 465 require.NoError(t, err) 466 require.Equal(t, uc.Issuer, pSk) 467 468 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--tag", "foo") 469 require.NoError(t, err) 470 uc, err = ts.Store.ReadUserClaim("A", "u") 471 require.NoError(t, err) 472 require.Equal(t, uc.Issuer, pSk) 473 } 474 475 func Test_EditUserSubs(t *testing.T) { 476 ts := NewTestStore(t, "O") 477 defer ts.Done(t) 478 ts.AddAccount(t, "A") 479 ts.AddUser(t, "A", "U") 480 uc, err := ts.Store.ReadUserClaim("A", "U") 481 require.NoError(t, err) 482 require.Equal(t, int64(-1), uc.Subs) 483 484 _, _, err = ExecuteCmd(CreateEditUserCmd(), "--subs", "100") 485 require.NoError(t, err) 486 uc, err = ts.Store.ReadUserClaim("A", "U") 487 require.NoError(t, err) 488 require.Equal(t, int64(100), uc.Subs) 489 require.NoError(t, err) 490 } 491 492 func Test_EditUserData(t *testing.T) { 493 ts := NewTestStore(t, "O") 494 defer ts.Done(t) 495 ts.AddAccount(t, "A") 496 ts.AddUser(t, "A", "U") 497 uc, err := ts.Store.ReadUserClaim("A", "U") 498 require.NoError(t, err) 499 require.Equal(t, int64(-1), uc.Limits.Data) 500 501 _, _, err = ExecuteCmd(HoistRootFlags(CreateEditUserCmd()), "--data", "1Kib") 502 require.NoError(t, err) 503 uc, err = ts.Store.ReadUserClaim("A", "U") 504 require.NoError(t, err) 505 require.Equal(t, int64(1024), uc.Limits.Data) 506 require.NoError(t, err) 507 }