1package consul 2 3import ( 4 "fmt" 5 "io/ioutil" 6 "net/rpc" 7 "os" 8 "path/filepath" 9 "strings" 10 "testing" 11 "time" 12 13 uuid "github.com/hashicorp/go-uuid" 14 msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc" 15 "github.com/stretchr/testify/require" 16 "gopkg.in/square/go-jose.v2/jwt" 17 18 "github.com/hashicorp/consul/acl" 19 "github.com/hashicorp/consul/agent/consul/authmethod/kubeauth" 20 "github.com/hashicorp/consul/agent/consul/authmethod/testauth" 21 "github.com/hashicorp/consul/agent/structs" 22 "github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest" 23 "github.com/hashicorp/consul/sdk/freeport" 24 "github.com/hashicorp/consul/sdk/testutil" 25 "github.com/hashicorp/consul/sdk/testutil/retry" 26) 27 28func TestACLEndpoint_Bootstrap(t *testing.T) { 29 if testing.Short() { 30 t.Skip("too slow for testing.Short") 31 } 32 33 t.Parallel() 34 _, srv, codec := testACLServerWithConfig(t, func(c *Config) { 35 c.Build = "0.8.0" // Too low for auto init of bootstrap. 36 c.ACLDatacenter = "dc1" 37 c.ACLsEnabled = true 38 // remove the default as we want to bootstrap 39 c.ACLMasterToken = "" 40 }, false) 41 waitForLeaderEstablishment(t, srv) 42 43 // Expect an error initially since ACL bootstrap is not initialized. 44 arg := structs.DCSpecificRequest{ 45 Datacenter: "dc1", 46 } 47 var out structs.ACL 48 // We can only do some high 49 // level checks on the ACL since we don't have control over the UUID or 50 // Raft indexes at this level. 51 err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", &arg, &out) 52 require.NoError(t, err) 53 require.Len(t, out.ID, len("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")) 54 require.True(t, strings.HasPrefix(out.Name, "Bootstrap Token")) 55 require.Equal(t, structs.ACLTokenTypeManagement, out.Type) 56 require.NotEqual(t, uint64(0), out.CreateIndex) 57 require.NotEqual(t, uint64(0), out.ModifyIndex) 58 59 // Finally, make sure that another attempt is rejected. 60 err = msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", &arg, &out) 61 testutil.RequireErrorContains(t, err, structs.ACLBootstrapNotAllowedErr.Error()) 62} 63 64func TestACLEndpoint_BootstrapTokens(t *testing.T) { 65 if testing.Short() { 66 t.Skip("too slow for testing.Short") 67 } 68 69 t.Parallel() 70 dir, srv, codec := testACLServerWithConfig(t, func(c *Config) { 71 // remove this as we are bootstrapping 72 c.ACLMasterToken = "" 73 }, false) 74 waitForLeaderEstablishment(t, srv) 75 76 // Expect an error initially since ACL bootstrap is not initialized. 77 arg := structs.DCSpecificRequest{ 78 Datacenter: "dc1", 79 } 80 var out structs.ACLToken 81 // We can only do some high 82 // level checks on the ACL since we don't have control over the UUID or 83 // Raft indexes at this level. 84 require.NoError(t, msgpackrpc.CallWithCodec(codec, "ACL.BootstrapTokens", &arg, &out)) 85 require.Equal(t, 36, len(out.AccessorID)) 86 require.True(t, strings.HasPrefix(out.Description, "Bootstrap Token")) 87 require.Equal(t, out.Type, structs.ACLTokenTypeManagement) 88 require.True(t, out.CreateIndex > 0) 89 require.Equal(t, out.CreateIndex, out.ModifyIndex) 90 91 // Finally, make sure that another attempt is rejected. 92 err := msgpackrpc.CallWithCodec(codec, "ACL.BootstrapTokens", &arg, &out) 93 require.Error(t, err) 94 require.True(t, strings.HasPrefix(err.Error(), structs.ACLBootstrapNotAllowedErr.Error())) 95 96 _, resetIdx, err := srv.fsm.State().CanBootstrapACLToken() 97 require.NoError(t, err) 98 99 resetPath := filepath.Join(dir, "acl-bootstrap-reset") 100 require.NoError(t, ioutil.WriteFile(resetPath, []byte(fmt.Sprintf("%d", resetIdx)), 0600)) 101 102 oldID := out.AccessorID 103 // Finally, make sure that another attempt is rejected. 104 require.NoError(t, msgpackrpc.CallWithCodec(codec, "ACL.BootstrapTokens", &arg, &out)) 105 require.Equal(t, 36, len(out.AccessorID)) 106 require.NotEqual(t, oldID, out.AccessorID) 107 require.True(t, strings.HasPrefix(out.Description, "Bootstrap Token")) 108 require.Equal(t, out.Type, structs.ACLTokenTypeManagement) 109 require.True(t, out.CreateIndex > 0) 110 require.Equal(t, out.CreateIndex, out.ModifyIndex) 111} 112 113func TestACLEndpoint_Apply(t *testing.T) { 114 if testing.Short() { 115 t.Skip("too slow for testing.Short") 116 } 117 118 t.Parallel() 119 _, srv, codec := testACLServerWithConfig(t, nil, false) 120 waitForLeaderEstablishment(t, srv) 121 122 arg := structs.ACLRequest{ 123 Datacenter: "dc1", 124 Op: structs.ACLSet, 125 ACL: structs.ACL{ 126 Name: "User token", 127 Type: structs.ACLTokenTypeClient, 128 }, 129 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 130 } 131 var out string 132 err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 133 require.NoError(t, err) 134 id := out 135 136 // Verify 137 state := srv.fsm.State() 138 _, s, err := state.ACLTokenGetBySecret(nil, out, nil) 139 require.NoError(t, err) 140 require.NotNil(t, s) 141 require.Equal(t, out, s.SecretID) 142 require.Equal(t, "User token", s.Description) 143 144 // Do a delete 145 arg.Op = structs.ACLDelete 146 arg.ACL.ID = out 147 err = msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 148 require.NoError(t, err) 149 150 // Verify 151 _, s, err = state.ACLTokenGetBySecret(nil, id, nil) 152 require.NoError(t, err) 153 require.Nil(t, s) 154} 155 156func TestACLEndpoint_Update_PurgeCache(t *testing.T) { 157 if testing.Short() { 158 t.Skip("too slow for testing.Short") 159 } 160 161 t.Parallel() 162 _, srv, codec := testACLServerWithConfig(t, nil, false) 163 waitForLeaderEstablishment(t, srv) 164 165 arg := structs.ACLRequest{ 166 Datacenter: "dc1", 167 Op: structs.ACLSet, 168 ACL: structs.ACL{ 169 Name: "User token", 170 Type: structs.ACLTokenTypeClient, 171 Rules: `key "" { policy = "read"}`, 172 }, 173 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 174 } 175 var out string 176 err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 177 require.NoError(t, err) 178 id := out 179 180 // Resolve 181 acl1, err := srv.ResolveToken(id) 182 require.NoError(t, err) 183 require.NotNil(t, acl1) 184 require.Equal(t, acl.Allow, acl1.KeyRead("foo", nil)) 185 186 // Do an update 187 arg.ACL.ID = out 188 arg.ACL.Rules = `{"key": {"": {"policy": "deny"}}}` 189 err = msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 190 require.NoError(t, err) 191 192 // Resolve again 193 acl2, err := srv.ResolveToken(id) 194 require.NoError(t, err) 195 require.NotNil(t, acl2) 196 require.NotSame(t, acl2, acl1) 197 require.NotEqual(t, acl.Allow, acl2.KeyRead("foo", nil)) 198 199 // Do a delete 200 arg.Op = structs.ACLDelete 201 arg.ACL.Rules = "" 202 err = msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 203 require.NoError(t, err) 204 205 // Resolve again 206 acl3, err := srv.ResolveToken(id) 207 require.True(t, acl.IsErrNotFound(err), "Error %v is not acl.ErrNotFound", err) 208 require.Nil(t, acl3) 209} 210 211func TestACLEndpoint_Apply_CustomID(t *testing.T) { 212 if testing.Short() { 213 t.Skip("too slow for testing.Short") 214 } 215 216 t.Parallel() 217 _, srv, codec := testACLServerWithConfig(t, nil, false) 218 waitForLeaderEstablishment(t, srv) 219 220 arg := structs.ACLRequest{ 221 Datacenter: "dc1", 222 Op: structs.ACLSet, 223 ACL: structs.ACL{ 224 ID: "foobarbaz", // Specify custom ID, does not exist 225 Name: "User token", 226 Type: structs.ACLTokenTypeClient, 227 }, 228 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 229 } 230 var out string 231 err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 232 require.NoError(t, err) 233 require.Equal(t, "foobarbaz", out) 234 235 // Verify 236 state := srv.fsm.State() 237 _, s, err := state.ACLTokenGetBySecret(nil, out, nil) 238 require.NoError(t, err) 239 require.NotNil(t, s) 240 require.Equal(t, out, s.SecretID) 241 require.Equal(t, "User token", s.Description) 242} 243 244func TestACLEndpoint_Apply_Denied(t *testing.T) { 245 if testing.Short() { 246 t.Skip("too slow for testing.Short") 247 } 248 249 t.Parallel() 250 _, srv, codec := testACLServerWithConfig(t, nil, false) 251 waitForLeaderEstablishment(t, srv) 252 253 arg := structs.ACLRequest{ 254 Datacenter: "dc1", 255 Op: structs.ACLSet, 256 ACL: structs.ACL{ 257 Name: "User token", 258 Type: structs.ACLTokenTypeClient, 259 }, 260 } 261 var out string 262 err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 263 require.True(t, acl.IsErrPermissionDenied(err), "Err %v is not acl.PermissionDenied", err) 264} 265 266func TestACLEndpoint_Apply_DeleteAnon(t *testing.T) { 267 if testing.Short() { 268 t.Skip("too slow for testing.Short") 269 } 270 271 t.Parallel() 272 _, srv, codec := testACLServerWithConfig(t, nil, false) 273 waitForLeaderEstablishment(t, srv) 274 275 arg := structs.ACLRequest{ 276 Datacenter: "dc1", 277 Op: structs.ACLDelete, 278 ACL: structs.ACL{ 279 ID: anonymousToken, 280 Name: "User token", 281 Type: structs.ACLTokenTypeClient, 282 }, 283 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 284 } 285 var out string 286 err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 287 testutil.RequireErrorContains(t, err, "delete anonymous") 288} 289 290func TestACLEndpoint_Apply_RootChange(t *testing.T) { 291 if testing.Short() { 292 t.Skip("too slow for testing.Short") 293 } 294 295 t.Parallel() 296 _, srv, codec := testACLServerWithConfig(t, nil, false) 297 waitForLeaderEstablishment(t, srv) 298 299 arg := structs.ACLRequest{ 300 Datacenter: "dc1", 301 Op: structs.ACLSet, 302 ACL: structs.ACL{ 303 ID: "manage", 304 Name: "User token", 305 Type: structs.ACLTokenTypeClient, 306 }, 307 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 308 } 309 var out string 310 err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 311 testutil.RequireErrorContains(t, err, "root ACL") 312} 313 314func TestACLEndpoint_Get(t *testing.T) { 315 if testing.Short() { 316 t.Skip("too slow for testing.Short") 317 } 318 319 t.Parallel() 320 _, srv, codec := testACLServerWithConfig(t, nil, false) 321 waitForLeaderEstablishment(t, srv) 322 323 arg := structs.ACLRequest{ 324 Datacenter: "dc1", 325 Op: structs.ACLSet, 326 ACL: structs.ACL{ 327 Name: "User token", 328 Type: structs.ACLTokenTypeClient, 329 }, 330 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 331 } 332 var out string 333 err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 334 require.NoError(t, err) 335 336 getR := structs.ACLSpecificRequest{ 337 Datacenter: "dc1", 338 ACL: out, 339 } 340 var acls structs.IndexedACLs 341 err = msgpackrpc.CallWithCodec(codec, "ACL.Get", &getR, &acls) 342 require.NoError(t, err) 343 require.NotEqual(t, uint64(0), acls.Index) 344 require.Len(t, acls.ACLs, 1) 345 require.Equal(t, out, acls.ACLs[0].ID) 346} 347 348func TestACLEndpoint_GetPolicy(t *testing.T) { 349 if testing.Short() { 350 t.Skip("too slow for testing.Short") 351 } 352 353 t.Parallel() 354 _, srv, codec := testACLServerWithConfig(t, nil, false) 355 waitForLeaderEstablishment(t, srv) 356 357 arg := structs.ACLRequest{ 358 Datacenter: "dc1", 359 Op: structs.ACLSet, 360 ACL: structs.ACL{ 361 Name: "User token", 362 Type: structs.ACLTokenTypeClient, 363 }, 364 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 365 } 366 var out string 367 err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 368 require.NoError(t, err) 369 370 getR := structs.ACLPolicyResolveLegacyRequest{ 371 Datacenter: "dc1", 372 ACL: out, 373 } 374 375 var acls structs.ACLPolicyResolveLegacyResponse 376 retry.Run(t, func(r *retry.R) { 377 err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", &getR, &acls) 378 379 require.NoError(r, err) 380 require.NotNil(t, acls.Policy) 381 require.Equal(t, 30*time.Second, acls.TTL) 382 }) 383 384 // Do a conditional lookup with etag 385 getR.ETag = acls.ETag 386 var out2 structs.ACLPolicyResolveLegacyResponse 387 require.NoError(t, msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", &getR, &out2)) 388 389 require.Nil(t, out2.Policy) 390 require.Equal(t, 30*time.Second, out2.TTL) 391} 392 393func TestACLEndpoint_GetPolicy_Management(t *testing.T) { 394 if testing.Short() { 395 t.Skip("too slow for testing.Short") 396 } 397 398 t.Parallel() 399 _, srv, codec := testACLServerWithConfig(t, nil, false) 400 401 // wait for leader election and leader establishment to finish. 402 // after this the global management policy, master token and 403 // anonymous token will have been injected into the state store 404 // and we will be ready to resolve the master token 405 waitForLeaderEstablishment(t, srv) 406 407 req := structs.ACLPolicyResolveLegacyRequest{ 408 Datacenter: srv.config.Datacenter, 409 ACL: TestDefaultMasterToken, 410 } 411 412 var resp structs.ACLPolicyResolveLegacyResponse 413 require.NoError(t, msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", &req, &resp)) 414 require.Equal(t, "manage", resp.Parent) 415} 416 417func TestACLEndpoint_List(t *testing.T) { 418 if testing.Short() { 419 t.Skip("too slow for testing.Short") 420 } 421 422 t.Parallel() 423 _, srv, codec := testACLServerWithConfig(t, nil, false) 424 waitForLeaderEstablishment(t, srv) 425 var expectedIDs []string 426 427 for i := 0; i < 5; i++ { 428 arg := structs.ACLRequest{ 429 Datacenter: "dc1", 430 Op: structs.ACLSet, 431 ACL: structs.ACL{ 432 Name: "User token", 433 Type: structs.ACLTokenTypeClient, 434 }, 435 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 436 } 437 var out string 438 err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out) 439 require.NoError(t, err) 440 expectedIDs = append(expectedIDs, out) 441 } 442 443 getR := structs.DCSpecificRequest{ 444 Datacenter: "dc1", 445 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 446 } 447 var acls structs.IndexedACLs 448 err := msgpackrpc.CallWithCodec(codec, "ACL.List", &getR, &acls) 449 require.NoError(t, err) 450 require.NotEqual(t, uint64(0), acls.Index) 451 452 // 5 + master 453 require.Len(t, acls.ACLs, 6) 454 var actualIDs []string 455 for i := 0; i < len(acls.ACLs); i++ { 456 s := acls.ACLs[i] 457 if s.ID == anonymousToken || s.ID == TestDefaultMasterToken { 458 continue 459 } 460 461 require.Equal(t, "User token", s.Name) 462 463 actualIDs = append(actualIDs, s.ID) 464 } 465 466 require.ElementsMatch(t, expectedIDs, actualIDs) 467} 468 469func TestACLEndpoint_List_Denied(t *testing.T) { 470 if testing.Short() { 471 t.Skip("too slow for testing.Short") 472 } 473 474 t.Parallel() 475 _, srv, codec := testACLServerWithConfig(t, nil, false) 476 waitForLeaderEstablishment(t, srv) 477 478 getR := structs.DCSpecificRequest{ 479 Datacenter: "dc1", 480 } 481 var acls structs.IndexedACLs 482 err := msgpackrpc.CallWithCodec(codec, "ACL.List", &getR, &acls) 483 require.True(t, acl.IsErrPermissionDenied(err), "Err %v is not an acl.ErrPermissionDenied", err) 484} 485 486func TestACLEndpoint_ReplicationStatus(t *testing.T) { 487 if testing.Short() { 488 t.Skip("too slow for testing.Short") 489 } 490 491 t.Parallel() 492 _, srv, codec := testACLServerWithConfig(t, func(c *Config) { 493 c.ACLDatacenter = "dc2" 494 c.ACLTokenReplication = true 495 c.ACLReplicationRate = 100 496 c.ACLReplicationBurst = 100 497 }, true) 498 waitForLeaderEstablishment(t, srv) 499 500 getR := structs.DCSpecificRequest{ 501 Datacenter: "dc1", 502 } 503 504 retry.Run(t, func(r *retry.R) { 505 var status structs.ACLReplicationStatus 506 err := msgpackrpc.CallWithCodec(codec, "ACL.ReplicationStatus", &getR, &status) 507 require.NoError(t, err) 508 509 require.True(r, status.Enabled) 510 require.True(r, status.Running) 511 require.Equal(r, "dc2", status.SourceDatacenter) 512 }) 513} 514 515func TestACLEndpoint_TokenRead(t *testing.T) { 516 if testing.Short() { 517 t.Skip("too slow for testing.Short") 518 } 519 520 t.Parallel() 521 _, srv, codec := testACLServerWithConfig(t, func(c *Config) { 522 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 523 c.ACLTokenMaxExpirationTTL = 5 * time.Second 524 }, false) 525 526 waitForLeaderEstablishment(t, srv) 527 528 acl := ACL{srv: srv} 529 530 t.Run("exists and matches what we created", func(t *testing.T) { 531 token, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil) 532 require.NoError(t, err) 533 534 req := structs.ACLTokenGetRequest{ 535 Datacenter: "dc1", 536 TokenID: token.AccessorID, 537 TokenIDType: structs.ACLTokenAccessor, 538 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 539 } 540 541 resp := structs.ACLTokenResponse{} 542 543 err = acl.TokenRead(&req, &resp) 544 require.NoError(t, err) 545 546 require.Equal(t, token, resp.Token) 547 }) 548 549 t.Run("expired tokens are filtered", func(t *testing.T) { 550 // insert a token that will expire 551 token, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(t *structs.ACLToken) { 552 t.ExpirationTTL = 200 * time.Millisecond 553 }) 554 require.NoError(t, err) 555 556 t.Run("readable until expiration", func(t *testing.T) { 557 req := structs.ACLTokenGetRequest{ 558 Datacenter: "dc1", 559 TokenID: token.AccessorID, 560 TokenIDType: structs.ACLTokenAccessor, 561 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 562 } 563 564 resp := structs.ACLTokenResponse{} 565 566 require.NoError(t, acl.TokenRead(&req, &resp)) 567 require.Equal(t, token, resp.Token) 568 }) 569 570 t.Run("not returned when expired", func(t *testing.T) { 571 req := structs.ACLTokenGetRequest{ 572 Datacenter: "dc1", 573 TokenID: token.AccessorID, 574 TokenIDType: structs.ACLTokenAccessor, 575 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 576 } 577 578 resp := structs.ACLTokenResponse{} 579 580 retry.Run(t, func(r *retry.R) { 581 require.NoError(r, acl.TokenRead(&req, &resp)) 582 require.Nil(r, resp.Token) 583 }) 584 }) 585 }) 586 587 t.Run("nil when token does not exist", func(t *testing.T) { 588 fakeID, err := uuid.GenerateUUID() 589 require.NoError(t, err) 590 591 req := structs.ACLTokenGetRequest{ 592 Datacenter: "dc1", 593 TokenID: fakeID, 594 TokenIDType: structs.ACLTokenAccessor, 595 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 596 } 597 598 resp := structs.ACLTokenResponse{} 599 600 err = acl.TokenRead(&req, &resp) 601 require.Nil(t, resp.Token) 602 require.NoError(t, err) 603 }) 604 605 t.Run("validates ID format", func(t *testing.T) { 606 req := structs.ACLTokenGetRequest{ 607 Datacenter: "dc1", 608 TokenID: "definitely-really-certainly-not-a-uuid", 609 TokenIDType: structs.ACLTokenAccessor, 610 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 611 } 612 613 resp := structs.ACLTokenResponse{} 614 615 err := acl.TokenRead(&req, &resp) 616 require.Nil(t, resp.Token) 617 require.EqualError(t, err, "failed acl token lookup: index error: UUID must be 36 characters") 618 }) 619} 620 621func TestACLEndpoint_TokenClone(t *testing.T) { 622 if testing.Short() { 623 t.Skip("too slow for testing.Short") 624 } 625 626 t.Parallel() 627 628 _, srv, codec := testACLServerWithConfig(t, func(c *Config) { 629 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 630 c.ACLTokenMaxExpirationTTL = 5 * time.Second 631 }, false) 632 waitForLeaderEstablishment(t, srv) 633 634 p1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 635 require.NoError(t, err) 636 637 r1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 638 require.NoError(t, err) 639 640 t1, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(t *structs.ACLToken) { 641 t.Policies = []structs.ACLTokenPolicyLink{ 642 {ID: p1.ID}, 643 } 644 t.Roles = []structs.ACLTokenRoleLink{ 645 {ID: r1.ID}, 646 } 647 t.ServiceIdentities = []*structs.ACLServiceIdentity{ 648 {ServiceName: "web"}, 649 } 650 t.NodeIdentities = []*structs.ACLNodeIdentity{ 651 {NodeName: "foo", Datacenter: "bar"}, 652 } 653 }) 654 require.NoError(t, err) 655 656 endpoint := ACL{srv: srv} 657 658 t.Run("normal", func(t *testing.T) { 659 req := structs.ACLTokenSetRequest{ 660 Datacenter: "dc1", 661 ACLToken: structs.ACLToken{AccessorID: t1.AccessorID}, 662 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 663 } 664 665 t2 := structs.ACLToken{} 666 667 err = endpoint.TokenClone(&req, &t2) 668 require.NoError(t, err) 669 670 require.Equal(t, t1.Description, t2.Description) 671 require.Equal(t, t1.Policies, t2.Policies) 672 require.Equal(t, t1.Roles, t2.Roles) 673 require.Equal(t, t1.ServiceIdentities, t2.ServiceIdentities) 674 require.Equal(t, t1.NodeIdentities, t2.NodeIdentities) 675 require.Equal(t, t1.Rules, t2.Rules) 676 require.Equal(t, t1.Local, t2.Local) 677 require.NotEqual(t, t1.AccessorID, t2.AccessorID) 678 require.NotEqual(t, t1.SecretID, t2.SecretID) 679 }) 680 681 t.Run("can't clone expired token", func(t *testing.T) { 682 // insert a token that will expire 683 t1, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(t *structs.ACLToken) { 684 t.ExpirationTTL = 11 * time.Millisecond 685 }) 686 require.NoError(t, err) 687 688 time.Sleep(30 * time.Millisecond) 689 690 req := structs.ACLTokenSetRequest{ 691 Datacenter: "dc1", 692 ACLToken: structs.ACLToken{AccessorID: t1.AccessorID}, 693 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 694 } 695 696 t2 := structs.ACLToken{} 697 698 err = endpoint.TokenClone(&req, &t2) 699 require.Error(t, err) 700 require.Equal(t, acl.ErrNotFound, err) 701 }) 702} 703 704func TestACLEndpoint_TokenSet(t *testing.T) { 705 if testing.Short() { 706 t.Skip("too slow for testing.Short") 707 } 708 709 t.Parallel() 710 711 _, srv, codec := testACLServerWithConfig(t, func(c *Config) { 712 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 713 c.ACLTokenMaxExpirationTTL = 5 * time.Second 714 }, false) 715 waitForLeaderEstablishment(t, srv) 716 717 acl := ACL{srv: srv} 718 719 var tokenID string 720 721 t.Run("Create it", func(t *testing.T) { 722 req := structs.ACLTokenSetRequest{ 723 Datacenter: "dc1", 724 ACLToken: structs.ACLToken{ 725 Description: "foobar", 726 Policies: nil, 727 Local: false, 728 NodeIdentities: []*structs.ACLNodeIdentity{ 729 { 730 NodeName: "foo", 731 Datacenter: "dc1", 732 }, 733 }, 734 }, 735 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 736 } 737 738 resp := structs.ACLToken{} 739 740 err := acl.TokenSet(&req, &resp) 741 require.NoError(t, err) 742 743 // Get the token directly to validate that it exists 744 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 745 require.NoError(t, err) 746 token := tokenResp.Token 747 748 require.NotNil(t, token) 749 require.NotNil(t, token.AccessorID) 750 require.Equal(t, token.Description, "foobar") 751 require.Equal(t, token.AccessorID, resp.AccessorID) 752 require.Len(t, token.NodeIdentities, 1) 753 require.Equal(t, "foo", token.NodeIdentities[0].NodeName) 754 require.Equal(t, "dc1", token.NodeIdentities[0].Datacenter) 755 756 tokenID = token.AccessorID 757 }) 758 759 t.Run("Update it", func(t *testing.T) { 760 req := structs.ACLTokenSetRequest{ 761 Datacenter: "dc1", 762 ACLToken: structs.ACLToken{ 763 Description: "new-description", 764 AccessorID: tokenID, 765 }, 766 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 767 } 768 769 resp := structs.ACLToken{} 770 771 err := acl.TokenSet(&req, &resp) 772 require.NoError(t, err) 773 774 // Get the token directly to validate that it exists 775 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 776 require.NoError(t, err) 777 token := tokenResp.Token 778 779 require.NotNil(t, token) 780 require.NotNil(t, token.AccessorID) 781 require.Equal(t, token.Description, "new-description") 782 require.Equal(t, token.AccessorID, resp.AccessorID) 783 require.Empty(t, token.NodeIdentities) 784 }) 785 786 t.Run("Create it using Policies linked by id and name", func(t *testing.T) { 787 policy1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 788 require.NoError(t, err) 789 policy2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 790 require.NoError(t, err) 791 792 req := structs.ACLTokenSetRequest{ 793 Datacenter: "dc1", 794 ACLToken: structs.ACLToken{ 795 Description: "foobar", 796 Policies: []structs.ACLTokenPolicyLink{ 797 { 798 ID: policy1.ID, 799 }, 800 { 801 Name: policy2.Name, 802 }, 803 }, 804 Local: false, 805 }, 806 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 807 } 808 809 resp := structs.ACLToken{} 810 811 err = acl.TokenSet(&req, &resp) 812 require.NoError(t, err) 813 814 // Delete both policies to ensure that we skip resolving ID->Name 815 // in the returned data. 816 require.NoError(t, deleteTestPolicy(codec, TestDefaultMasterToken, "dc1", policy1.ID)) 817 require.NoError(t, deleteTestPolicy(codec, TestDefaultMasterToken, "dc1", policy2.ID)) 818 819 // Get the token directly to validate that it exists 820 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 821 require.NoError(t, err) 822 token := tokenResp.Token 823 824 require.NotNil(t, token) 825 require.NotNil(t, token.AccessorID) 826 require.Equal(t, token.Description, "foobar") 827 require.Equal(t, token.AccessorID, resp.AccessorID) 828 829 require.Len(t, token.Policies, 0) 830 }) 831 832 t.Run("Create it using Roles linked by id and name", func(t *testing.T) { 833 role1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 834 require.NoError(t, err) 835 role2, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 836 require.NoError(t, err) 837 838 req := structs.ACLTokenSetRequest{ 839 Datacenter: "dc1", 840 ACLToken: structs.ACLToken{ 841 Description: "foobar", 842 Roles: []structs.ACLTokenRoleLink{ 843 { 844 ID: role1.ID, 845 }, 846 { 847 Name: role2.Name, 848 }, 849 }, 850 Local: false, 851 }, 852 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 853 } 854 855 resp := structs.ACLToken{} 856 857 err = acl.TokenSet(&req, &resp) 858 require.NoError(t, err) 859 860 // Delete both roles to ensure that we skip resolving ID->Name 861 // in the returned data. 862 require.NoError(t, deleteTestRole(codec, TestDefaultMasterToken, "dc1", role1.ID)) 863 require.NoError(t, deleteTestRole(codec, TestDefaultMasterToken, "dc1", role2.ID)) 864 865 // Get the token directly to validate that it exists 866 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 867 require.NoError(t, err) 868 token := tokenResp.Token 869 870 require.NotNil(t, token) 871 require.NotNil(t, token.AccessorID) 872 require.Equal(t, token.Description, "foobar") 873 require.Equal(t, token.AccessorID, resp.AccessorID) 874 875 require.Len(t, token.Roles, 0) 876 }) 877 878 t.Run("Create it with AuthMethod set outside of login", func(t *testing.T) { 879 req := structs.ACLTokenSetRequest{ 880 Datacenter: "dc1", 881 ACLToken: structs.ACLToken{ 882 Description: "foobar", 883 AuthMethod: "fakemethod", 884 }, 885 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 886 } 887 888 resp := structs.ACLToken{} 889 890 err := acl.TokenSet(&req, &resp) 891 testutil.RequireErrorContains(t, err, "AuthMethod field is disallowed outside of Login") 892 }) 893 894 t.Run("Update auth method linked token and try to change auth method", func(t *testing.T) { 895 acl := ACL{srv: srv} 896 897 testSessionID := testauth.StartSession() 898 defer testauth.ResetSession(testSessionID) 899 testauth.InstallSessionToken(testSessionID, "fake-token", "default", "demo", "abc123") 900 901 method1, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID) 902 require.NoError(t, err) 903 904 _, err = upsertTestBindingRule(codec, TestDefaultMasterToken, "dc1", method1.Name, "", structs.BindingRuleBindTypeService, "demo") 905 require.NoError(t, err) 906 907 // create a token in one method 908 methodToken := structs.ACLToken{} 909 require.NoError(t, acl.Login(&structs.ACLLoginRequest{ 910 Auth: &structs.ACLLoginParams{ 911 AuthMethod: method1.Name, 912 BearerToken: "fake-token", 913 }, 914 Datacenter: "dc1", 915 }, &methodToken)) 916 917 method2, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "") 918 require.NoError(t, err) 919 920 // try to update the token and change the method 921 req := structs.ACLTokenSetRequest{ 922 Datacenter: "dc1", 923 ACLToken: structs.ACLToken{ 924 AccessorID: methodToken.AccessorID, 925 SecretID: methodToken.SecretID, 926 AuthMethod: method2.Name, 927 Description: "updated token", 928 Local: true, 929 }, 930 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 931 } 932 933 resp := structs.ACLToken{} 934 935 err = acl.TokenSet(&req, &resp) 936 testutil.RequireErrorContains(t, err, "Cannot change AuthMethod") 937 }) 938 939 t.Run("Update auth method linked token and let the SecretID and AuthMethod be defaulted", func(t *testing.T) { 940 acl := ACL{srv: srv} 941 942 testSessionID := testauth.StartSession() 943 defer testauth.ResetSession(testSessionID) 944 testauth.InstallSessionToken(testSessionID, "fake-token", "default", "demo", "abc123") 945 946 method, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID) 947 require.NoError(t, err) 948 949 _, err = upsertTestBindingRule(codec, TestDefaultMasterToken, "dc1", method.Name, "", structs.BindingRuleBindTypeService, "demo") 950 require.NoError(t, err) 951 952 methodToken := structs.ACLToken{} 953 require.NoError(t, acl.Login(&structs.ACLLoginRequest{ 954 Auth: &structs.ACLLoginParams{ 955 AuthMethod: method.Name, 956 BearerToken: "fake-token", 957 }, 958 Datacenter: "dc1", 959 }, &methodToken)) 960 961 req := structs.ACLTokenSetRequest{ 962 Datacenter: "dc1", 963 ACLToken: structs.ACLToken{ 964 AccessorID: methodToken.AccessorID, 965 // SecretID: methodToken.SecretID, 966 // AuthMethod: method.Name, 967 Description: "updated token", 968 Local: true, 969 }, 970 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 971 } 972 973 resp := structs.ACLToken{} 974 975 require.NoError(t, acl.TokenSet(&req, &resp)) 976 977 // Get the token directly to validate that it exists 978 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 979 require.NoError(t, err) 980 token := tokenResp.Token 981 982 require.NotNil(t, token) 983 require.Len(t, token.Roles, 0) 984 require.Equal(t, "updated token", token.Description) 985 require.True(t, token.Local) 986 require.Equal(t, methodToken.SecretID, token.SecretID) 987 require.Equal(t, methodToken.AuthMethod, token.AuthMethod) 988 }) 989 990 t.Run("Create it with invalid service identity (empty)", func(t *testing.T) { 991 req := structs.ACLTokenSetRequest{ 992 Datacenter: "dc1", 993 ACLToken: structs.ACLToken{ 994 Description: "foobar", 995 Policies: nil, 996 Local: false, 997 ServiceIdentities: []*structs.ACLServiceIdentity{ 998 {ServiceName: ""}, 999 }, 1000 }, 1001 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1002 } 1003 1004 resp := structs.ACLToken{} 1005 1006 err := acl.TokenSet(&req, &resp) 1007 testutil.RequireErrorContains(t, err, "Service identity is missing the service name field") 1008 }) 1009 1010 t.Run("Create it with invalid service identity (too large)", func(t *testing.T) { 1011 long := strings.Repeat("x", serviceIdentityNameMaxLength+1) 1012 req := structs.ACLTokenSetRequest{ 1013 Datacenter: "dc1", 1014 ACLToken: structs.ACLToken{ 1015 Description: "foobar", 1016 Policies: nil, 1017 Local: false, 1018 ServiceIdentities: []*structs.ACLServiceIdentity{ 1019 {ServiceName: long}, 1020 }, 1021 }, 1022 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1023 } 1024 1025 resp := structs.ACLToken{} 1026 1027 err := acl.TokenSet(&req, &resp) 1028 require.NotNil(t, err) 1029 }) 1030 1031 for _, test := range []struct { 1032 name string 1033 ok bool 1034 }{ 1035 {"-abc", false}, 1036 {"abc-", false}, 1037 {"a-bc", true}, 1038 {"_abc", false}, 1039 {"abc_", false}, 1040 {"a_bc", true}, 1041 {":abc", false}, 1042 {"abc:", false}, 1043 {"a:bc", false}, 1044 {"Abc", false}, 1045 {"aBc", false}, 1046 {"abC", false}, 1047 {"0abc", true}, 1048 {"abc0", true}, 1049 {"a0bc", true}, 1050 } { 1051 var testName string 1052 if test.ok { 1053 testName = "Create it with valid service identity (by regex): " + test.name 1054 } else { 1055 testName = "Create it with invalid service identity (by regex): " + test.name 1056 } 1057 t.Run(testName, func(t *testing.T) { 1058 req := structs.ACLTokenSetRequest{ 1059 Datacenter: "dc1", 1060 ACLToken: structs.ACLToken{ 1061 Description: "foobar", 1062 Policies: nil, 1063 Local: false, 1064 ServiceIdentities: []*structs.ACLServiceIdentity{ 1065 {ServiceName: test.name}, 1066 }, 1067 }, 1068 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1069 } 1070 1071 resp := structs.ACLToken{} 1072 1073 err := acl.TokenSet(&req, &resp) 1074 if test.ok { 1075 require.NoError(t, err) 1076 1077 // Get the token directly to validate that it exists 1078 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 1079 require.NoError(t, err) 1080 token := tokenResp.Token 1081 require.NotNil(t, token) 1082 require.ElementsMatch(t, req.ACLToken.ServiceIdentities, token.ServiceIdentities) 1083 } else { 1084 require.NotNil(t, err) 1085 } 1086 }) 1087 } 1088 1089 t.Run("Create it with two of the same service identities", func(t *testing.T) { 1090 req := structs.ACLTokenSetRequest{ 1091 Datacenter: "dc1", 1092 ACLToken: structs.ACLToken{ 1093 Description: "foobar", 1094 Policies: nil, 1095 Local: false, 1096 ServiceIdentities: []*structs.ACLServiceIdentity{ 1097 {ServiceName: "example"}, 1098 {ServiceName: "example"}, 1099 }, 1100 }, 1101 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1102 } 1103 1104 resp := structs.ACLToken{} 1105 1106 err := acl.TokenSet(&req, &resp) 1107 require.NoError(t, err) 1108 1109 // Get the token directly to validate that it exists 1110 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 1111 require.NoError(t, err) 1112 token := tokenResp.Token 1113 require.NotNil(t, token) 1114 require.Len(t, token.ServiceIdentities, 1) 1115 }) 1116 1117 t.Run("Create it with two of the same service identities and different DCs", func(t *testing.T) { 1118 req := structs.ACLTokenSetRequest{ 1119 Datacenter: "dc1", 1120 ACLToken: structs.ACLToken{ 1121 Description: "foobar", 1122 Policies: nil, 1123 Local: false, 1124 ServiceIdentities: []*structs.ACLServiceIdentity{ 1125 { 1126 ServiceName: "example", 1127 Datacenters: []string{"dc2", "dc3"}, 1128 }, 1129 { 1130 ServiceName: "example", 1131 Datacenters: []string{"dc1", "dc2"}, 1132 }, 1133 }, 1134 }, 1135 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1136 } 1137 1138 resp := structs.ACLToken{} 1139 1140 err := acl.TokenSet(&req, &resp) 1141 require.NoError(t, err) 1142 1143 // Get the token directly to validate that it exists 1144 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 1145 require.NoError(t, err) 1146 token := tokenResp.Token 1147 require.NotNil(t, token) 1148 require.Len(t, token.ServiceIdentities, 1) 1149 svcid := token.ServiceIdentities[0] 1150 require.Equal(t, "example", svcid.ServiceName) 1151 require.ElementsMatch(t, []string{"dc1", "dc2", "dc3"}, svcid.Datacenters) 1152 }) 1153 1154 t.Run("Create it with invalid service identity (datacenters set on local token)", func(t *testing.T) { 1155 req := structs.ACLTokenSetRequest{ 1156 Datacenter: "dc1", 1157 ACLToken: structs.ACLToken{ 1158 Description: "foobar", 1159 Policies: nil, 1160 Local: true, 1161 ServiceIdentities: []*structs.ACLServiceIdentity{ 1162 {ServiceName: "foo", Datacenters: []string{"dc2"}}, 1163 }, 1164 }, 1165 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1166 } 1167 1168 resp := structs.ACLToken{} 1169 1170 err := acl.TokenSet(&req, &resp) 1171 testutil.RequireErrorContains(t, err, "cannot specify a list of datacenters on a local token") 1172 }) 1173 1174 for _, test := range []struct { 1175 name string 1176 offset time.Duration 1177 errString string 1178 errStringTTL string 1179 }{ 1180 {"before create time", -5 * time.Minute, "ExpirationTime cannot be before CreateTime", ""}, 1181 {"too soon", 1 * time.Millisecond, "ExpirationTime cannot be less than", "ExpirationTime cannot be less than"}, 1182 {"too distant", 25 * time.Hour, "ExpirationTime cannot be more than", "ExpirationTime cannot be more than"}, 1183 } { 1184 t.Run("Create it with an expiration time that is "+test.name, func(t *testing.T) { 1185 req := structs.ACLTokenSetRequest{ 1186 Datacenter: "dc1", 1187 ACLToken: structs.ACLToken{ 1188 Description: "foobar", 1189 Policies: nil, 1190 Local: false, 1191 ExpirationTime: timePointer(time.Now().Add(test.offset)), 1192 }, 1193 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1194 } 1195 1196 resp := structs.ACLToken{} 1197 1198 err := acl.TokenSet(&req, &resp) 1199 if test.errString != "" { 1200 testutil.RequireErrorContains(t, err, test.errString) 1201 } else { 1202 require.NotNil(t, err) 1203 } 1204 }) 1205 1206 t.Run("Create it with an expiration TTL that is "+test.name, func(t *testing.T) { 1207 req := structs.ACLTokenSetRequest{ 1208 Datacenter: "dc1", 1209 ACLToken: structs.ACLToken{ 1210 Description: "foobar", 1211 Policies: nil, 1212 Local: false, 1213 ExpirationTTL: test.offset, 1214 }, 1215 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1216 } 1217 1218 resp := structs.ACLToken{} 1219 1220 err := acl.TokenSet(&req, &resp) 1221 if test.errString != "" { 1222 testutil.RequireErrorContains(t, err, test.errStringTTL) 1223 } else { 1224 require.NotNil(t, err) 1225 } 1226 }) 1227 } 1228 1229 t.Run("Create it with expiration time AND expiration TTL set (error)", func(t *testing.T) { 1230 req := structs.ACLTokenSetRequest{ 1231 Datacenter: "dc1", 1232 ACLToken: structs.ACLToken{ 1233 Description: "foobar", 1234 Policies: nil, 1235 Local: false, 1236 ExpirationTime: timePointer(time.Now().Add(4 * time.Second)), 1237 ExpirationTTL: 4 * time.Second, 1238 }, 1239 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1240 } 1241 1242 resp := structs.ACLToken{} 1243 1244 err := acl.TokenSet(&req, &resp) 1245 testutil.RequireErrorContains(t, err, "Expiration TTL and Expiration Time cannot both be set") 1246 }) 1247 1248 t.Run("Create it with expiration time using TTLs", func(t *testing.T) { 1249 req := structs.ACLTokenSetRequest{ 1250 Datacenter: "dc1", 1251 ACLToken: structs.ACLToken{ 1252 Description: "foobar", 1253 Policies: nil, 1254 Local: false, 1255 ExpirationTTL: 4 * time.Second, 1256 }, 1257 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1258 } 1259 1260 resp := structs.ACLToken{} 1261 1262 err := acl.TokenSet(&req, &resp) 1263 require.NoError(t, err) 1264 1265 // Get the token directly to validate that it exists 1266 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 1267 require.NoError(t, err) 1268 token := tokenResp.Token 1269 1270 expectExpTime := resp.CreateTime.Add(4 * time.Second) 1271 1272 require.NotNil(t, token) 1273 require.NotNil(t, token.AccessorID) 1274 require.Equal(t, token.Description, "foobar") 1275 require.Equal(t, token.AccessorID, resp.AccessorID) 1276 requireTimeEquals(t, &expectExpTime, resp.ExpirationTime) 1277 1278 tokenID = token.AccessorID 1279 }) 1280 1281 var expTime time.Time 1282 t.Run("Create it with expiration time", func(t *testing.T) { 1283 expTime = time.Now().Add(4 * time.Second) 1284 req := structs.ACLTokenSetRequest{ 1285 Datacenter: "dc1", 1286 ACLToken: structs.ACLToken{ 1287 Description: "foobar", 1288 Policies: nil, 1289 Local: false, 1290 ExpirationTime: &expTime, 1291 }, 1292 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1293 } 1294 1295 resp := structs.ACLToken{} 1296 1297 err := acl.TokenSet(&req, &resp) 1298 require.NoError(t, err) 1299 1300 // Get the token directly to validate that it exists 1301 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 1302 require.NoError(t, err) 1303 token := tokenResp.Token 1304 1305 require.NotNil(t, token) 1306 require.NotNil(t, token.AccessorID) 1307 require.Equal(t, token.Description, "foobar") 1308 require.Equal(t, token.AccessorID, resp.AccessorID) 1309 requireTimeEquals(t, &expTime, resp.ExpirationTime) 1310 1311 tokenID = token.AccessorID 1312 }) 1313 1314 // do not insert another test at this point: these tests need to be serial 1315 1316 t.Run("Update expiration time is not allowed", func(t *testing.T) { 1317 req := structs.ACLTokenSetRequest{ 1318 Datacenter: "dc1", 1319 ACLToken: structs.ACLToken{ 1320 Description: "new-description", 1321 AccessorID: tokenID, 1322 ExpirationTime: timePointer(expTime.Add(-1 * time.Second)), 1323 }, 1324 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1325 } 1326 1327 resp := structs.ACLToken{} 1328 1329 err := acl.TokenSet(&req, &resp) 1330 testutil.RequireErrorContains(t, err, "Cannot change expiration time") 1331 }) 1332 1333 // do not insert another test at this point: these tests need to be serial 1334 1335 t.Run("Update anything except expiration time is ok - omit expiration time and let it default", func(t *testing.T) { 1336 req := structs.ACLTokenSetRequest{ 1337 Datacenter: "dc1", 1338 ACLToken: structs.ACLToken{ 1339 Description: "new-description-1", 1340 AccessorID: tokenID, 1341 }, 1342 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1343 } 1344 1345 resp := structs.ACLToken{} 1346 1347 err := acl.TokenSet(&req, &resp) 1348 require.NoError(t, err) 1349 1350 // Get the token directly to validate that it exists 1351 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 1352 require.NoError(t, err) 1353 token := tokenResp.Token 1354 1355 require.NotNil(t, token) 1356 require.NotNil(t, token.AccessorID) 1357 require.Equal(t, token.Description, "new-description-1") 1358 require.Equal(t, token.AccessorID, resp.AccessorID) 1359 requireTimeEquals(t, &expTime, resp.ExpirationTime) 1360 }) 1361 1362 t.Run("Update anything except expiration time is ok", func(t *testing.T) { 1363 req := structs.ACLTokenSetRequest{ 1364 Datacenter: "dc1", 1365 ACLToken: structs.ACLToken{ 1366 Description: "new-description-2", 1367 AccessorID: tokenID, 1368 ExpirationTime: &expTime, 1369 }, 1370 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1371 } 1372 1373 resp := structs.ACLToken{} 1374 1375 err := acl.TokenSet(&req, &resp) 1376 require.NoError(t, err) 1377 1378 // Get the token directly to validate that it exists 1379 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 1380 require.NoError(t, err) 1381 token := tokenResp.Token 1382 1383 require.NotNil(t, token) 1384 require.NotNil(t, token.AccessorID) 1385 require.Equal(t, token.Description, "new-description-2") 1386 require.Equal(t, token.AccessorID, resp.AccessorID) 1387 requireTimeEquals(t, &expTime, resp.ExpirationTime) 1388 }) 1389 1390 t.Run("cannot update a token that is past its expiration time", func(t *testing.T) { 1391 // create a token that will expire 1392 expiringToken, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) { 1393 token.ExpirationTTL = 11 * time.Millisecond 1394 }) 1395 require.NoError(t, err) 1396 1397 time.Sleep(20 * time.Millisecond) // now 'expiringToken' is expired 1398 1399 req := structs.ACLTokenSetRequest{ 1400 Datacenter: "dc1", 1401 ACLToken: structs.ACLToken{ 1402 Description: "new-description", 1403 AccessorID: expiringToken.AccessorID, 1404 ExpirationTTL: 4 * time.Second, 1405 }, 1406 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1407 } 1408 1409 resp := structs.ACLToken{} 1410 1411 err = acl.TokenSet(&req, &resp) 1412 testutil.RequireErrorContains(t, err, "Cannot find token") 1413 }) 1414 1415 t.Run("invalid node identity - no name", func(t *testing.T) { 1416 req := structs.ACLTokenSetRequest{ 1417 Datacenter: "dc1", 1418 ACLToken: structs.ACLToken{ 1419 NodeIdentities: []*structs.ACLNodeIdentity{ 1420 { 1421 Datacenter: "dc1", 1422 }, 1423 }, 1424 }, 1425 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1426 } 1427 1428 resp := structs.ACLToken{} 1429 1430 err := acl.TokenSet(&req, &resp) 1431 testutil.RequireErrorContains(t, err, "Node identity is missing the node name field on this token") 1432 }) 1433 1434 t.Run("invalid node identity - invalid name", func(t *testing.T) { 1435 req := structs.ACLTokenSetRequest{ 1436 Datacenter: "dc1", 1437 ACLToken: structs.ACLToken{ 1438 NodeIdentities: []*structs.ACLNodeIdentity{ 1439 { 1440 NodeName: "foo.bar", 1441 Datacenter: "dc1", 1442 }, 1443 }, 1444 }, 1445 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1446 } 1447 1448 resp := structs.ACLToken{} 1449 1450 err := acl.TokenSet(&req, &resp) 1451 testutil.RequireErrorContains(t, err, "Node identity has an invalid name.") 1452 }) 1453 t.Run("invalid node identity - no datacenter", func(t *testing.T) { 1454 req := structs.ACLTokenSetRequest{ 1455 Datacenter: "dc1", 1456 ACLToken: structs.ACLToken{ 1457 NodeIdentities: []*structs.ACLNodeIdentity{ 1458 { 1459 NodeName: "foo", 1460 }, 1461 }, 1462 }, 1463 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1464 } 1465 1466 resp := structs.ACLToken{} 1467 1468 err := acl.TokenSet(&req, &resp) 1469 testutil.RequireErrorContains(t, err, "Node identity is missing the datacenter field on this token") 1470 }) 1471} 1472 1473func TestACLEndpoint_TokenSet_CustomID(t *testing.T) { 1474 if testing.Short() { 1475 t.Skip("too slow for testing.Short") 1476 } 1477 1478 t.Parallel() 1479 1480 _, srv, codec := testACLServerWithConfig(t, nil, false) 1481 waitForLeaderEstablishment(t, srv) 1482 1483 acl := ACL{srv: srv} 1484 1485 // No Create Arg 1486 t.Run("no create arg", func(t *testing.T) { 1487 req := structs.ACLTokenSetRequest{ 1488 Datacenter: "dc1", 1489 ACLToken: structs.ACLToken{ 1490 AccessorID: "5d62a983-bcab-4e0c-9bcd-5dabebe3e273", 1491 SecretID: "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb", 1492 Description: "foobar", 1493 Policies: nil, 1494 Local: false, 1495 }, 1496 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1497 } 1498 1499 resp := structs.ACLToken{} 1500 1501 err := acl.TokenSet(&req, &resp) 1502 require.Error(t, err) 1503 }) 1504 1505 // Use the Create Arg 1506 t.Run("create arg", func(t *testing.T) { 1507 req := structs.ACLTokenSetRequest{ 1508 Datacenter: "dc1", 1509 ACLToken: structs.ACLToken{ 1510 AccessorID: "5d62a983-bcab-4e0c-9bcd-5dabebe3e273", 1511 SecretID: "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb", 1512 Description: "foobar", 1513 Policies: nil, 1514 Local: false, 1515 }, 1516 Create: true, 1517 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1518 } 1519 1520 resp := structs.ACLToken{} 1521 1522 err := acl.TokenSet(&req, &resp) 1523 require.NoError(t, err) 1524 1525 // Get the token directly to validate that it exists 1526 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID) 1527 require.NoError(t, err) 1528 token := tokenResp.Token 1529 1530 require.NotNil(t, token) 1531 require.Equal(t, req.ACLToken.AccessorID, token.AccessorID) 1532 require.Equal(t, req.ACLToken.SecretID, token.SecretID) 1533 require.Equal(t, token.Description, "foobar") 1534 }) 1535 1536 // Reserved AccessorID 1537 t.Run("reserved AccessorID", func(t *testing.T) { 1538 req := structs.ACLTokenSetRequest{ 1539 Datacenter: "dc1", 1540 ACLToken: structs.ACLToken{ 1541 AccessorID: "00000000-0000-0000-0000-000000000073", 1542 Description: "foobar", 1543 Policies: nil, 1544 Local: false, 1545 }, 1546 Create: true, 1547 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1548 } 1549 1550 resp := structs.ACLToken{} 1551 1552 err := acl.TokenSet(&req, &resp) 1553 require.Error(t, err) 1554 }) 1555 1556 // Reserved SecretID 1557 t.Run("reserved SecretID", func(t *testing.T) { 1558 req := structs.ACLTokenSetRequest{ 1559 Datacenter: "dc1", 1560 ACLToken: structs.ACLToken{ 1561 SecretID: "00000000-0000-0000-0000-000000000073", 1562 Description: "foobar", 1563 Policies: nil, 1564 Local: false, 1565 }, 1566 Create: true, 1567 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1568 } 1569 1570 resp := structs.ACLToken{} 1571 1572 err := acl.TokenSet(&req, &resp) 1573 require.Error(t, err) 1574 }) 1575 1576 // Accessor is dup 1577 t.Run("accessor Dup", func(t *testing.T) { 1578 req := structs.ACLTokenSetRequest{ 1579 Datacenter: "dc1", 1580 ACLToken: structs.ACLToken{ 1581 AccessorID: "5d62a983-bcab-4e0c-9bcd-5dabebe3e273", 1582 Description: "foobar", 1583 Policies: nil, 1584 Local: false, 1585 }, 1586 Create: true, 1587 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1588 } 1589 1590 resp := structs.ACLToken{} 1591 1592 err := acl.TokenSet(&req, &resp) 1593 require.Error(t, err) 1594 }) 1595 1596 // Accessor is dup of secret 1597 t.Run("accessor dup of secret", func(t *testing.T) { 1598 req := structs.ACLTokenSetRequest{ 1599 Datacenter: "dc1", 1600 ACLToken: structs.ACLToken{ 1601 AccessorID: "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb", 1602 Description: "foobar", 1603 Policies: nil, 1604 Local: false, 1605 }, 1606 Create: true, 1607 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1608 } 1609 1610 resp := structs.ACLToken{} 1611 1612 err := acl.TokenSet(&req, &resp) 1613 require.Error(t, err) 1614 }) 1615 1616 // Secret is dup of Accessor 1617 t.Run("secret dup of accessor", func(t *testing.T) { 1618 req := structs.ACLTokenSetRequest{ 1619 Datacenter: "dc1", 1620 ACLToken: structs.ACLToken{ 1621 SecretID: "5d62a983-bcab-4e0c-9bcd-5dabebe3e273", 1622 Description: "foobar", 1623 Policies: nil, 1624 Local: false, 1625 }, 1626 Create: true, 1627 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1628 } 1629 1630 resp := structs.ACLToken{} 1631 1632 err := acl.TokenSet(&req, &resp) 1633 require.Error(t, err) 1634 }) 1635 1636 // Secret is dup 1637 t.Run("secret dup", func(t *testing.T) { 1638 req := structs.ACLTokenSetRequest{ 1639 Datacenter: "dc1", 1640 ACLToken: structs.ACLToken{ 1641 SecretID: "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb", 1642 Description: "foobar", 1643 Policies: nil, 1644 Local: false, 1645 }, 1646 Create: true, 1647 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1648 } 1649 1650 resp := structs.ACLToken{} 1651 1652 err := acl.TokenSet(&req, &resp) 1653 require.Error(t, err) 1654 }) 1655 1656 // Update Accessor attempt 1657 t.Run("update accessor", func(t *testing.T) { 1658 req := structs.ACLTokenSetRequest{ 1659 Datacenter: "dc1", 1660 ACLToken: structs.ACLToken{ 1661 AccessorID: "75a0d6a9-6882-4f7a-a053-906db1d55a73", 1662 SecretID: "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb", 1663 Description: "foobar", 1664 Policies: nil, 1665 Local: false, 1666 }, 1667 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1668 } 1669 1670 resp := structs.ACLToken{} 1671 1672 err := acl.TokenSet(&req, &resp) 1673 require.Error(t, err) 1674 }) 1675 1676 // Update Accessor attempt - with Create 1677 t.Run("update accessor create", func(t *testing.T) { 1678 req := structs.ACLTokenSetRequest{ 1679 Datacenter: "dc1", 1680 ACLToken: structs.ACLToken{ 1681 AccessorID: "75a0d6a9-6882-4f7a-a053-906db1d55a73", 1682 SecretID: "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb", 1683 Description: "foobar", 1684 Policies: nil, 1685 Local: false, 1686 }, 1687 Create: true, 1688 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1689 } 1690 1691 resp := structs.ACLToken{} 1692 1693 err := acl.TokenSet(&req, &resp) 1694 require.Error(t, err) 1695 }) 1696 1697 // Update Secret attempt 1698 t.Run("update secret", func(t *testing.T) { 1699 req := structs.ACLTokenSetRequest{ 1700 Datacenter: "dc1", 1701 ACLToken: structs.ACLToken{ 1702 AccessorID: "5d62a983-bcab-4e0c-9bcd-5dabebe3e273", 1703 SecretID: "f551f807-b3a7-4483-9ade-97230c974bf3", 1704 Description: "foobar", 1705 Policies: nil, 1706 Local: false, 1707 }, 1708 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1709 } 1710 1711 resp := structs.ACLToken{} 1712 1713 err := acl.TokenSet(&req, &resp) 1714 require.Error(t, err) 1715 }) 1716 1717 // Update Secret attempt - with Create 1718 t.Run("update secret create", func(t *testing.T) { 1719 req := structs.ACLTokenSetRequest{ 1720 Datacenter: "dc1", 1721 ACLToken: structs.ACLToken{ 1722 AccessorID: "5d62a983-bcab-4e0c-9bcd-5dabebe3e273", 1723 SecretID: "f551f807-b3a7-4483-9ade-97230c974bf3", 1724 Description: "foobar", 1725 Policies: nil, 1726 Local: false, 1727 }, 1728 Create: true, 1729 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1730 } 1731 1732 resp := structs.ACLToken{} 1733 1734 err := acl.TokenSet(&req, &resp) 1735 require.Error(t, err) 1736 }) 1737} 1738 1739func TestACLEndpoint_TokenSet_anon(t *testing.T) { 1740 if testing.Short() { 1741 t.Skip("too slow for testing.Short") 1742 } 1743 1744 t.Parallel() 1745 1746 _, srv, codec := testACLServerWithConfig(t, nil, false) 1747 waitForLeaderEstablishment(t, srv) 1748 1749 policy, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 1750 require.NoError(t, err) 1751 1752 acl := ACL{srv: srv} 1753 1754 // Assign the policies to a token 1755 tokenUpsertReq := structs.ACLTokenSetRequest{ 1756 Datacenter: "dc1", 1757 ACLToken: structs.ACLToken{ 1758 AccessorID: structs.ACLTokenAnonymousID, 1759 Policies: []structs.ACLTokenPolicyLink{ 1760 { 1761 ID: policy.ID, 1762 }, 1763 }, 1764 }, 1765 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1766 } 1767 token := structs.ACLToken{} 1768 err = acl.TokenSet(&tokenUpsertReq, &token) 1769 require.NoError(t, err) 1770 require.NotEmpty(t, token.SecretID) 1771 1772 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", structs.ACLTokenAnonymousID) 1773 require.NoError(t, err) 1774 require.Equal(t, len(tokenResp.Token.Policies), 1) 1775 require.Equal(t, tokenResp.Token.Policies[0].ID, policy.ID) 1776 1777} 1778 1779func TestACLEndpoint_TokenDelete(t *testing.T) { 1780 if testing.Short() { 1781 t.Skip("too slow for testing.Short") 1782 } 1783 1784 t.Parallel() 1785 1786 _, s1, codec := testACLServerWithConfig(t, func(c *Config) { 1787 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 1788 c.ACLTokenMaxExpirationTTL = 5 * time.Second 1789 }, false) 1790 1791 _, s2, codec2 := testACLServerWithConfig(t, func(c *Config) { 1792 c.Datacenter = "dc2" 1793 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 1794 c.ACLTokenMaxExpirationTTL = 5 * time.Second 1795 // token replication is required to test deleting non-local tokens in secondary dc 1796 c.ACLTokenReplication = true 1797 }, true) 1798 1799 waitForLeaderEstablishment(t, s1) 1800 waitForLeaderEstablishment(t, s2) 1801 1802 // Try to join 1803 joinWAN(t, s2, s1) 1804 1805 waitForNewACLs(t, s1) 1806 waitForNewACLs(t, s2) 1807 1808 // Ensure s2 is authoritative. 1809 waitForNewACLReplication(t, s2, structs.ACLReplicateTokens, 1, 1, 0) 1810 1811 acl := ACL{srv: s1} 1812 acl2 := ACL{srv: s2} 1813 1814 existingToken, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil) 1815 require.NoError(t, err) 1816 1817 t.Run("deletes a token that has an expiration time in the future", func(t *testing.T) { 1818 // create a token that will expire 1819 testToken, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) { 1820 token.ExpirationTTL = 4 * time.Second 1821 }) 1822 require.NoError(t, err) 1823 1824 // Make sure the token is listable 1825 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", testToken.AccessorID) 1826 require.NoError(t, err) 1827 require.NotNil(t, tokenResp.Token) 1828 1829 // Now try to delete it (this should work). 1830 req := structs.ACLTokenDeleteRequest{ 1831 Datacenter: "dc1", 1832 TokenID: testToken.AccessorID, 1833 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1834 } 1835 1836 var resp string 1837 1838 err = acl.TokenDelete(&req, &resp) 1839 require.NoError(t, err) 1840 1841 // Make sure the token is gone 1842 tokenResp, err = retrieveTestToken(codec, TestDefaultMasterToken, "dc1", testToken.AccessorID) 1843 require.NoError(t, err) 1844 require.Nil(t, tokenResp.Token) 1845 }) 1846 1847 t.Run("deletes a token that is past its expiration time", func(t *testing.T) { 1848 // create a token that will expire 1849 expiringToken, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) { 1850 token.ExpirationTTL = 11 * time.Millisecond 1851 }) 1852 require.NoError(t, err) 1853 1854 time.Sleep(20 * time.Millisecond) // now 'expiringToken' is expired 1855 1856 // Make sure the token is not listable (filtered due to expiry) 1857 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", expiringToken.AccessorID) 1858 require.NoError(t, err) 1859 require.Nil(t, tokenResp.Token) 1860 1861 // Now try to delete it (this should work). 1862 req := structs.ACLTokenDeleteRequest{ 1863 Datacenter: "dc1", 1864 TokenID: expiringToken.AccessorID, 1865 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1866 } 1867 1868 var resp string 1869 1870 err = acl.TokenDelete(&req, &resp) 1871 require.NoError(t, err) 1872 1873 // Make sure the token is still gone (this time it's actually gone) 1874 tokenResp, err = retrieveTestToken(codec, TestDefaultMasterToken, "dc1", expiringToken.AccessorID) 1875 require.NoError(t, err) 1876 require.Nil(t, tokenResp.Token) 1877 }) 1878 1879 t.Run("deletes a token", func(t *testing.T) { 1880 req := structs.ACLTokenDeleteRequest{ 1881 Datacenter: "dc1", 1882 TokenID: existingToken.AccessorID, 1883 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1884 } 1885 1886 var resp string 1887 1888 err = acl.TokenDelete(&req, &resp) 1889 require.NoError(t, err) 1890 1891 // Make sure the token is gone 1892 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", existingToken.AccessorID) 1893 require.Nil(t, tokenResp.Token) 1894 require.NoError(t, err) 1895 }) 1896 1897 t.Run("can't delete itself", func(t *testing.T) { 1898 readReq := structs.ACLTokenGetRequest{ 1899 Datacenter: "dc1", 1900 TokenID: TestDefaultMasterToken, 1901 TokenIDType: structs.ACLTokenSecret, 1902 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 1903 } 1904 1905 var out structs.ACLTokenResponse 1906 1907 err := acl.TokenRead(&readReq, &out) 1908 1909 require.NoError(t, err) 1910 1911 req := structs.ACLTokenDeleteRequest{ 1912 Datacenter: "dc1", 1913 TokenID: out.Token.AccessorID, 1914 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1915 } 1916 1917 var resp string 1918 err = acl.TokenDelete(&req, &resp) 1919 require.EqualError(t, err, "Deletion of the request's authorization token is not permitted") 1920 }) 1921 1922 t.Run("errors when token doesn't exist", func(t *testing.T) { 1923 fakeID, err := uuid.GenerateUUID() 1924 require.NoError(t, err) 1925 1926 req := structs.ACLTokenDeleteRequest{ 1927 Datacenter: "dc1", 1928 TokenID: fakeID, 1929 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1930 } 1931 1932 var resp string 1933 1934 err = acl.TokenDelete(&req, &resp) 1935 require.NoError(t, err) 1936 1937 // token should be nil 1938 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", existingToken.AccessorID) 1939 require.Nil(t, tokenResp.Token) 1940 require.NoError(t, err) 1941 }) 1942 1943 t.Run("don't segfault when attempting to delete non existent token in secondary dc", func(t *testing.T) { 1944 fakeID, err := uuid.GenerateUUID() 1945 require.NoError(t, err) 1946 1947 req := structs.ACLTokenDeleteRequest{ 1948 Datacenter: "dc2", 1949 TokenID: fakeID, 1950 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1951 } 1952 1953 var resp string 1954 1955 err = acl2.TokenDelete(&req, &resp) 1956 require.NoError(t, err) 1957 1958 // token should be nil 1959 tokenResp, err := retrieveTestToken(codec2, TestDefaultMasterToken, "dc1", existingToken.AccessorID) 1960 require.Nil(t, tokenResp.Token) 1961 require.NoError(t, err) 1962 }) 1963} 1964 1965func TestACLEndpoint_TokenDelete_anon(t *testing.T) { 1966 if testing.Short() { 1967 t.Skip("too slow for testing.Short") 1968 } 1969 1970 t.Parallel() 1971 1972 _, srv, codec := testACLServerWithConfig(t, nil, false) 1973 waitForLeaderEstablishment(t, srv) 1974 1975 acl := ACL{srv: srv} 1976 1977 req := structs.ACLTokenDeleteRequest{ 1978 Datacenter: "dc1", 1979 TokenID: structs.ACLTokenAnonymousID, 1980 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 1981 } 1982 1983 var resp string 1984 1985 err := acl.TokenDelete(&req, &resp) 1986 require.EqualError(t, err, "Delete operation not permitted on the anonymous token") 1987 1988 // Make sure the token is still there 1989 tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", structs.ACLTokenAnonymousID) 1990 require.NoError(t, err) 1991 require.NotNil(t, tokenResp.Token) 1992} 1993 1994func TestACLEndpoint_TokenList(t *testing.T) { 1995 if testing.Short() { 1996 t.Skip("too slow for testing.Short") 1997 } 1998 1999 t.Parallel() 2000 2001 _, srv, codec := testACLServerWithConfig(t, func(c *Config) { 2002 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 2003 c.ACLTokenMaxExpirationTTL = 5 * time.Second 2004 }, false) 2005 waitForLeaderEstablishment(t, srv) 2006 2007 acl := ACL{srv: srv} 2008 2009 t1, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil) 2010 require.NoError(t, err) 2011 2012 t2, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil) 2013 require.NoError(t, err) 2014 2015 masterTokenAccessorID, err := retrieveTestTokenAccessorForSecret(codec, TestDefaultMasterToken, "dc1", TestDefaultMasterToken) 2016 require.NoError(t, err) 2017 2018 t.Run("normal", func(t *testing.T) { 2019 // this will still be racey even with inserting the token + ttl inside the test function 2020 // however previously inserting it outside of the subtest func resulted in this being 2021 // extra flakey due to there being more code that needed to run to setup the subtest 2022 // between when we inserted the token and when we performed the listing. 2023 t3, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) { 2024 token.ExpirationTTL = 50 * time.Millisecond 2025 }) 2026 require.NoError(t, err) 2027 2028 req := structs.ACLTokenListRequest{ 2029 Datacenter: "dc1", 2030 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2031 } 2032 2033 resp := structs.ACLTokenListResponse{} 2034 2035 err = acl.TokenList(&req, &resp) 2036 require.NoError(t, err) 2037 2038 tokens := []string{ 2039 masterTokenAccessorID, 2040 structs.ACLTokenAnonymousID, 2041 t1.AccessorID, 2042 t2.AccessorID, 2043 t3.AccessorID, 2044 } 2045 require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens) 2046 }) 2047 2048 time.Sleep(50 * time.Millisecond) // now 't3' is expired 2049 2050 t.Run("filter expired", func(t *testing.T) { 2051 req := structs.ACLTokenListRequest{ 2052 Datacenter: "dc1", 2053 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2054 } 2055 2056 resp := structs.ACLTokenListResponse{} 2057 2058 err = acl.TokenList(&req, &resp) 2059 require.NoError(t, err) 2060 2061 tokens := []string{ 2062 masterTokenAccessorID, 2063 structs.ACLTokenAnonymousID, 2064 t1.AccessorID, 2065 t2.AccessorID, 2066 } 2067 require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens) 2068 }) 2069 2070 t.Run("filter SecretID for acl:read", func(t *testing.T) { 2071 rules := ` 2072 acl = "read" 2073 ` 2074 readOnlyToken, err := upsertTestTokenWithPolicyRules(codec, TestDefaultMasterToken, "dc1", rules) 2075 require.NoError(t, err) 2076 2077 req := structs.ACLTokenListRequest{ 2078 Datacenter: "dc1", 2079 QueryOptions: structs.QueryOptions{Token: readOnlyToken.SecretID}, 2080 } 2081 2082 resp := structs.ACLTokenListResponse{} 2083 2084 err = acl.TokenList(&req, &resp) 2085 require.NoError(t, err) 2086 2087 tokens := []string{ 2088 masterTokenAccessorID, 2089 structs.ACLTokenAnonymousID, 2090 readOnlyToken.AccessorID, 2091 t1.AccessorID, 2092 t2.AccessorID, 2093 } 2094 require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens) 2095 for _, token := range resp.Tokens { 2096 require.Equal(t, redactedToken, token.SecretID) 2097 } 2098 }) 2099} 2100 2101func TestACLEndpoint_TokenBatchRead(t *testing.T) { 2102 if testing.Short() { 2103 t.Skip("too slow for testing.Short") 2104 } 2105 2106 t.Parallel() 2107 2108 _, srv, codec := testACLServerWithConfig(t, func(c *Config) { 2109 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 2110 c.ACLTokenMaxExpirationTTL = 5 * time.Second 2111 }, false) 2112 waitForLeaderEstablishment(t, srv) 2113 2114 acl := ACL{srv: srv} 2115 2116 t1, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil) 2117 require.NoError(t, err) 2118 2119 t2, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil) 2120 require.NoError(t, err) 2121 2122 t3, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) { 2123 token.ExpirationTTL = 4 * time.Second 2124 }) 2125 require.NoError(t, err) 2126 2127 t.Run("normal", func(t *testing.T) { 2128 tokens := []string{t1.AccessorID, t2.AccessorID, t3.AccessorID} 2129 2130 req := structs.ACLTokenBatchGetRequest{ 2131 Datacenter: "dc1", 2132 AccessorIDs: tokens, 2133 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2134 } 2135 2136 resp := structs.ACLTokenBatchResponse{} 2137 2138 err = acl.TokenBatchRead(&req, &resp) 2139 require.NoError(t, err) 2140 require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens) 2141 }) 2142 2143 time.Sleep(20 * time.Millisecond) // now 't3' is expired 2144 2145 t.Run("returns expired tokens", func(t *testing.T) { 2146 tokens := []string{t1.AccessorID, t2.AccessorID, t3.AccessorID} 2147 2148 req := structs.ACLTokenBatchGetRequest{ 2149 Datacenter: "dc1", 2150 AccessorIDs: tokens, 2151 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2152 } 2153 2154 resp := structs.ACLTokenBatchResponse{} 2155 2156 err = acl.TokenBatchRead(&req, &resp) 2157 require.NoError(t, err) 2158 require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens) 2159 }) 2160} 2161 2162func TestACLEndpoint_PolicyRead(t *testing.T) { 2163 if testing.Short() { 2164 t.Skip("too slow for testing.Short") 2165 } 2166 2167 t.Parallel() 2168 _, srv, codec := testACLServerWithConfig(t, nil, false) 2169 waitForLeaderEstablishment(t, srv) 2170 2171 policy, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2172 require.NoError(t, err) 2173 2174 acl := ACL{srv: srv} 2175 2176 req := structs.ACLPolicyGetRequest{ 2177 Datacenter: "dc1", 2178 PolicyID: policy.ID, 2179 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2180 } 2181 2182 resp := structs.ACLPolicyResponse{} 2183 2184 err = acl.PolicyRead(&req, &resp) 2185 require.NoError(t, err) 2186 require.Equal(t, policy, resp.Policy) 2187} 2188 2189func TestACLEndpoint_PolicyReadByName(t *testing.T) { 2190 if testing.Short() { 2191 t.Skip("too slow for testing.Short") 2192 } 2193 2194 t.Parallel() 2195 _, srv, codec := testACLServerWithConfig(t, nil, false) 2196 waitForLeaderEstablishment(t, srv) 2197 2198 policy, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2199 require.NoError(t, err) 2200 2201 acl := ACL{srv: srv} 2202 2203 req := structs.ACLPolicyGetRequest{ 2204 Datacenter: "dc1", 2205 PolicyName: policy.Name, 2206 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2207 } 2208 2209 resp := structs.ACLPolicyResponse{} 2210 2211 err = acl.PolicyRead(&req, &resp) 2212 require.NoError(t, err) 2213 require.Equal(t, policy, resp.Policy) 2214} 2215 2216func TestACLEndpoint_PolicyBatchRead(t *testing.T) { 2217 if testing.Short() { 2218 t.Skip("too slow for testing.Short") 2219 } 2220 2221 t.Parallel() 2222 2223 _, srv, codec := testACLServerWithConfig(t, nil, false) 2224 waitForLeaderEstablishment(t, srv) 2225 2226 p1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2227 require.NoError(t, err) 2228 2229 p2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2230 require.NoError(t, err) 2231 2232 acl := ACL{srv: srv} 2233 policies := []string{p1.ID, p2.ID} 2234 2235 req := structs.ACLPolicyBatchGetRequest{ 2236 Datacenter: "dc1", 2237 PolicyIDs: policies, 2238 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2239 } 2240 2241 resp := structs.ACLPolicyBatchResponse{} 2242 2243 err = acl.PolicyBatchRead(&req, &resp) 2244 require.NoError(t, err) 2245 require.ElementsMatch(t, gatherIDs(t, resp.Policies), []string{p1.ID, p2.ID}) 2246} 2247 2248func TestACLEndpoint_PolicySet(t *testing.T) { 2249 if testing.Short() { 2250 t.Skip("too slow for testing.Short") 2251 } 2252 2253 t.Parallel() 2254 2255 _, srv, codec := testACLServerWithConfig(t, nil, false) 2256 waitForLeaderEstablishment(t, srv) 2257 acl := ACL{srv: srv} 2258 2259 var policyID string 2260 2261 t.Run("Create it", func(t *testing.T) { 2262 req := structs.ACLPolicySetRequest{ 2263 Datacenter: "dc1", 2264 Policy: structs.ACLPolicy{ 2265 Description: "foobar", 2266 Name: "baz", 2267 Rules: "service \"\" { policy = \"read\" }", 2268 }, 2269 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2270 } 2271 resp := structs.ACLPolicy{} 2272 2273 err := acl.PolicySet(&req, &resp) 2274 require.NoError(t, err) 2275 require.NotNil(t, resp.ID) 2276 2277 // Get the policy directly to validate that it exists 2278 policyResp, err := retrieveTestPolicy(codec, TestDefaultMasterToken, "dc1", resp.ID) 2279 require.NoError(t, err) 2280 policy := policyResp.Policy 2281 2282 require.NotNil(t, policy.ID) 2283 require.Equal(t, policy.Description, "foobar") 2284 require.Equal(t, policy.Name, "baz") 2285 require.Equal(t, policy.Rules, "service \"\" { policy = \"read\" }") 2286 2287 policyID = policy.ID 2288 }) 2289 2290 t.Run("Name Dup", func(t *testing.T) { 2291 req := structs.ACLPolicySetRequest{ 2292 Datacenter: "dc1", 2293 Policy: structs.ACLPolicy{ 2294 Description: "foobar", 2295 Name: "baz", 2296 Rules: "service \"\" { policy = \"read\" }", 2297 }, 2298 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2299 } 2300 resp := structs.ACLPolicy{} 2301 2302 err := acl.PolicySet(&req, &resp) 2303 require.Error(t, err) 2304 }) 2305 2306 t.Run("Update it", func(t *testing.T) { 2307 req := structs.ACLPolicySetRequest{ 2308 Datacenter: "dc1", 2309 Policy: structs.ACLPolicy{ 2310 ID: policyID, 2311 Description: "bat", 2312 Name: "bar", 2313 Rules: "service \"\" { policy = \"write\" }", 2314 }, 2315 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2316 } 2317 resp := structs.ACLPolicy{} 2318 2319 err := acl.PolicySet(&req, &resp) 2320 require.NoError(t, err) 2321 require.NotNil(t, resp.ID) 2322 2323 // Get the policy directly to validate that it exists 2324 policyResp, err := retrieveTestPolicy(codec, TestDefaultMasterToken, "dc1", resp.ID) 2325 require.NoError(t, err) 2326 policy := policyResp.Policy 2327 2328 require.NotNil(t, policy.ID) 2329 require.Equal(t, policy.Description, "bat") 2330 require.Equal(t, policy.Name, "bar") 2331 require.Equal(t, policy.Rules, "service \"\" { policy = \"write\" }") 2332 }) 2333} 2334 2335func TestACLEndpoint_PolicySet_CustomID(t *testing.T) { 2336 if testing.Short() { 2337 t.Skip("too slow for testing.Short") 2338 } 2339 2340 t.Parallel() 2341 2342 _, srv, _ := testACLServerWithConfig(t, nil, false) 2343 waitForLeaderEstablishment(t, srv) 2344 2345 acl := ACL{srv: srv} 2346 2347 // Attempt to create policy with ID 2348 req := structs.ACLPolicySetRequest{ 2349 Datacenter: "dc1", 2350 Policy: structs.ACLPolicy{ 2351 ID: "7ee166a5-b4b7-453c-bdc0-bca8ce50823e", 2352 Description: "foobar", 2353 Name: "baz", 2354 Rules: "service \"\" { policy = \"read\" }", 2355 }, 2356 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2357 } 2358 resp := structs.ACLPolicy{} 2359 2360 err := acl.PolicySet(&req, &resp) 2361 require.Error(t, err) 2362} 2363 2364func TestACLEndpoint_PolicySet_globalManagement(t *testing.T) { 2365 if testing.Short() { 2366 t.Skip("too slow for testing.Short") 2367 } 2368 2369 t.Parallel() 2370 2371 _, srv, codec := testACLServerWithConfig(t, nil, false) 2372 waitForLeaderEstablishment(t, srv) 2373 2374 acl := ACL{srv: srv} 2375 2376 // Can't change the rules 2377 { 2378 req := structs.ACLPolicySetRequest{ 2379 Datacenter: "dc1", 2380 Policy: structs.ACLPolicy{ 2381 ID: structs.ACLPolicyGlobalManagementID, 2382 Name: "foobar", // This is required to get past validation 2383 Rules: "service \"\" { policy = \"write\" }", 2384 }, 2385 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2386 } 2387 resp := structs.ACLPolicy{} 2388 2389 err := acl.PolicySet(&req, &resp) 2390 require.EqualError(t, err, "Changing the Rules for the builtin global-management policy is not permitted") 2391 } 2392 2393 // Can rename it 2394 { 2395 req := structs.ACLPolicySetRequest{ 2396 Datacenter: "dc1", 2397 Policy: structs.ACLPolicy{ 2398 ID: structs.ACLPolicyGlobalManagementID, 2399 Name: "foobar", 2400 Rules: structs.ACLPolicyGlobalManagement, 2401 }, 2402 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2403 } 2404 resp := structs.ACLPolicy{} 2405 2406 err := acl.PolicySet(&req, &resp) 2407 require.NoError(t, err) 2408 2409 // Get the policy again 2410 policyResp, err := retrieveTestPolicy(codec, TestDefaultMasterToken, "dc1", structs.ACLPolicyGlobalManagementID) 2411 require.NoError(t, err) 2412 policy := policyResp.Policy 2413 2414 require.Equal(t, policy.ID, structs.ACLPolicyGlobalManagementID) 2415 require.Equal(t, policy.Name, "foobar") 2416 2417 } 2418} 2419 2420func TestACLEndpoint_PolicyDelete(t *testing.T) { 2421 if testing.Short() { 2422 t.Skip("too slow for testing.Short") 2423 } 2424 2425 t.Parallel() 2426 2427 _, srv, codec := testACLServerWithConfig(t, nil, false) 2428 waitForLeaderEstablishment(t, srv) 2429 2430 existingPolicy, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2431 require.NoError(t, err) 2432 2433 acl := ACL{srv: srv} 2434 2435 req := structs.ACLPolicyDeleteRequest{ 2436 Datacenter: "dc1", 2437 PolicyID: existingPolicy.ID, 2438 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2439 } 2440 2441 var resp string 2442 2443 err = acl.PolicyDelete(&req, &resp) 2444 require.NoError(t, err) 2445 2446 // Make sure the policy is gone 2447 tokenResp, err := retrieveTestPolicy(codec, TestDefaultMasterToken, "dc1", existingPolicy.ID) 2448 require.NoError(t, err) 2449 require.Nil(t, tokenResp.Policy) 2450} 2451 2452func TestACLEndpoint_PolicyDelete_globalManagement(t *testing.T) { 2453 if testing.Short() { 2454 t.Skip("too slow for testing.Short") 2455 } 2456 2457 t.Parallel() 2458 2459 _, srv, _ := testACLServerWithConfig(t, nil, false) 2460 waitForLeaderEstablishment(t, srv) 2461 acl := ACL{srv: srv} 2462 2463 req := structs.ACLPolicyDeleteRequest{ 2464 Datacenter: "dc1", 2465 PolicyID: structs.ACLPolicyGlobalManagementID, 2466 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2467 } 2468 var resp string 2469 2470 err := acl.PolicyDelete(&req, &resp) 2471 2472 require.EqualError(t, err, "Delete operation not permitted on the builtin global-management policy") 2473} 2474 2475func TestACLEndpoint_PolicyList(t *testing.T) { 2476 if testing.Short() { 2477 t.Skip("too slow for testing.Short") 2478 } 2479 2480 t.Parallel() 2481 2482 _, srv, codec := testACLServerWithConfig(t, nil, false) 2483 waitForLeaderEstablishment(t, srv) 2484 2485 p1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2486 require.NoError(t, err) 2487 2488 p2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2489 require.NoError(t, err) 2490 2491 acl := ACL{srv: srv} 2492 2493 req := structs.ACLPolicyListRequest{ 2494 Datacenter: "dc1", 2495 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2496 } 2497 2498 resp := structs.ACLPolicyListResponse{} 2499 2500 err = acl.PolicyList(&req, &resp) 2501 require.NoError(t, err) 2502 2503 policies := []string{ 2504 structs.ACLPolicyGlobalManagementID, 2505 p1.ID, 2506 p2.ID, 2507 } 2508 require.ElementsMatch(t, gatherIDs(t, resp.Policies), policies) 2509} 2510 2511func TestACLEndpoint_PolicyResolve(t *testing.T) { 2512 if testing.Short() { 2513 t.Skip("too slow for testing.Short") 2514 } 2515 2516 t.Parallel() 2517 2518 _, srv, codec := testACLServerWithConfig(t, nil, false) 2519 waitForLeaderEstablishment(t, srv) 2520 2521 p1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2522 require.NoError(t, err) 2523 2524 p2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2525 require.NoError(t, err) 2526 2527 acl := ACL{srv: srv} 2528 2529 policies := []string{p1.ID, p2.ID} 2530 2531 // Assign the policies to a token 2532 tokenUpsertReq := structs.ACLTokenSetRequest{ 2533 Datacenter: "dc1", 2534 ACLToken: structs.ACLToken{ 2535 Policies: []structs.ACLTokenPolicyLink{ 2536 { 2537 ID: p1.ID, 2538 }, 2539 { 2540 ID: p2.ID, 2541 }, 2542 }, 2543 }, 2544 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2545 } 2546 token := structs.ACLToken{} 2547 err = acl.TokenSet(&tokenUpsertReq, &token) 2548 require.NoError(t, err) 2549 require.NotEmpty(t, token.SecretID) 2550 2551 resp := structs.ACLPolicyBatchResponse{} 2552 req := structs.ACLPolicyBatchGetRequest{ 2553 Datacenter: "dc1", 2554 PolicyIDs: []string{p1.ID, p2.ID}, 2555 QueryOptions: structs.QueryOptions{Token: token.SecretID}, 2556 } 2557 err = acl.PolicyResolve(&req, &resp) 2558 require.NoError(t, err) 2559 require.ElementsMatch(t, gatherIDs(t, resp.Policies), policies) 2560} 2561 2562func TestACLEndpoint_RoleRead(t *testing.T) { 2563 if testing.Short() { 2564 t.Skip("too slow for testing.Short") 2565 } 2566 2567 t.Parallel() 2568 _, srv, codec := testACLServerWithConfig(t, nil, false) 2569 waitForLeaderEstablishment(t, srv) 2570 2571 role, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 2572 require.NoError(t, err) 2573 2574 acl := ACL{srv: srv} 2575 2576 req := structs.ACLRoleGetRequest{ 2577 Datacenter: "dc1", 2578 RoleID: role.ID, 2579 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2580 } 2581 2582 resp := structs.ACLRoleResponse{} 2583 2584 err = acl.RoleRead(&req, &resp) 2585 require.NoError(t, err) 2586 require.Equal(t, role, resp.Role) 2587} 2588 2589func TestACLEndpoint_RoleBatchRead(t *testing.T) { 2590 if testing.Short() { 2591 t.Skip("too slow for testing.Short") 2592 } 2593 2594 t.Parallel() 2595 2596 _, srv, codec := testACLServerWithConfig(t, nil, false) 2597 waitForLeaderEstablishment(t, srv) 2598 2599 r1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 2600 require.NoError(t, err) 2601 2602 r2, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 2603 require.NoError(t, err) 2604 2605 acl := ACL{srv: srv} 2606 roles := []string{r1.ID, r2.ID} 2607 2608 req := structs.ACLRoleBatchGetRequest{ 2609 Datacenter: "dc1", 2610 RoleIDs: roles, 2611 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 2612 } 2613 2614 resp := structs.ACLRoleBatchResponse{} 2615 2616 err = acl.RoleBatchRead(&req, &resp) 2617 require.NoError(t, err) 2618 require.ElementsMatch(t, gatherIDs(t, resp.Roles), roles) 2619} 2620 2621func TestACLEndpoint_RoleSet(t *testing.T) { 2622 if testing.Short() { 2623 t.Skip("too slow for testing.Short") 2624 } 2625 2626 t.Parallel() 2627 2628 _, srv, codec := testACLServerWithConfig(t, nil, false) 2629 waitForLeaderEstablishment(t, srv) 2630 2631 acl := ACL{srv: srv} 2632 var roleID string 2633 2634 testPolicy1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2635 require.NoError(t, err) 2636 testPolicy2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2637 require.NoError(t, err) 2638 2639 t.Run("Create it", func(t *testing.T) { 2640 req := structs.ACLRoleSetRequest{ 2641 Datacenter: "dc1", 2642 Role: structs.ACLRole{ 2643 Description: "foobar", 2644 Name: "baz", 2645 Policies: []structs.ACLRolePolicyLink{ 2646 { 2647 ID: testPolicy1.ID, 2648 }, 2649 }, 2650 NodeIdentities: []*structs.ACLNodeIdentity{ 2651 { 2652 NodeName: "foo", 2653 Datacenter: "bar", 2654 }, 2655 }, 2656 }, 2657 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2658 } 2659 resp := structs.ACLRole{} 2660 2661 err := acl.RoleSet(&req, &resp) 2662 require.NoError(t, err) 2663 require.NotNil(t, resp.ID) 2664 2665 // Get the role directly to validate that it exists 2666 roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID) 2667 require.NoError(t, err) 2668 role := roleResp.Role 2669 2670 require.NotNil(t, role.ID) 2671 require.Equal(t, role.Description, "foobar") 2672 require.Equal(t, role.Name, "baz") 2673 require.Len(t, role.Policies, 1) 2674 require.Equal(t, testPolicy1.ID, role.Policies[0].ID) 2675 require.Len(t, role.NodeIdentities, 1) 2676 require.Equal(t, "foo", role.NodeIdentities[0].NodeName) 2677 require.Equal(t, "bar", role.NodeIdentities[0].Datacenter) 2678 2679 roleID = role.ID 2680 }) 2681 2682 t.Run("Update it", func(t *testing.T) { 2683 req := structs.ACLRoleSetRequest{ 2684 Datacenter: "dc1", 2685 Role: structs.ACLRole{ 2686 ID: roleID, 2687 Description: "bat", 2688 Name: "bar", 2689 Policies: []structs.ACLRolePolicyLink{ 2690 { 2691 ID: testPolicy2.ID, 2692 }, 2693 }, 2694 }, 2695 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2696 } 2697 resp := structs.ACLRole{} 2698 2699 err := acl.RoleSet(&req, &resp) 2700 require.NoError(t, err) 2701 require.NotNil(t, resp.ID) 2702 2703 // Get the role directly to validate that it exists 2704 roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID) 2705 require.NoError(t, err) 2706 role := roleResp.Role 2707 2708 require.NotNil(t, role.ID) 2709 require.Equal(t, role.Description, "bat") 2710 require.Equal(t, role.Name, "bar") 2711 require.Len(t, role.Policies, 1) 2712 require.Equal(t, testPolicy2.ID, role.Policies[0].ID) 2713 require.Empty(t, role.NodeIdentities) 2714 }) 2715 2716 t.Run("Create it using Policies linked by id and name", func(t *testing.T) { 2717 policy1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2718 require.NoError(t, err) 2719 policy2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2720 require.NoError(t, err) 2721 2722 req := structs.ACLRoleSetRequest{ 2723 Datacenter: "dc1", 2724 Role: structs.ACLRole{ 2725 Description: "foobar", 2726 Name: "baz", 2727 Policies: []structs.ACLRolePolicyLink{ 2728 { 2729 ID: policy1.ID, 2730 }, 2731 { 2732 Name: policy2.Name, 2733 }, 2734 }, 2735 }, 2736 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2737 } 2738 resp := structs.ACLRole{} 2739 2740 err = acl.RoleSet(&req, &resp) 2741 require.NoError(t, err) 2742 require.NotNil(t, resp.ID) 2743 2744 // Delete both policies to ensure that we skip resolving ID->Name 2745 // in the returned data. 2746 require.NoError(t, deleteTestPolicy(codec, TestDefaultMasterToken, "dc1", policy1.ID)) 2747 require.NoError(t, deleteTestPolicy(codec, TestDefaultMasterToken, "dc1", policy2.ID)) 2748 2749 // Get the role directly to validate that it exists 2750 roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID) 2751 require.NoError(t, err) 2752 role := roleResp.Role 2753 2754 require.NotNil(t, role.ID) 2755 require.Equal(t, role.Description, "foobar") 2756 require.Equal(t, role.Name, "baz") 2757 2758 require.Len(t, role.Policies, 0) 2759 }) 2760 2761 roleNameGen := func(t *testing.T) string { 2762 t.Helper() 2763 name, err := uuid.GenerateUUID() 2764 require.NoError(t, err) 2765 return name 2766 } 2767 2768 t.Run("Create it with invalid service identity (empty)", func(t *testing.T) { 2769 req := structs.ACLRoleSetRequest{ 2770 Datacenter: "dc1", 2771 Role: structs.ACLRole{ 2772 Description: "foobar", 2773 Name: roleNameGen(t), 2774 ServiceIdentities: []*structs.ACLServiceIdentity{ 2775 {ServiceName: ""}, 2776 }, 2777 }, 2778 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2779 } 2780 resp := structs.ACLRole{} 2781 2782 err := acl.RoleSet(&req, &resp) 2783 testutil.RequireErrorContains(t, err, "Service identity is missing the service name field") 2784 }) 2785 2786 t.Run("Create it with invalid service identity (too large)", func(t *testing.T) { 2787 long := strings.Repeat("x", serviceIdentityNameMaxLength+1) 2788 req := structs.ACLRoleSetRequest{ 2789 Datacenter: "dc1", 2790 Role: structs.ACLRole{ 2791 Description: "foobar", 2792 Name: roleNameGen(t), 2793 ServiceIdentities: []*structs.ACLServiceIdentity{ 2794 {ServiceName: long}, 2795 }, 2796 }, 2797 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2798 } 2799 resp := structs.ACLRole{} 2800 2801 err := acl.RoleSet(&req, &resp) 2802 require.NotNil(t, err) 2803 }) 2804 2805 for _, test := range []struct { 2806 name string 2807 ok bool 2808 }{ 2809 {"-abc", false}, 2810 {"abc-", false}, 2811 {"a-bc", true}, 2812 {"_abc", false}, 2813 {"abc_", false}, 2814 {"a_bc", true}, 2815 {":abc", false}, 2816 {"abc:", false}, 2817 {"a:bc", false}, 2818 {"Abc", false}, 2819 {"aBc", false}, 2820 {"abC", false}, 2821 {"0abc", true}, 2822 {"abc0", true}, 2823 {"a0bc", true}, 2824 } { 2825 var testName string 2826 if test.ok { 2827 testName = "Create it with valid service identity (by regex): " + test.name 2828 } else { 2829 testName = "Create it with invalid service identity (by regex): " + test.name 2830 } 2831 t.Run(testName, func(t *testing.T) { 2832 req := structs.ACLRoleSetRequest{ 2833 Datacenter: "dc1", 2834 Role: structs.ACLRole{ 2835 Description: "foobar", 2836 Name: roleNameGen(t), 2837 ServiceIdentities: []*structs.ACLServiceIdentity{ 2838 {ServiceName: test.name}, 2839 }, 2840 }, 2841 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2842 } 2843 2844 resp := structs.ACLRole{} 2845 2846 err := acl.RoleSet(&req, &resp) 2847 if test.ok { 2848 require.NoError(t, err) 2849 2850 // Get the token directly to validate that it exists 2851 roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID) 2852 require.NoError(t, err) 2853 role := roleResp.Role 2854 require.ElementsMatch(t, req.Role.ServiceIdentities, role.ServiceIdentities) 2855 } else { 2856 require.NotNil(t, err) 2857 } 2858 }) 2859 } 2860 2861 t.Run("Create it with two of the same service identities", func(t *testing.T) { 2862 req := structs.ACLRoleSetRequest{ 2863 Datacenter: "dc1", 2864 Role: structs.ACLRole{ 2865 Description: "foobar", 2866 Name: roleNameGen(t), 2867 ServiceIdentities: []*structs.ACLServiceIdentity{ 2868 {ServiceName: "example"}, 2869 {ServiceName: "example"}, 2870 }, 2871 }, 2872 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2873 } 2874 2875 resp := structs.ACLRole{} 2876 2877 err := acl.RoleSet(&req, &resp) 2878 require.NoError(t, err) 2879 2880 // Get the role directly to validate that it exists 2881 roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID) 2882 require.NoError(t, err) 2883 role := roleResp.Role 2884 require.Len(t, role.ServiceIdentities, 1) 2885 }) 2886 2887 t.Run("Create it with two of the same service identities and different DCs", func(t *testing.T) { 2888 req := structs.ACLRoleSetRequest{ 2889 Datacenter: "dc1", 2890 Role: structs.ACLRole{ 2891 Description: "foobar", 2892 Name: roleNameGen(t), 2893 ServiceIdentities: []*structs.ACLServiceIdentity{ 2894 { 2895 ServiceName: "example", 2896 Datacenters: []string{"dc2", "dc3"}, 2897 }, 2898 { 2899 ServiceName: "example", 2900 Datacenters: []string{"dc1", "dc2"}, 2901 }, 2902 }, 2903 }, 2904 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2905 } 2906 2907 resp := structs.ACLRole{} 2908 2909 err := acl.RoleSet(&req, &resp) 2910 require.NoError(t, err) 2911 2912 // Get the role directly to validate that it exists 2913 roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID) 2914 require.NoError(t, err) 2915 role := roleResp.Role 2916 require.Len(t, role.ServiceIdentities, 1) 2917 svcid := role.ServiceIdentities[0] 2918 require.Equal(t, "example", svcid.ServiceName) 2919 require.ElementsMatch(t, []string{"dc1", "dc2", "dc3"}, svcid.Datacenters) 2920 }) 2921 2922 t.Run("invalid node identity - no name", func(t *testing.T) { 2923 req := structs.ACLRoleSetRequest{ 2924 Datacenter: "dc1", 2925 Role: structs.ACLRole{ 2926 Name: roleNameGen(t), 2927 NodeIdentities: []*structs.ACLNodeIdentity{ 2928 { 2929 Datacenter: "dc1", 2930 }, 2931 }, 2932 }, 2933 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2934 } 2935 2936 resp := structs.ACLRole{} 2937 2938 err := acl.RoleSet(&req, &resp) 2939 testutil.RequireErrorContains(t, err, "Node identity is missing the node name field on this role") 2940 }) 2941 2942 t.Run("invalid node identity - invalid name", func(t *testing.T) { 2943 req := structs.ACLRoleSetRequest{ 2944 Datacenter: "dc1", 2945 Role: structs.ACLRole{ 2946 Name: roleNameGen(t), 2947 NodeIdentities: []*structs.ACLNodeIdentity{ 2948 { 2949 NodeName: "foo.bar", 2950 Datacenter: "dc1", 2951 }, 2952 }, 2953 }, 2954 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2955 } 2956 2957 resp := structs.ACLRole{} 2958 2959 err := acl.RoleSet(&req, &resp) 2960 testutil.RequireErrorContains(t, err, "Node identity has an invalid name.") 2961 }) 2962 t.Run("invalid node identity - no datacenter", func(t *testing.T) { 2963 req := structs.ACLRoleSetRequest{ 2964 Datacenter: "dc1", 2965 Role: structs.ACLRole{ 2966 Name: roleNameGen(t), 2967 NodeIdentities: []*structs.ACLNodeIdentity{ 2968 { 2969 NodeName: "foo", 2970 }, 2971 }, 2972 }, 2973 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 2974 } 2975 2976 resp := structs.ACLRole{} 2977 2978 err := acl.RoleSet(&req, &resp) 2979 testutil.RequireErrorContains(t, err, "Node identity is missing the datacenter field on this role") 2980 }) 2981} 2982 2983func TestACLEndpoint_RoleSet_names(t *testing.T) { 2984 if testing.Short() { 2985 t.Skip("too slow for testing.Short") 2986 } 2987 2988 t.Parallel() 2989 2990 _, srv, codec := testACLServerWithConfig(t, nil, false) 2991 waitForLeaderEstablishment(t, srv) 2992 2993 acl := ACL{srv: srv} 2994 testPolicy1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1") 2995 2996 require.NoError(t, err) 2997 2998 for _, test := range []struct { 2999 name string 3000 ok bool 3001 }{ 3002 {"", false}, 3003 {"-bad", true}, 3004 {"bad-", true}, 3005 {"bad?bad", false}, 3006 {strings.Repeat("x", 257), false}, 3007 {strings.Repeat("x", 256), true}, 3008 {"-abc", true}, 3009 {"abc-", true}, 3010 {"a-bc", true}, 3011 {"_abc", true}, 3012 {"abc_", true}, 3013 {"a_bc", true}, 3014 {":abc", false}, 3015 {"abc:", false}, 3016 {"a:bc", false}, 3017 {"Abc", true}, 3018 {"aBc", true}, 3019 {"abC", true}, 3020 {"0abc", true}, 3021 {"abc0", true}, 3022 {"a0bc", true}, 3023 } { 3024 var testName string 3025 if test.ok { 3026 testName = "create with valid name: " + test.name 3027 } else { 3028 testName = "create with invalid name: " + test.name 3029 } 3030 3031 t.Run(testName, func(t *testing.T) { 3032 // cleanup from a prior insertion that may have succeeded 3033 require.NoError(t, deleteTestRoleByName(codec, TestDefaultMasterToken, "dc1", test.name)) 3034 3035 req := structs.ACLRoleSetRequest{ 3036 Datacenter: "dc1", 3037 Role: structs.ACLRole{ 3038 Name: test.name, 3039 Description: "foobar", 3040 Policies: []structs.ACLRolePolicyLink{ 3041 { 3042 ID: testPolicy1.ID, 3043 }, 3044 }, 3045 }, 3046 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3047 } 3048 resp := structs.ACLRole{} 3049 3050 err := acl.RoleSet(&req, &resp) 3051 if test.ok { 3052 require.NoError(t, err) 3053 3054 roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID) 3055 require.NoError(t, err) 3056 role := roleResp.Role 3057 require.Equal(t, test.name, role.Name) 3058 } else { 3059 require.Error(t, err) 3060 } 3061 }) 3062 } 3063} 3064 3065func TestACLEndpoint_RoleDelete(t *testing.T) { 3066 if testing.Short() { 3067 t.Skip("too slow for testing.Short") 3068 } 3069 3070 t.Parallel() 3071 3072 _, srv, codec := testACLServerWithConfig(t, nil, false) 3073 waitForLeaderEstablishment(t, srv) 3074 existingRole, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 3075 3076 require.NoError(t, err) 3077 3078 acl := ACL{srv: srv} 3079 3080 req := structs.ACLRoleDeleteRequest{ 3081 Datacenter: "dc1", 3082 RoleID: existingRole.ID, 3083 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3084 } 3085 3086 var resp string 3087 3088 err = acl.RoleDelete(&req, &resp) 3089 require.NoError(t, err) 3090 3091 // Make sure the role is gone 3092 roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", existingRole.ID) 3093 require.NoError(t, err) 3094 require.Nil(t, roleResp.Role) 3095} 3096 3097func TestACLEndpoint_RoleList(t *testing.T) { 3098 if testing.Short() { 3099 t.Skip("too slow for testing.Short") 3100 } 3101 3102 t.Parallel() 3103 3104 _, srv, codec := testACLServerWithConfig(t, nil, false) 3105 waitForLeaderEstablishment(t, srv) 3106 3107 r1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 3108 require.NoError(t, err) 3109 3110 r2, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 3111 require.NoError(t, err) 3112 3113 acl := ACL{srv: srv} 3114 3115 req := structs.ACLRoleListRequest{ 3116 Datacenter: "dc1", 3117 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 3118 } 3119 3120 resp := structs.ACLRoleListResponse{} 3121 3122 err = acl.RoleList(&req, &resp) 3123 require.NoError(t, err) 3124 require.ElementsMatch(t, gatherIDs(t, resp.Roles), []string{r1.ID, r2.ID}) 3125} 3126 3127func TestACLEndpoint_RoleResolve(t *testing.T) { 3128 if testing.Short() { 3129 t.Skip("too slow for testing.Short") 3130 } 3131 3132 t.Parallel() 3133 3134 _, srv, codec := testACLServerWithConfig(t, nil, false) 3135 waitForLeaderEstablishment(t, srv) 3136 3137 t.Run("Normal", func(t *testing.T) { 3138 r1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 3139 require.NoError(t, err) 3140 3141 r2, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") 3142 require.NoError(t, err) 3143 3144 acl := ACL{srv: srv} 3145 3146 // Assign the roles to a token 3147 tokenUpsertReq := structs.ACLTokenSetRequest{ 3148 Datacenter: "dc1", 3149 ACLToken: structs.ACLToken{ 3150 Roles: []structs.ACLTokenRoleLink{ 3151 { 3152 ID: r1.ID, 3153 }, 3154 { 3155 ID: r2.ID, 3156 }, 3157 }, 3158 }, 3159 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3160 } 3161 token := structs.ACLToken{} 3162 err = acl.TokenSet(&tokenUpsertReq, &token) 3163 require.NoError(t, err) 3164 require.NotEmpty(t, token.SecretID) 3165 3166 resp := structs.ACLRoleBatchResponse{} 3167 req := structs.ACLRoleBatchGetRequest{ 3168 Datacenter: "dc1", 3169 RoleIDs: []string{r1.ID, r2.ID}, 3170 QueryOptions: structs.QueryOptions{Token: token.SecretID}, 3171 } 3172 err = acl.RoleResolve(&req, &resp) 3173 require.NoError(t, err) 3174 require.ElementsMatch(t, gatherIDs(t, resp.Roles), []string{r1.ID, r2.ID}) 3175 }) 3176} 3177 3178func TestACLEndpoint_AuthMethodSet(t *testing.T) { 3179 if testing.Short() { 3180 t.Skip("too slow for testing.Short") 3181 } 3182 3183 t.Parallel() 3184 3185 tempDir, err := ioutil.TempDir("", "consul") 3186 require.NoError(t, err) 3187 t.Cleanup(func() { os.RemoveAll(tempDir) }) 3188 _, srv, codec := testACLServerWithConfig(t, nil, false) 3189 3190 waitForLeaderEstablishment(t, srv) 3191 3192 acl := ACL{srv: srv} 3193 3194 newAuthMethod := func(name string) structs.ACLAuthMethod { 3195 return structs.ACLAuthMethod{ 3196 Name: name, 3197 Description: "test", 3198 Type: "testing", 3199 } 3200 } 3201 3202 t.Run("Create", func(t *testing.T) { 3203 reqMethod := newAuthMethod("test") 3204 3205 req := structs.ACLAuthMethodSetRequest{ 3206 Datacenter: "dc1", 3207 AuthMethod: reqMethod, 3208 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3209 } 3210 resp := structs.ACLAuthMethod{} 3211 3212 err := acl.AuthMethodSet(&req, &resp) 3213 require.NoError(t, err) 3214 3215 // Get the method directly to validate that it exists 3216 methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name) 3217 require.NoError(t, err) 3218 method := methodResp.AuthMethod 3219 3220 require.Equal(t, method.Name, "test") 3221 require.Equal(t, method.Description, "test") 3222 require.Equal(t, method.Type, "testing") 3223 }) 3224 3225 t.Run("Update fails; not allowed to change types", func(t *testing.T) { 3226 reqMethod := newAuthMethod("test") 3227 reqMethod.Type = "invalid" 3228 3229 req := structs.ACLAuthMethodSetRequest{ 3230 Datacenter: "dc1", 3231 AuthMethod: reqMethod, 3232 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3233 } 3234 resp := structs.ACLAuthMethod{} 3235 3236 err := acl.AuthMethodSet(&req, &resp) 3237 require.Error(t, err) 3238 }) 3239 3240 t.Run("Update - allow type to default", func(t *testing.T) { 3241 reqMethod := newAuthMethod("test") 3242 reqMethod.DisplayName = "updated display name 1" 3243 reqMethod.Description = "test modified 1" 3244 reqMethod.Type = "" // unset 3245 3246 req := structs.ACLAuthMethodSetRequest{ 3247 Datacenter: "dc1", 3248 AuthMethod: reqMethod, 3249 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3250 } 3251 resp := structs.ACLAuthMethod{} 3252 3253 err := acl.AuthMethodSet(&req, &resp) 3254 require.NoError(t, err) 3255 3256 // Get the method directly to validate that it exists 3257 methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name) 3258 require.NoError(t, err) 3259 method := methodResp.AuthMethod 3260 3261 require.Equal(t, method.Name, "test") 3262 require.Equal(t, method.DisplayName, "updated display name 1") 3263 require.Equal(t, method.Description, "test modified 1") 3264 require.Equal(t, method.Type, "testing") 3265 }) 3266 3267 t.Run("Update - specify type", func(t *testing.T) { 3268 reqMethod := newAuthMethod("test") 3269 reqMethod.DisplayName = "updated display name 2" 3270 reqMethod.Description = "test modified 2" 3271 3272 req := structs.ACLAuthMethodSetRequest{ 3273 Datacenter: "dc1", 3274 AuthMethod: reqMethod, 3275 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3276 } 3277 resp := structs.ACLAuthMethod{} 3278 3279 err := acl.AuthMethodSet(&req, &resp) 3280 require.NoError(t, err) 3281 3282 // Get the method directly to validate that it exists 3283 methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name) 3284 require.NoError(t, err) 3285 method := methodResp.AuthMethod 3286 3287 require.Equal(t, method.Name, "test") 3288 require.Equal(t, method.DisplayName, "updated display name 2") 3289 require.Equal(t, method.Description, "test modified 2") 3290 require.Equal(t, method.Type, "testing") 3291 }) 3292 3293 t.Run("Create with no name", func(t *testing.T) { 3294 req := structs.ACLAuthMethodSetRequest{ 3295 Datacenter: "dc1", 3296 AuthMethod: newAuthMethod(""), 3297 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3298 } 3299 resp := structs.ACLAuthMethod{} 3300 3301 err := acl.AuthMethodSet(&req, &resp) 3302 require.Error(t, err) 3303 }) 3304 3305 t.Run("Create with invalid type", func(t *testing.T) { 3306 req := structs.ACLAuthMethodSetRequest{ 3307 Datacenter: "dc1", 3308 AuthMethod: structs.ACLAuthMethod{ 3309 Name: "invalid", 3310 Description: "invalid test", 3311 Type: "invalid", 3312 }, 3313 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3314 } 3315 resp := structs.ACLAuthMethod{} 3316 3317 err := acl.AuthMethodSet(&req, &resp) 3318 require.Error(t, err) 3319 }) 3320 3321 for _, test := range []struct { 3322 name string 3323 ok bool 3324 }{ 3325 {strings.Repeat("x", 129), false}, 3326 {strings.Repeat("x", 128), true}, 3327 {"-abc", true}, 3328 {"abc-", true}, 3329 {"a-bc", true}, 3330 {"_abc", true}, 3331 {"abc_", true}, 3332 {"a_bc", true}, 3333 {":abc", false}, 3334 {"abc:", false}, 3335 {"a:bc", false}, 3336 {"Abc", true}, 3337 {"aBc", true}, 3338 {"abC", true}, 3339 {"0abc", true}, 3340 {"abc0", true}, 3341 {"a0bc", true}, 3342 } { 3343 var testName string 3344 if test.ok { 3345 testName = "Create with valid name (by regex): " + test.name 3346 } else { 3347 testName = "Create with invalid name (by regex): " + test.name 3348 } 3349 t.Run(testName, func(t *testing.T) { 3350 req := structs.ACLAuthMethodSetRequest{ 3351 Datacenter: "dc1", 3352 AuthMethod: newAuthMethod(test.name), 3353 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3354 } 3355 resp := structs.ACLAuthMethod{} 3356 3357 err := acl.AuthMethodSet(&req, &resp) 3358 3359 if test.ok { 3360 require.NoError(t, err) 3361 3362 // Get the method directly to validate that it exists 3363 methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name) 3364 require.NoError(t, err) 3365 method := methodResp.AuthMethod 3366 3367 require.Equal(t, method.Name, test.name) 3368 require.Equal(t, method.Type, "testing") 3369 } else { 3370 require.Error(t, err) 3371 } 3372 }) 3373 } 3374 3375 t.Run("Create with MaxTokenTTL", func(t *testing.T) { 3376 reqMethod := newAuthMethod("test") 3377 reqMethod.MaxTokenTTL = 5 * time.Minute 3378 3379 req := structs.ACLAuthMethodSetRequest{ 3380 Datacenter: "dc1", 3381 AuthMethod: reqMethod, 3382 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3383 } 3384 resp := structs.ACLAuthMethod{} 3385 3386 err := acl.AuthMethodSet(&req, &resp) 3387 require.NoError(t, err) 3388 3389 // Get the method directly to validate that it exists 3390 methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name) 3391 require.NoError(t, err) 3392 method := methodResp.AuthMethod 3393 3394 require.Equal(t, method.Name, "test") 3395 require.Equal(t, method.Description, "test") 3396 require.Equal(t, method.Type, "testing") 3397 require.Equal(t, method.MaxTokenTTL, 5*time.Minute) 3398 }) 3399 3400 t.Run("Update - change MaxTokenTTL", func(t *testing.T) { 3401 reqMethod := newAuthMethod("test") 3402 reqMethod.DisplayName = "updated display name 2" 3403 reqMethod.Description = "test modified 2" 3404 reqMethod.MaxTokenTTL = 8 * time.Minute 3405 3406 req := structs.ACLAuthMethodSetRequest{ 3407 Datacenter: "dc1", 3408 AuthMethod: reqMethod, 3409 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3410 } 3411 resp := structs.ACLAuthMethod{} 3412 3413 err := acl.AuthMethodSet(&req, &resp) 3414 require.NoError(t, err) 3415 3416 // Get the method directly to validate that it exists 3417 methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name) 3418 require.NoError(t, err) 3419 method := methodResp.AuthMethod 3420 3421 require.Equal(t, method.Name, "test") 3422 require.Equal(t, method.DisplayName, "updated display name 2") 3423 require.Equal(t, method.Description, "test modified 2") 3424 require.Equal(t, method.Type, "testing") 3425 require.Equal(t, method.MaxTokenTTL, 8*time.Minute) 3426 }) 3427 3428 t.Run("Create with MaxTokenTTL too small", func(t *testing.T) { 3429 reqMethod := newAuthMethod("test") 3430 reqMethod.MaxTokenTTL = 1 * time.Millisecond 3431 3432 req := structs.ACLAuthMethodSetRequest{ 3433 Datacenter: "dc1", 3434 AuthMethod: reqMethod, 3435 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3436 } 3437 resp := structs.ACLAuthMethod{} 3438 3439 err := acl.AuthMethodSet(&req, &resp) 3440 testutil.RequireErrorContains(t, err, "MaxTokenTTL 1ms cannot be less than") 3441 }) 3442 3443 t.Run("Create with MaxTokenTTL too big", func(t *testing.T) { 3444 reqMethod := newAuthMethod("test") 3445 reqMethod.MaxTokenTTL = 25 * time.Hour 3446 3447 req := structs.ACLAuthMethodSetRequest{ 3448 Datacenter: "dc1", 3449 AuthMethod: reqMethod, 3450 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3451 } 3452 resp := structs.ACLAuthMethod{} 3453 3454 err := acl.AuthMethodSet(&req, &resp) 3455 testutil.RequireErrorContains(t, err, "MaxTokenTTL 25h0m0s cannot be more than") 3456 }) 3457} 3458 3459func TestACLEndpoint_AuthMethodDelete(t *testing.T) { 3460 if testing.Short() { 3461 t.Skip("too slow for testing.Short") 3462 } 3463 3464 t.Parallel() 3465 3466 _, srv, codec := testACLServerWithConfig(t, nil, false) 3467 waitForLeaderEstablishment(t, srv) 3468 3469 testSessionID := testauth.StartSession() 3470 defer testauth.ResetSession(testSessionID) 3471 3472 existingMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID) 3473 require.NoError(t, err) 3474 3475 acl := ACL{srv: srv} 3476 3477 t.Run("normal", func(t *testing.T) { 3478 req := structs.ACLAuthMethodDeleteRequest{ 3479 Datacenter: "dc1", 3480 AuthMethodName: existingMethod.Name, 3481 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3482 } 3483 3484 var ignored bool 3485 err = acl.AuthMethodDelete(&req, &ignored) 3486 require.NoError(t, err) 3487 3488 // Make sure the method is gone 3489 methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", existingMethod.Name) 3490 require.NoError(t, err) 3491 require.Nil(t, methodResp.AuthMethod) 3492 }) 3493 3494 t.Run("delete something that doesn't exist", func(t *testing.T) { 3495 req := structs.ACLAuthMethodDeleteRequest{ 3496 Datacenter: "dc1", 3497 AuthMethodName: "missing", 3498 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3499 } 3500 3501 var ignored bool 3502 err = acl.AuthMethodDelete(&req, &ignored) 3503 require.NoError(t, err) 3504 }) 3505} 3506 3507// Deleting an auth method atomically deletes all rules and tokens as well. 3508func TestACLEndpoint_AuthMethodDelete_RuleAndTokenCascade(t *testing.T) { 3509 if testing.Short() { 3510 t.Skip("too slow for testing.Short") 3511 } 3512 3513 t.Parallel() 3514 3515 _, srv, codec := testACLServerWithConfig(t, nil, false) 3516 waitForLeaderEstablishment(t, srv) 3517 3518 testSessionID1 := testauth.StartSession() 3519 defer testauth.ResetSession(testSessionID1) 3520 testauth.InstallSessionToken(testSessionID1, "fake-token1", "default", "abc", "abc123") 3521 3522 testSessionID2 := testauth.StartSession() 3523 defer testauth.ResetSession(testSessionID2) 3524 testauth.InstallSessionToken(testSessionID2, "fake-token2", "default", "abc", "abc123") 3525 3526 createToken := func(methodName, bearerToken string) *structs.ACLToken { 3527 acl := ACL{srv: srv} 3528 3529 resp := structs.ACLToken{} 3530 3531 require.NoError(t, acl.Login(&structs.ACLLoginRequest{ 3532 Auth: &structs.ACLLoginParams{ 3533 AuthMethod: methodName, 3534 BearerToken: bearerToken, 3535 }, 3536 Datacenter: "dc1", 3537 }, &resp)) 3538 3539 return &resp 3540 } 3541 3542 method1, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID1) 3543 require.NoError(t, err) 3544 i1_r1, err := upsertTestBindingRule( 3545 codec, TestDefaultMasterToken, "dc1", 3546 method1.Name, 3547 "serviceaccount.name==abc", 3548 structs.BindingRuleBindTypeService, 3549 "abc", 3550 ) 3551 require.NoError(t, err) 3552 i1_r2, err := upsertTestBindingRule( 3553 codec, TestDefaultMasterToken, "dc1", 3554 method1.Name, 3555 "serviceaccount.name==def", 3556 structs.BindingRuleBindTypeService, 3557 "def", 3558 ) 3559 require.NoError(t, err) 3560 i1_t1 := createToken(method1.Name, "fake-token1") 3561 i1_t2 := createToken(method1.Name, "fake-token1") 3562 3563 method2, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID2) 3564 require.NoError(t, err) 3565 i2_r1, err := upsertTestBindingRule( 3566 codec, TestDefaultMasterToken, "dc1", 3567 method2.Name, 3568 "serviceaccount.name==abc", 3569 structs.BindingRuleBindTypeService, 3570 "abc", 3571 ) 3572 require.NoError(t, err) 3573 i2_r2, err := upsertTestBindingRule( 3574 codec, TestDefaultMasterToken, "dc1", 3575 method2.Name, 3576 "serviceaccount.name==def", 3577 structs.BindingRuleBindTypeService, 3578 "def", 3579 ) 3580 require.NoError(t, err) 3581 i2_t1 := createToken(method2.Name, "fake-token2") 3582 i2_t2 := createToken(method2.Name, "fake-token2") 3583 3584 acl := ACL{srv: srv} 3585 3586 req := structs.ACLAuthMethodDeleteRequest{ 3587 Datacenter: "dc1", 3588 AuthMethodName: method1.Name, 3589 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3590 } 3591 3592 var ignored bool 3593 err = acl.AuthMethodDelete(&req, &ignored) 3594 require.NoError(t, err) 3595 3596 // Make sure the method is gone. 3597 methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", method1.Name) 3598 require.NoError(t, err) 3599 require.Nil(t, methodResp.AuthMethod) 3600 3601 // Make sure the rules and tokens are gone. 3602 for _, id := range []string{i1_r1.ID, i1_r2.ID} { 3603 ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", id) 3604 require.NoError(t, err) 3605 require.Nil(t, ruleResp.BindingRule) 3606 } 3607 for _, id := range []string{i1_t1.AccessorID, i1_t2.AccessorID} { 3608 tokResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", id) 3609 require.NoError(t, err) 3610 require.Nil(t, tokResp.Token) 3611 } 3612 3613 // Make sure the rules and tokens for the untouched auth method are still there. 3614 for _, id := range []string{i2_r1.ID, i2_r2.ID} { 3615 ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", id) 3616 require.NoError(t, err) 3617 require.NotNil(t, ruleResp.BindingRule) 3618 } 3619 for _, id := range []string{i2_t1.AccessorID, i2_t2.AccessorID} { 3620 tokResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", id) 3621 require.NoError(t, err) 3622 require.NotNil(t, tokResp.Token) 3623 } 3624} 3625 3626func TestACLEndpoint_AuthMethodList(t *testing.T) { 3627 if testing.Short() { 3628 t.Skip("too slow for testing.Short") 3629 } 3630 3631 t.Parallel() 3632 3633 _, srv, codec := testACLServerWithConfig(t, nil, false) 3634 waitForLeaderEstablishment(t, srv) 3635 3636 i1, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "") 3637 require.NoError(t, err) 3638 3639 i2, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "") 3640 require.NoError(t, err) 3641 3642 acl := ACL{srv: srv} 3643 3644 req := structs.ACLAuthMethodListRequest{ 3645 Datacenter: "dc1", 3646 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 3647 } 3648 3649 resp := structs.ACLAuthMethodListResponse{} 3650 3651 err = acl.AuthMethodList(&req, &resp) 3652 require.NoError(t, err) 3653 require.ElementsMatch(t, gatherIDs(t, resp.AuthMethods), []string{i1.Name, i2.Name}) 3654} 3655 3656func TestACLEndpoint_BindingRuleSet(t *testing.T) { 3657 if testing.Short() { 3658 t.Skip("too slow for testing.Short") 3659 } 3660 3661 t.Parallel() 3662 3663 _, srv, codec := testACLServerWithConfig(t, nil, false) 3664 waitForLeaderEstablishment(t, srv) 3665 acl := ACL{srv: srv} 3666 3667 var ruleID string 3668 3669 testAuthMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "") 3670 require.NoError(t, err) 3671 3672 otherTestAuthMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "") 3673 require.NoError(t, err) 3674 3675 newRule := func() structs.ACLBindingRule { 3676 return structs.ACLBindingRule{ 3677 Description: "foobar", 3678 AuthMethod: testAuthMethod.Name, 3679 Selector: "serviceaccount.name==abc", 3680 BindType: structs.BindingRuleBindTypeService, 3681 BindName: "abc", 3682 } 3683 } 3684 3685 requireSetErrors := func(t *testing.T, reqRule structs.ACLBindingRule) { 3686 req := structs.ACLBindingRuleSetRequest{ 3687 Datacenter: "dc1", 3688 BindingRule: reqRule, 3689 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3690 } 3691 resp := structs.ACLBindingRule{} 3692 3693 err := acl.BindingRuleSet(&req, &resp) 3694 require.Error(t, err) 3695 } 3696 3697 requireOK := func(t *testing.T, reqRule structs.ACLBindingRule) *structs.ACLBindingRule { 3698 req := structs.ACLBindingRuleSetRequest{ 3699 Datacenter: "dc1", 3700 BindingRule: reqRule, 3701 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3702 } 3703 resp := structs.ACLBindingRule{} 3704 3705 err := acl.BindingRuleSet(&req, &resp) 3706 require.NoError(t, err) 3707 require.NotEmpty(t, resp.ID) 3708 return &resp 3709 } 3710 3711 t.Run("Create it", func(t *testing.T) { 3712 reqRule := newRule() 3713 3714 req := structs.ACLBindingRuleSetRequest{ 3715 Datacenter: "dc1", 3716 BindingRule: reqRule, 3717 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3718 } 3719 resp := structs.ACLBindingRule{} 3720 3721 err := acl.BindingRuleSet(&req, &resp) 3722 require.NoError(t, err) 3723 require.NotNil(t, resp.ID) 3724 3725 // Get the rule directly to validate that it exists 3726 ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", resp.ID) 3727 require.NoError(t, err) 3728 rule := ruleResp.BindingRule 3729 3730 require.NotEmpty(t, rule.ID) 3731 require.Equal(t, rule.Description, "foobar") 3732 require.Equal(t, rule.AuthMethod, testAuthMethod.Name) 3733 require.Equal(t, "serviceaccount.name==abc", rule.Selector) 3734 require.Equal(t, structs.BindingRuleBindTypeService, rule.BindType) 3735 require.Equal(t, "abc", rule.BindName) 3736 3737 ruleID = rule.ID 3738 }) 3739 3740 t.Run("Bind Node", func(t *testing.T) { 3741 req := structs.ACLBindingRuleSetRequest{ 3742 Datacenter: "dc1", 3743 BindingRule: structs.ACLBindingRule{ 3744 Description: "foobar", 3745 AuthMethod: testAuthMethod.Name, 3746 Selector: "serviceaccount.name==abc", 3747 BindType: structs.BindingRuleBindTypeNode, 3748 BindName: "test-node", 3749 }, 3750 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3751 } 3752 var resp structs.ACLBindingRule 3753 3754 err := acl.BindingRuleSet(&req, &resp) 3755 require.NoError(t, err) 3756 require.NotNil(t, resp.ID) 3757 3758 // Get the rule directly to validate that it exists 3759 ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", resp.ID) 3760 require.NoError(t, err) 3761 rule := ruleResp.BindingRule 3762 3763 require.NotEmpty(t, rule.ID) 3764 require.Equal(t, rule.Description, "foobar") 3765 require.Equal(t, rule.AuthMethod, testAuthMethod.Name) 3766 require.Equal(t, "serviceaccount.name==abc", rule.Selector) 3767 require.Equal(t, structs.BindingRuleBindTypeNode, rule.BindType) 3768 require.Equal(t, "test-node", rule.BindName) 3769 }) 3770 3771 t.Run("Update fails; cannot change method name", func(t *testing.T) { 3772 reqRule := newRule() 3773 reqRule.ID = ruleID 3774 reqRule.AuthMethod = otherTestAuthMethod.Name 3775 requireSetErrors(t, reqRule) 3776 }) 3777 3778 t.Run("Update it - omit method name", func(t *testing.T) { 3779 reqRule := newRule() 3780 reqRule.ID = ruleID 3781 reqRule.Description = "foobar modified 1" 3782 reqRule.Selector = "serviceaccount.namespace==def" 3783 reqRule.BindType = structs.BindingRuleBindTypeRole 3784 reqRule.BindName = "def" 3785 reqRule.AuthMethod = "" // clear 3786 3787 req := structs.ACLBindingRuleSetRequest{ 3788 Datacenter: "dc1", 3789 BindingRule: reqRule, 3790 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3791 } 3792 resp := structs.ACLBindingRule{} 3793 3794 err := acl.BindingRuleSet(&req, &resp) 3795 require.NoError(t, err) 3796 require.NotNil(t, resp.ID) 3797 3798 // Get the rule directly to validate that it exists 3799 ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", resp.ID) 3800 require.NoError(t, err) 3801 rule := ruleResp.BindingRule 3802 3803 require.NotEmpty(t, rule.ID) 3804 require.Equal(t, rule.Description, "foobar modified 1") 3805 require.Equal(t, rule.AuthMethod, testAuthMethod.Name) 3806 require.Equal(t, "serviceaccount.namespace==def", rule.Selector) 3807 require.Equal(t, structs.BindingRuleBindTypeRole, rule.BindType) 3808 require.Equal(t, "def", rule.BindName) 3809 }) 3810 3811 t.Run("Update it - specify method name", func(t *testing.T) { 3812 reqRule := newRule() 3813 reqRule.ID = ruleID 3814 reqRule.Description = "foobar modified 2" 3815 reqRule.Selector = "serviceaccount.namespace==def" 3816 reqRule.BindType = structs.BindingRuleBindTypeRole 3817 reqRule.BindName = "def" 3818 3819 req := structs.ACLBindingRuleSetRequest{ 3820 Datacenter: "dc1", 3821 BindingRule: reqRule, 3822 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3823 } 3824 resp := structs.ACLBindingRule{} 3825 3826 err := acl.BindingRuleSet(&req, &resp) 3827 require.NoError(t, err) 3828 require.NotNil(t, resp.ID) 3829 3830 // Get the rule directly to validate that it exists 3831 ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", resp.ID) 3832 require.NoError(t, err) 3833 rule := ruleResp.BindingRule 3834 3835 require.NotEmpty(t, rule.ID) 3836 require.Equal(t, rule.Description, "foobar modified 2") 3837 require.Equal(t, rule.AuthMethod, testAuthMethod.Name) 3838 require.Equal(t, "serviceaccount.namespace==def", rule.Selector) 3839 require.Equal(t, structs.BindingRuleBindTypeRole, rule.BindType) 3840 require.Equal(t, "def", rule.BindName) 3841 }) 3842 3843 t.Run("Create fails; empty method name", func(t *testing.T) { 3844 reqRule := newRule() 3845 reqRule.AuthMethod = "" 3846 requireSetErrors(t, reqRule) 3847 }) 3848 3849 t.Run("Create fails; unknown method name", func(t *testing.T) { 3850 reqRule := newRule() 3851 reqRule.AuthMethod = "unknown" 3852 requireSetErrors(t, reqRule) 3853 }) 3854 3855 t.Run("Create with no explicit selector", func(t *testing.T) { 3856 reqRule := newRule() 3857 reqRule.Selector = "" 3858 3859 rule := requireOK(t, reqRule) 3860 require.Empty(t, rule.Selector, 0) 3861 }) 3862 3863 t.Run("Create fails; match selector with unknown vars", func(t *testing.T) { 3864 reqRule := newRule() 3865 reqRule.Selector = "serviceaccount.name==a and serviceaccount.bizarroname==b" 3866 requireSetErrors(t, reqRule) 3867 }) 3868 3869 t.Run("Create fails; match selector invalid", func(t *testing.T) { 3870 reqRule := newRule() 3871 reqRule.Selector = "serviceaccount.name" 3872 requireSetErrors(t, reqRule) 3873 }) 3874 3875 t.Run("Create fails; empty bind type", func(t *testing.T) { 3876 reqRule := newRule() 3877 reqRule.BindType = "" 3878 requireSetErrors(t, reqRule) 3879 }) 3880 3881 t.Run("Create fails; empty bind name", func(t *testing.T) { 3882 reqRule := newRule() 3883 reqRule.BindName = "" 3884 requireSetErrors(t, reqRule) 3885 }) 3886 3887 t.Run("Create fails; invalid bind type", func(t *testing.T) { 3888 reqRule := newRule() 3889 reqRule.BindType = "invalid" 3890 requireSetErrors(t, reqRule) 3891 }) 3892 3893 t.Run("Create fails; bind name with unknown vars", func(t *testing.T) { 3894 reqRule := newRule() 3895 reqRule.BindName = "method-${serviceaccount.bizarroname}" 3896 requireSetErrors(t, reqRule) 3897 }) 3898 3899 t.Run("Create fails; invalid bind name no template", func(t *testing.T) { 3900 reqRule := newRule() 3901 reqRule.BindName = "-abc:" 3902 requireSetErrors(t, reqRule) 3903 }) 3904 3905 t.Run("Create fails; invalid bind name with template", func(t *testing.T) { 3906 reqRule := newRule() 3907 reqRule.BindName = "method-${serviceaccount.name" 3908 requireSetErrors(t, reqRule) 3909 }) 3910 t.Run("Create fails; invalid bind name after template computed", func(t *testing.T) { 3911 reqRule := newRule() 3912 reqRule.BindName = "method-${serviceaccount.name}:blah-" 3913 requireSetErrors(t, reqRule) 3914 }) 3915} 3916 3917func TestACLEndpoint_BindingRuleDelete(t *testing.T) { 3918 if testing.Short() { 3919 t.Skip("too slow for testing.Short") 3920 } 3921 3922 t.Parallel() 3923 3924 _, srv, codec := testACLServerWithConfig(t, nil, false) 3925 waitForLeaderEstablishment(t, srv) 3926 3927 testAuthMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "") 3928 require.NoError(t, err) 3929 3930 existingRule, err := upsertTestBindingRule( 3931 codec, TestDefaultMasterToken, "dc1", 3932 testAuthMethod.Name, 3933 "serviceaccount.name==abc", 3934 structs.BindingRuleBindTypeService, 3935 "abc", 3936 ) 3937 require.NoError(t, err) 3938 3939 acl := ACL{srv: srv} 3940 3941 t.Run("normal", func(t *testing.T) { 3942 req := structs.ACLBindingRuleDeleteRequest{ 3943 Datacenter: "dc1", 3944 BindingRuleID: existingRule.ID, 3945 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3946 } 3947 3948 var ignored bool 3949 err = acl.BindingRuleDelete(&req, &ignored) 3950 require.NoError(t, err) 3951 3952 // Make sure the rule is gone 3953 ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", existingRule.ID) 3954 require.NoError(t, err) 3955 require.Nil(t, ruleResp.BindingRule) 3956 }) 3957 3958 t.Run("delete something that doesn't exist", func(t *testing.T) { 3959 fakeID, err := uuid.GenerateUUID() 3960 require.NoError(t, err) 3961 3962 req := structs.ACLBindingRuleDeleteRequest{ 3963 Datacenter: "dc1", 3964 BindingRuleID: fakeID, 3965 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 3966 } 3967 3968 var ignored bool 3969 err = acl.BindingRuleDelete(&req, &ignored) 3970 require.NoError(t, err) 3971 }) 3972} 3973 3974func TestACLEndpoint_BindingRuleList(t *testing.T) { 3975 if testing.Short() { 3976 t.Skip("too slow for testing.Short") 3977 } 3978 3979 t.Parallel() 3980 3981 _, srv, codec := testACLServerWithConfig(t, nil, false) 3982 waitForLeaderEstablishment(t, srv) 3983 3984 testAuthMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "") 3985 require.NoError(t, err) 3986 3987 r1, err := upsertTestBindingRule( 3988 codec, TestDefaultMasterToken, "dc1", 3989 testAuthMethod.Name, 3990 "serviceaccount.name==abc", 3991 structs.BindingRuleBindTypeService, 3992 "abc", 3993 ) 3994 require.NoError(t, err) 3995 3996 r2, err := upsertTestBindingRule( 3997 codec, TestDefaultMasterToken, "dc1", 3998 testAuthMethod.Name, 3999 "serviceaccount.name==def", 4000 structs.BindingRuleBindTypeService, 4001 "def", 4002 ) 4003 require.NoError(t, err) 4004 4005 acl := ACL{srv: srv} 4006 4007 req := structs.ACLBindingRuleListRequest{ 4008 Datacenter: "dc1", 4009 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 4010 } 4011 4012 resp := structs.ACLBindingRuleListResponse{} 4013 4014 err = acl.BindingRuleList(&req, &resp) 4015 require.NoError(t, err) 4016 require.ElementsMatch(t, gatherIDs(t, resp.BindingRules), []string{r1.ID, r2.ID}) 4017} 4018 4019func TestACLEndpoint_SecureIntroEndpoints_LocalTokensDisabled(t *testing.T) { 4020 if testing.Short() { 4021 t.Skip("too slow for testing.Short") 4022 } 4023 4024 t.Parallel() 4025 4026 _, s1, _ := testACLServerWithConfig(t, func(c *Config) { 4027 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 4028 c.ACLTokenMaxExpirationTTL = 5 * time.Second 4029 }, false) 4030 waitForLeaderEstablishment(t, s1) 4031 4032 _, s2, _ := testACLServerWithConfig(t, func(c *Config) { 4033 c.Datacenter = "dc2" 4034 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 4035 c.ACLTokenMaxExpirationTTL = 5 * time.Second 4036 // disable local tokens 4037 c.ACLTokenReplication = false 4038 }, true) 4039 waitForLeaderEstablishment(t, s2) 4040 4041 // Try to join 4042 joinWAN(t, s2, s1) 4043 4044 waitForNewACLs(t, s1) 4045 waitForNewACLs(t, s2) 4046 4047 acl2 := ACL{srv: s2} 4048 var ignored bool 4049 4050 errString := errAuthMethodsRequireTokenReplication.Error() 4051 4052 t.Run("AuthMethodRead", func(t *testing.T) { 4053 testutil.RequireErrorContains(t, 4054 acl2.AuthMethodRead(&structs.ACLAuthMethodGetRequest{Datacenter: "dc2"}, 4055 &structs.ACLAuthMethodResponse{}), 4056 errString, 4057 ) 4058 }) 4059 t.Run("AuthMethodSet", func(t *testing.T) { 4060 testutil.RequireErrorContains(t, 4061 acl2.AuthMethodSet(&structs.ACLAuthMethodSetRequest{Datacenter: "dc2"}, 4062 &structs.ACLAuthMethod{}), 4063 errString, 4064 ) 4065 }) 4066 t.Run("AuthMethodDelete", func(t *testing.T) { 4067 testutil.RequireErrorContains(t, 4068 acl2.AuthMethodDelete(&structs.ACLAuthMethodDeleteRequest{Datacenter: "dc2"}, &ignored), 4069 errString, 4070 ) 4071 }) 4072 t.Run("AuthMethodList", func(t *testing.T) { 4073 testutil.RequireErrorContains(t, 4074 acl2.AuthMethodList(&structs.ACLAuthMethodListRequest{Datacenter: "dc2"}, 4075 &structs.ACLAuthMethodListResponse{}), 4076 errString, 4077 ) 4078 }) 4079 4080 t.Run("BindingRuleRead", func(t *testing.T) { 4081 testutil.RequireErrorContains(t, 4082 acl2.BindingRuleRead(&structs.ACLBindingRuleGetRequest{Datacenter: "dc2"}, 4083 &structs.ACLBindingRuleResponse{}), 4084 errString, 4085 ) 4086 }) 4087 t.Run("BindingRuleSet", func(t *testing.T) { 4088 testutil.RequireErrorContains(t, 4089 acl2.BindingRuleSet(&structs.ACLBindingRuleSetRequest{Datacenter: "dc2"}, 4090 &structs.ACLBindingRule{}), 4091 errString, 4092 ) 4093 }) 4094 t.Run("BindingRuleDelete", func(t *testing.T) { 4095 testutil.RequireErrorContains(t, 4096 acl2.BindingRuleDelete(&structs.ACLBindingRuleDeleteRequest{Datacenter: "dc2"}, &ignored), 4097 errString, 4098 ) 4099 }) 4100 t.Run("BindingRuleList", func(t *testing.T) { 4101 testutil.RequireErrorContains(t, 4102 acl2.BindingRuleList(&structs.ACLBindingRuleListRequest{Datacenter: "dc2"}, 4103 &structs.ACLBindingRuleListResponse{}), 4104 errString, 4105 ) 4106 }) 4107 4108 t.Run("Login", func(t *testing.T) { 4109 testutil.RequireErrorContains(t, 4110 acl2.Login(&structs.ACLLoginRequest{Datacenter: "dc2"}, 4111 &structs.ACLToken{}), 4112 errString, 4113 ) 4114 }) 4115 t.Run("Logout", func(t *testing.T) { 4116 testutil.RequireErrorContains(t, 4117 acl2.Logout(&structs.ACLLogoutRequest{Datacenter: "dc2"}, &ignored), 4118 errString, 4119 ) 4120 }) 4121} 4122 4123func TestACLEndpoint_SecureIntroEndpoints_OnlyCreateLocalData(t *testing.T) { 4124 if testing.Short() { 4125 t.Skip("too slow for testing.Short") 4126 } 4127 4128 t.Parallel() 4129 4130 _, s1, codec1 := testACLServerWithConfig(t, func(c *Config) { 4131 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 4132 c.ACLTokenMaxExpirationTTL = 5 * time.Second 4133 }, false) 4134 waitForLeaderEstablishment(t, s1) 4135 4136 _, s2, codec2 := testACLServerWithConfig(t, func(c *Config) { 4137 c.Datacenter = "dc2" 4138 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 4139 c.ACLTokenMaxExpirationTTL = 5 * time.Second 4140 // enable token replication so secure intro works 4141 c.ACLTokenReplication = true 4142 }, true) 4143 waitForLeaderEstablishment(t, s2) 4144 4145 // Try to join 4146 joinWAN(t, s2, s1) 4147 4148 waitForNewACLs(t, s1) 4149 waitForNewACLs(t, s2) 4150 4151 // Ensure s2 is authoritative. 4152 waitForNewACLReplication(t, s2, structs.ACLReplicateTokens, 1, 1, 0) 4153 4154 acl := ACL{srv: s1} 4155 acl2 := ACL{srv: s2} 4156 4157 // 4158 // this order is specific so that we can do it in one pass 4159 // 4160 4161 testSessionID_1 := testauth.StartSession() 4162 defer testauth.ResetSession(testSessionID_1) 4163 4164 testSessionID_2 := testauth.StartSession() 4165 defer testauth.ResetSession(testSessionID_2) 4166 4167 testauth.InstallSessionToken( 4168 testSessionID_1, 4169 "fake-web1-token", 4170 "default", "web1", "abc123", 4171 ) 4172 testauth.InstallSessionToken( 4173 testSessionID_2, 4174 "fake-web2-token", 4175 "default", "web2", "def456", 4176 ) 4177 4178 t.Run("create auth method", func(t *testing.T) { 4179 req := structs.ACLAuthMethodSetRequest{ 4180 Datacenter: "dc2", 4181 AuthMethod: structs.ACLAuthMethod{ 4182 Name: "testmethod", 4183 Description: "test original", 4184 Type: "testing", 4185 Config: map[string]interface{}{ 4186 "SessionID": testSessionID_2, 4187 }, 4188 }, 4189 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4190 } 4191 resp := structs.ACLAuthMethod{} 4192 4193 require.NoError(t, acl2.AuthMethodSet(&req, &resp)) 4194 4195 // present in dc2 4196 resp2, err := retrieveTestAuthMethod(codec2, TestDefaultMasterToken, "dc2", "testmethod") 4197 require.NoError(t, err) 4198 require.NotNil(t, resp2.AuthMethod) 4199 require.Equal(t, "test original", resp2.AuthMethod.Description) 4200 // absent in dc1 4201 resp2, err = retrieveTestAuthMethod(codec1, TestDefaultMasterToken, "dc1", "testmethod") 4202 require.NoError(t, err) 4203 require.Nil(t, resp2.AuthMethod) 4204 }) 4205 4206 t.Run("update auth method", func(t *testing.T) { 4207 req := structs.ACLAuthMethodSetRequest{ 4208 Datacenter: "dc2", 4209 AuthMethod: structs.ACLAuthMethod{ 4210 Name: "testmethod", 4211 Description: "test updated", 4212 Config: map[string]interface{}{ 4213 "SessionID": testSessionID_2, 4214 }, 4215 }, 4216 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4217 } 4218 resp := structs.ACLAuthMethod{} 4219 4220 require.NoError(t, acl2.AuthMethodSet(&req, &resp)) 4221 4222 // present in dc2 4223 resp2, err := retrieveTestAuthMethod(codec2, TestDefaultMasterToken, "dc2", "testmethod") 4224 require.NoError(t, err) 4225 require.NotNil(t, resp2.AuthMethod) 4226 require.Equal(t, "test updated", resp2.AuthMethod.Description) 4227 // absent in dc1 4228 resp2, err = retrieveTestAuthMethod(codec1, TestDefaultMasterToken, "dc1", "testmethod") 4229 require.NoError(t, err) 4230 require.Nil(t, resp2.AuthMethod) 4231 }) 4232 4233 t.Run("read auth method", func(t *testing.T) { 4234 // present in dc2 4235 req := structs.ACLAuthMethodGetRequest{ 4236 Datacenter: "dc2", 4237 AuthMethodName: "testmethod", 4238 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 4239 } 4240 resp := structs.ACLAuthMethodResponse{} 4241 require.NoError(t, acl2.AuthMethodRead(&req, &resp)) 4242 require.NotNil(t, resp.AuthMethod) 4243 require.Equal(t, "test updated", resp.AuthMethod.Description) 4244 4245 // absent in dc1 4246 req = structs.ACLAuthMethodGetRequest{ 4247 Datacenter: "dc1", 4248 AuthMethodName: "testmethod", 4249 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 4250 } 4251 resp = structs.ACLAuthMethodResponse{} 4252 require.NoError(t, acl.AuthMethodRead(&req, &resp)) 4253 require.Nil(t, resp.AuthMethod) 4254 }) 4255 4256 t.Run("list auth method", func(t *testing.T) { 4257 // present in dc2 4258 req := structs.ACLAuthMethodListRequest{ 4259 Datacenter: "dc2", 4260 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 4261 } 4262 resp := structs.ACLAuthMethodListResponse{} 4263 require.NoError(t, acl2.AuthMethodList(&req, &resp)) 4264 require.Len(t, resp.AuthMethods, 1) 4265 4266 // absent in dc1 4267 req = structs.ACLAuthMethodListRequest{ 4268 Datacenter: "dc1", 4269 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 4270 } 4271 resp = structs.ACLAuthMethodListResponse{} 4272 require.NoError(t, acl.AuthMethodList(&req, &resp)) 4273 require.Len(t, resp.AuthMethods, 0) 4274 }) 4275 4276 var ruleID string 4277 t.Run("create binding rule", func(t *testing.T) { 4278 req := structs.ACLBindingRuleSetRequest{ 4279 Datacenter: "dc2", 4280 BindingRule: structs.ACLBindingRule{ 4281 Description: "test original", 4282 AuthMethod: "testmethod", 4283 BindType: structs.BindingRuleBindTypeService, 4284 BindName: "${serviceaccount.name}", 4285 }, 4286 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4287 } 4288 4289 resp := structs.ACLBindingRule{} 4290 4291 require.NoError(t, acl2.BindingRuleSet(&req, &resp)) 4292 ruleID = resp.ID 4293 4294 // present in dc2 4295 resp2, err := retrieveTestBindingRule(codec2, TestDefaultMasterToken, "dc2", ruleID) 4296 require.NoError(t, err) 4297 require.NotNil(t, resp2.BindingRule) 4298 require.Equal(t, "test original", resp2.BindingRule.Description) 4299 // absent in dc1 4300 resp2, err = retrieveTestBindingRule(codec1, TestDefaultMasterToken, "dc1", ruleID) 4301 require.NoError(t, err) 4302 require.Nil(t, resp2.BindingRule) 4303 }) 4304 4305 t.Run("update binding rule", func(t *testing.T) { 4306 req := structs.ACLBindingRuleSetRequest{ 4307 Datacenter: "dc2", 4308 BindingRule: structs.ACLBindingRule{ 4309 ID: ruleID, 4310 Description: "test updated", 4311 AuthMethod: "testmethod", 4312 BindType: structs.BindingRuleBindTypeService, 4313 BindName: "${serviceaccount.name}", 4314 }, 4315 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4316 } 4317 4318 resp := structs.ACLBindingRule{} 4319 4320 require.NoError(t, acl2.BindingRuleSet(&req, &resp)) 4321 ruleID = resp.ID 4322 4323 // present in dc2 4324 resp2, err := retrieveTestBindingRule(codec2, TestDefaultMasterToken, "dc2", ruleID) 4325 require.NoError(t, err) 4326 require.NotNil(t, resp2.BindingRule) 4327 require.Equal(t, "test updated", resp2.BindingRule.Description) 4328 // absent in dc1 4329 resp2, err = retrieveTestBindingRule(codec1, TestDefaultMasterToken, "dc1", ruleID) 4330 require.NoError(t, err) 4331 require.Nil(t, resp2.BindingRule) 4332 }) 4333 4334 t.Run("read binding rule", func(t *testing.T) { 4335 // present in dc2 4336 req := structs.ACLBindingRuleGetRequest{ 4337 Datacenter: "dc2", 4338 BindingRuleID: ruleID, 4339 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 4340 } 4341 resp := structs.ACLBindingRuleResponse{} 4342 require.NoError(t, acl2.BindingRuleRead(&req, &resp)) 4343 require.NotNil(t, resp.BindingRule) 4344 require.Equal(t, "test updated", resp.BindingRule.Description) 4345 4346 // absent in dc1 4347 req = structs.ACLBindingRuleGetRequest{ 4348 Datacenter: "dc1", 4349 BindingRuleID: ruleID, 4350 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 4351 } 4352 resp = structs.ACLBindingRuleResponse{} 4353 require.NoError(t, acl.BindingRuleRead(&req, &resp)) 4354 require.Nil(t, resp.BindingRule) 4355 }) 4356 4357 t.Run("list binding rule", func(t *testing.T) { 4358 // present in dc2 4359 req := structs.ACLBindingRuleListRequest{ 4360 Datacenter: "dc2", 4361 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 4362 } 4363 resp := structs.ACLBindingRuleListResponse{} 4364 require.NoError(t, acl2.BindingRuleList(&req, &resp)) 4365 require.Len(t, resp.BindingRules, 1) 4366 4367 // absent in dc1 4368 req = structs.ACLBindingRuleListRequest{ 4369 Datacenter: "dc1", 4370 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 4371 } 4372 resp = structs.ACLBindingRuleListResponse{} 4373 require.NoError(t, acl.BindingRuleList(&req, &resp)) 4374 require.Len(t, resp.BindingRules, 0) 4375 }) 4376 4377 var remoteToken *structs.ACLToken 4378 t.Run("login in remote", func(t *testing.T) { 4379 req := structs.ACLLoginRequest{ 4380 Datacenter: "dc2", 4381 Auth: &structs.ACLLoginParams{ 4382 AuthMethod: "testmethod", 4383 BearerToken: "fake-web2-token", 4384 }, 4385 } 4386 resp := structs.ACLToken{} 4387 4388 require.NoError(t, acl2.Login(&req, &resp)) 4389 remoteToken = &resp 4390 4391 // present in dc2 4392 resp2, err := retrieveTestToken(codec2, TestDefaultMasterToken, "dc2", remoteToken.AccessorID) 4393 require.NoError(t, err) 4394 require.NotNil(t, resp2.Token) 4395 require.Len(t, resp2.Token.ServiceIdentities, 1) 4396 require.Equal(t, "web2", resp2.Token.ServiceIdentities[0].ServiceName) 4397 // absent in dc1 4398 resp2, err = retrieveTestToken(codec1, TestDefaultMasterToken, "dc1", remoteToken.AccessorID) 4399 require.NoError(t, err) 4400 require.Nil(t, resp2.Token) 4401 }) 4402 4403 // We delay until now to setup an auth method and binding rule in the 4404 // primary so our earlier listing tests were sane. We need to be able to 4405 // use auth methods in both datacenters in order to verify Logout is 4406 // properly scoped. 4407 t.Run("initialize primary so we can test logout", func(t *testing.T) { 4408 reqAM := structs.ACLAuthMethodSetRequest{ 4409 Datacenter: "dc1", 4410 AuthMethod: structs.ACLAuthMethod{ 4411 Name: "primarymethod", 4412 Type: "testing", 4413 Config: map[string]interface{}{ 4414 "SessionID": testSessionID_1, 4415 }, 4416 }, 4417 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4418 } 4419 respAM := structs.ACLAuthMethod{} 4420 require.NoError(t, acl.AuthMethodSet(&reqAM, &respAM)) 4421 4422 reqBR := structs.ACLBindingRuleSetRequest{ 4423 Datacenter: "dc1", 4424 BindingRule: structs.ACLBindingRule{ 4425 AuthMethod: "primarymethod", 4426 BindType: structs.BindingRuleBindTypeService, 4427 BindName: "${serviceaccount.name}", 4428 }, 4429 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4430 } 4431 4432 respBR := structs.ACLBindingRule{} 4433 require.NoError(t, acl.BindingRuleSet(&reqBR, &respBR)) 4434 }) 4435 4436 var primaryToken *structs.ACLToken 4437 t.Run("login in primary", func(t *testing.T) { 4438 req := structs.ACLLoginRequest{ 4439 Datacenter: "dc1", 4440 Auth: &structs.ACLLoginParams{ 4441 AuthMethod: "primarymethod", 4442 BearerToken: "fake-web1-token", 4443 }, 4444 } 4445 resp := structs.ACLToken{} 4446 4447 require.NoError(t, acl.Login(&req, &resp)) 4448 primaryToken = &resp 4449 4450 // present in dc1 4451 resp2, err := retrieveTestToken(codec1, TestDefaultMasterToken, "dc1", primaryToken.AccessorID) 4452 require.NoError(t, err) 4453 require.NotNil(t, resp2.Token) 4454 require.Len(t, resp2.Token.ServiceIdentities, 1) 4455 require.Equal(t, "web1", resp2.Token.ServiceIdentities[0].ServiceName) 4456 // absent in dc2 4457 resp2, err = retrieveTestToken(codec2, TestDefaultMasterToken, "dc2", primaryToken.AccessorID) 4458 require.NoError(t, err) 4459 require.Nil(t, resp2.Token) 4460 }) 4461 4462 t.Run("logout of remote token in remote dc", func(t *testing.T) { 4463 // if the other test fails this one will to but will now not segfault 4464 require.NotNil(t, remoteToken) 4465 4466 req := structs.ACLLogoutRequest{ 4467 Datacenter: "dc2", 4468 WriteRequest: structs.WriteRequest{Token: remoteToken.SecretID}, 4469 } 4470 4471 var ignored bool 4472 require.NoError(t, acl.Logout(&req, &ignored)) 4473 4474 // absent in dc2 4475 resp2, err := retrieveTestToken(codec2, TestDefaultMasterToken, "dc2", remoteToken.AccessorID) 4476 require.NoError(t, err) 4477 require.Nil(t, resp2.Token) 4478 // absent in dc1 4479 resp2, err = retrieveTestToken(codec1, TestDefaultMasterToken, "dc1", remoteToken.AccessorID) 4480 require.NoError(t, err) 4481 require.Nil(t, resp2.Token) 4482 }) 4483 4484 t.Run("logout of primary token in remote dc should not work", func(t *testing.T) { 4485 req := structs.ACLLogoutRequest{ 4486 Datacenter: "dc2", 4487 WriteRequest: structs.WriteRequest{Token: primaryToken.SecretID}, 4488 } 4489 4490 var ignored bool 4491 testutil.RequireErrorContains(t, acl.Logout(&req, &ignored), "ACL not found") 4492 4493 // present in dc1 4494 resp2, err := retrieveTestToken(codec1, TestDefaultMasterToken, "dc1", primaryToken.AccessorID) 4495 require.NoError(t, err) 4496 require.NotNil(t, resp2.Token) 4497 require.Len(t, resp2.Token.ServiceIdentities, 1) 4498 require.Equal(t, "web1", resp2.Token.ServiceIdentities[0].ServiceName) 4499 // absent in dc2 4500 resp2, err = retrieveTestToken(codec2, TestDefaultMasterToken, "dc2", primaryToken.AccessorID) 4501 require.NoError(t, err) 4502 require.Nil(t, resp2.Token) 4503 }) 4504 4505 // Don't trigger the auth method delete cascade so we know the individual 4506 // endpoints follow the rules. 4507 4508 t.Run("delete binding rule", func(t *testing.T) { 4509 req := structs.ACLBindingRuleDeleteRequest{ 4510 Datacenter: "dc2", 4511 BindingRuleID: ruleID, 4512 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4513 } 4514 4515 var ignored bool 4516 require.NoError(t, acl2.BindingRuleDelete(&req, &ignored)) 4517 4518 // absent in dc2 4519 resp2, err := retrieveTestBindingRule(codec2, TestDefaultMasterToken, "dc2", ruleID) 4520 require.NoError(t, err) 4521 require.Nil(t, resp2.BindingRule) 4522 // absent in dc1 4523 resp2, err = retrieveTestBindingRule(codec1, TestDefaultMasterToken, "dc1", ruleID) 4524 require.NoError(t, err) 4525 require.Nil(t, resp2.BindingRule) 4526 }) 4527 4528 t.Run("delete auth method", func(t *testing.T) { 4529 req := structs.ACLAuthMethodDeleteRequest{ 4530 Datacenter: "dc2", 4531 AuthMethodName: "testmethod", 4532 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4533 } 4534 4535 var ignored bool 4536 require.NoError(t, acl2.AuthMethodDelete(&req, &ignored)) 4537 4538 // absent in dc2 4539 resp2, err := retrieveTestAuthMethod(codec2, TestDefaultMasterToken, "dc2", "testmethod") 4540 require.NoError(t, err) 4541 require.Nil(t, resp2.AuthMethod) 4542 // absent in dc1 4543 resp2, err = retrieveTestAuthMethod(codec1, TestDefaultMasterToken, "dc1", "testmethod") 4544 require.NoError(t, err) 4545 require.Nil(t, resp2.AuthMethod) 4546 }) 4547} 4548 4549func TestACLEndpoint_Login(t *testing.T) { 4550 if testing.Short() { 4551 t.Skip("too slow for testing.Short") 4552 } 4553 4554 t.Parallel() 4555 4556 _, srv, codec := testACLServerWithConfig(t, nil, false) 4557 waitForLeaderEstablishment(t, srv) 4558 4559 acl := ACL{srv: srv} 4560 4561 testSessionID := testauth.StartSession() 4562 defer testauth.ResetSession(testSessionID) 4563 4564 testauth.InstallSessionToken( 4565 testSessionID, 4566 "fake-web", // no rules 4567 "default", "web", "abc123", 4568 ) 4569 testauth.InstallSessionToken( 4570 testSessionID, 4571 "fake-db", // 1 rule (service) 4572 "default", "db", "def456", 4573 ) 4574 testauth.InstallSessionToken( 4575 testSessionID, 4576 "fake-vault", // 1 rule (role) 4577 "default", "vault", "jkl012", 4578 ) 4579 testauth.InstallSessionToken( 4580 testSessionID, 4581 "fake-monolith", // 2 rules (one of each) 4582 "default", "monolith", "ghi789", 4583 ) 4584 testauth.InstallSessionToken( 4585 testSessionID, 4586 "fake-node", 4587 "default", "mynode", "jkl101", 4588 ) 4589 4590 method, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID) 4591 require.NoError(t, err) 4592 4593 // 'fake-db' rules 4594 ruleDB, err := upsertTestBindingRule( 4595 codec, TestDefaultMasterToken, "dc1", method.Name, 4596 "serviceaccount.namespace==default and serviceaccount.name==db", 4597 structs.BindingRuleBindTypeService, 4598 "method-${serviceaccount.name}", 4599 ) 4600 require.NoError(t, err) 4601 4602 // 'fake-vault' rules 4603 _, err = upsertTestBindingRule( 4604 codec, TestDefaultMasterToken, "dc1", method.Name, 4605 "serviceaccount.namespace==default and serviceaccount.name==vault", 4606 structs.BindingRuleBindTypeRole, 4607 "method-${serviceaccount.name}", 4608 ) 4609 require.NoError(t, err) 4610 4611 // 'fake-monolith' rules 4612 _, err = upsertTestBindingRule( 4613 codec, TestDefaultMasterToken, "dc1", method.Name, 4614 "serviceaccount.namespace==default and serviceaccount.name==monolith", 4615 structs.BindingRuleBindTypeService, 4616 "method-${serviceaccount.name}", 4617 ) 4618 require.NoError(t, err) 4619 _, err = upsertTestBindingRule( 4620 codec, TestDefaultMasterToken, "dc1", method.Name, 4621 "serviceaccount.namespace==default and serviceaccount.name==monolith", 4622 structs.BindingRuleBindTypeRole, 4623 "method-${serviceaccount.name}", 4624 ) 4625 require.NoError(t, err) 4626 4627 // node identity rule 4628 _, err = upsertTestBindingRule( 4629 codec, TestDefaultMasterToken, "dc1", method.Name, 4630 "serviceaccount.namespace==default and serviceaccount.name==mynode", 4631 structs.BindingRuleBindTypeNode, 4632 "${serviceaccount.name}", 4633 ) 4634 require.NoError(t, err) 4635 4636 t.Run("do not provide a token", func(t *testing.T) { 4637 req := structs.ACLLoginRequest{ 4638 Auth: &structs.ACLLoginParams{ 4639 AuthMethod: method.Name, 4640 BearerToken: "fake-web", 4641 Meta: map[string]string{"pod": "pod1"}, 4642 }, 4643 Datacenter: "dc1", 4644 } 4645 req.Token = "nope" 4646 resp := structs.ACLToken{} 4647 4648 testutil.RequireErrorContains(t, acl.Login(&req, &resp), "do not provide a token") 4649 }) 4650 4651 t.Run("unknown method", func(t *testing.T) { 4652 req := structs.ACLLoginRequest{ 4653 Auth: &structs.ACLLoginParams{ 4654 AuthMethod: method.Name + "-notexist", 4655 BearerToken: "fake-web", 4656 Meta: map[string]string{"pod": "pod1"}, 4657 }, 4658 Datacenter: "dc1", 4659 } 4660 resp := structs.ACLToken{} 4661 4662 testutil.RequireErrorContains(t, acl.Login(&req, &resp), fmt.Sprintf("auth method %q not found", method.Name+"-notexist")) 4663 }) 4664 4665 t.Run("invalid method token", func(t *testing.T) { 4666 req := structs.ACLLoginRequest{ 4667 Auth: &structs.ACLLoginParams{ 4668 AuthMethod: method.Name, 4669 BearerToken: "invalid", 4670 Meta: map[string]string{"pod": "pod1"}, 4671 }, 4672 Datacenter: "dc1", 4673 } 4674 resp := structs.ACLToken{} 4675 4676 require.Error(t, acl.Login(&req, &resp)) 4677 }) 4678 4679 t.Run("valid method token no bindings", func(t *testing.T) { 4680 req := structs.ACLLoginRequest{ 4681 Auth: &structs.ACLLoginParams{ 4682 AuthMethod: method.Name, 4683 BearerToken: "fake-web", 4684 Meta: map[string]string{"pod": "pod1"}, 4685 }, 4686 Datacenter: "dc1", 4687 } 4688 resp := structs.ACLToken{} 4689 4690 testutil.RequireErrorContains(t, acl.Login(&req, &resp), "Permission denied") 4691 }) 4692 4693 t.Run("valid method token 1 role binding and role does not exist", func(t *testing.T) { 4694 req := structs.ACLLoginRequest{ 4695 Auth: &structs.ACLLoginParams{ 4696 AuthMethod: method.Name, 4697 BearerToken: "fake-vault", 4698 Meta: map[string]string{"pod": "pod1"}, 4699 }, 4700 Datacenter: "dc1", 4701 } 4702 resp := structs.ACLToken{} 4703 4704 testutil.RequireErrorContains(t, acl.Login(&req, &resp), "Permission denied") 4705 }) 4706 4707 // create the role so that the bindtype=role login works 4708 var vaultRoleID string 4709 { 4710 arg := structs.ACLRoleSetRequest{ 4711 Datacenter: "dc1", 4712 Role: structs.ACLRole{ 4713 Name: "method-vault", 4714 }, 4715 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4716 } 4717 4718 var out structs.ACLRole 4719 require.NoError(t, acl.RoleSet(&arg, &out)) 4720 4721 vaultRoleID = out.ID 4722 } 4723 4724 t.Run("valid method token 1 role binding and role now exists", func(t *testing.T) { 4725 req := structs.ACLLoginRequest{ 4726 Auth: &structs.ACLLoginParams{ 4727 AuthMethod: method.Name, 4728 BearerToken: "fake-vault", 4729 Meta: map[string]string{"pod": "pod1"}, 4730 }, 4731 Datacenter: "dc1", 4732 } 4733 resp := structs.ACLToken{} 4734 4735 require.NoError(t, acl.Login(&req, &resp)) 4736 4737 require.Equal(t, method.Name, resp.AuthMethod) 4738 require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description) 4739 require.True(t, resp.Local) 4740 require.Len(t, resp.ServiceIdentities, 0) 4741 require.Len(t, resp.Roles, 1) 4742 role := resp.Roles[0] 4743 require.Equal(t, vaultRoleID, role.ID) 4744 require.Equal(t, "method-vault", role.Name) 4745 }) 4746 4747 t.Run("valid method token 1 service binding 1 role binding and role does not exist", func(t *testing.T) { 4748 req := structs.ACLLoginRequest{ 4749 Auth: &structs.ACLLoginParams{ 4750 AuthMethod: method.Name, 4751 BearerToken: "fake-monolith", 4752 Meta: map[string]string{"pod": "pod1"}, 4753 }, 4754 Datacenter: "dc1", 4755 } 4756 resp := structs.ACLToken{} 4757 4758 require.NoError(t, acl.Login(&req, &resp)) 4759 4760 require.Equal(t, method.Name, resp.AuthMethod) 4761 require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description) 4762 require.True(t, resp.Local) 4763 require.Len(t, resp.ServiceIdentities, 1) 4764 require.Len(t, resp.Roles, 0) 4765 svcid := resp.ServiceIdentities[0] 4766 require.Len(t, svcid.Datacenters, 0) 4767 require.Equal(t, "method-monolith", svcid.ServiceName) 4768 }) 4769 4770 // create the role so that the bindtype=role login works 4771 var monolithRoleID string 4772 { 4773 arg := structs.ACLRoleSetRequest{ 4774 Datacenter: "dc1", 4775 Role: structs.ACLRole{ 4776 Name: "method-monolith", 4777 }, 4778 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4779 } 4780 4781 var out structs.ACLRole 4782 require.NoError(t, acl.RoleSet(&arg, &out)) 4783 4784 monolithRoleID = out.ID 4785 } 4786 4787 t.Run("valid method token 1 service binding 1 role binding and role now exists", func(t *testing.T) { 4788 req := structs.ACLLoginRequest{ 4789 Auth: &structs.ACLLoginParams{ 4790 AuthMethod: method.Name, 4791 BearerToken: "fake-monolith", 4792 Meta: map[string]string{"pod": "pod1"}, 4793 }, 4794 Datacenter: "dc1", 4795 } 4796 resp := structs.ACLToken{} 4797 4798 require.NoError(t, acl.Login(&req, &resp)) 4799 4800 require.Equal(t, method.Name, resp.AuthMethod) 4801 require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description) 4802 require.True(t, resp.Local) 4803 require.Len(t, resp.ServiceIdentities, 1) 4804 require.Len(t, resp.Roles, 1) 4805 role := resp.Roles[0] 4806 require.Equal(t, monolithRoleID, role.ID) 4807 require.Equal(t, "method-monolith", role.Name) 4808 svcid := resp.ServiceIdentities[0] 4809 require.Len(t, svcid.Datacenters, 0) 4810 require.Equal(t, "method-monolith", svcid.ServiceName) 4811 }) 4812 4813 t.Run("valid bearer token 1 service binding", func(t *testing.T) { 4814 req := structs.ACLLoginRequest{ 4815 Auth: &structs.ACLLoginParams{ 4816 AuthMethod: method.Name, 4817 BearerToken: "fake-db", 4818 Meta: map[string]string{"pod": "pod1"}, 4819 }, 4820 Datacenter: "dc1", 4821 } 4822 resp := structs.ACLToken{} 4823 4824 require.NoError(t, acl.Login(&req, &resp)) 4825 4826 require.Equal(t, method.Name, resp.AuthMethod) 4827 require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description) 4828 require.True(t, resp.Local) 4829 require.Len(t, resp.Roles, 0) 4830 require.Len(t, resp.ServiceIdentities, 1) 4831 svcid := resp.ServiceIdentities[0] 4832 require.Len(t, svcid.Datacenters, 0) 4833 require.Equal(t, "method-db", svcid.ServiceName) 4834 }) 4835 4836 t.Run("valid bearer token 1 node binding", func(t *testing.T) { 4837 req := structs.ACLLoginRequest{ 4838 Auth: &structs.ACLLoginParams{ 4839 AuthMethod: method.Name, 4840 BearerToken: "fake-node", 4841 Meta: map[string]string{"node": "true"}, 4842 }, 4843 Datacenter: "dc1", 4844 } 4845 resp := structs.ACLToken{} 4846 4847 require.NoError(t, acl.Login(&req, &resp)) 4848 4849 require.Equal(t, method.Name, resp.AuthMethod) 4850 require.Equal(t, `token created via login: {"node":"true"}`, resp.Description) 4851 require.True(t, resp.Local) 4852 require.Empty(t, resp.Roles) 4853 require.Empty(t, resp.ServiceIdentities) 4854 require.Len(t, resp.NodeIdentities, 1) 4855 nodeid := resp.NodeIdentities[0] 4856 require.Equal(t, "mynode", nodeid.NodeName) 4857 require.Equal(t, "dc1", nodeid.Datacenter) 4858 }) 4859 4860 { 4861 req := structs.ACLBindingRuleSetRequest{ 4862 Datacenter: "dc1", 4863 BindingRule: structs.ACLBindingRule{ 4864 AuthMethod: ruleDB.AuthMethod, 4865 BindType: structs.BindingRuleBindTypeService, 4866 BindName: ruleDB.BindName, 4867 Selector: "", 4868 }, 4869 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4870 } 4871 4872 var out structs.ACLBindingRule 4873 require.NoError(t, acl.BindingRuleSet(&req, &out)) 4874 } 4875 4876 t.Run("valid bearer token 1 binding (no selectors this time)", func(t *testing.T) { 4877 req := structs.ACLLoginRequest{ 4878 Auth: &structs.ACLLoginParams{ 4879 AuthMethod: method.Name, 4880 BearerToken: "fake-db", 4881 Meta: map[string]string{"pod": "pod1"}, 4882 }, 4883 Datacenter: "dc1", 4884 } 4885 resp := structs.ACLToken{} 4886 4887 require.NoError(t, acl.Login(&req, &resp)) 4888 4889 require.Equal(t, method.Name, resp.AuthMethod) 4890 require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description) 4891 require.True(t, resp.Local) 4892 require.Len(t, resp.Roles, 0) 4893 require.Len(t, resp.ServiceIdentities, 1) 4894 svcid := resp.ServiceIdentities[0] 4895 require.Len(t, svcid.Datacenters, 0) 4896 require.Equal(t, "method-db", svcid.ServiceName) 4897 }) 4898 4899 testSessionID_2 := testauth.StartSession() 4900 defer testauth.ResetSession(testSessionID_2) 4901 { 4902 // Update the method to force the cache to invalidate for the next 4903 // subtest. 4904 updated := *method 4905 updated.Description = "updated for the test" 4906 updated.Config = map[string]interface{}{ 4907 "SessionID": testSessionID_2, 4908 } 4909 4910 req := structs.ACLAuthMethodSetRequest{ 4911 Datacenter: "dc1", 4912 AuthMethod: updated, 4913 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 4914 } 4915 4916 var ignored structs.ACLAuthMethod 4917 require.NoError(t, acl.AuthMethodSet(&req, &ignored)) 4918 } 4919 4920 t.Run("updating the method invalidates the cache", func(t *testing.T) { 4921 // We'll try to login with the 'fake-db' cred which DOES exist in the 4922 // old fake validator, but no longer exists in the new fake validator. 4923 req := structs.ACLLoginRequest{ 4924 Auth: &structs.ACLLoginParams{ 4925 AuthMethod: method.Name, 4926 BearerToken: "fake-db", 4927 Meta: map[string]string{"pod": "pod1"}, 4928 }, 4929 Datacenter: "dc1", 4930 } 4931 resp := structs.ACLToken{} 4932 4933 testutil.RequireErrorContains(t, acl.Login(&req, &resp), "ACL not found") 4934 }) 4935} 4936 4937func TestACLEndpoint_Login_with_MaxTokenTTL(t *testing.T) { 4938 if testing.Short() { 4939 t.Skip("too slow for testing.Short") 4940 } 4941 4942 t.Parallel() 4943 4944 _, srv, codec := testACLServerWithConfig(t, nil, false) 4945 waitForLeaderEstablishment(t, srv) 4946 4947 acl := ACL{srv: srv} 4948 4949 testSessionID := testauth.StartSession() 4950 defer testauth.ResetSession(testSessionID) 4951 4952 testauth.InstallSessionToken( 4953 testSessionID, 4954 "fake-web", // no rules 4955 "default", "web", "abc123", 4956 ) 4957 4958 method, err := upsertTestCustomizedAuthMethod(codec, TestDefaultMasterToken, "dc1", func(method *structs.ACLAuthMethod) { 4959 method.MaxTokenTTL = 5 * time.Minute 4960 method.Config = map[string]interface{}{ 4961 "SessionID": testSessionID, 4962 } 4963 }) 4964 require.NoError(t, err) 4965 4966 _, err = upsertTestBindingRule( 4967 codec, TestDefaultMasterToken, "dc1", method.Name, 4968 "", 4969 structs.BindingRuleBindTypeService, 4970 "web", 4971 ) 4972 require.NoError(t, err) 4973 4974 // Create a token. 4975 req := structs.ACLLoginRequest{ 4976 Auth: &structs.ACLLoginParams{ 4977 AuthMethod: method.Name, 4978 BearerToken: "fake-web", 4979 Meta: map[string]string{"pod": "pod1"}, 4980 }, 4981 Datacenter: "dc1", 4982 } 4983 4984 resp := structs.ACLToken{} 4985 require.NoError(t, acl.Login(&req, &resp)) 4986 4987 got := &resp 4988 got.CreateIndex = 0 4989 got.ModifyIndex = 0 4990 got.AccessorID = "" 4991 got.SecretID = "" 4992 got.Hash = nil 4993 4994 defaultEntMeta := structs.DefaultEnterpriseMeta() 4995 expect := &structs.ACLToken{ 4996 AuthMethod: method.Name, 4997 Description: `token created via login: {"pod":"pod1"}`, 4998 Local: true, 4999 CreateTime: got.CreateTime, 5000 ExpirationTime: timePointer(got.CreateTime.Add(method.MaxTokenTTL)), 5001 ServiceIdentities: []*structs.ACLServiceIdentity{ 5002 {ServiceName: "web"}, 5003 }, 5004 EnterpriseMeta: *defaultEntMeta, 5005 } 5006 expect.ACLAuthMethodEnterpriseMeta.FillWithEnterpriseMeta(defaultEntMeta) 5007 require.Equal(t, got, expect) 5008} 5009 5010func TestACLEndpoint_Login_with_TokenLocality(t *testing.T) { 5011 if testing.Short() { 5012 t.Skip("too slow for testing.Short") 5013 } 5014 5015 t.Parallel() 5016 5017 _, s1, codec := testACLServerWithConfig(t, func(c *Config) { 5018 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 5019 c.ACLTokenMaxExpirationTTL = 5 * time.Second 5020 }, false) 5021 5022 _, s2, _ := testACLServerWithConfig(t, func(c *Config) { 5023 c.Datacenter = "dc2" 5024 c.ACLTokenMinExpirationTTL = 10 * time.Millisecond 5025 c.ACLTokenMaxExpirationTTL = 5 * time.Second 5026 // token replication is required to test deleting non-local tokens in secondary dc 5027 c.ACLTokenReplication = true 5028 }, true) 5029 5030 waitForLeaderEstablishment(t, s1) 5031 waitForLeaderEstablishment(t, s2) 5032 5033 joinWAN(t, s2, s1) 5034 5035 waitForNewACLs(t, s1) 5036 waitForNewACLs(t, s2) 5037 5038 // Ensure s2 is authoritative. 5039 waitForNewACLReplication(t, s2, structs.ACLReplicateTokens, 1, 1, 0) 5040 5041 acl := ACL{srv: s1} 5042 acl2 := ACL{srv: s2} 5043 5044 testSessionID := testauth.StartSession() 5045 defer testauth.ResetSession(testSessionID) 5046 5047 testauth.InstallSessionToken( 5048 testSessionID, 5049 "fake-web", // no rules 5050 "default", "web", "abc123", 5051 ) 5052 5053 cases := map[string]struct { 5054 tokenLocality string 5055 expectLocal bool 5056 deleteFromReplica bool 5057 }{ 5058 "empty": {tokenLocality: "", expectLocal: true}, 5059 "local": {tokenLocality: "local", expectLocal: true}, 5060 "global dc1 delete": {tokenLocality: "global", expectLocal: false, deleteFromReplica: false}, 5061 "global dc2 delete": {tokenLocality: "global", expectLocal: false, deleteFromReplica: true}, 5062 } 5063 5064 for name, tc := range cases { 5065 tc := tc 5066 t.Run(name, func(t *testing.T) { 5067 method, err := upsertTestCustomizedAuthMethod(codec, TestDefaultMasterToken, "dc1", func(method *structs.ACLAuthMethod) { 5068 method.TokenLocality = tc.tokenLocality 5069 method.Config = map[string]interface{}{ 5070 "SessionID": testSessionID, 5071 } 5072 }) 5073 require.NoError(t, err) 5074 5075 _, err = upsertTestBindingRule( 5076 codec, TestDefaultMasterToken, "dc1", method.Name, 5077 "", 5078 structs.BindingRuleBindTypeService, 5079 "web", 5080 ) 5081 require.NoError(t, err) 5082 5083 // Create a token. 5084 req := structs.ACLLoginRequest{ 5085 Auth: &structs.ACLLoginParams{ 5086 AuthMethod: method.Name, 5087 BearerToken: "fake-web", 5088 Meta: map[string]string{"pod": "pod1"}, 5089 }, 5090 Datacenter: "dc1", 5091 } 5092 5093 resp := structs.ACLToken{} 5094 require.NoError(t, acl.Login(&req, &resp)) 5095 5096 secretID := resp.SecretID 5097 5098 got := resp.Clone() 5099 got.CreateIndex = 0 5100 got.ModifyIndex = 0 5101 got.AccessorID = "" 5102 got.SecretID = "" 5103 got.Hash = nil 5104 5105 defaultEntMeta := structs.DefaultEnterpriseMeta() 5106 expect := &structs.ACLToken{ 5107 AuthMethod: method.Name, 5108 Description: `token created via login: {"pod":"pod1"}`, 5109 Local: tc.expectLocal, 5110 CreateTime: got.CreateTime, 5111 ServiceIdentities: []*structs.ACLServiceIdentity{ 5112 {ServiceName: "web"}, 5113 }, 5114 EnterpriseMeta: *defaultEntMeta, 5115 } 5116 expect.ACLAuthMethodEnterpriseMeta.FillWithEnterpriseMeta(defaultEntMeta) 5117 require.Equal(t, got, expect) 5118 5119 // Now turn around and nuke it. 5120 var ( 5121 logoutACL ACL 5122 logoutDC string 5123 ) 5124 if tc.deleteFromReplica { 5125 // wait for it to show up 5126 retry.Run(t, func(r *retry.R) { 5127 var resp structs.ACLTokenResponse 5128 require.NoError(r, acl2.TokenRead(&structs.ACLTokenGetRequest{ 5129 TokenID: secretID, 5130 TokenIDType: structs.ACLTokenSecret, 5131 Datacenter: "dc2", 5132 EnterpriseMeta: *defaultEntMeta, 5133 QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken}, 5134 }, &resp)) 5135 require.NotNil(r, resp.Token, "cannot lookup token with secretID %q", secretID) 5136 }) 5137 5138 logoutACL = acl2 5139 logoutDC = "dc2" 5140 } else { 5141 logoutACL = acl 5142 logoutDC = "dc1" 5143 } 5144 5145 logoutReq := structs.ACLLogoutRequest{ 5146 Datacenter: logoutDC, 5147 WriteRequest: structs.WriteRequest{Token: secretID}, 5148 } 5149 5150 var ignored bool 5151 require.NoError(t, logoutACL.Logout(&logoutReq, &ignored)) 5152 }) 5153 } 5154} 5155 5156func TestACLEndpoint_Login_k8s(t *testing.T) { 5157 if testing.Short() { 5158 t.Skip("too slow for testing.Short") 5159 } 5160 5161 t.Parallel() 5162 5163 _, srv, codec := testACLServerWithConfig(t, nil, false) 5164 waitForLeaderEstablishment(t, srv) 5165 5166 acl := ACL{srv: srv} 5167 5168 // spin up a fake api server 5169 testSrv := kubeauth.StartTestAPIServer(t) 5170 defer testSrv.Stop() 5171 5172 testSrv.AuthorizeJWT(goodJWT_A) 5173 testSrv.SetAllowedServiceAccount( 5174 "default", 5175 "demo", 5176 "76091af4-4b56-11e9-ac4b-708b11801cbe", 5177 "", 5178 goodJWT_B, 5179 ) 5180 5181 method, err := upsertTestKubernetesAuthMethod( 5182 codec, TestDefaultMasterToken, "dc1", 5183 testSrv.CACert(), 5184 testSrv.Addr(), 5185 goodJWT_A, 5186 ) 5187 require.NoError(t, err) 5188 5189 t.Run("invalid bearer token", func(t *testing.T) { 5190 req := structs.ACLLoginRequest{ 5191 Auth: &structs.ACLLoginParams{ 5192 AuthMethod: method.Name, 5193 BearerToken: "invalid", 5194 Meta: map[string]string{"pod": "pod1"}, 5195 }, 5196 Datacenter: "dc1", 5197 } 5198 resp := structs.ACLToken{} 5199 5200 require.Error(t, acl.Login(&req, &resp)) 5201 }) 5202 5203 t.Run("valid bearer token no bindings", func(t *testing.T) { 5204 req := structs.ACLLoginRequest{ 5205 Auth: &structs.ACLLoginParams{ 5206 AuthMethod: method.Name, 5207 BearerToken: goodJWT_B, 5208 Meta: map[string]string{"pod": "pod1"}, 5209 }, 5210 Datacenter: "dc1", 5211 } 5212 resp := structs.ACLToken{} 5213 5214 testutil.RequireErrorContains(t, acl.Login(&req, &resp), "Permission denied") 5215 }) 5216 5217 _, err = upsertTestBindingRule( 5218 codec, TestDefaultMasterToken, "dc1", method.Name, 5219 "serviceaccount.namespace==default", 5220 structs.BindingRuleBindTypeService, 5221 "${serviceaccount.name}", 5222 ) 5223 require.NoError(t, err) 5224 5225 t.Run("valid bearer token 1 service binding", func(t *testing.T) { 5226 req := structs.ACLLoginRequest{ 5227 Auth: &structs.ACLLoginParams{ 5228 AuthMethod: method.Name, 5229 BearerToken: goodJWT_B, 5230 Meta: map[string]string{"pod": "pod1"}, 5231 }, 5232 Datacenter: "dc1", 5233 } 5234 resp := structs.ACLToken{} 5235 5236 require.NoError(t, acl.Login(&req, &resp)) 5237 5238 require.Equal(t, method.Name, resp.AuthMethod) 5239 require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description) 5240 require.True(t, resp.Local) 5241 require.Len(t, resp.Roles, 0) 5242 require.Len(t, resp.ServiceIdentities, 1) 5243 svcid := resp.ServiceIdentities[0] 5244 require.Len(t, svcid.Datacenters, 0) 5245 require.Equal(t, "demo", svcid.ServiceName) 5246 }) 5247 5248 // annotate the account 5249 testSrv.SetAllowedServiceAccount( 5250 "default", 5251 "demo", 5252 "76091af4-4b56-11e9-ac4b-708b11801cbe", 5253 "alternate-name", 5254 goodJWT_B, 5255 ) 5256 5257 t.Run("valid bearer token 1 service binding - with annotation", func(t *testing.T) { 5258 req := structs.ACLLoginRequest{ 5259 Auth: &structs.ACLLoginParams{ 5260 AuthMethod: method.Name, 5261 BearerToken: goodJWT_B, 5262 Meta: map[string]string{"pod": "pod1"}, 5263 }, 5264 Datacenter: "dc1", 5265 } 5266 resp := structs.ACLToken{} 5267 5268 require.NoError(t, acl.Login(&req, &resp)) 5269 5270 require.Equal(t, method.Name, resp.AuthMethod) 5271 require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description) 5272 require.True(t, resp.Local) 5273 require.Len(t, resp.Roles, 0) 5274 require.Len(t, resp.ServiceIdentities, 1) 5275 svcid := resp.ServiceIdentities[0] 5276 require.Len(t, svcid.Datacenters, 0) 5277 require.Equal(t, "alternate-name", svcid.ServiceName) 5278 }) 5279} 5280 5281func TestACLEndpoint_Login_jwt(t *testing.T) { 5282 if testing.Short() { 5283 t.Skip("too slow for testing.Short") 5284 } 5285 5286 t.Parallel() 5287 5288 _, srv, codec := testACLServerWithConfig(t, nil, false) 5289 waitForLeaderEstablishment(t, srv) 5290 5291 acl := ACL{srv: srv} 5292 5293 // spin up a fake oidc server 5294 oidcServer := startSSOTestServer(t) 5295 pubKey, privKey := oidcServer.SigningKeys() 5296 5297 type mConfig = map[string]interface{} 5298 cases := map[string]struct { 5299 f func(config mConfig) 5300 issuer string 5301 expectErr string 5302 }{ 5303 "success - jwt static keys": {func(config mConfig) { 5304 config["BoundIssuer"] = "https://legit.issuer.internal/" 5305 config["JWTValidationPubKeys"] = []string{pubKey} 5306 }, 5307 "https://legit.issuer.internal/", 5308 ""}, 5309 "success - jwt jwks": {func(config mConfig) { 5310 config["JWKSURL"] = oidcServer.Addr() + "/certs" 5311 config["JWKSCACert"] = oidcServer.CACert() 5312 }, 5313 "https://legit.issuer.internal/", 5314 ""}, 5315 "success - jwt oidc discovery": {func(config mConfig) { 5316 config["OIDCDiscoveryURL"] = oidcServer.Addr() 5317 config["OIDCDiscoveryCACert"] = oidcServer.CACert() 5318 }, 5319 oidcServer.Addr(), 5320 ""}, 5321 } 5322 5323 for name, tc := range cases { 5324 tc := tc 5325 t.Run(name, func(t *testing.T) { 5326 method, err := upsertTestCustomizedAuthMethod(codec, TestDefaultMasterToken, "dc1", func(method *structs.ACLAuthMethod) { 5327 method.Type = "jwt" 5328 method.Config = map[string]interface{}{ 5329 "JWTSupportedAlgs": []string{"ES256"}, 5330 "ClaimMappings": map[string]string{ 5331 "first_name": "name", 5332 "/org/primary": "primary_org", 5333 }, 5334 "ListClaimMappings": map[string]string{ 5335 "https://consul.test/groups": "groups", 5336 }, 5337 "BoundAudiences": []string{"https://consul.test"}, 5338 } 5339 if tc.f != nil { 5340 tc.f(method.Config) 5341 } 5342 }) 5343 require.NoError(t, err) 5344 5345 t.Run("invalid bearer token", func(t *testing.T) { 5346 req := structs.ACLLoginRequest{ 5347 Auth: &structs.ACLLoginParams{ 5348 AuthMethod: method.Name, 5349 BearerToken: "invalid", 5350 }, 5351 Datacenter: "dc1", 5352 } 5353 resp := structs.ACLToken{} 5354 5355 require.Error(t, acl.Login(&req, &resp)) 5356 }) 5357 5358 cl := jwt.Claims{ 5359 Subject: "r3qXcK2bix9eFECzsU3Sbmh0K16fatW6@clients", 5360 Audience: jwt.Audience{"https://consul.test"}, 5361 Issuer: tc.issuer, 5362 NotBefore: jwt.NewNumericDate(time.Now().Add(-5 * time.Second)), 5363 Expiry: jwt.NewNumericDate(time.Now().Add(5 * time.Second)), 5364 } 5365 5366 type orgs struct { 5367 Primary string `json:"primary"` 5368 } 5369 5370 privateCl := struct { 5371 FirstName string `json:"first_name"` 5372 Org orgs `json:"org"` 5373 Groups []string `json:"https://consul.test/groups"` 5374 }{ 5375 FirstName: "jeff2", 5376 Org: orgs{"engineering"}, 5377 Groups: []string{"foo", "bar"}, 5378 } 5379 5380 jwtData, err := oidcauthtest.SignJWT(privKey, cl, privateCl) 5381 require.NoError(t, err) 5382 5383 t.Run("valid bearer token no bindings", func(t *testing.T) { 5384 req := structs.ACLLoginRequest{ 5385 Auth: &structs.ACLLoginParams{ 5386 AuthMethod: method.Name, 5387 BearerToken: jwtData, 5388 }, 5389 Datacenter: "dc1", 5390 } 5391 resp := structs.ACLToken{} 5392 5393 testutil.RequireErrorContains(t, acl.Login(&req, &resp), "Permission denied") 5394 }) 5395 5396 _, err = upsertTestBindingRule( 5397 codec, TestDefaultMasterToken, "dc1", method.Name, 5398 "value.name == jeff2 and value.primary_org == engineering and foo in list.groups", 5399 structs.BindingRuleBindTypeService, 5400 "test--${value.name}--${value.primary_org}", 5401 ) 5402 require.NoError(t, err) 5403 5404 t.Run("valid bearer token 1 service binding", func(t *testing.T) { 5405 req := structs.ACLLoginRequest{ 5406 Auth: &structs.ACLLoginParams{ 5407 AuthMethod: method.Name, 5408 BearerToken: jwtData, 5409 }, 5410 Datacenter: "dc1", 5411 } 5412 resp := structs.ACLToken{} 5413 5414 require.NoError(t, acl.Login(&req, &resp)) 5415 5416 require.Equal(t, method.Name, resp.AuthMethod) 5417 require.Equal(t, `token created via login`, resp.Description) 5418 require.True(t, resp.Local) 5419 require.Len(t, resp.Roles, 0) 5420 require.Len(t, resp.ServiceIdentities, 1) 5421 svcid := resp.ServiceIdentities[0] 5422 require.Len(t, svcid.Datacenters, 0) 5423 require.Equal(t, "test--jeff2--engineering", svcid.ServiceName) 5424 }) 5425 }) 5426 } 5427} 5428 5429func startSSOTestServer(t *testing.T) *oidcauthtest.Server { 5430 ports := freeport.MustTake(1) 5431 return oidcauthtest.Start(t, oidcauthtest.WithPort( 5432 ports[0], 5433 func() { freeport.Return(ports) }, 5434 )) 5435} 5436 5437func TestACLEndpoint_Logout(t *testing.T) { 5438 if testing.Short() { 5439 t.Skip("too slow for testing.Short") 5440 } 5441 5442 t.Parallel() 5443 5444 _, srv, codec := testACLServerWithConfig(t, nil, false) 5445 waitForLeaderEstablishment(t, srv) 5446 5447 acl := ACL{srv: srv} 5448 5449 testSessionID := testauth.StartSession() 5450 defer testauth.ResetSession(testSessionID) 5451 testauth.InstallSessionToken( 5452 testSessionID, 5453 "fake-db", // 1 rule 5454 "default", "db", "def456", 5455 ) 5456 5457 method, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID) 5458 require.NoError(t, err) 5459 5460 _, err = upsertTestBindingRule( 5461 codec, TestDefaultMasterToken, "dc1", method.Name, 5462 "", 5463 structs.BindingRuleBindTypeService, 5464 "method-${serviceaccount.name}", 5465 ) 5466 require.NoError(t, err) 5467 5468 t.Run("you must provide a token", func(t *testing.T) { 5469 req := structs.ACLLogoutRequest{ 5470 Datacenter: "dc1", 5471 // WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 5472 } 5473 req.Token = "" 5474 var ignored bool 5475 5476 testutil.RequireErrorContains(t, acl.Logout(&req, &ignored), "ACL not found") 5477 }) 5478 5479 t.Run("logout from deleted token", func(t *testing.T) { 5480 req := structs.ACLLogoutRequest{ 5481 Datacenter: "dc1", 5482 WriteRequest: structs.WriteRequest{Token: "not-found"}, 5483 } 5484 var ignored bool 5485 testutil.RequireErrorContains(t, acl.Logout(&req, &ignored), "ACL not found") 5486 }) 5487 5488 t.Run("logout from non-auth method-linked token should fail", func(t *testing.T) { 5489 req := structs.ACLLogoutRequest{ 5490 Datacenter: "dc1", 5491 WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken}, 5492 } 5493 var ignored bool 5494 testutil.RequireErrorContains(t, acl.Logout(&req, &ignored), "Permission denied") 5495 }) 5496 5497 t.Run("login then logout", func(t *testing.T) { 5498 // Create a totally legit Login token. 5499 loginReq := structs.ACLLoginRequest{ 5500 Auth: &structs.ACLLoginParams{ 5501 AuthMethod: method.Name, 5502 BearerToken: "fake-db", 5503 }, 5504 Datacenter: "dc1", 5505 } 5506 loginToken := structs.ACLToken{} 5507 5508 require.NoError(t, acl.Login(&loginReq, &loginToken)) 5509 require.NotEmpty(t, loginToken.SecretID) 5510 5511 // Now turn around and nuke it. 5512 req := structs.ACLLogoutRequest{ 5513 Datacenter: "dc1", 5514 WriteRequest: structs.WriteRequest{Token: loginToken.SecretID}, 5515 } 5516 5517 var ignored bool 5518 require.NoError(t, acl.Logout(&req, &ignored)) 5519 }) 5520} 5521 5522func gatherIDs(t *testing.T, v interface{}) []string { 5523 t.Helper() 5524 5525 var out []string 5526 switch x := v.(type) { 5527 case []*structs.ACLRole: 5528 for _, r := range x { 5529 out = append(out, r.ID) 5530 } 5531 case structs.ACLRoles: 5532 for _, r := range x { 5533 out = append(out, r.ID) 5534 } 5535 case []*structs.ACLPolicy: 5536 for _, p := range x { 5537 out = append(out, p.ID) 5538 } 5539 case structs.ACLPolicyListStubs: 5540 for _, p := range x { 5541 out = append(out, p.ID) 5542 } 5543 case []*structs.ACLToken: 5544 for _, p := range x { 5545 out = append(out, p.AccessorID) 5546 } 5547 case structs.ACLTokenListStubs: 5548 for _, p := range x { 5549 out = append(out, p.AccessorID) 5550 } 5551 case []*structs.ACLAuthMethod: 5552 for _, p := range x { 5553 out = append(out, p.Name) 5554 } 5555 case structs.ACLAuthMethodListStubs: 5556 for _, p := range x { 5557 out = append(out, p.Name) 5558 } 5559 case []*structs.ACLBindingRule: 5560 for _, p := range x { 5561 out = append(out, p.ID) 5562 } 5563 case structs.ACLBindingRules: 5564 for _, p := range x { 5565 out = append(out, p.ID) 5566 } 5567 default: 5568 t.Fatalf("unknown type: %T", x) 5569 } 5570 return out 5571} 5572 5573func TestValidateBindingRuleBindName(t *testing.T) { 5574 t.Parallel() 5575 5576 type testcase struct { 5577 name string 5578 bindType string 5579 bindName string 5580 fields string 5581 valid bool // valid HIL, invalid contents 5582 err bool // invalid HIL 5583 } 5584 5585 for _, test := range []testcase{ 5586 {"no bind type", 5587 "", "", "", false, false}, 5588 {"bad bind type", 5589 "invalid", "blah", "", false, true}, 5590 // valid HIL, invalid name 5591 {"empty", 5592 "both", "", "", false, false}, 5593 {"just end", 5594 "both", "}", "", false, false}, 5595 {"var without start", 5596 "both", " item }", "item", false, false}, 5597 {"two vars missing second start", 5598 "both", "before-${ item }after--more }", "item,more", false, false}, 5599 // names for the two types are validated differently 5600 {"@ is disallowed", 5601 "both", "bad@name", "", false, false}, 5602 {"leading dash", 5603 "role", "-name", "", true, false}, 5604 {"leading dash", 5605 "service", "-name", "", false, false}, 5606 {"trailing dash", 5607 "role", "name-", "", true, false}, 5608 {"trailing dash", 5609 "service", "name-", "", false, false}, 5610 {"inner dash", 5611 "both", "name-end", "", true, false}, 5612 {"upper case", 5613 "role", "NAME", "", true, false}, 5614 {"upper case", 5615 "service", "NAME", "", false, false}, 5616 // valid HIL, valid name 5617 {"no vars", 5618 "both", "nothing", "", true, false}, 5619 {"just var", 5620 "both", "${item}", "item", true, false}, 5621 {"var in middle", 5622 "both", "before-${item}after", "item", true, false}, 5623 {"two vars", 5624 "both", "before-${item}after-${more}", "item,more", true, false}, 5625 // bad 5626 {"no bind name", 5627 "both", "", "", false, false}, 5628 {"just start", 5629 "both", "${", "", false, true}, 5630 {"backwards", 5631 "both", "}${", "", false, true}, 5632 {"no varname", 5633 "both", "${}", "", false, true}, 5634 {"missing map key", 5635 "both", "${item}", "", false, true}, 5636 {"var without end", 5637 "both", "${ item ", "item", false, true}, 5638 {"two vars missing first end", 5639 "both", "before-${ item after-${ more }", "item,more", false, true}, 5640 } { 5641 var cases []testcase 5642 if test.bindType == "both" { 5643 test1 := test 5644 test1.bindType = "role" 5645 test2 := test 5646 test2.bindType = "service" 5647 cases = []testcase{test1, test2} 5648 } else { 5649 cases = []testcase{test} 5650 } 5651 5652 for _, test := range cases { 5653 test := test 5654 t.Run(test.bindType+"--"+test.name, func(t *testing.T) { 5655 t.Parallel() 5656 valid, err := validateBindingRuleBindName( 5657 test.bindType, 5658 test.bindName, 5659 strings.Split(test.fields, ","), 5660 ) 5661 if test.err { 5662 require.NotNil(t, err) 5663 require.False(t, valid) 5664 } else { 5665 require.NoError(t, err) 5666 require.Equal(t, test.valid, valid) 5667 } 5668 }) 5669 } 5670 } 5671} 5672 5673// upsertTestToken creates a token for testing purposes 5674func upsertTestToken(codec rpc.ClientCodec, masterToken string, datacenter string, 5675 tokenModificationFn func(token *structs.ACLToken)) (*structs.ACLToken, error) { 5676 arg := structs.ACLTokenSetRequest{ 5677 Datacenter: datacenter, 5678 ACLToken: structs.ACLToken{ 5679 Description: "User token", 5680 Local: false, 5681 Policies: nil, 5682 }, 5683 WriteRequest: structs.WriteRequest{Token: masterToken}, 5684 } 5685 5686 if tokenModificationFn != nil { 5687 tokenModificationFn(&arg.ACLToken) 5688 } 5689 5690 var out structs.ACLToken 5691 5692 err := msgpackrpc.CallWithCodec(codec, "ACL.TokenSet", &arg, &out) 5693 5694 if err != nil { 5695 return nil, err 5696 } 5697 5698 if out.AccessorID == "" { 5699 return nil, fmt.Errorf("AccessorID is nil: %v", out) 5700 } 5701 5702 return &out, nil 5703} 5704 5705func upsertTestTokenWithPolicyRules(codec rpc.ClientCodec, masterToken string, datacenter string, rules string) (*structs.ACLToken, error) { 5706 policy, err := upsertTestPolicyWithRules(codec, masterToken, datacenter, rules) 5707 if err != nil { 5708 return nil, err 5709 } 5710 5711 token, err := upsertTestToken(codec, masterToken, datacenter, func(token *structs.ACLToken) { 5712 token.Policies = []structs.ACLTokenPolicyLink{{ID: policy.ID}} 5713 }) 5714 if err != nil { 5715 return nil, err 5716 } 5717 5718 return token, nil 5719} 5720 5721func retrieveTestTokenAccessorForSecret(codec rpc.ClientCodec, masterToken string, datacenter string, id string) (string, error) { 5722 arg := structs.ACLTokenGetRequest{ 5723 TokenID: id, 5724 TokenIDType: structs.ACLTokenSecret, 5725 Datacenter: datacenter, 5726 QueryOptions: structs.QueryOptions{Token: masterToken}, 5727 } 5728 5729 var out structs.ACLTokenResponse 5730 5731 err := msgpackrpc.CallWithCodec(codec, "ACL.TokenRead", &arg, &out) 5732 5733 if err != nil { 5734 return "", err 5735 } 5736 5737 if out.Token == nil { 5738 return "", nil 5739 } 5740 5741 return out.Token.AccessorID, nil 5742} 5743 5744// retrieveTestToken returns a policy for testing purposes 5745func retrieveTestToken(codec rpc.ClientCodec, masterToken string, datacenter string, id string) (*structs.ACLTokenResponse, error) { 5746 arg := structs.ACLTokenGetRequest{ 5747 Datacenter: datacenter, 5748 TokenID: id, 5749 TokenIDType: structs.ACLTokenAccessor, 5750 QueryOptions: structs.QueryOptions{Token: masterToken}, 5751 } 5752 5753 var out structs.ACLTokenResponse 5754 5755 err := msgpackrpc.CallWithCodec(codec, "ACL.TokenRead", &arg, &out) 5756 5757 if err != nil { 5758 return nil, err 5759 } 5760 5761 return &out, nil 5762} 5763 5764func deleteTestToken(codec rpc.ClientCodec, masterToken string, datacenter string, tokenAccessor string) error { 5765 arg := structs.ACLTokenDeleteRequest{ 5766 Datacenter: datacenter, 5767 TokenID: tokenAccessor, 5768 WriteRequest: structs.WriteRequest{Token: masterToken}, 5769 } 5770 5771 var ignored string 5772 err := msgpackrpc.CallWithCodec(codec, "ACL.TokenDelete", &arg, &ignored) 5773 return err 5774} 5775 5776func deleteTestPolicy(codec rpc.ClientCodec, masterToken string, datacenter string, policyID string) error { 5777 arg := structs.ACLPolicyDeleteRequest{ 5778 Datacenter: datacenter, 5779 PolicyID: policyID, 5780 WriteRequest: structs.WriteRequest{Token: masterToken}, 5781 } 5782 5783 var ignored string 5784 err := msgpackrpc.CallWithCodec(codec, "ACL.PolicyDelete", &arg, &ignored) 5785 return err 5786} 5787 5788func upsertTestCustomizedPolicy(codec rpc.ClientCodec, masterToken string, datacenter string, policyModificationFn func(policy *structs.ACLPolicy)) (*structs.ACLPolicy, error) { 5789 // Make sure test policies can't collide 5790 policyUnq, err := uuid.GenerateUUID() 5791 if err != nil { 5792 return nil, err 5793 } 5794 5795 arg := structs.ACLPolicySetRequest{ 5796 Datacenter: datacenter, 5797 Policy: structs.ACLPolicy{ 5798 Name: fmt.Sprintf("test-policy-%s", policyUnq), 5799 }, 5800 WriteRequest: structs.WriteRequest{Token: masterToken}, 5801 } 5802 5803 if policyModificationFn != nil { 5804 policyModificationFn(&arg.Policy) 5805 } 5806 5807 var out structs.ACLPolicy 5808 5809 err = msgpackrpc.CallWithCodec(codec, "ACL.PolicySet", &arg, &out) 5810 5811 if err != nil { 5812 return nil, err 5813 } 5814 5815 if out.ID == "" { 5816 return nil, fmt.Errorf("ID is nil: %v", out) 5817 } 5818 5819 return &out, nil 5820} 5821 5822// upsertTestPolicy creates a policy for testing purposes 5823func upsertTestPolicy(codec rpc.ClientCodec, masterToken string, datacenter string) (*structs.ACLPolicy, error) { 5824 return upsertTestPolicyWithRules(codec, masterToken, datacenter, "") 5825} 5826 5827func upsertTestPolicyWithRules(codec rpc.ClientCodec, masterToken string, datacenter string, rules string) (*structs.ACLPolicy, error) { 5828 return upsertTestCustomizedPolicy(codec, masterToken, datacenter, func(policy *structs.ACLPolicy) { 5829 policy.Rules = rules 5830 }) 5831} 5832 5833// retrieveTestPolicy returns a policy for testing purposes 5834func retrieveTestPolicy(codec rpc.ClientCodec, masterToken string, datacenter string, id string) (*structs.ACLPolicyResponse, error) { 5835 arg := structs.ACLPolicyGetRequest{ 5836 Datacenter: datacenter, 5837 PolicyID: id, 5838 QueryOptions: structs.QueryOptions{Token: masterToken}, 5839 } 5840 5841 var out structs.ACLPolicyResponse 5842 5843 err := msgpackrpc.CallWithCodec(codec, "ACL.PolicyRead", &arg, &out) 5844 5845 if err != nil { 5846 return nil, err 5847 } 5848 5849 return &out, nil 5850} 5851 5852func deleteTestRole(codec rpc.ClientCodec, masterToken string, datacenter string, roleID string) error { 5853 arg := structs.ACLRoleDeleteRequest{ 5854 Datacenter: datacenter, 5855 RoleID: roleID, 5856 WriteRequest: structs.WriteRequest{Token: masterToken}, 5857 } 5858 5859 var ignored string 5860 err := msgpackrpc.CallWithCodec(codec, "ACL.RoleDelete", &arg, &ignored) 5861 return err 5862} 5863 5864func deleteTestRoleByName(codec rpc.ClientCodec, masterToken string, datacenter string, roleName string) error { 5865 resp, err := retrieveTestRoleByName(codec, masterToken, datacenter, roleName) 5866 if err != nil { 5867 return err 5868 } 5869 if resp.Role == nil { 5870 return nil 5871 } 5872 5873 return deleteTestRole(codec, masterToken, datacenter, resp.Role.ID) 5874} 5875 5876// upsertTestRole creates a role for testing purposes 5877func upsertTestRole(codec rpc.ClientCodec, masterToken string, datacenter string) (*structs.ACLRole, error) { 5878 return upsertTestCustomizedRole(codec, masterToken, datacenter, nil) 5879} 5880 5881func upsertTestCustomizedRole(codec rpc.ClientCodec, masterToken string, datacenter string, modify func(role *structs.ACLRole)) (*structs.ACLRole, error) { 5882 // Make sure test roles can't collide 5883 roleUnq, err := uuid.GenerateUUID() 5884 if err != nil { 5885 return nil, err 5886 } 5887 5888 arg := structs.ACLRoleSetRequest{ 5889 Datacenter: datacenter, 5890 Role: structs.ACLRole{ 5891 Name: fmt.Sprintf("test-role-%s", roleUnq), 5892 }, 5893 WriteRequest: structs.WriteRequest{Token: masterToken}, 5894 } 5895 5896 if modify != nil { 5897 modify(&arg.Role) 5898 } 5899 5900 var out structs.ACLRole 5901 5902 err = msgpackrpc.CallWithCodec(codec, "ACL.RoleSet", &arg, &out) 5903 5904 if err != nil { 5905 return nil, err 5906 } 5907 5908 if out.ID == "" { 5909 return nil, fmt.Errorf("ID is nil: %v", out) 5910 } 5911 5912 return &out, nil 5913} 5914 5915func retrieveTestRole(codec rpc.ClientCodec, masterToken string, datacenter string, id string) (*structs.ACLRoleResponse, error) { 5916 arg := structs.ACLRoleGetRequest{ 5917 Datacenter: datacenter, 5918 RoleID: id, 5919 QueryOptions: structs.QueryOptions{Token: masterToken}, 5920 } 5921 5922 var out structs.ACLRoleResponse 5923 5924 err := msgpackrpc.CallWithCodec(codec, "ACL.RoleRead", &arg, &out) 5925 5926 if err != nil { 5927 return nil, err 5928 } 5929 5930 return &out, nil 5931} 5932 5933func retrieveTestRoleByName(codec rpc.ClientCodec, masterToken string, datacenter string, name string) (*structs.ACLRoleResponse, error) { 5934 arg := structs.ACLRoleGetRequest{ 5935 Datacenter: datacenter, 5936 RoleName: name, 5937 QueryOptions: structs.QueryOptions{Token: masterToken}, 5938 } 5939 5940 var out structs.ACLRoleResponse 5941 5942 err := msgpackrpc.CallWithCodec(codec, "ACL.RoleRead", &arg, &out) 5943 5944 if err != nil { 5945 return nil, err 5946 } 5947 5948 return &out, nil 5949} 5950 5951func deleteTestAuthMethod(codec rpc.ClientCodec, masterToken string, datacenter string, methodName string) error { 5952 arg := structs.ACLAuthMethodDeleteRequest{ 5953 Datacenter: datacenter, 5954 AuthMethodName: methodName, 5955 WriteRequest: structs.WriteRequest{Token: masterToken}, 5956 } 5957 5958 var ignored string 5959 err := msgpackrpc.CallWithCodec(codec, "ACL.AuthMethodDelete", &arg, &ignored) 5960 return err 5961} 5962func upsertTestAuthMethod( 5963 codec rpc.ClientCodec, masterToken string, datacenter string, 5964 sessionID string, 5965) (*structs.ACLAuthMethod, error) { 5966 return upsertTestCustomizedAuthMethod(codec, masterToken, datacenter, func(method *structs.ACLAuthMethod) { 5967 method.Config = map[string]interface{}{ 5968 "SessionID": sessionID, 5969 } 5970 }) 5971} 5972 5973func upsertTestCustomizedAuthMethod( 5974 codec rpc.ClientCodec, masterToken string, datacenter string, 5975 modify func(method *structs.ACLAuthMethod), 5976) (*structs.ACLAuthMethod, error) { 5977 name, err := uuid.GenerateUUID() 5978 if err != nil { 5979 return nil, err 5980 } 5981 5982 req := structs.ACLAuthMethodSetRequest{ 5983 Datacenter: datacenter, 5984 AuthMethod: structs.ACLAuthMethod{ 5985 Name: "test-method-" + name, 5986 Type: "testing", 5987 }, 5988 WriteRequest: structs.WriteRequest{Token: masterToken}, 5989 } 5990 5991 if modify != nil { 5992 modify(&req.AuthMethod) 5993 } 5994 5995 var out structs.ACLAuthMethod 5996 5997 err = msgpackrpc.CallWithCodec(codec, "ACL.AuthMethodSet", &req, &out) 5998 if err != nil { 5999 return nil, err 6000 } 6001 6002 return &out, nil 6003} 6004 6005func upsertTestKubernetesAuthMethod( 6006 codec rpc.ClientCodec, masterToken string, datacenter string, 6007 caCert, kubeHost, kubeJWT string, 6008) (*structs.ACLAuthMethod, error) { 6009 name, err := uuid.GenerateUUID() 6010 if err != nil { 6011 return nil, err 6012 } 6013 6014 if kubeHost == "" { 6015 kubeHost = "https://abc:8443" 6016 } 6017 if kubeJWT == "" { 6018 kubeJWT = goodJWT_A 6019 } 6020 6021 req := structs.ACLAuthMethodSetRequest{ 6022 Datacenter: datacenter, 6023 AuthMethod: structs.ACLAuthMethod{ 6024 Name: "test-method-" + name, 6025 Type: "kubernetes", 6026 Config: map[string]interface{}{ 6027 "Host": kubeHost, 6028 "CACert": caCert, 6029 "ServiceAccountJWT": kubeJWT, 6030 }, 6031 }, 6032 WriteRequest: structs.WriteRequest{Token: masterToken}, 6033 } 6034 6035 var out structs.ACLAuthMethod 6036 6037 err = msgpackrpc.CallWithCodec(codec, "ACL.AuthMethodSet", &req, &out) 6038 if err != nil { 6039 return nil, err 6040 } 6041 6042 return &out, nil 6043} 6044 6045func retrieveTestAuthMethod(codec rpc.ClientCodec, masterToken string, datacenter string, name string) (*structs.ACLAuthMethodResponse, error) { 6046 arg := structs.ACLAuthMethodGetRequest{ 6047 Datacenter: datacenter, 6048 AuthMethodName: name, 6049 QueryOptions: structs.QueryOptions{Token: masterToken}, 6050 } 6051 6052 var out structs.ACLAuthMethodResponse 6053 6054 err := msgpackrpc.CallWithCodec(codec, "ACL.AuthMethodRead", &arg, &out) 6055 6056 if err != nil { 6057 return nil, err 6058 } 6059 6060 return &out, nil 6061} 6062 6063func deleteTestBindingRule(codec rpc.ClientCodec, masterToken string, datacenter string, ruleID string) error { 6064 arg := structs.ACLBindingRuleDeleteRequest{ 6065 Datacenter: datacenter, 6066 BindingRuleID: ruleID, 6067 WriteRequest: structs.WriteRequest{Token: masterToken}, 6068 } 6069 6070 var ignored string 6071 err := msgpackrpc.CallWithCodec(codec, "ACL.BindingRuleDelete", &arg, &ignored) 6072 return err 6073} 6074 6075func upsertTestBindingRule( 6076 codec rpc.ClientCodec, 6077 masterToken string, 6078 datacenter string, 6079 methodName string, 6080 selector string, 6081 bindType string, 6082 bindName string, 6083) (*structs.ACLBindingRule, error) { 6084 return upsertTestCustomizedBindingRule(codec, masterToken, datacenter, func(rule *structs.ACLBindingRule) { 6085 rule.AuthMethod = methodName 6086 rule.BindType = bindType 6087 rule.BindName = bindName 6088 rule.Selector = selector 6089 }) 6090} 6091 6092func upsertTestCustomizedBindingRule(codec rpc.ClientCodec, masterToken string, datacenter string, modify func(rule *structs.ACLBindingRule)) (*structs.ACLBindingRule, error) { 6093 req := structs.ACLBindingRuleSetRequest{ 6094 Datacenter: datacenter, 6095 BindingRule: structs.ACLBindingRule{}, 6096 WriteRequest: structs.WriteRequest{Token: masterToken}, 6097 } 6098 6099 if modify != nil { 6100 modify(&req.BindingRule) 6101 } 6102 6103 var out structs.ACLBindingRule 6104 6105 err := msgpackrpc.CallWithCodec(codec, "ACL.BindingRuleSet", &req, &out) 6106 if err != nil { 6107 return nil, err 6108 } 6109 6110 return &out, nil 6111} 6112 6113func retrieveTestBindingRule(codec rpc.ClientCodec, masterToken string, datacenter string, ruleID string) (*structs.ACLBindingRuleResponse, error) { 6114 arg := structs.ACLBindingRuleGetRequest{ 6115 Datacenter: datacenter, 6116 BindingRuleID: ruleID, 6117 QueryOptions: structs.QueryOptions{Token: masterToken}, 6118 } 6119 6120 var out structs.ACLBindingRuleResponse 6121 6122 err := msgpackrpc.CallWithCodec(codec, "ACL.BindingRuleRead", &arg, &out) 6123 6124 if err != nil { 6125 return nil, err 6126 } 6127 6128 return &out, nil 6129} 6130 6131func requireTimeEquals(t *testing.T, expect, got *time.Time) { 6132 t.Helper() 6133 if expect == nil && got == nil { 6134 return 6135 } else if expect == nil && got != nil { 6136 t.Fatalf("expected=NIL != got=%q", *got) 6137 } else if expect != nil && got == nil { 6138 t.Fatalf("expected=%q != got=NIL", *expect) 6139 } else if !expect.Equal(*got) { 6140 t.Fatalf("expected=%q != got=%q", *expect, *got) 6141 } 6142} 6143 6144// 'default/admin' 6145const goodJWT_A = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFkbWluLXRva2VuLXFsejQyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNzM4YmMyNTEtNjUzMi0xMWU5LWI2N2YtNDhlNmM4YjhlY2I1Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6YWRtaW4ifQ.ixMlnWrAG7NVuTTKu8cdcYfM7gweS3jlKaEsIBNGOVEjPE7rtXtgMkAwjQTdYR08_0QBjkgzy5fQC5ZNyglSwONJ-bPaXGvhoH1cTnRi1dz9H_63CfqOCvQP1sbdkMeRxNTGVAyWZT76rXoCUIfHP4LY2I8aab0KN9FTIcgZRF0XPTtT70UwGIrSmRpxW38zjiy2ymWL01cc5VWGhJqVysmWmYk3wNp0h5N57H_MOrz4apQR4pKaamzskzjLxO55gpbmZFC76qWuUdexAR7DT2fpbHLOw90atN_NlLMY-VrXyW3-Ei5EhYaVreMB9PSpKwkrA4jULITohV-sxpa1LA" 6146 6147// 'default/demo' 6148const goodJWT_B = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlbW8tdG9rZW4ta21iOW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVtbyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6Ijc2MDkxYWY0LTRiNTYtMTFlOS1hYzRiLTcwOGIxMTgwMWNiZSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlbW8ifQ.ZiAHjijBAOsKdum0Aix6lgtkLkGo9_Tu87dWQ5Zfwnn3r2FejEWDAnftTft1MqqnMzivZ9Wyyki5ZjQRmTAtnMPJuHC-iivqY4Wh4S6QWCJ1SivBv5tMZR79t5t8mE7R1-OHwst46spru1pps9wt9jsA04d3LpV0eeKYgdPTVaQKklxTm397kIMUugA6yINIBQ3Rh8eQqBgNwEmL4iqyYubzHLVkGkoP9MJikFI05vfRiHtYr-piXz6JFDzXMQj9rW6xtMmrBSn79ChbyvC5nz-Nj2rJPnHsb_0rDUbmXY5PpnMhBpdSH-CbZ4j8jsiib6DtaGJhVZeEQ1GjsFAZwQ" 6149