1// Copyright 2016 The etcd Authors 2// 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 15package e2e 16 17import ( 18 "fmt" 19 "os" 20 "testing" 21 "time" 22 23 "go.etcd.io/etcd/clientv3" 24) 25 26func TestCtlV3AuthEnable(t *testing.T) { testCtl(t, authEnableTest) } 27func TestCtlV3AuthDisable(t *testing.T) { testCtl(t, authDisableTest) } 28func TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKeyTest) } 29func TestCtlV3AuthRoleUpdate(t *testing.T) { testCtl(t, authRoleUpdateTest) } 30func TestCtlV3AuthUserDeleteDuringOps(t *testing.T) { testCtl(t, authUserDeleteDuringOpsTest) } 31func TestCtlV3AuthRoleRevokeDuringOps(t *testing.T) { testCtl(t, authRoleRevokeDuringOpsTest) } 32func TestCtlV3AuthTxn(t *testing.T) { testCtl(t, authTestTxn) } 33func TestCtlV3AuthTxnJWT(t *testing.T) { testCtl(t, authTestTxn, withCfg(configJWT)) } 34func TestCtlV3AuthPrefixPerm(t *testing.T) { testCtl(t, authTestPrefixPerm) } 35func TestCtlV3AuthMemberAdd(t *testing.T) { testCtl(t, authTestMemberAdd) } 36func TestCtlV3AuthMemberRemove(t *testing.T) { 37 testCtl(t, authTestMemberRemove, withQuorum(), withNoStrictReconfig()) 38} 39func TestCtlV3AuthMemberUpdate(t *testing.T) { testCtl(t, authTestMemberUpdate) } 40func TestCtlV3AuthCertCN(t *testing.T) { testCtl(t, authTestCertCN, withCfg(configClientTLSCertAuth)) } 41func TestCtlV3AuthRevokeWithDelete(t *testing.T) { testCtl(t, authTestRevokeWithDelete) } 42func TestCtlV3AuthInvalidMgmt(t *testing.T) { testCtl(t, authTestInvalidMgmt) } 43func TestCtlV3AuthFromKeyPerm(t *testing.T) { testCtl(t, authTestFromKeyPerm) } 44func TestCtlV3AuthAndWatch(t *testing.T) { testCtl(t, authTestWatch) } 45func TestCtlV3AuthAndWatchJWT(t *testing.T) { testCtl(t, authTestWatch, withCfg(configJWT)) } 46 47func TestCtlV3AuthLeaseTestKeepAlive(t *testing.T) { testCtl(t, authLeaseTestKeepAlive) } 48func TestCtlV3AuthLeaseTestTimeToLiveExpired(t *testing.T) { 49 testCtl(t, authLeaseTestTimeToLiveExpired) 50} 51func TestCtlV3AuthLeaseGrantLeases(t *testing.T) { testCtl(t, authLeaseTestLeaseGrantLeases) } 52func TestCtlV3AuthLeaseGrantLeasesJWT(t *testing.T) { 53 testCtl(t, authLeaseTestLeaseGrantLeases, withCfg(configJWT)) 54} 55func TestCtlV3AuthLeaseRevoke(t *testing.T) { testCtl(t, authLeaseTestLeaseRevoke) } 56 57func TestCtlV3AuthRoleGet(t *testing.T) { testCtl(t, authTestRoleGet) } 58func TestCtlV3AuthUserGet(t *testing.T) { testCtl(t, authTestUserGet) } 59func TestCtlV3AuthRoleList(t *testing.T) { testCtl(t, authTestRoleList) } 60 61func TestCtlV3AuthDefrag(t *testing.T) { testCtl(t, authTestDefrag) } 62func TestCtlV3AuthEndpointHealth(t *testing.T) { 63 testCtl(t, authTestEndpointHealth, withQuorum()) 64} 65func TestCtlV3AuthSnapshot(t *testing.T) { testCtl(t, authTestSnapshot) } 66func TestCtlV3AuthSnapshotJWT(t *testing.T) { testCtl(t, authTestSnapshot, withCfg(configJWT)) } 67func TestCtlV3AuthCertCNAndUsername(t *testing.T) { 68 testCtl(t, authTestCertCNAndUsername, withCfg(configClientTLSCertAuth)) 69} 70func TestCtlV3AuthJWTExpire(t *testing.T) { testCtl(t, authTestJWTExpire, withCfg(configJWT)) } 71func TestCtlV3AuthCertCNAndUsernameNoPassword(t *testing.T) { 72 testCtl(t, authTestCertCNAndUsernameNoPassword, withCfg(configClientTLSCertAuth)) 73} 74 75func authEnableTest(cx ctlCtx) { 76 if err := authEnable(cx); err != nil { 77 cx.t.Fatal(err) 78 } 79} 80 81func authEnable(cx ctlCtx) error { 82 // create root user with root role 83 if err := ctlV3User(cx, []string{"add", "root", "--interactive=false"}, "User root created", []string{"root"}); err != nil { 84 return fmt.Errorf("failed to create root user %v", err) 85 } 86 if err := ctlV3User(cx, []string{"grant-role", "root", "root"}, "Role root is granted to user root", nil); err != nil { 87 return fmt.Errorf("failed to grant root user root role %v", err) 88 } 89 if err := ctlV3AuthEnable(cx); err != nil { 90 return fmt.Errorf("authEnableTest ctlV3AuthEnable error (%v)", err) 91 } 92 return nil 93} 94 95func ctlV3AuthEnable(cx ctlCtx) error { 96 cmdArgs := append(cx.PrefixArgs(), "auth", "enable") 97 return spawnWithExpect(cmdArgs, "Authentication Enabled") 98} 99 100func authDisableTest(cx ctlCtx) { 101 // a key that isn't granted to test-user 102 if err := ctlV3Put(cx, "hoo", "a", ""); err != nil { 103 cx.t.Fatal(err) 104 } 105 106 if err := authEnable(cx); err != nil { 107 cx.t.Fatal(err) 108 } 109 110 cx.user, cx.pass = "root", "root" 111 authSetupTestUser(cx) 112 113 // test-user doesn't have the permission, it must fail 114 cx.user, cx.pass = "test-user", "pass" 115 if err := ctlV3PutFailPerm(cx, "hoo", "bar"); err != nil { 116 cx.t.Fatal(err) 117 } 118 119 cx.user, cx.pass = "root", "root" 120 if err := ctlV3AuthDisable(cx); err != nil { 121 cx.t.Fatalf("authDisableTest ctlV3AuthDisable error (%v)", err) 122 } 123 124 // now ErrAuthNotEnabled of Authenticate() is simply ignored 125 cx.user, cx.pass = "test-user", "pass" 126 if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil { 127 cx.t.Fatal(err) 128 } 129 130 // now the key can be accessed 131 cx.user, cx.pass = "", "" 132 if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil { 133 cx.t.Fatal(err) 134 } 135 // confirm put succeeded 136 if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar"}}...); err != nil { 137 cx.t.Fatal(err) 138 } 139} 140 141func ctlV3AuthDisable(cx ctlCtx) error { 142 cmdArgs := append(cx.PrefixArgs(), "auth", "disable") 143 return spawnWithExpect(cmdArgs, "Authentication Disabled") 144} 145 146func authCredWriteKeyTest(cx ctlCtx) { 147 // baseline key to check for failed puts 148 if err := ctlV3Put(cx, "foo", "a", ""); err != nil { 149 cx.t.Fatal(err) 150 } 151 152 if err := authEnable(cx); err != nil { 153 cx.t.Fatal(err) 154 } 155 156 cx.user, cx.pass = "root", "root" 157 authSetupTestUser(cx) 158 159 // confirm root role can access to all keys 160 if err := ctlV3Put(cx, "foo", "bar", ""); err != nil { 161 cx.t.Fatal(err) 162 } 163 if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil { 164 cx.t.Fatal(err) 165 } 166 167 // try invalid user 168 cx.user, cx.pass = "a", "b" 169 if err := ctlV3PutFailAuth(cx, "foo", "bar"); err != nil { 170 cx.t.Fatal(err) 171 } 172 // confirm put failed 173 cx.user, cx.pass = "test-user", "pass" 174 if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil { 175 cx.t.Fatal(err) 176 } 177 178 // try good user 179 cx.user, cx.pass = "test-user", "pass" 180 if err := ctlV3Put(cx, "foo", "bar2", ""); err != nil { 181 cx.t.Fatal(err) 182 } 183 // confirm put succeeded 184 if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar2"}}...); err != nil { 185 cx.t.Fatal(err) 186 } 187 188 // try bad password 189 cx.user, cx.pass = "test-user", "badpass" 190 if err := ctlV3PutFailAuth(cx, "foo", "baz"); err != nil { 191 cx.t.Fatal(err) 192 } 193 // confirm put failed 194 cx.user, cx.pass = "test-user", "pass" 195 if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar2"}}...); err != nil { 196 cx.t.Fatal(err) 197 } 198} 199 200func authRoleUpdateTest(cx ctlCtx) { 201 if err := ctlV3Put(cx, "foo", "bar", ""); err != nil { 202 cx.t.Fatal(err) 203 } 204 205 if err := authEnable(cx); err != nil { 206 cx.t.Fatal(err) 207 } 208 209 cx.user, cx.pass = "root", "root" 210 authSetupTestUser(cx) 211 212 // try put to not granted key 213 cx.user, cx.pass = "test-user", "pass" 214 if err := ctlV3PutFailPerm(cx, "hoo", "bar"); err != nil { 215 cx.t.Fatal(err) 216 } 217 218 // grant a new key 219 cx.user, cx.pass = "root", "root" 220 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "hoo", "", false}); err != nil { 221 cx.t.Fatal(err) 222 } 223 224 // try a newly granted key 225 cx.user, cx.pass = "test-user", "pass" 226 if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil { 227 cx.t.Fatal(err) 228 } 229 // confirm put succeeded 230 if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar"}}...); err != nil { 231 cx.t.Fatal(err) 232 } 233 234 // revoke the newly granted key 235 cx.user, cx.pass = "root", "root" 236 if err := ctlV3RoleRevokePermission(cx, "test-role", "hoo", "", false); err != nil { 237 cx.t.Fatal(err) 238 } 239 240 // try put to the revoked key 241 cx.user, cx.pass = "test-user", "pass" 242 if err := ctlV3PutFailPerm(cx, "hoo", "bar"); err != nil { 243 cx.t.Fatal(err) 244 } 245 246 // confirm a key still granted can be accessed 247 if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil { 248 cx.t.Fatal(err) 249 } 250} 251 252func authUserDeleteDuringOpsTest(cx ctlCtx) { 253 if err := ctlV3Put(cx, "foo", "bar", ""); err != nil { 254 cx.t.Fatal(err) 255 } 256 257 if err := authEnable(cx); err != nil { 258 cx.t.Fatal(err) 259 } 260 261 cx.user, cx.pass = "root", "root" 262 authSetupTestUser(cx) 263 264 // create a key 265 cx.user, cx.pass = "test-user", "pass" 266 if err := ctlV3Put(cx, "foo", "bar", ""); err != nil { 267 cx.t.Fatal(err) 268 } 269 // confirm put succeeded 270 if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil { 271 cx.t.Fatal(err) 272 } 273 274 // delete the user 275 cx.user, cx.pass = "root", "root" 276 err := ctlV3User(cx, []string{"delete", "test-user"}, "User test-user deleted", []string{}) 277 if err != nil { 278 cx.t.Fatal(err) 279 } 280 281 // check the user is deleted 282 cx.user, cx.pass = "test-user", "pass" 283 if err := ctlV3PutFailAuth(cx, "foo", "baz"); err != nil { 284 cx.t.Fatal(err) 285 } 286} 287 288func authRoleRevokeDuringOpsTest(cx ctlCtx) { 289 if err := ctlV3Put(cx, "foo", "bar", ""); err != nil { 290 cx.t.Fatal(err) 291 } 292 293 if err := authEnable(cx); err != nil { 294 cx.t.Fatal(err) 295 } 296 297 cx.user, cx.pass = "root", "root" 298 authSetupTestUser(cx) 299 300 // create a key 301 cx.user, cx.pass = "test-user", "pass" 302 if err := ctlV3Put(cx, "foo", "bar", ""); err != nil { 303 cx.t.Fatal(err) 304 } 305 // confirm put succeeded 306 if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil { 307 cx.t.Fatal(err) 308 } 309 310 // create a new role 311 cx.user, cx.pass = "root", "root" 312 if err := ctlV3Role(cx, []string{"add", "test-role2"}, "Role test-role2 created"); err != nil { 313 cx.t.Fatal(err) 314 } 315 // grant a new key to the new role 316 if err := ctlV3RoleGrantPermission(cx, "test-role2", grantingPerm{true, true, "hoo", "", false}); err != nil { 317 cx.t.Fatal(err) 318 } 319 // grant the new role to the user 320 if err := ctlV3User(cx, []string{"grant-role", "test-user", "test-role2"}, "Role test-role2 is granted to user test-user", nil); err != nil { 321 cx.t.Fatal(err) 322 } 323 324 // try a newly granted key 325 cx.user, cx.pass = "test-user", "pass" 326 if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil { 327 cx.t.Fatal(err) 328 } 329 // confirm put succeeded 330 if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar"}}...); err != nil { 331 cx.t.Fatal(err) 332 } 333 334 // revoke a role from the user 335 cx.user, cx.pass = "root", "root" 336 err := ctlV3User(cx, []string{"revoke-role", "test-user", "test-role"}, "Role test-role is revoked from user test-user", []string{}) 337 if err != nil { 338 cx.t.Fatal(err) 339 } 340 341 // check the role is revoked and permission is lost from the user 342 cx.user, cx.pass = "test-user", "pass" 343 if err := ctlV3PutFailPerm(cx, "foo", "baz"); err != nil { 344 cx.t.Fatal(err) 345 } 346 347 // try a key that can be accessed from the remaining role 348 cx.user, cx.pass = "test-user", "pass" 349 if err := ctlV3Put(cx, "hoo", "bar2", ""); err != nil { 350 cx.t.Fatal(err) 351 } 352 // confirm put succeeded 353 if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar2"}}...); err != nil { 354 cx.t.Fatal(err) 355 } 356} 357 358func ctlV3PutFailAuth(cx ctlCtx, key, val string) error { 359 return spawnWithExpect(append(cx.PrefixArgs(), "put", key, val), "authentication failed") 360} 361 362func ctlV3PutFailPerm(cx ctlCtx, key, val string) error { 363 return spawnWithExpect(append(cx.PrefixArgs(), "put", key, val), "permission denied") 364} 365 366func authSetupTestUser(cx ctlCtx) { 367 if err := ctlV3User(cx, []string{"add", "test-user", "--interactive=false"}, "User test-user created", []string{"pass"}); err != nil { 368 cx.t.Fatal(err) 369 } 370 if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "Role test-role created"); err != nil { 371 cx.t.Fatal(err) 372 } 373 if err := ctlV3User(cx, []string{"grant-role", "test-user", "test-role"}, "Role test-role is granted to user test-user", nil); err != nil { 374 cx.t.Fatal(err) 375 } 376 cmd := append(cx.PrefixArgs(), "role", "grant-permission", "test-role", "readwrite", "foo") 377 if err := spawnWithExpect(cmd, "Role test-role updated"); err != nil { 378 cx.t.Fatal(err) 379 } 380} 381 382func authTestTxn(cx ctlCtx) { 383 // keys with 1 suffix aren't granted to test-user 384 // keys with 2 suffix are granted to test-user 385 386 keys := []string{"c1", "s1", "f1"} 387 grantedKeys := []string{"c2", "s2", "f2"} 388 for _, key := range keys { 389 if err := ctlV3Put(cx, key, "v", ""); err != nil { 390 cx.t.Fatal(err) 391 } 392 } 393 394 for _, key := range grantedKeys { 395 if err := ctlV3Put(cx, key, "v", ""); err != nil { 396 cx.t.Fatal(err) 397 } 398 } 399 400 if err := authEnable(cx); err != nil { 401 cx.t.Fatal(err) 402 } 403 404 cx.user, cx.pass = "root", "root" 405 authSetupTestUser(cx) 406 407 // grant keys to test-user 408 cx.user, cx.pass = "root", "root" 409 for _, key := range grantedKeys { 410 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, key, "", false}); err != nil { 411 cx.t.Fatal(err) 412 } 413 } 414 415 // now test txn 416 cx.interactive = true 417 cx.user, cx.pass = "test-user", "pass" 418 419 rqs := txnRequests{ 420 compare: []string{`version("c2") = "1"`}, 421 ifSucess: []string{"get s2"}, 422 ifFail: []string{"get f2"}, 423 results: []string{"SUCCESS", "s2", "v"}, 424 } 425 if err := ctlV3Txn(cx, rqs); err != nil { 426 cx.t.Fatal(err) 427 } 428 429 // a key of compare case isn't granted 430 rqs = txnRequests{ 431 compare: []string{`version("c1") = "1"`}, 432 ifSucess: []string{"get s2"}, 433 ifFail: []string{"get f2"}, 434 results: []string{"Error: etcdserver: permission denied"}, 435 } 436 if err := ctlV3Txn(cx, rqs); err != nil { 437 cx.t.Fatal(err) 438 } 439 440 // a key of success case isn't granted 441 rqs = txnRequests{ 442 compare: []string{`version("c2") = "1"`}, 443 ifSucess: []string{"get s1"}, 444 ifFail: []string{"get f2"}, 445 results: []string{"Error: etcdserver: permission denied"}, 446 } 447 if err := ctlV3Txn(cx, rqs); err != nil { 448 cx.t.Fatal(err) 449 } 450 451 // a key of failure case isn't granted 452 rqs = txnRequests{ 453 compare: []string{`version("c2") = "1"`}, 454 ifSucess: []string{"get s2"}, 455 ifFail: []string{"get f1"}, 456 results: []string{"Error: etcdserver: permission denied"}, 457 } 458 if err := ctlV3Txn(cx, rqs); err != nil { 459 cx.t.Fatal(err) 460 } 461} 462 463func authTestPrefixPerm(cx ctlCtx) { 464 if err := authEnable(cx); err != nil { 465 cx.t.Fatal(err) 466 } 467 468 cx.user, cx.pass = "root", "root" 469 authSetupTestUser(cx) 470 471 prefix := "/prefix/" // directory like prefix 472 // grant keys to test-user 473 cx.user, cx.pass = "root", "root" 474 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, prefix, "", true}); err != nil { 475 cx.t.Fatal(err) 476 } 477 478 // try a prefix granted permission 479 cx.user, cx.pass = "test-user", "pass" 480 for i := 0; i < 10; i++ { 481 key := fmt.Sprintf("%s%d", prefix, i) 482 if err := ctlV3Put(cx, key, "val", ""); err != nil { 483 cx.t.Fatal(err) 484 } 485 } 486 487 if err := ctlV3PutFailPerm(cx, clientv3.GetPrefixRangeEnd(prefix), "baz"); err != nil { 488 cx.t.Fatal(err) 489 } 490 491 // grant the entire keys to test-user 492 cx.user, cx.pass = "root", "root" 493 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "", "", true}); err != nil { 494 cx.t.Fatal(err) 495 } 496 497 prefix2 := "/prefix2/" 498 cx.user, cx.pass = "test-user", "pass" 499 for i := 0; i < 10; i++ { 500 key := fmt.Sprintf("%s%d", prefix2, i) 501 if err := ctlV3Put(cx, key, "val", ""); err != nil { 502 cx.t.Fatal(err) 503 } 504 } 505} 506 507func authTestMemberAdd(cx ctlCtx) { 508 if err := authEnable(cx); err != nil { 509 cx.t.Fatal(err) 510 } 511 512 cx.user, cx.pass = "root", "root" 513 authSetupTestUser(cx) 514 515 peerURL := fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+11) 516 // ordinary user cannot add a new member 517 cx.user, cx.pass = "test-user", "pass" 518 if err := ctlV3MemberAdd(cx, peerURL, false); err == nil { 519 cx.t.Fatalf("ordinary user must not be allowed to add a member") 520 } 521 522 // root can add a new member 523 cx.user, cx.pass = "root", "root" 524 if err := ctlV3MemberAdd(cx, peerURL, false); err != nil { 525 cx.t.Fatal(err) 526 } 527} 528 529func authTestMemberRemove(cx ctlCtx) { 530 if err := authEnable(cx); err != nil { 531 cx.t.Fatal(err) 532 } 533 534 cx.user, cx.pass = "root", "root" 535 authSetupTestUser(cx) 536 537 ep, memIDToRemove, clusterID := cx.memberToRemove() 538 539 // ordinary user cannot remove a member 540 cx.user, cx.pass = "test-user", "pass" 541 if err := ctlV3MemberRemove(cx, ep, memIDToRemove, clusterID); err == nil { 542 cx.t.Fatalf("ordinary user must not be allowed to remove a member") 543 } 544 545 // root can remove a member 546 cx.user, cx.pass = "root", "root" 547 if err := ctlV3MemberRemove(cx, ep, memIDToRemove, clusterID); err != nil { 548 cx.t.Fatal(err) 549 } 550} 551 552func authTestMemberUpdate(cx ctlCtx) { 553 if err := authEnable(cx); err != nil { 554 cx.t.Fatal(err) 555 } 556 557 cx.user, cx.pass = "root", "root" 558 authSetupTestUser(cx) 559 560 mr, err := getMemberList(cx) 561 if err != nil { 562 cx.t.Fatal(err) 563 } 564 565 // ordinary user cannot update a member 566 cx.user, cx.pass = "test-user", "pass" 567 peerURL := fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+11) 568 memberID := fmt.Sprintf("%x", mr.Members[0].ID) 569 if err = ctlV3MemberUpdate(cx, memberID, peerURL); err == nil { 570 cx.t.Fatalf("ordinary user must not be allowed to update a member") 571 } 572 573 // root can update a member 574 cx.user, cx.pass = "root", "root" 575 if err = ctlV3MemberUpdate(cx, memberID, peerURL); err != nil { 576 cx.t.Fatal(err) 577 } 578} 579 580func authTestCertCN(cx ctlCtx) { 581 if err := authEnable(cx); err != nil { 582 cx.t.Fatal(err) 583 } 584 585 cx.user, cx.pass = "root", "root" 586 if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil { 587 cx.t.Fatal(err) 588 } 589 if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "Role test-role created"); err != nil { 590 cx.t.Fatal(err) 591 } 592 if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role"}, "Role test-role is granted to user example.com", nil); err != nil { 593 cx.t.Fatal(err) 594 } 595 596 // grant a new key 597 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "hoo", "", false}); err != nil { 598 cx.t.Fatal(err) 599 } 600 601 // try a granted key 602 cx.user, cx.pass = "", "" 603 if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil { 604 cx.t.Error(err) 605 } 606 607 // try a non granted key 608 cx.user, cx.pass = "", "" 609 if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil { 610 cx.t.Error(err) 611 } 612} 613 614func authTestRevokeWithDelete(cx ctlCtx) { 615 if err := authEnable(cx); err != nil { 616 cx.t.Fatal(err) 617 } 618 619 cx.user, cx.pass = "root", "root" 620 authSetupTestUser(cx) 621 622 // create a new role 623 cx.user, cx.pass = "root", "root" 624 if err := ctlV3Role(cx, []string{"add", "test-role2"}, "Role test-role2 created"); err != nil { 625 cx.t.Fatal(err) 626 } 627 628 // grant the new role to the user 629 if err := ctlV3User(cx, []string{"grant-role", "test-user", "test-role2"}, "Role test-role2 is granted to user test-user", nil); err != nil { 630 cx.t.Fatal(err) 631 } 632 633 // check the result 634 if err := ctlV3User(cx, []string{"get", "test-user"}, "Roles: test-role test-role2", nil); err != nil { 635 cx.t.Fatal(err) 636 } 637 638 // delete the role, test-role2 must be revoked from test-user 639 if err := ctlV3Role(cx, []string{"delete", "test-role2"}, "Role test-role2 deleted"); err != nil { 640 cx.t.Fatal(err) 641 } 642 643 // check the result 644 if err := ctlV3User(cx, []string{"get", "test-user"}, "Roles: test-role", nil); err != nil { 645 cx.t.Fatal(err) 646 } 647} 648 649func authTestInvalidMgmt(cx ctlCtx) { 650 if err := authEnable(cx); err != nil { 651 cx.t.Fatal(err) 652 } 653 654 if err := ctlV3Role(cx, []string{"delete", "root"}, "Error: etcdserver: invalid auth management"); err == nil { 655 cx.t.Fatal("deleting the role root must not be allowed") 656 } 657 658 if err := ctlV3User(cx, []string{"revoke-role", "root", "root"}, "Error: etcdserver: invalid auth management", []string{}); err == nil { 659 cx.t.Fatal("revoking the role root from the user root must not be allowed") 660 } 661} 662 663func authTestFromKeyPerm(cx ctlCtx) { 664 if err := authEnable(cx); err != nil { 665 cx.t.Fatal(err) 666 } 667 668 cx.user, cx.pass = "root", "root" 669 authSetupTestUser(cx) 670 671 // grant keys after z to test-user 672 cx.user, cx.pass = "root", "root" 673 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "z", "\x00", false}); err != nil { 674 cx.t.Fatal(err) 675 } 676 677 // try the granted open ended permission 678 cx.user, cx.pass = "test-user", "pass" 679 for i := 0; i < 10; i++ { 680 key := fmt.Sprintf("z%d", i) 681 if err := ctlV3Put(cx, key, "val", ""); err != nil { 682 cx.t.Fatal(err) 683 } 684 } 685 largeKey := "" 686 for i := 0; i < 10; i++ { 687 largeKey += "\xff" 688 if err := ctlV3Put(cx, largeKey, "val", ""); err != nil { 689 cx.t.Fatal(err) 690 } 691 } 692 693 // try a non granted key 694 if err := ctlV3PutFailPerm(cx, "x", "baz"); err != nil { 695 cx.t.Fatal(err) 696 } 697 698 // revoke the open ended permission 699 cx.user, cx.pass = "root", "root" 700 if err := ctlV3RoleRevokePermission(cx, "test-role", "z", "", true); err != nil { 701 cx.t.Fatal(err) 702 } 703 704 // try the revoked open ended permission 705 cx.user, cx.pass = "test-user", "pass" 706 for i := 0; i < 10; i++ { 707 key := fmt.Sprintf("z%d", i) 708 if err := ctlV3PutFailPerm(cx, key, "val"); err != nil { 709 cx.t.Fatal(err) 710 } 711 } 712 713 // grant the entire keys 714 cx.user, cx.pass = "root", "root" 715 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "", "\x00", false}); err != nil { 716 cx.t.Fatal(err) 717 } 718 719 // try keys, of course it must be allowed because test-role has a permission of the entire keys 720 cx.user, cx.pass = "test-user", "pass" 721 for i := 0; i < 10; i++ { 722 key := fmt.Sprintf("z%d", i) 723 if err := ctlV3Put(cx, key, "val", ""); err != nil { 724 cx.t.Fatal(err) 725 } 726 } 727 728 // revoke the entire keys 729 cx.user, cx.pass = "root", "root" 730 if err := ctlV3RoleRevokePermission(cx, "test-role", "", "", true); err != nil { 731 cx.t.Fatal(err) 732 } 733 734 // try the revoked entire key permission 735 cx.user, cx.pass = "test-user", "pass" 736 for i := 0; i < 10; i++ { 737 key := fmt.Sprintf("z%d", i) 738 if err := ctlV3PutFailPerm(cx, key, "val"); err != nil { 739 cx.t.Fatal(err) 740 } 741 } 742} 743 744func authLeaseTestKeepAlive(cx ctlCtx) { 745 if err := authEnable(cx); err != nil { 746 cx.t.Fatal(err) 747 } 748 749 cx.user, cx.pass = "root", "root" 750 authSetupTestUser(cx) 751 // put with TTL 10 seconds and keep-alive 752 leaseID, err := ctlV3LeaseGrant(cx, 10) 753 if err != nil { 754 cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseGrant error (%v)", err) 755 } 756 if err := ctlV3Put(cx, "key", "val", leaseID); err != nil { 757 cx.t.Fatalf("leaseTestKeepAlive: ctlV3Put error (%v)", err) 758 } 759 if err := ctlV3LeaseKeepAlive(cx, leaseID); err != nil { 760 cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseKeepAlive error (%v)", err) 761 } 762 if err := ctlV3Get(cx, []string{"key"}, kv{"key", "val"}); err != nil { 763 cx.t.Fatalf("leaseTestKeepAlive: ctlV3Get error (%v)", err) 764 } 765} 766 767func authLeaseTestTimeToLiveExpired(cx ctlCtx) { 768 if err := authEnable(cx); err != nil { 769 cx.t.Fatal(err) 770 } 771 772 cx.user, cx.pass = "root", "root" 773 authSetupTestUser(cx) 774 775 ttl := 3 776 if err := leaseTestTimeToLiveExpire(cx, ttl); err != nil { 777 cx.t.Fatalf("leaseTestTimeToLiveExpire: error (%v)", err) 778 } 779} 780 781func authLeaseTestLeaseGrantLeases(cx ctlCtx) { 782 cx.user, cx.pass = "root", "root" 783 authSetupTestUser(cx) 784 785 if err := leaseTestGrantLeasesList(cx); err != nil { 786 cx.t.Fatalf("authLeaseTestLeaseGrantLeases: error (%v)", err) 787 } 788} 789 790func authLeaseTestLeaseRevoke(cx ctlCtx) { 791 cx.user, cx.pass = "root", "root" 792 authSetupTestUser(cx) 793 794 // put with TTL 10 seconds and revoke 795 leaseID, err := ctlV3LeaseGrant(cx, 10) 796 if err != nil { 797 cx.t.Fatalf("ctlV3LeaseGrant error (%v)", err) 798 } 799 if err := ctlV3Put(cx, "key", "val", leaseID); err != nil { 800 cx.t.Fatalf("ctlV3Put error (%v)", err) 801 } 802 if err := ctlV3LeaseRevoke(cx, leaseID); err != nil { 803 cx.t.Fatalf("ctlV3LeaseRevoke error (%v)", err) 804 } 805 if err := ctlV3GetWithErr(cx, []string{"key"}, []string{"retrying of unary invoker failed"}); err != nil { // expect errors 806 cx.t.Fatalf("ctlV3GetWithErr error (%v)", err) 807 } 808} 809 810func authTestWatch(cx ctlCtx) { 811 if err := authEnable(cx); err != nil { 812 cx.t.Fatal(err) 813 } 814 815 cx.user, cx.pass = "root", "root" 816 authSetupTestUser(cx) 817 818 // grant a key range 819 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "key", "key4", false}); err != nil { 820 cx.t.Fatal(err) 821 } 822 823 tests := []struct { 824 puts []kv 825 args []string 826 827 wkv []kvExec 828 want bool 829 }{ 830 { // watch 1 key, should be successful 831 []kv{{"key", "value"}}, 832 []string{"key", "--rev", "1"}, 833 []kvExec{{key: "key", val: "value"}}, 834 true, 835 }, 836 { // watch 3 keys by range, should be successful 837 []kv{{"key1", "val1"}, {"key3", "val3"}, {"key2", "val2"}}, 838 []string{"key", "key3", "--rev", "1"}, 839 []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}}, 840 true, 841 }, 842 843 { // watch 1 key, should not be successful 844 []kv{}, 845 []string{"key5", "--rev", "1"}, 846 []kvExec{}, 847 false, 848 }, 849 { // watch 3 keys by range, should not be successful 850 []kv{}, 851 []string{"key", "key6", "--rev", "1"}, 852 []kvExec{}, 853 false, 854 }, 855 } 856 857 cx.user, cx.pass = "test-user", "pass" 858 for i, tt := range tests { 859 donec := make(chan struct{}) 860 go func(i int, puts []kv) { 861 defer close(donec) 862 for j := range puts { 863 if err := ctlV3Put(cx, puts[j].key, puts[j].val, ""); err != nil { 864 cx.t.Errorf("watchTest #%d-%d: ctlV3Put error (%v)", i, j, err) 865 } 866 } 867 }(i, tt.puts) 868 869 var err error 870 if tt.want { 871 err = ctlV3Watch(cx, tt.args, tt.wkv...) 872 } else { 873 err = ctlV3WatchFailPerm(cx, tt.args) 874 } 875 876 if err != nil { 877 if cx.dialTimeout > 0 && !isGRPCTimedout(err) { 878 cx.t.Errorf("watchTest #%d: ctlV3Watch error (%v)", i, err) 879 } 880 } 881 882 <-donec 883 } 884 885} 886 887func authTestRoleGet(cx ctlCtx) { 888 if err := authEnable(cx); err != nil { 889 cx.t.Fatal(err) 890 } 891 cx.user, cx.pass = "root", "root" 892 authSetupTestUser(cx) 893 894 expected := []string{ 895 "Role test-role", 896 "KV Read:", "foo", 897 "KV Write:", "foo", 898 } 899 if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), expected...); err != nil { 900 cx.t.Fatal(err) 901 } 902 903 // test-user can get the information of test-role because it belongs to the role 904 cx.user, cx.pass = "test-user", "pass" 905 if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), expected...); err != nil { 906 cx.t.Fatal(err) 907 } 908 909 // test-user cannot get the information of root because it doesn't belong to the role 910 expected = []string{ 911 "Error: etcdserver: permission denied", 912 } 913 if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "root"), expected...); err != nil { 914 cx.t.Fatal(err) 915 } 916} 917 918func authTestUserGet(cx ctlCtx) { 919 if err := authEnable(cx); err != nil { 920 cx.t.Fatal(err) 921 } 922 cx.user, cx.pass = "root", "root" 923 authSetupTestUser(cx) 924 925 expected := []string{ 926 "User: test-user", 927 "Roles: test-role", 928 } 929 930 if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), expected...); err != nil { 931 cx.t.Fatal(err) 932 } 933 934 // test-user can get the information of test-user itself 935 cx.user, cx.pass = "test-user", "pass" 936 if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), expected...); err != nil { 937 cx.t.Fatal(err) 938 } 939 940 // test-user cannot get the information of root 941 expected = []string{ 942 "Error: etcdserver: permission denied", 943 } 944 if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "root"), expected...); err != nil { 945 cx.t.Fatal(err) 946 } 947} 948 949func authTestRoleList(cx ctlCtx) { 950 if err := authEnable(cx); err != nil { 951 cx.t.Fatal(err) 952 } 953 cx.user, cx.pass = "root", "root" 954 authSetupTestUser(cx) 955 if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "list"), "test-role"); err != nil { 956 cx.t.Fatal(err) 957 } 958} 959 960func authTestDefrag(cx ctlCtx) { 961 maintenanceInitKeys(cx) 962 963 if err := authEnable(cx); err != nil { 964 cx.t.Fatal(err) 965 } 966 967 cx.user, cx.pass = "root", "root" 968 authSetupTestUser(cx) 969 970 // ordinary user cannot defrag 971 cx.user, cx.pass = "test-user", "pass" 972 if err := ctlV3Defrag(cx); err == nil { 973 cx.t.Fatal("ordinary user should not be able to issue a defrag request") 974 } 975 976 // root can defrag 977 cx.user, cx.pass = "root", "root" 978 if err := ctlV3Defrag(cx); err != nil { 979 cx.t.Fatal(err) 980 } 981} 982 983func authTestSnapshot(cx ctlCtx) { 984 maintenanceInitKeys(cx) 985 986 if err := authEnable(cx); err != nil { 987 cx.t.Fatal(err) 988 } 989 990 cx.user, cx.pass = "root", "root" 991 authSetupTestUser(cx) 992 993 fpath := "test-auth.snapshot" 994 defer os.RemoveAll(fpath) 995 996 // ordinary user cannot save a snapshot 997 cx.user, cx.pass = "test-user", "pass" 998 if err := ctlV3SnapshotSave(cx, fpath); err == nil { 999 cx.t.Fatal("ordinary user should not be able to save a snapshot") 1000 } 1001 1002 // root can save a snapshot 1003 cx.user, cx.pass = "root", "root" 1004 if err := ctlV3SnapshotSave(cx, fpath); err != nil { 1005 cx.t.Fatalf("snapshotTest ctlV3SnapshotSave error (%v)", err) 1006 } 1007 1008 st, err := getSnapshotStatus(cx, fpath) 1009 if err != nil { 1010 cx.t.Fatalf("snapshotTest getSnapshotStatus error (%v)", err) 1011 } 1012 if st.Revision != 4 { 1013 cx.t.Fatalf("expected 4, got %d", st.Revision) 1014 } 1015 if st.TotalKey < 3 { 1016 cx.t.Fatalf("expected at least 3, got %d", st.TotalKey) 1017 } 1018} 1019 1020func authTestEndpointHealth(cx ctlCtx) { 1021 if err := authEnable(cx); err != nil { 1022 cx.t.Fatal(err) 1023 } 1024 1025 cx.user, cx.pass = "root", "root" 1026 authSetupTestUser(cx) 1027 1028 if err := ctlV3EndpointHealth(cx); err != nil { 1029 cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err) 1030 } 1031 1032 // health checking with an ordinary user "succeeds" since permission denial goes through consensus 1033 cx.user, cx.pass = "test-user", "pass" 1034 if err := ctlV3EndpointHealth(cx); err != nil { 1035 cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err) 1036 } 1037 1038 // succeed if permissions granted for ordinary user 1039 cx.user, cx.pass = "root", "root" 1040 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "health", "", false}); err != nil { 1041 cx.t.Fatal(err) 1042 } 1043 cx.user, cx.pass = "test-user", "pass" 1044 if err := ctlV3EndpointHealth(cx); err != nil { 1045 cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err) 1046 } 1047} 1048 1049func certCNAndUsername(cx ctlCtx, noPassword bool) { 1050 if err := authEnable(cx); err != nil { 1051 cx.t.Fatal(err) 1052 } 1053 1054 cx.user, cx.pass = "root", "root" 1055 authSetupTestUser(cx) 1056 1057 if noPassword { 1058 if err := ctlV3User(cx, []string{"add", "example.com", "--no-password"}, "User example.com created", []string{""}); err != nil { 1059 cx.t.Fatal(err) 1060 } 1061 } else { 1062 if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil { 1063 cx.t.Fatal(err) 1064 } 1065 } 1066 if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role-cn"), "Role test-role-cn created"); err != nil { 1067 cx.t.Fatal(err) 1068 } 1069 if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role-cn"}, "Role test-role-cn is granted to user example.com", nil); err != nil { 1070 cx.t.Fatal(err) 1071 } 1072 1073 // grant a new key for CN based user 1074 if err := ctlV3RoleGrantPermission(cx, "test-role-cn", grantingPerm{true, true, "hoo", "", false}); err != nil { 1075 cx.t.Fatal(err) 1076 } 1077 1078 // grant a new key for username based user 1079 if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "bar", "", false}); err != nil { 1080 cx.t.Fatal(err) 1081 } 1082 1083 // try a granted key for CN based user 1084 cx.user, cx.pass = "", "" 1085 if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil { 1086 cx.t.Error(err) 1087 } 1088 1089 // try a granted key for username based user 1090 cx.user, cx.pass = "test-user", "pass" 1091 if err := ctlV3Put(cx, "bar", "bar", ""); err != nil { 1092 cx.t.Error(err) 1093 } 1094 1095 // try a non granted key for both of them 1096 cx.user, cx.pass = "", "" 1097 if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil { 1098 cx.t.Error(err) 1099 } 1100 1101 cx.user, cx.pass = "test-user", "pass" 1102 if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil { 1103 cx.t.Error(err) 1104 } 1105} 1106 1107func authTestCertCNAndUsername(cx ctlCtx) { 1108 certCNAndUsername(cx, false) 1109} 1110 1111func authTestCertCNAndUsernameNoPassword(cx ctlCtx) { 1112 certCNAndUsername(cx, true) 1113} 1114 1115func authTestJWTExpire(cx ctlCtx) { 1116 if err := authEnable(cx); err != nil { 1117 cx.t.Fatal(err) 1118 } 1119 1120 cx.user, cx.pass = "root", "root" 1121 authSetupTestUser(cx) 1122 1123 // try a granted key 1124 if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil { 1125 cx.t.Error(err) 1126 } 1127 1128 // wait an expiration of my JWT token 1129 <-time.After(3 * time.Second) 1130 1131 if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil { 1132 cx.t.Error(err) 1133 } 1134} 1135