github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/acl_endpoint.go (about) 1 package consul 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "regexp" 9 "time" 10 11 "github.com/armon/go-metrics" 12 "github.com/hashicorp/consul/acl" 13 "github.com/hashicorp/consul/agent/consul/state" 14 "github.com/hashicorp/consul/agent/structs" 15 "github.com/hashicorp/consul/lib" 16 "github.com/hashicorp/go-memdb" 17 "github.com/hashicorp/go-uuid" 18 ) 19 20 const ( 21 // aclBootstrapReset is the file name to create in the data dir. It's only contents 22 // should be the reset index 23 aclBootstrapReset = "acl-bootstrap-reset" 24 ) 25 26 // Regex for matching 27 var validPolicyName = regexp.MustCompile(`^[A-Za-z0-9\-_]{1,128}$`) 28 29 // ACL endpoint is used to manipulate ACLs 30 type ACL struct { 31 srv *Server 32 } 33 34 // fileBootstrapResetIndex retrieves the reset index specified by the administrator from 35 // the file on disk. 36 // 37 // Q: What is the bootstrap reset index? 38 // A: If you happen to lose acess to all tokens capable of ACL management you need a way 39 // to get back into your system. This allows an admin to write the current 40 // bootstrap "index" into a special file on disk to override the mechanism preventing 41 // a second token bootstrap. The index will be retrieved by a API call to /v1/acl/bootstrap 42 // When already bootstrapped this API will return the reset index necessary within 43 // the error response. Once set in the file, the bootstrap API can be used again to 44 // get a new token. 45 // 46 // Q: Why is the reset index not in the config? 47 // A: We want to be able to remove the reset index once we have used it. This prevents 48 // accidentally allowing bootstrapping yet again after a snapshot restore. 49 // 50 func (a *ACL) fileBootstrapResetIndex() uint64 { 51 // Determine the file path to check 52 path := filepath.Join(a.srv.config.DataDir, aclBootstrapReset) 53 54 // Read the file 55 raw, err := ioutil.ReadFile(path) 56 if err != nil { 57 if !os.IsNotExist(err) { 58 a.srv.logger.Printf("[ERR] acl.bootstrap: failed to read %q: %v", path, err) 59 } 60 return 0 61 } 62 63 // Attempt to parse the file 64 var resetIdx uint64 65 if _, err := fmt.Sscanf(string(raw), "%d", &resetIdx); err != nil { 66 a.srv.logger.Printf("[ERR] acl.bootstrap: failed to parse %q: %v", path, err) 67 return 0 68 } 69 70 // Return the reset index 71 a.srv.logger.Printf("[DEBUG] acl.bootstrap: parsed %q: reset index %d", path, resetIdx) 72 return resetIdx 73 } 74 75 func (a *ACL) removeBootstrapResetFile() { 76 if err := os.Remove(filepath.Join(a.srv.config.DataDir, aclBootstrapReset)); err != nil { 77 a.srv.logger.Printf("[WARN] acl.bootstrap: failed to remove bootstrap file: %v", err) 78 } 79 } 80 81 func (a *ACL) aclPreCheck() error { 82 if !a.srv.ACLsEnabled() { 83 return acl.ErrDisabled 84 } 85 86 if a.srv.UseLegacyACLs() { 87 return fmt.Errorf("The ACL system is currently in legacy mode.") 88 } 89 90 return nil 91 } 92 93 // Bootstrap is used to perform a one-time ACL bootstrap operation on 94 // a cluster to get the first management token. 95 func (a *ACL) BootstrapTokens(args *structs.DCSpecificRequest, reply *structs.ACLToken) error { 96 if err := a.aclPreCheck(); err != nil { 97 return err 98 } 99 if done, err := a.srv.forward("ACL.BootstrapTokens", args, args, reply); done { 100 return err 101 } 102 103 // Verify we are allowed to serve this request 104 if !a.srv.InACLDatacenter() { 105 return acl.ErrDisabled 106 } 107 108 // By doing some pre-checks we can head off later bootstrap attempts 109 // without having to run them through Raft, which should curb abuse. 110 state := a.srv.fsm.State() 111 allowed, resetIdx, err := state.CanBootstrapACLToken() 112 if err != nil { 113 return err 114 } 115 var specifiedIndex uint64 = 0 116 if !allowed { 117 // Check if there is a reset index specified 118 specifiedIndex = a.fileBootstrapResetIndex() 119 if specifiedIndex == 0 { 120 return fmt.Errorf("ACL bootstrap no longer allowed (reset index: %d)", resetIdx) 121 } else if specifiedIndex != resetIdx { 122 return fmt.Errorf("Invalid bootstrap reset index (specified %d, reset index: %d)", specifiedIndex, resetIdx) 123 } 124 } 125 126 // remove the bootstrap override file now that we have the index from it and it was valid. 127 // whether bootstrapping works or not is irrelevant as we really don't want this file hanging around 128 // in case a snapshot restore is done. In that case we don't want to accidentally allow re-bootstrapping 129 // just because the file was unchanged. 130 a.removeBootstrapResetFile() 131 132 accessor, err := lib.GenerateUUID(a.srv.checkTokenUUID) 133 if err != nil { 134 return err 135 } 136 secret, err := lib.GenerateUUID(a.srv.checkTokenUUID) 137 if err != nil { 138 return err 139 } 140 141 req := structs.ACLTokenBootstrapRequest{ 142 Token: structs.ACLToken{ 143 AccessorID: accessor, 144 SecretID: secret, 145 Description: "Bootstrap Token (Global Management)", 146 Policies: []structs.ACLTokenPolicyLink{ 147 { 148 ID: structs.ACLPolicyGlobalManagementID, 149 }, 150 }, 151 CreateTime: time.Now(), 152 Local: false, 153 // DEPRECATED (ACL-Legacy-Compat) - This is used so that the bootstrap token is still visible via the v1 acl APIs 154 Type: structs.ACLTokenTypeManagement, 155 }, 156 ResetIndex: specifiedIndex, 157 } 158 159 req.Token.SetHash(true) 160 161 resp, err := a.srv.raftApply(structs.ACLBootstrapRequestType, &req) 162 if err != nil { 163 return err 164 } 165 166 if err, ok := resp.(error); ok { 167 return err 168 } 169 170 if _, token, err := state.ACLTokenGetByAccessor(nil, accessor); err == nil { 171 *reply = *token 172 } 173 174 a.srv.logger.Printf("[INFO] consul.acl: ACL bootstrap completed") 175 return nil 176 } 177 178 func (a *ACL) TokenRead(args *structs.ACLTokenGetRequest, reply *structs.ACLTokenResponse) error { 179 if err := a.aclPreCheck(); err != nil { 180 return err 181 } 182 183 // clients will not know whether the server has local token store. In the case 184 // where it doesn't we will transparently forward requests. 185 if !a.srv.LocalTokensEnabled() { 186 args.Datacenter = a.srv.config.ACLDatacenter 187 } 188 189 if done, err := a.srv.forward("ACL.TokenRead", args, args, reply); done { 190 return err 191 } 192 193 var rule acl.Authorizer 194 if args.TokenIDType == structs.ACLTokenAccessor { 195 var err error 196 // Only ACLRead privileges are required to list tokens 197 // However if you do not have ACLWrite as well the token 198 // secrets will be redacted 199 if rule, err = a.srv.ResolveToken(args.Token); err != nil { 200 return err 201 } else if rule == nil || !rule.ACLRead() { 202 return acl.ErrPermissionDenied 203 } 204 } 205 206 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 207 func(ws memdb.WatchSet, state *state.Store) error { 208 var index uint64 209 var token *structs.ACLToken 210 var err error 211 212 if args.TokenIDType == structs.ACLTokenAccessor { 213 index, token, err = state.ACLTokenGetByAccessor(ws, args.TokenID) 214 if token != nil { 215 a.srv.filterACLWithAuthorizer(rule, &token) 216 if !rule.ACLWrite() { 217 reply.Redacted = true 218 } 219 } 220 } else { 221 index, token, err = state.ACLTokenGetBySecret(ws, args.TokenID) 222 } 223 224 if err != nil { 225 return err 226 } 227 228 reply.Index, reply.Token = index, token 229 return nil 230 }) 231 } 232 233 func (a *ACL) TokenClone(args *structs.ACLTokenSetRequest, reply *structs.ACLToken) error { 234 if err := a.aclPreCheck(); err != nil { 235 return err 236 } 237 238 // clients will not know whether the server has local token store. In the case 239 // where it doesn't we will transparently forward requests. 240 if !a.srv.LocalTokensEnabled() { 241 args.Datacenter = a.srv.config.ACLDatacenter 242 } 243 244 if done, err := a.srv.forward("ACL.TokenClone", args, args, reply); done { 245 return err 246 } 247 248 defer metrics.MeasureSince([]string{"acl", "token", "clone"}, time.Now()) 249 250 if rule, err := a.srv.ResolveToken(args.Token); err != nil { 251 return err 252 } else if rule == nil || !rule.ACLWrite() { 253 return acl.ErrPermissionDenied 254 } 255 256 _, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.ACLToken.AccessorID) 257 if err != nil { 258 return err 259 } else if token == nil { 260 return acl.ErrNotFound 261 } else if !a.srv.InACLDatacenter() && !token.Local { 262 // global token writes must be forwarded to the primary DC 263 args.Datacenter = a.srv.config.ACLDatacenter 264 return a.srv.forwardDC("ACL.TokenClone", a.srv.config.ACLDatacenter, args, reply) 265 } 266 267 if token.Rules != "" { 268 return fmt.Errorf("Cannot clone a legacy ACL with this endpoint") 269 } 270 271 cloneReq := structs.ACLTokenSetRequest{ 272 Datacenter: args.Datacenter, 273 ACLToken: structs.ACLToken{ 274 Policies: token.Policies, 275 Local: token.Local, 276 Description: token.Description, 277 }, 278 WriteRequest: args.WriteRequest, 279 } 280 281 if args.ACLToken.Description != "" { 282 cloneReq.ACLToken.Description = args.ACLToken.Description 283 } 284 285 return a.tokenSetInternal(&cloneReq, reply, false) 286 } 287 288 func (a *ACL) TokenSet(args *structs.ACLTokenSetRequest, reply *structs.ACLToken) error { 289 if err := a.aclPreCheck(); err != nil { 290 return err 291 } 292 293 // Global token creation/modification always goes to the ACL DC 294 if !args.ACLToken.Local { 295 args.Datacenter = a.srv.config.ACLDatacenter 296 } else if !a.srv.LocalTokensEnabled() { 297 return fmt.Errorf("Local tokens are disabled") 298 } 299 300 if done, err := a.srv.forward("ACL.TokenSet", args, args, reply); done { 301 return err 302 } 303 304 defer metrics.MeasureSince([]string{"acl", "token", "upsert"}, time.Now()) 305 306 // Verify token is permitted to modify ACLs 307 if rule, err := a.srv.ResolveToken(args.Token); err != nil { 308 return err 309 } else if rule == nil || !rule.ACLWrite() { 310 return acl.ErrPermissionDenied 311 } 312 313 return a.tokenSetInternal(args, reply, false) 314 } 315 316 func (a *ACL) tokenSetInternal(args *structs.ACLTokenSetRequest, reply *structs.ACLToken, upgrade bool) error { 317 token := &args.ACLToken 318 319 if !a.srv.LocalTokensEnabled() { 320 // local token operations 321 return fmt.Errorf("Cannot upsert tokens within this datacenter") 322 } else if !a.srv.InACLDatacenter() && !token.Local { 323 return fmt.Errorf("Cannot upsert global tokens within this datacenter") 324 } 325 326 state := a.srv.fsm.State() 327 328 if token.AccessorID == "" { 329 // Token Create 330 var err error 331 332 // Generate the AccessorID 333 token.AccessorID, err = lib.GenerateUUID(a.srv.checkTokenUUID) 334 if err != nil { 335 return err 336 } 337 338 // Generate the SecretID - not supporting non-UUID secrets 339 token.SecretID, err = lib.GenerateUUID(a.srv.checkTokenUUID) 340 if err != nil { 341 return err 342 } 343 344 token.CreateTime = time.Now() 345 } else { 346 // Token Update 347 if _, err := uuid.ParseUUID(token.AccessorID); err != nil { 348 return fmt.Errorf("AccessorID is not a valid UUID") 349 } 350 351 // DEPRECATED (ACL-Legacy-Compat) - maybe get rid of this in the future 352 // and instead do a ParseUUID check. New tokens will not have 353 // secrets generated by users but rather they will always be UUIDs. 354 // However if users just continue the upgrade cycle they may still 355 // have tokens using secrets that are not UUIDS 356 // The RootAuthorizer checks that the SecretID is not "allow", "deny" 357 // or "manage" as a precaution against something accidentally using 358 // one of these root policies by setting the secret to it. 359 if acl.RootAuthorizer(token.SecretID) != nil { 360 return acl.PermissionDeniedError{Cause: "Cannot modify root ACL"} 361 } 362 363 // Verify the token exists 364 _, existing, err := state.ACLTokenGetByAccessor(nil, token.AccessorID) 365 if err != nil { 366 return fmt.Errorf("Failed to lookup the acl token %q: %v", token.AccessorID, err) 367 } 368 if existing == nil { 369 return fmt.Errorf("Cannot find token %q", token.AccessorID) 370 } 371 if token.SecretID == "" { 372 token.SecretID = existing.SecretID 373 } else if existing.SecretID != token.SecretID { 374 return fmt.Errorf("Changing a tokens SecretID is not permitted") 375 } 376 377 // Cannot toggle the "Global" mode 378 if token.Local != existing.Local { 379 return fmt.Errorf("cannot toggle local mode of %s", token.AccessorID) 380 } 381 382 if upgrade { 383 token.CreateTime = time.Now() 384 } else { 385 token.CreateTime = existing.CreateTime 386 } 387 } 388 389 policyIDs := make(map[string]struct{}) 390 var policies []structs.ACLTokenPolicyLink 391 392 // Validate all the policy names and convert them to policy IDs 393 for _, link := range token.Policies { 394 if link.ID == "" { 395 _, policy, err := state.ACLPolicyGetByName(nil, link.Name) 396 if err != nil { 397 return fmt.Errorf("Error looking up policy for name %q: %v", link.Name, err) 398 } 399 if policy == nil { 400 return fmt.Errorf("No such ACL policy with name %q", link.Name) 401 } 402 link.ID = policy.ID 403 } 404 405 // Do not store the policy name within raft/memdb as the policy could be renamed in the future. 406 link.Name = "" 407 408 // dedup policy links by id 409 if _, ok := policyIDs[link.ID]; !ok { 410 policies = append(policies, link) 411 policyIDs[link.ID] = struct{}{} 412 } 413 } 414 token.Policies = policies 415 416 if token.Rules != "" { 417 return fmt.Errorf("Rules cannot be specified for this token") 418 } 419 420 if token.Type != "" { 421 return fmt.Errorf("Type cannot be specified for this token") 422 } 423 424 token.SetHash(true) 425 426 req := &structs.ACLTokenBatchSetRequest{ 427 Tokens: structs.ACLTokens{token}, 428 CAS: false, 429 } 430 431 resp, err := a.srv.raftApply(structs.ACLTokenSetRequestType, req) 432 if err != nil { 433 return fmt.Errorf("Failed to apply token write request: %v", err) 434 } 435 436 // Purge the identity from the cache to prevent using the previous definition of the identity 437 a.srv.acls.cache.RemoveIdentity(token.SecretID) 438 439 if respErr, ok := resp.(error); ok { 440 return respErr 441 } 442 443 if _, updatedToken, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, token.AccessorID); err == nil && token != nil { 444 *reply = *updatedToken 445 } else { 446 return fmt.Errorf("Failed to retrieve the token after insertion") 447 } 448 449 return nil 450 } 451 452 func (a *ACL) TokenDelete(args *structs.ACLTokenDeleteRequest, reply *string) error { 453 if err := a.aclPreCheck(); err != nil { 454 return err 455 } 456 457 if !a.srv.LocalTokensEnabled() { 458 args.Datacenter = a.srv.config.ACLDatacenter 459 } 460 461 if done, err := a.srv.forward("ACL.TokenDelete", args, args, reply); done { 462 return err 463 } 464 465 defer metrics.MeasureSince([]string{"acl", "token", "delete"}, time.Now()) 466 467 // Verify token is permitted to modify ACLs 468 if rule, err := a.srv.ResolveToken(args.Token); err != nil { 469 return err 470 } else if rule == nil || !rule.ACLWrite() { 471 return acl.ErrPermissionDenied 472 } 473 474 if _, err := uuid.ParseUUID(args.TokenID); err != nil { 475 return fmt.Errorf("Accessor ID is missing or an invalid UUID") 476 } 477 478 if args.TokenID == structs.ACLTokenAnonymousID { 479 return fmt.Errorf("Delete operation not permitted on the anonymous token") 480 } 481 482 // grab the token here so we can invalidate our cache later on 483 _, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.TokenID) 484 if err != nil { 485 return err 486 } 487 488 if token != nil { 489 if args.Token == token.SecretID { 490 return fmt.Errorf("Deletion of the request's authorization token is not permitted") 491 } 492 493 if !a.srv.InACLDatacenter() && !token.Local { 494 args.Datacenter = a.srv.config.ACLDatacenter 495 return a.srv.forwardDC("ACL.TokenDelete", a.srv.config.ACLDatacenter, args, reply) 496 } 497 } 498 499 req := &structs.ACLTokenBatchDeleteRequest{ 500 TokenIDs: []string{args.TokenID}, 501 } 502 503 resp, err := a.srv.raftApply(structs.ACLTokenDeleteRequestType, req) 504 if err != nil { 505 return fmt.Errorf("Failed to apply token delete request: %v", err) 506 } 507 508 // Purge the identity from the cache to prevent using the previous definition of the identity 509 if token != nil { 510 a.srv.acls.cache.RemoveIdentity(token.SecretID) 511 } 512 513 if respErr, ok := resp.(error); ok { 514 return respErr 515 } 516 517 if reply != nil && token != nil { 518 *reply = token.AccessorID 519 } 520 521 return nil 522 } 523 524 func (a *ACL) TokenList(args *structs.ACLTokenListRequest, reply *structs.ACLTokenListResponse) error { 525 if err := a.aclPreCheck(); err != nil { 526 return err 527 } 528 529 if !a.srv.LocalTokensEnabled() { 530 if args.Datacenter != a.srv.config.ACLDatacenter { 531 args.Datacenter = a.srv.config.ACLDatacenter 532 args.IncludeLocal = false 533 args.IncludeGlobal = true 534 } 535 args.Datacenter = a.srv.config.ACLDatacenter 536 } 537 538 if done, err := a.srv.forward("ACL.TokenList", args, args, reply); done { 539 return err 540 } 541 542 rule, err := a.srv.ResolveToken(args.Token) 543 if err != nil { 544 return err 545 } else if rule == nil || !rule.ACLRead() { 546 return acl.ErrPermissionDenied 547 } 548 549 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 550 func(ws memdb.WatchSet, state *state.Store) error { 551 index, tokens, err := state.ACLTokenList(ws, args.IncludeLocal, args.IncludeGlobal, args.Policy) 552 if err != nil { 553 return err 554 } 555 556 stubs := make([]*structs.ACLTokenListStub, 0, len(tokens)) 557 for _, token := range tokens { 558 stubs = append(stubs, token.Stub()) 559 } 560 reply.Index, reply.Tokens = index, stubs 561 return nil 562 }) 563 } 564 565 func (a *ACL) TokenBatchRead(args *structs.ACLTokenBatchGetRequest, reply *structs.ACLTokenBatchResponse) error { 566 if err := a.aclPreCheck(); err != nil { 567 return err 568 } 569 570 if !a.srv.LocalTokensEnabled() { 571 args.Datacenter = a.srv.config.ACLDatacenter 572 } 573 574 if done, err := a.srv.forward("ACL.TokenBatchRead", args, args, reply); done { 575 return err 576 } 577 578 rule, err := a.srv.ResolveToken(args.Token) 579 if err != nil { 580 return err 581 } else if rule == nil || !rule.ACLRead() { 582 return acl.ErrPermissionDenied 583 } 584 585 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 586 func(ws memdb.WatchSet, state *state.Store) error { 587 index, tokens, err := state.ACLTokenBatchGet(ws, args.AccessorIDs) 588 if err != nil { 589 return err 590 } 591 592 a.srv.filterACLWithAuthorizer(rule, &tokens) 593 594 reply.Index, reply.Tokens = index, tokens 595 reply.Redacted = !rule.ACLWrite() 596 return nil 597 }) 598 } 599 600 func (a *ACL) PolicyRead(args *structs.ACLPolicyGetRequest, reply *structs.ACLPolicyResponse) error { 601 if err := a.aclPreCheck(); err != nil { 602 return err 603 } 604 605 if done, err := a.srv.forward("ACL.PolicyRead", args, args, reply); done { 606 return err 607 } 608 609 if rule, err := a.srv.ResolveToken(args.Token); err != nil { 610 return err 611 } else if rule == nil || !rule.ACLRead() { 612 return acl.ErrPermissionDenied 613 } 614 615 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 616 func(ws memdb.WatchSet, state *state.Store) error { 617 index, policy, err := state.ACLPolicyGetByID(ws, args.PolicyID) 618 619 if err != nil { 620 return err 621 } 622 623 reply.Index, reply.Policy = index, policy 624 return nil 625 }) 626 } 627 628 func (a *ACL) PolicyBatchRead(args *structs.ACLPolicyBatchGetRequest, reply *structs.ACLPolicyBatchResponse) error { 629 if err := a.aclPreCheck(); err != nil { 630 return err 631 } 632 633 if done, err := a.srv.forward("ACL.PolicyBatchRead", args, args, reply); done { 634 return err 635 } 636 637 if rule, err := a.srv.ResolveToken(args.Token); err != nil { 638 return err 639 } else if rule == nil || !rule.ACLRead() { 640 return acl.ErrPermissionDenied 641 } 642 643 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 644 func(ws memdb.WatchSet, state *state.Store) error { 645 index, policies, err := state.ACLPolicyBatchGet(ws, args.PolicyIDs) 646 if err != nil { 647 return err 648 } 649 650 reply.Index, reply.Policies = index, policies 651 return nil 652 }) 653 } 654 655 func (a *ACL) PolicySet(args *structs.ACLPolicySetRequest, reply *structs.ACLPolicy) error { 656 if err := a.aclPreCheck(); err != nil { 657 return err 658 } 659 660 if !a.srv.InACLDatacenter() { 661 args.Datacenter = a.srv.config.ACLDatacenter 662 } 663 664 if done, err := a.srv.forward("ACL.PolicySet", args, args, reply); done { 665 return err 666 } 667 668 defer metrics.MeasureSince([]string{"acl", "policy", "upsert"}, time.Now()) 669 670 // Verify token is permitted to modify ACLs 671 if rule, err := a.srv.ResolveToken(args.Token); err != nil { 672 return err 673 } else if rule == nil || !rule.ACLWrite() { 674 return acl.ErrPermissionDenied 675 } 676 677 policy := &args.Policy 678 state := a.srv.fsm.State() 679 680 // Almost all of the checks here are also done in the state store. However, 681 // we want to prevent the raft operations when we know they are going to fail 682 // so we still do them here. 683 684 // ensure a name is set 685 if policy.Name == "" { 686 return fmt.Errorf("Invalid Policy: no Name is set") 687 } 688 689 if !validPolicyName.MatchString(policy.Name) { 690 return fmt.Errorf("Invalid Policy: invalid Name. Only alphanumeric characters, '-' and '_' are allowed") 691 } 692 693 if policy.ID == "" { 694 // with no policy ID one will be generated 695 var err error 696 697 policy.ID, err = lib.GenerateUUID(a.srv.checkPolicyUUID) 698 if err != nil { 699 return err 700 } 701 702 // validate the name is unique 703 if _, existing, err := state.ACLPolicyGetByName(nil, policy.Name); err != nil { 704 return fmt.Errorf("acl policy lookup by name failed: %v", err) 705 } else if existing != nil { 706 return fmt.Errorf("Invalid Policy: A Policy with Name %q already exists", policy.Name) 707 } 708 } else { 709 if _, err := uuid.ParseUUID(policy.ID); err != nil { 710 return fmt.Errorf("Policy ID invalid UUID") 711 } 712 713 // Verify the policy exists 714 _, existing, err := state.ACLPolicyGetByID(nil, policy.ID) 715 if err != nil { 716 return fmt.Errorf("acl policy lookup failed: %v", err) 717 } else if existing == nil { 718 return fmt.Errorf("cannot find policy %s", policy.ID) 719 } 720 721 if existing.Name != policy.Name { 722 if _, nameMatch, err := state.ACLPolicyGetByName(nil, policy.Name); err != nil { 723 return fmt.Errorf("acl policy lookup by name failed: %v", err) 724 } else if nameMatch != nil { 725 return fmt.Errorf("Invalid Policy: A policy with name %q already exists", policy.Name) 726 } 727 } 728 729 if policy.ID == structs.ACLPolicyGlobalManagementID { 730 if policy.Datacenters != nil || len(policy.Datacenters) > 0 { 731 return fmt.Errorf("Changing the Datacenters of the builtin global-management policy is not permitted") 732 } 733 734 if policy.Rules != existing.Rules { 735 return fmt.Errorf("Changing the Rules for the builtin global-management policy is not permitted") 736 } 737 } 738 } 739 740 // validate the rules 741 _, err := acl.NewPolicyFromSource("", 0, policy.Rules, policy.Syntax, a.srv.sentinel) 742 if err != nil { 743 return err 744 } 745 746 // calculate the hash for this policy 747 policy.SetHash(true) 748 749 req := &structs.ACLPolicyBatchSetRequest{ 750 Policies: structs.ACLPolicies{policy}, 751 } 752 753 resp, err := a.srv.raftApply(structs.ACLPolicySetRequestType, req) 754 if err != nil { 755 return fmt.Errorf("Failed to apply policy upsert request: %v", err) 756 } 757 758 // Remove from the cache to prevent stale cache usage 759 a.srv.acls.cache.RemovePolicy(policy.ID) 760 761 if respErr, ok := resp.(error); ok { 762 return respErr 763 } 764 765 if _, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, policy.ID); err == nil && policy != nil { 766 *reply = *policy 767 } 768 769 return nil 770 } 771 772 func (a *ACL) PolicyDelete(args *structs.ACLPolicyDeleteRequest, reply *string) error { 773 if err := a.aclPreCheck(); err != nil { 774 return err 775 } 776 777 if !a.srv.InACLDatacenter() { 778 args.Datacenter = a.srv.config.ACLDatacenter 779 } 780 781 if done, err := a.srv.forward("ACL.PolicyDelete", args, args, reply); done { 782 return err 783 } 784 785 defer metrics.MeasureSince([]string{"acl", "policy", "delete"}, time.Now()) 786 787 // Verify token is permitted to modify ACLs 788 if rule, err := a.srv.ResolveToken(args.Token); err != nil { 789 return err 790 } else if rule == nil || !rule.ACLWrite() { 791 return acl.ErrPermissionDenied 792 } 793 794 _, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, args.PolicyID) 795 if err != nil { 796 return err 797 } 798 799 if policy == nil { 800 return nil 801 } 802 803 if policy.ID == structs.ACLPolicyGlobalManagementID { 804 return fmt.Errorf("Delete operation not permitted on the builtin global-management policy") 805 } 806 807 req := structs.ACLPolicyBatchDeleteRequest{ 808 PolicyIDs: []string{args.PolicyID}, 809 } 810 811 resp, err := a.srv.raftApply(structs.ACLPolicyDeleteRequestType, &req) 812 if err != nil { 813 return fmt.Errorf("Failed to apply policy delete request: %v", err) 814 } 815 816 a.srv.acls.cache.RemovePolicy(policy.ID) 817 818 if respErr, ok := resp.(error); ok { 819 return respErr 820 } 821 822 if policy != nil { 823 *reply = policy.Name 824 } 825 826 return nil 827 } 828 829 func (a *ACL) PolicyList(args *structs.ACLPolicyListRequest, reply *structs.ACLPolicyListResponse) error { 830 if err := a.aclPreCheck(); err != nil { 831 return err 832 } 833 834 if done, err := a.srv.forward("ACL.PolicyList", args, args, reply); done { 835 return err 836 } 837 838 if rule, err := a.srv.ResolveToken(args.Token); err != nil { 839 return err 840 } else if rule == nil || !rule.ACLRead() { 841 return acl.ErrPermissionDenied 842 } 843 844 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 845 func(ws memdb.WatchSet, state *state.Store) error { 846 index, policies, err := state.ACLPolicyList(ws) 847 if err != nil { 848 return err 849 } 850 851 var stubs structs.ACLPolicyListStubs 852 for _, policy := range policies { 853 stubs = append(stubs, policy.Stub()) 854 } 855 856 reply.Index, reply.Policies = index, stubs 857 return nil 858 }) 859 } 860 861 // PolicyResolve is used to retrieve a subset of the policies associated with a given token 862 // The policy ids in the args simply act as a filter on the policy set assigned to the token 863 func (a *ACL) PolicyResolve(args *structs.ACLPolicyBatchGetRequest, reply *structs.ACLPolicyBatchResponse) error { 864 if err := a.aclPreCheck(); err != nil { 865 return err 866 } 867 868 if done, err := a.srv.forward("ACL.PolicyResolve", args, args, reply); done { 869 return err 870 } 871 872 // get full list of policies for this token 873 identity, policies, err := a.srv.acls.resolveTokenToIdentityAndPolicies(args.Token) 874 if err != nil { 875 return err 876 } 877 878 idMap := make(map[string]*structs.ACLPolicy) 879 for _, policyID := range identity.PolicyIDs() { 880 idMap[policyID] = nil 881 } 882 for _, policy := range policies { 883 idMap[policy.ID] = policy 884 } 885 886 for _, policyID := range args.PolicyIDs { 887 if policy, ok := idMap[policyID]; ok { 888 // only add non-deleted policies 889 if policy != nil { 890 reply.Policies = append(reply.Policies, policy) 891 } 892 } else { 893 // send a permission denied to indicate that the request included 894 // policy ids not associated with this token 895 return acl.ErrPermissionDenied 896 } 897 } 898 899 a.srv.setQueryMeta(&reply.QueryMeta) 900 901 return nil 902 } 903 904 // makeACLETag returns an ETag for the given parent and policy. 905 func makeACLETag(parent string, policy *acl.Policy) string { 906 return fmt.Sprintf("%s:%s", parent, policy.ID) 907 } 908 909 // GetPolicy is used to retrieve a compiled policy object with a TTL. Does not 910 // support a blocking query. 911 func (a *ACL) GetPolicy(args *structs.ACLPolicyResolveLegacyRequest, reply *structs.ACLPolicyResolveLegacyResponse) error { 912 if done, err := a.srv.forward("ACL.GetPolicy", args, args, reply); done { 913 return err 914 } 915 916 // Verify we are allowed to serve this request 917 if a.srv.config.ACLDatacenter != a.srv.config.Datacenter { 918 return acl.ErrDisabled 919 } 920 921 // Get the policy via the cache 922 parent := a.srv.config.ACLDefaultPolicy 923 924 policy, err := a.srv.acls.GetMergedPolicyForToken(args.ACL) 925 if err != nil { 926 return err 927 } 928 929 // translates the structures internals to most closely match what could be expressed in the original rule language 930 policy = policy.ConvertToLegacy() 931 932 // Generate an ETag 933 etag := makeACLETag(parent, policy) 934 935 // Setup the response 936 reply.ETag = etag 937 reply.TTL = a.srv.config.ACLTokenTTL 938 a.srv.setQueryMeta(&reply.QueryMeta) 939 940 // Only send the policy on an Etag mis-match 941 if args.ETag != etag { 942 reply.Parent = parent 943 reply.Policy = policy 944 } 945 return nil 946 } 947 948 // ReplicationStatus is used to retrieve the current ACL replication status. 949 func (a *ACL) ReplicationStatus(args *structs.DCSpecificRequest, 950 reply *structs.ACLReplicationStatus) error { 951 // This must be sent to the leader, so we fix the args since we are 952 // re-using a structure where we don't support all the options. 953 args.RequireConsistent = true 954 args.AllowStale = false 955 if done, err := a.srv.forward("ACL.ReplicationStatus", args, args, reply); done { 956 return err 957 } 958 959 // There's no ACL token required here since this doesn't leak any 960 // sensitive information, and we don't want people to have to use 961 // management tokens if they are querying this via a health check. 962 963 // Poll the latest status. 964 a.srv.aclReplicationStatusLock.RLock() 965 *reply = a.srv.aclReplicationStatus 966 a.srv.aclReplicationStatusLock.RUnlock() 967 return nil 968 }