1package consul 2 3import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "regexp" 12 "time" 13 14 "github.com/armon/go-metrics" 15 "github.com/armon/go-metrics/prometheus" 16 "github.com/hashicorp/go-bexpr" 17 "github.com/hashicorp/go-hclog" 18 memdb "github.com/hashicorp/go-memdb" 19 uuid "github.com/hashicorp/go-uuid" 20 21 "github.com/hashicorp/consul/acl" 22 "github.com/hashicorp/consul/agent/consul/authmethod" 23 "github.com/hashicorp/consul/agent/consul/state" 24 "github.com/hashicorp/consul/agent/structs" 25 "github.com/hashicorp/consul/lib" 26 "github.com/hashicorp/consul/lib/template" 27) 28 29const ( 30 // aclBootstrapReset is the file name to create in the data dir. It's only contents 31 // should be the reset index 32 aclBootstrapReset = "acl-bootstrap-reset" 33) 34 35var ACLEndpointSummaries = []prometheus.SummaryDefinition{ 36 { 37 Name: []string{"acl", "token", "clone"}, 38 Help: "", 39 }, 40 { 41 Name: []string{"acl", "token", "upsert"}, 42 Help: "", 43 }, 44 { 45 Name: []string{"acl", "token", "delete"}, 46 Help: "", 47 }, 48 { 49 Name: []string{"acl", "policy", "upsert"}, 50 Help: "", 51 }, 52 { 53 Name: []string{"acl", "policy", "delete"}, 54 Help: "", 55 }, 56 { 57 Name: []string{"acl", "policy", "delete"}, 58 Help: "", 59 }, 60 { 61 Name: []string{"acl", "role", "upsert"}, 62 Help: "", 63 }, 64 { 65 Name: []string{"acl", "role", "delete"}, 66 Help: "", 67 }, 68 { 69 Name: []string{"acl", "bindingrule", "upsert"}, 70 Help: "", 71 }, 72 { 73 Name: []string{"acl", "bindingrule", "delete"}, 74 Help: "", 75 }, 76 { 77 Name: []string{"acl", "authmethod", "upsert"}, 78 Help: "", 79 }, 80 { 81 Name: []string{"acl", "authmethod", "delete"}, 82 Help: "", 83 }, 84 { 85 Name: []string{"acl", "login"}, 86 Help: "", 87 }, 88 { 89 Name: []string{"acl", "login"}, 90 Help: "", 91 }, 92 { 93 Name: []string{"acl", "logout"}, 94 Help: "", 95 }, 96 { 97 Name: []string{"acl", "logout"}, 98 Help: "", 99 }, 100} 101 102// Regex for matching 103var ( 104 validPolicyName = regexp.MustCompile(`^[A-Za-z0-9\-_]{1,128}$`) 105 validServiceIdentityName = regexp.MustCompile(`^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$`) 106 serviceIdentityNameMaxLength = 256 107 validNodeIdentityName = regexp.MustCompile(`^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$`) 108 nodeIdentityNameMaxLength = 256 109 validRoleName = regexp.MustCompile(`^[A-Za-z0-9\-_]{1,256}$`) 110 validAuthMethod = regexp.MustCompile(`^[A-Za-z0-9\-_]{1,128}$`) 111) 112 113// ACL endpoint is used to manipulate ACLs 114type ACL struct { 115 srv *Server 116 logger hclog.Logger 117} 118 119// fileBootstrapResetIndex retrieves the reset index specified by the administrator from 120// the file on disk. 121// 122// Q: What is the bootstrap reset index? 123// A: If you happen to lose acess to all tokens capable of ACL management you need a way 124// to get back into your system. This allows an admin to write the current 125// bootstrap "index" into a special file on disk to override the mechanism preventing 126// a second token bootstrap. The index will be retrieved by a API call to /v1/acl/bootstrap 127// When already bootstrapped this API will return the reset index necessary within 128// the error response. Once set in the file, the bootstrap API can be used again to 129// get a new token. 130// 131// Q: Why is the reset index not in the config? 132// A: We want to be able to remove the reset index once we have used it. This prevents 133// accidentally allowing bootstrapping yet again after a snapshot restore. 134// 135func (a *ACL) fileBootstrapResetIndex() uint64 { 136 // Determine the file path to check 137 path := filepath.Join(a.srv.config.DataDir, aclBootstrapReset) 138 139 // Read the file 140 raw, err := ioutil.ReadFile(path) 141 if err != nil { 142 if !os.IsNotExist(err) { 143 a.logger.Error("bootstrap: failed to read path", 144 "path", path, 145 "error", err, 146 ) 147 } 148 return 0 149 } 150 151 // Attempt to parse the file 152 var resetIdx uint64 153 if _, err := fmt.Sscanf(string(raw), "%d", &resetIdx); err != nil { 154 a.logger.Error("failed to parse bootstrap reset index path", "path", path, "error", err) 155 return 0 156 } 157 158 // Return the reset index 159 a.logger.Debug("parsed bootstrap reset index path", "path", path, "reset_index", resetIdx) 160 return resetIdx 161} 162 163func (a *ACL) removeBootstrapResetFile() { 164 if err := os.Remove(filepath.Join(a.srv.config.DataDir, aclBootstrapReset)); err != nil { 165 a.logger.Warn("failed to remove bootstrap file", "error", err) 166 } 167} 168 169func (a *ACL) aclPreCheck() error { 170 if !a.srv.config.ACLsEnabled { 171 return acl.ErrDisabled 172 } 173 174 if a.srv.UseLegacyACLs() { 175 return fmt.Errorf("The ACL system is currently in legacy mode.") 176 } 177 178 return nil 179} 180 181// Bootstrap is used to perform a one-time ACL bootstrap operation on 182// a cluster to get the first management token. 183func (a *ACL) BootstrapTokens(args *structs.DCSpecificRequest, reply *structs.ACLToken) error { 184 if err := a.aclPreCheck(); err != nil { 185 return err 186 } 187 if done, err := a.srv.ForwardRPC("ACL.BootstrapTokens", args, reply); done { 188 return err 189 } 190 191 if err := a.srv.aclBootstrapAllowed(); err != nil { 192 return err 193 } 194 195 // Verify we are allowed to serve this request 196 if !a.srv.InACLDatacenter() { 197 return acl.ErrDisabled 198 } 199 200 // By doing some pre-checks we can head off later bootstrap attempts 201 // without having to run them through Raft, which should curb abuse. 202 state := a.srv.fsm.State() 203 allowed, resetIdx, err := state.CanBootstrapACLToken() 204 if err != nil { 205 return err 206 } 207 var specifiedIndex uint64 = 0 208 if !allowed { 209 // Check if there is a reset index specified 210 specifiedIndex = a.fileBootstrapResetIndex() 211 if specifiedIndex == 0 { 212 return fmt.Errorf("ACL bootstrap no longer allowed (reset index: %d)", resetIdx) 213 } else if specifiedIndex != resetIdx { 214 return fmt.Errorf("Invalid bootstrap reset index (specified %d, reset index: %d)", specifiedIndex, resetIdx) 215 } 216 } 217 218 // remove the bootstrap override file now that we have the index from it and it was valid. 219 // whether bootstrapping works or not is irrelevant as we really don't want this file hanging around 220 // in case a snapshot restore is done. In that case we don't want to accidentally allow re-bootstrapping 221 // just because the file was unchanged. 222 a.removeBootstrapResetFile() 223 224 accessor, err := lib.GenerateUUID(a.srv.checkTokenUUID) 225 if err != nil { 226 return err 227 } 228 secret, err := lib.GenerateUUID(a.srv.checkTokenUUID) 229 if err != nil { 230 return err 231 } 232 233 req := structs.ACLTokenBootstrapRequest{ 234 Token: structs.ACLToken{ 235 AccessorID: accessor, 236 SecretID: secret, 237 Description: "Bootstrap Token (Global Management)", 238 Policies: []structs.ACLTokenPolicyLink{ 239 { 240 ID: structs.ACLPolicyGlobalManagementID, 241 }, 242 }, 243 CreateTime: time.Now(), 244 Local: false, 245 // DEPRECATED (ACL-Legacy-Compat) - This is used so that the bootstrap token is still visible via the v1 acl APIs 246 Type: structs.ACLTokenTypeManagement, 247 EnterpriseMeta: *structs.DefaultEnterpriseMeta(), 248 }, 249 ResetIndex: specifiedIndex, 250 } 251 252 req.Token.SetHash(true) 253 254 _, err = a.srv.raftApply(structs.ACLBootstrapRequestType, &req) 255 if err != nil { 256 return err 257 } 258 259 if _, token, err := state.ACLTokenGetByAccessor(nil, accessor, structs.DefaultEnterpriseMeta()); err == nil { 260 *reply = *token 261 } 262 263 a.logger.Info("ACL bootstrap completed") 264 return nil 265} 266 267func (a *ACL) TokenRead(args *structs.ACLTokenGetRequest, reply *structs.ACLTokenResponse) error { 268 if err := a.aclPreCheck(); err != nil { 269 return err 270 } 271 272 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 273 return err 274 } 275 276 // clients will not know whether the server has local token store. In the case 277 // where it doesn't we will transparently forward requests. 278 if !a.srv.LocalTokensEnabled() { 279 args.Datacenter = a.srv.config.ACLDatacenter 280 } 281 282 if done, err := a.srv.ForwardRPC("ACL.TokenRead", args, reply); done { 283 return err 284 } 285 286 var authz acl.Authorizer 287 288 if args.TokenIDType == structs.ACLTokenAccessor { 289 var err error 290 var authzContext acl.AuthorizerContext 291 // Only ACLRead privileges are required to list tokens 292 // However if you do not have ACLWrite as well the token 293 // secrets will be redacted 294 if authz, err = a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil { 295 return err 296 } else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 297 return acl.ErrPermissionDenied 298 } 299 } 300 301 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 302 func(ws memdb.WatchSet, state *state.Store) error { 303 var index uint64 304 var token *structs.ACLToken 305 var err error 306 307 if args.TokenIDType == structs.ACLTokenAccessor { 308 index, token, err = state.ACLTokenGetByAccessor(ws, args.TokenID, &args.EnterpriseMeta) 309 if token != nil { 310 a.srv.filterACLWithAuthorizer(authz, &token) 311 312 // token secret was redacted 313 if token.SecretID == redactedToken { 314 reply.Redacted = true 315 } 316 } 317 } else { 318 index, token, err = state.ACLTokenGetBySecret(ws, args.TokenID, nil) 319 // no extra validation is needed here. If you have the secret ID you can read it. 320 } 321 322 if token != nil && token.IsExpired(time.Now()) { 323 token = nil 324 } 325 326 if err != nil { 327 return err 328 } 329 330 reply.Index, reply.Token = index, token 331 reply.SourceDatacenter = args.Datacenter 332 return nil 333 }) 334} 335 336func (a *ACL) TokenClone(args *structs.ACLTokenSetRequest, reply *structs.ACLToken) error { 337 if err := a.aclPreCheck(); err != nil { 338 return err 339 } 340 341 if err := a.srv.validateEnterpriseRequest(&args.ACLToken.EnterpriseMeta, true); err != nil { 342 return err 343 } 344 345 // clients will not know whether the server has local token store. In the case 346 // where it doesn't we will transparently forward requests. 347 if !a.srv.LocalTokensEnabled() { 348 args.Datacenter = a.srv.config.ACLDatacenter 349 } 350 351 if done, err := a.srv.ForwardRPC("ACL.TokenClone", args, reply); done { 352 return err 353 } 354 355 defer metrics.MeasureSince([]string{"acl", "token", "clone"}, time.Now()) 356 357 var authzContext acl.AuthorizerContext 358 authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.ACLToken.EnterpriseMeta, &authzContext) 359 if err != nil { 360 return err 361 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 362 return acl.ErrPermissionDenied 363 } 364 365 _, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.ACLToken.AccessorID, &args.ACLToken.EnterpriseMeta) 366 if err != nil { 367 return err 368 } else if token == nil || token.IsExpired(time.Now()) { 369 return acl.ErrNotFound 370 } else if !a.srv.InACLDatacenter() && !token.Local { 371 // global token writes must be forwarded to the primary DC 372 args.Datacenter = a.srv.config.ACLDatacenter 373 return a.srv.forwardDC("ACL.TokenClone", a.srv.config.ACLDatacenter, args, reply) 374 } 375 376 if token.AuthMethod != "" { 377 return fmt.Errorf("Cannot clone a token created from an auth method") 378 } 379 380 if token.Rules != "" { 381 return fmt.Errorf("Cannot clone a legacy ACL with this endpoint") 382 } 383 384 cloneReq := structs.ACLTokenSetRequest{ 385 Datacenter: args.Datacenter, 386 ACLToken: structs.ACLToken{ 387 Policies: token.Policies, 388 Roles: token.Roles, 389 ServiceIdentities: token.ServiceIdentities, 390 NodeIdentities: token.NodeIdentities, 391 Local: token.Local, 392 Description: token.Description, 393 ExpirationTime: token.ExpirationTime, 394 EnterpriseMeta: args.ACLToken.EnterpriseMeta, 395 }, 396 WriteRequest: args.WriteRequest, 397 } 398 399 if args.ACLToken.Description != "" { 400 cloneReq.ACLToken.Description = args.ACLToken.Description 401 } 402 403 return a.tokenSetInternal(&cloneReq, reply, false) 404} 405 406func (a *ACL) TokenSet(args *structs.ACLTokenSetRequest, reply *structs.ACLToken) error { 407 if err := a.aclPreCheck(); err != nil { 408 return err 409 } 410 411 if err := a.srv.validateEnterpriseRequest(&args.ACLToken.EnterpriseMeta, true); err != nil { 412 return err 413 } 414 415 // Global token creation/modification always goes to the ACL DC 416 if !args.ACLToken.Local { 417 args.Datacenter = a.srv.config.ACLDatacenter 418 } else if !a.srv.LocalTokensEnabled() { 419 return fmt.Errorf("Local tokens are disabled") 420 } 421 422 if done, err := a.srv.ForwardRPC("ACL.TokenSet", args, reply); done { 423 return err 424 } 425 426 defer metrics.MeasureSince([]string{"acl", "token", "upsert"}, time.Now()) 427 428 // Verify token is permitted to modify ACLs 429 var authzContext acl.AuthorizerContext 430 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.ACLToken.EnterpriseMeta, &authzContext); err != nil { 431 return err 432 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 433 return acl.ErrPermissionDenied 434 } 435 436 return a.tokenSetInternal(args, reply, false) 437} 438 439func (a *ACL) tokenSetInternal(args *structs.ACLTokenSetRequest, reply *structs.ACLToken, fromLogin bool) error { 440 token := &args.ACLToken 441 442 if !a.srv.LocalTokensEnabled() { 443 // local token operations 444 return fmt.Errorf("Cannot upsert tokens within this datacenter") 445 } else if !a.srv.InACLDatacenter() && !token.Local { 446 return fmt.Errorf("Cannot upsert global tokens within this datacenter") 447 } 448 449 state := a.srv.fsm.State() 450 451 var accessorMatch *structs.ACLToken 452 var secretMatch *structs.ACLToken 453 var err error 454 455 if token.AccessorID != "" { 456 _, accessorMatch, err = state.ACLTokenGetByAccessor(nil, token.AccessorID, nil) 457 if err != nil { 458 return fmt.Errorf("Failed acl token lookup by accessor: %v", err) 459 } 460 } 461 if token.SecretID != "" { 462 _, secretMatch, err = state.ACLTokenGetBySecret(nil, token.SecretID, nil) 463 if err != nil { 464 return fmt.Errorf("Failed acl token lookup by secret: %v", err) 465 } 466 } 467 468 if token.AccessorID == "" || args.Create { 469 // Token Create 470 471 // Generate the AccessorID if not specified 472 if token.AccessorID == "" { 473 token.AccessorID, err = lib.GenerateUUID(a.srv.checkTokenUUID) 474 if err != nil { 475 return err 476 } 477 } else if _, err := uuid.ParseUUID(token.AccessorID); err != nil { 478 return fmt.Errorf("Invalid Token: AccessorID is not a valid UUID") 479 } else if accessorMatch != nil { 480 return fmt.Errorf("Invalid Token: AccessorID is already in use") 481 } else if _, match, err := state.ACLTokenGetBySecret(nil, token.AccessorID, nil); err != nil || match != nil { 482 if err != nil { 483 return fmt.Errorf("Failed to lookup the acl token: %v", err) 484 } 485 return fmt.Errorf("Invalid Token: AccessorID is already in use") 486 } else if structs.ACLIDReserved(token.AccessorID) { 487 return fmt.Errorf("Invalid Token: UUIDs with the prefix %q are reserved", structs.ACLReservedPrefix) 488 } 489 490 // Generate the SecretID if not specified 491 if token.SecretID == "" { 492 token.SecretID, err = lib.GenerateUUID(a.srv.checkTokenUUID) 493 if err != nil { 494 return err 495 } 496 } else if _, err := uuid.ParseUUID(token.SecretID); err != nil { 497 return fmt.Errorf("Invalid Token: SecretID is not a valid UUID") 498 } else if secretMatch != nil { 499 return fmt.Errorf("Invalid Token: SecretID is already in use") 500 } else if _, match, err := state.ACLTokenGetByAccessor(nil, token.SecretID, nil); err != nil || match != nil { 501 if err != nil { 502 return fmt.Errorf("Failed to lookup the acl token: %v", err) 503 } 504 return fmt.Errorf("Invalid Token: SecretID is already in use") 505 } else if structs.ACLIDReserved(token.SecretID) { 506 return fmt.Errorf("Invalid Token: UUIDs with the prefix %q are reserved", structs.ACLReservedPrefix) 507 } 508 509 token.CreateTime = time.Now() 510 511 if fromLogin { 512 if token.AuthMethod == "" { 513 return fmt.Errorf("AuthMethod field is required during Login") 514 } 515 } else { 516 if token.AuthMethod != "" { 517 return fmt.Errorf("AuthMethod field is disallowed outside of Login") 518 } 519 } 520 521 // Ensure an ExpirationTTL is valid if provided. 522 if token.ExpirationTTL != 0 { 523 if token.ExpirationTTL < 0 { 524 return fmt.Errorf("Token Expiration TTL '%s' should be > 0", token.ExpirationTTL) 525 } 526 if token.HasExpirationTime() { 527 return fmt.Errorf("Token Expiration TTL and Expiration Time cannot both be set") 528 } 529 530 token.ExpirationTime = timePointer(token.CreateTime.Add(token.ExpirationTTL)) 531 token.ExpirationTTL = 0 532 } 533 534 if token.HasExpirationTime() { 535 if token.CreateTime.After(*token.ExpirationTime) { 536 return fmt.Errorf("ExpirationTime cannot be before CreateTime") 537 } 538 539 expiresIn := token.ExpirationTime.Sub(token.CreateTime) 540 if expiresIn > a.srv.config.ACLTokenMaxExpirationTTL { 541 return fmt.Errorf("ExpirationTime cannot be more than %s in the future (was %s)", 542 a.srv.config.ACLTokenMaxExpirationTTL, expiresIn) 543 } else if expiresIn < a.srv.config.ACLTokenMinExpirationTTL { 544 return fmt.Errorf("ExpirationTime cannot be less than %s in the future (was %s)", 545 a.srv.config.ACLTokenMinExpirationTTL, expiresIn) 546 } 547 } 548 } else { 549 // Token Update 550 if _, err := uuid.ParseUUID(token.AccessorID); err != nil { 551 return fmt.Errorf("AccessorID is not a valid UUID") 552 } 553 554 // DEPRECATED (ACL-Legacy-Compat) - maybe get rid of this in the future 555 // and instead do a ParseUUID check. New tokens will not have 556 // secrets generated by users but rather they will always be UUIDs. 557 // However if users just continue the upgrade cycle they may still 558 // have tokens using secrets that are not UUIDS 559 // The RootAuthorizer checks that the SecretID is not "allow", "deny" 560 // or "manage" as a precaution against something accidentally using 561 // one of these root policies by setting the secret to it. 562 if acl.RootAuthorizer(token.SecretID) != nil { 563 return acl.PermissionDeniedError{Cause: "Cannot modify root ACL"} 564 } 565 566 // Verify the token exists 567 if accessorMatch == nil || accessorMatch.IsExpired(time.Now()) { 568 return fmt.Errorf("Cannot find token %q", token.AccessorID) 569 } 570 if token.SecretID == "" { 571 token.SecretID = accessorMatch.SecretID 572 } else if accessorMatch.SecretID != token.SecretID { 573 return fmt.Errorf("Changing a tokens SecretID is not permitted") 574 } 575 576 // Cannot toggle the "Global" mode 577 if token.Local != accessorMatch.Local { 578 return fmt.Errorf("cannot toggle local mode of %s", token.AccessorID) 579 } 580 581 if token.AuthMethod == "" { 582 token.AuthMethod = accessorMatch.AuthMethod 583 } else if token.AuthMethod != accessorMatch.AuthMethod { 584 return fmt.Errorf("Cannot change AuthMethod of %s", token.AccessorID) 585 } 586 587 if token.ExpirationTTL != 0 { 588 return fmt.Errorf("Cannot change expiration time of %s", token.AccessorID) 589 } 590 591 if !token.HasExpirationTime() { 592 token.ExpirationTime = accessorMatch.ExpirationTime 593 } else if !accessorMatch.HasExpirationTime() { 594 return fmt.Errorf("Cannot change expiration time of %s", token.AccessorID) 595 } else if !token.ExpirationTime.Equal(*accessorMatch.ExpirationTime) { 596 return fmt.Errorf("Cannot change expiration time of %s", token.AccessorID) 597 } 598 599 token.CreateTime = accessorMatch.CreateTime 600 } 601 602 policyIDs := make(map[string]struct{}) 603 var policies []structs.ACLTokenPolicyLink 604 605 // Validate all the policy names and convert them to policy IDs 606 for _, link := range token.Policies { 607 if link.ID == "" { 608 _, policy, err := state.ACLPolicyGetByName(nil, link.Name, &token.EnterpriseMeta) 609 if err != nil { 610 return fmt.Errorf("Error looking up policy for name %q: %v", link.Name, err) 611 } 612 if policy == nil { 613 return fmt.Errorf("No such ACL policy with name %q", link.Name) 614 } 615 link.ID = policy.ID 616 } else { 617 _, policy, err := state.ACLPolicyGetByID(nil, link.ID, &token.EnterpriseMeta) 618 if err != nil { 619 return fmt.Errorf("Error looking up policy for id %q: %v", link.ID, err) 620 } 621 622 if policy == nil { 623 return fmt.Errorf("No such ACL policy with ID %q", link.ID) 624 } 625 } 626 627 // Do not store the policy name within raft/memdb as the policy could be renamed in the future. 628 link.Name = "" 629 630 // dedup policy links by id 631 if _, ok := policyIDs[link.ID]; !ok { 632 policies = append(policies, link) 633 policyIDs[link.ID] = struct{}{} 634 } 635 } 636 token.Policies = policies 637 638 roleIDs := make(map[string]struct{}) 639 var roles []structs.ACLTokenRoleLink 640 641 // Validate all the role names and convert them to role IDs. 642 for _, link := range token.Roles { 643 if link.ID == "" { 644 _, role, err := state.ACLRoleGetByName(nil, link.Name, &token.EnterpriseMeta) 645 if err != nil { 646 return fmt.Errorf("Error looking up role for name %q: %v", link.Name, err) 647 } 648 if role == nil { 649 return fmt.Errorf("No such ACL role with name %q", link.Name) 650 } 651 link.ID = role.ID 652 } else { 653 _, role, err := state.ACLRoleGetByID(nil, link.ID, &token.EnterpriseMeta) 654 if err != nil { 655 return fmt.Errorf("Error looking up role for id %q: %v", link.ID, err) 656 } 657 658 if role == nil { 659 return fmt.Errorf("No such ACL role with ID %q", link.ID) 660 } 661 } 662 663 // Do not store the role name within raft/memdb as the role could be renamed in the future. 664 link.Name = "" 665 666 // dedup role links by id 667 if _, ok := roleIDs[link.ID]; !ok { 668 roles = append(roles, link) 669 roleIDs[link.ID] = struct{}{} 670 } 671 } 672 token.Roles = roles 673 674 for _, svcid := range token.ServiceIdentities { 675 if svcid.ServiceName == "" { 676 return fmt.Errorf("Service identity is missing the service name field on this token") 677 } 678 if token.Local && len(svcid.Datacenters) > 0 { 679 return fmt.Errorf("Service identity %q cannot specify a list of datacenters on a local token", svcid.ServiceName) 680 } 681 if !isValidServiceIdentityName(svcid.ServiceName) { 682 return fmt.Errorf("Service identity %q has an invalid name. Only alphanumeric characters, '-' and '_' are allowed", svcid.ServiceName) 683 } 684 } 685 token.ServiceIdentities = dedupeServiceIdentities(token.ServiceIdentities) 686 687 for _, nodeid := range token.NodeIdentities { 688 if nodeid.NodeName == "" { 689 return fmt.Errorf("Node identity is missing the node name field on this token") 690 } 691 if nodeid.Datacenter == "" { 692 return fmt.Errorf("Node identity is missing the datacenter field on this token") 693 } 694 if !isValidNodeIdentityName(nodeid.NodeName) { 695 return fmt.Errorf("Node identity has an invalid name. Only alphanumeric characters, '-' and '_' are allowed") 696 } 697 } 698 token.NodeIdentities = dedupeNodeIdentities(token.NodeIdentities) 699 700 if token.Rules != "" { 701 return fmt.Errorf("Rules cannot be specified for this token") 702 } 703 704 if token.Type != "" { 705 return fmt.Errorf("Type cannot be specified for this token") 706 } 707 708 token.SetHash(true) 709 710 // validate the enterprise meta 711 err = state.ACLTokenUpsertValidateEnterprise(token, accessorMatch) 712 if err != nil { 713 return err 714 } 715 716 req := &structs.ACLTokenBatchSetRequest{ 717 Tokens: structs.ACLTokens{token}, 718 CAS: false, 719 } 720 721 if fromLogin { 722 // Logins may attempt to link to roles that do not exist. These 723 // may be persisted, but don't allow tokens to be created that 724 // have no privileges (i.e. role links that point nowhere). 725 req.AllowMissingLinks = true 726 req.ProhibitUnprivileged = true 727 } 728 729 _, err = a.srv.raftApply(structs.ACLTokenSetRequestType, req) 730 if err != nil { 731 return fmt.Errorf("Failed to apply token write request: %v", err) 732 } 733 734 // Purge the identity from the cache to prevent using the previous definition of the identity 735 a.srv.acls.cache.RemoveIdentity(tokenSecretCacheID(token.SecretID)) 736 737 // Don't check expiration times here as it doesn't really matter. 738 if _, updatedToken, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, token.AccessorID, nil); err == nil && updatedToken != nil { 739 *reply = *updatedToken 740 } else { 741 return fmt.Errorf("Failed to retrieve the token after insertion") 742 } 743 744 return nil 745} 746 747func validateBindingRuleBindName(bindType, bindName string, availableFields []string) (bool, error) { 748 if bindType == "" || bindName == "" { 749 return false, nil 750 } 751 752 fakeVarMap := make(map[string]string) 753 for _, v := range availableFields { 754 fakeVarMap[v] = "fake" 755 } 756 757 _, valid, err := computeBindingRuleBindName(bindType, bindName, fakeVarMap) 758 if err != nil { 759 return false, err 760 } 761 return valid, nil 762} 763 764// computeBindingRuleBindName processes the HIL for the provided bind type+name 765// using the projected variables. 766// 767// - If the HIL is invalid ("", false, AN_ERROR) is returned. 768// - If the computed name is not valid for the type ("INVALID_NAME", false, nil) is returned. 769// - If the computed name is valid for the type ("VALID_NAME", true, nil) is returned. 770func computeBindingRuleBindName(bindType, bindName string, projectedVars map[string]string) (string, bool, error) { 771 bindName, err := template.InterpolateHIL(bindName, projectedVars, true) 772 if err != nil { 773 return "", false, err 774 } 775 776 valid := false 777 778 switch bindType { 779 case structs.BindingRuleBindTypeService: 780 valid = isValidServiceIdentityName(bindName) 781 case structs.BindingRuleBindTypeNode: 782 valid = isValidNodeIdentityName(bindName) 783 case structs.BindingRuleBindTypeRole: 784 valid = validRoleName.MatchString(bindName) 785 786 default: 787 return "", false, fmt.Errorf("unknown binding rule bind type: %s", bindType) 788 } 789 790 return bindName, valid, nil 791} 792 793// isValidServiceIdentityName returns true if the provided name can be used as 794// an ACLServiceIdentity ServiceName. This is more restrictive than standard 795// catalog registration, which basically takes the view that "everything is 796// valid". 797func isValidServiceIdentityName(name string) bool { 798 if len(name) < 1 || len(name) > serviceIdentityNameMaxLength { 799 return false 800 } 801 return validServiceIdentityName.MatchString(name) 802} 803 804// isValidNodeIdentityName returns true if the provided name can be used as 805// an ACLNodeIdentity NodeName. This is more restrictive than standard 806// catalog registration, which basically takes the view that "everything is 807// valid". 808func isValidNodeIdentityName(name string) bool { 809 if len(name) < 1 || len(name) > nodeIdentityNameMaxLength { 810 return false 811 } 812 return validNodeIdentityName.MatchString(name) 813} 814 815func (a *ACL) TokenDelete(args *structs.ACLTokenDeleteRequest, reply *string) error { 816 if err := a.aclPreCheck(); err != nil { 817 return err 818 } 819 820 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil { 821 return err 822 } 823 824 if !a.srv.LocalTokensEnabled() { 825 args.Datacenter = a.srv.config.ACLDatacenter 826 } 827 828 if done, err := a.srv.ForwardRPC("ACL.TokenDelete", args, reply); done { 829 return err 830 } 831 832 defer metrics.MeasureSince([]string{"acl", "token", "delete"}, time.Now()) 833 834 // Verify token is permitted to modify ACLs 835 var authzContext acl.AuthorizerContext 836 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil { 837 return err 838 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 839 return acl.ErrPermissionDenied 840 } 841 842 if _, err := uuid.ParseUUID(args.TokenID); err != nil { 843 return fmt.Errorf("Accessor ID is missing or an invalid UUID") 844 } 845 846 if args.TokenID == structs.ACLTokenAnonymousID { 847 return fmt.Errorf("Delete operation not permitted on the anonymous token") 848 } 849 850 // grab the token here so we can invalidate our cache later on 851 _, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.TokenID, &args.EnterpriseMeta) 852 if err != nil { 853 return err 854 } 855 856 if token != nil { 857 if args.Token == token.SecretID { 858 return fmt.Errorf("Deletion of the request's authorization token is not permitted") 859 } 860 861 // No need to check expiration time because it's being deleted. 862 863 // token found in secondary DC but its not local so it must be deleted in the primary 864 if !a.srv.InACLDatacenter() && !token.Local { 865 args.Datacenter = a.srv.config.ACLDatacenter 866 return a.srv.forwardDC("ACL.TokenDelete", a.srv.config.ACLDatacenter, args, reply) 867 } 868 } else if !a.srv.InACLDatacenter() { 869 // token not found in secondary DC - attempt to delete within the primary 870 args.Datacenter = a.srv.config.ACLDatacenter 871 return a.srv.forwardDC("ACL.TokenDelete", a.srv.config.ACLDatacenter, args, reply) 872 } else { 873 // in Primary Datacenter but the token does not exist - return early as there is nothing to do. 874 return nil 875 } 876 877 req := &structs.ACLTokenBatchDeleteRequest{ 878 TokenIDs: []string{args.TokenID}, 879 } 880 881 _, err = a.srv.raftApply(structs.ACLTokenDeleteRequestType, req) 882 if err != nil { 883 return fmt.Errorf("Failed to apply token delete request: %v", err) 884 } 885 886 // Purge the identity from the cache to prevent using the previous definition of the identity 887 a.srv.acls.cache.RemoveIdentity(tokenSecretCacheID(token.SecretID)) 888 889 if reply != nil { 890 *reply = token.AccessorID 891 } 892 893 return nil 894} 895 896func (a *ACL) TokenList(args *structs.ACLTokenListRequest, reply *structs.ACLTokenListResponse) error { 897 if err := a.aclPreCheck(); err != nil { 898 return err 899 } 900 901 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 902 return err 903 } 904 905 if !a.srv.LocalTokensEnabled() { 906 if args.Datacenter != a.srv.config.ACLDatacenter { 907 args.Datacenter = a.srv.config.ACLDatacenter 908 args.IncludeLocal = false 909 args.IncludeGlobal = true 910 } 911 args.Datacenter = a.srv.config.ACLDatacenter 912 } 913 914 if done, err := a.srv.ForwardRPC("ACL.TokenList", args, reply); done { 915 return err 916 } 917 918 var authzContext acl.AuthorizerContext 919 var requestMeta structs.EnterpriseMeta 920 authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &requestMeta, &authzContext) 921 if err != nil { 922 return err 923 } 924 // merge the token default meta into the requests meta 925 args.EnterpriseMeta.Merge(&requestMeta) 926 args.EnterpriseMeta.FillAuthzContext(&authzContext) 927 if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 928 return acl.ErrPermissionDenied 929 } 930 931 var methodMeta *structs.EnterpriseMeta 932 if args.AuthMethod != "" { 933 methodMeta = args.ACLAuthMethodEnterpriseMeta.ToEnterpriseMeta() 934 // attempt to merge in the overall meta, wildcards will not be merged 935 methodMeta.MergeNoWildcard(&args.EnterpriseMeta) 936 // in the event that the meta above didn't merge due to being a wildcard 937 // we ensure that proper token based meta inference occurs 938 methodMeta.Merge(&requestMeta) 939 } 940 941 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 942 func(ws memdb.WatchSet, state *state.Store) error { 943 index, tokens, err := state.ACLTokenList(ws, args.IncludeLocal, args.IncludeGlobal, args.Policy, args.Role, args.AuthMethod, methodMeta, &args.EnterpriseMeta) 944 if err != nil { 945 return err 946 } 947 948 now := time.Now() 949 950 stubs := make([]*structs.ACLTokenListStub, 0, len(tokens)) 951 for _, token := range tokens { 952 if token.IsExpired(now) { 953 continue 954 } 955 stubs = append(stubs, token.Stub()) 956 } 957 958 // filter down to just the tokens that the requester has permissions to read 959 if err := a.srv.filterACLWithAuthorizer(authz, &stubs); err != nil { 960 return err 961 } 962 963 reply.Index, reply.Tokens = index, stubs 964 return nil 965 }) 966} 967 968func (a *ACL) TokenBatchRead(args *structs.ACLTokenBatchGetRequest, reply *structs.ACLTokenBatchResponse) error { 969 if err := a.aclPreCheck(); err != nil { 970 return err 971 } 972 973 if !a.srv.LocalTokensEnabled() { 974 args.Datacenter = a.srv.config.ACLDatacenter 975 } 976 977 if done, err := a.srv.ForwardRPC("ACL.TokenBatchRead", args, reply); done { 978 return err 979 } 980 981 authz, err := a.srv.ResolveToken(args.Token) 982 if err != nil { 983 return err 984 } else if authz == nil { 985 return acl.ErrPermissionDenied 986 } 987 988 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 989 func(ws memdb.WatchSet, state *state.Store) error { 990 index, tokens, err := state.ACLTokenBatchGet(ws, args.AccessorIDs) 991 if err != nil { 992 return err 993 } 994 995 // This RPC is used for replication, so don't filter out expired tokens here. 996 997 // Filter the tokens down to just what we have permission to see - also redact 998 // secrets based on allowed permissions. We could just call filterACLWithAuthorizer 999 // on the whole token list but then it would require another pass through the token 1000 // list to determine if any secrets were redacted. Its a small amount of code to 1001 // process the loop so it was duplicated here and we instead call the filter func 1002 // with just a single token. 1003 ret := make(structs.ACLTokens, 0, len(tokens)) 1004 for _, token := range tokens { 1005 final := token 1006 a.srv.filterACLWithAuthorizer(authz, &final) 1007 if final != nil { 1008 ret = append(ret, final) 1009 if final.SecretID == redactedToken { 1010 reply.Redacted = true 1011 } 1012 } else { 1013 reply.Removed = true 1014 } 1015 } 1016 1017 reply.Index, reply.Tokens = index, ret 1018 return nil 1019 }) 1020} 1021 1022func (a *ACL) PolicyRead(args *structs.ACLPolicyGetRequest, reply *structs.ACLPolicyResponse) error { 1023 if err := a.aclPreCheck(); err != nil { 1024 return err 1025 } 1026 1027 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 1028 return err 1029 } 1030 1031 if done, err := a.srv.ForwardRPC("ACL.PolicyRead", args, reply); done { 1032 return err 1033 } 1034 1035 var authzContext acl.AuthorizerContext 1036 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil { 1037 return err 1038 } else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 1039 return acl.ErrPermissionDenied 1040 } 1041 1042 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 1043 func(ws memdb.WatchSet, state *state.Store) error { 1044 var ( 1045 index uint64 1046 policy *structs.ACLPolicy 1047 err error 1048 ) 1049 if args.PolicyID != "" { 1050 index, policy, err = state.ACLPolicyGetByID(ws, args.PolicyID, &args.EnterpriseMeta) 1051 } else { 1052 index, policy, err = state.ACLPolicyGetByName(ws, args.PolicyName, &args.EnterpriseMeta) 1053 } 1054 1055 if err != nil { 1056 return err 1057 } 1058 1059 reply.Index, reply.Policy = index, policy 1060 return nil 1061 }) 1062} 1063 1064func (a *ACL) PolicyBatchRead(args *structs.ACLPolicyBatchGetRequest, reply *structs.ACLPolicyBatchResponse) error { 1065 if err := a.aclPreCheck(); err != nil { 1066 return err 1067 } 1068 1069 if done, err := a.srv.ForwardRPC("ACL.PolicyBatchRead", args, reply); done { 1070 return err 1071 } 1072 1073 authz, err := a.srv.ResolveToken(args.Token) 1074 if err != nil { 1075 return err 1076 } else if authz == nil { 1077 return acl.ErrPermissionDenied 1078 } 1079 1080 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 1081 func(ws memdb.WatchSet, state *state.Store) error { 1082 index, policies, err := state.ACLPolicyBatchGet(ws, args.PolicyIDs) 1083 if err != nil { 1084 return err 1085 } 1086 1087 a.srv.filterACLWithAuthorizer(authz, &policies) 1088 1089 reply.Index, reply.Policies = index, policies 1090 return nil 1091 }) 1092} 1093 1094func (a *ACL) PolicySet(args *structs.ACLPolicySetRequest, reply *structs.ACLPolicy) error { 1095 if err := a.aclPreCheck(); err != nil { 1096 return err 1097 } 1098 1099 if err := a.srv.validateEnterpriseRequest(&args.Policy.EnterpriseMeta, true); err != nil { 1100 return err 1101 } 1102 1103 if !a.srv.InACLDatacenter() { 1104 args.Datacenter = a.srv.config.ACLDatacenter 1105 } 1106 1107 if done, err := a.srv.ForwardRPC("ACL.PolicySet", args, reply); done { 1108 return err 1109 } 1110 1111 defer metrics.MeasureSince([]string{"acl", "policy", "upsert"}, time.Now()) 1112 1113 // Verify token is permitted to modify ACLs 1114 var authzContext acl.AuthorizerContext 1115 1116 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.Policy.EnterpriseMeta, &authzContext); err != nil { 1117 return err 1118 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 1119 return acl.ErrPermissionDenied 1120 } 1121 1122 policy := &args.Policy 1123 state := a.srv.fsm.State() 1124 1125 // Almost all of the checks here are also done in the state store. However, 1126 // we want to prevent the raft operations when we know they are going to fail 1127 // so we still do them here. 1128 1129 // ensure a name is set 1130 if policy.Name == "" { 1131 return fmt.Errorf("Invalid Policy: no Name is set") 1132 } 1133 1134 if !validPolicyName.MatchString(policy.Name) { 1135 return fmt.Errorf("Invalid Policy: invalid Name. Only alphanumeric characters, '-' and '_' are allowed") 1136 } 1137 1138 var idMatch *structs.ACLPolicy 1139 var nameMatch *structs.ACLPolicy 1140 var err error 1141 1142 if policy.ID != "" { 1143 if _, err := uuid.ParseUUID(policy.ID); err != nil { 1144 return fmt.Errorf("Policy ID invalid UUID") 1145 } 1146 1147 _, idMatch, err = state.ACLPolicyGetByID(nil, policy.ID, nil) 1148 if err != nil { 1149 return fmt.Errorf("acl policy lookup by id failed: %v", err) 1150 } 1151 } 1152 _, nameMatch, err = state.ACLPolicyGetByName(nil, policy.Name, &policy.EnterpriseMeta) 1153 if err != nil { 1154 return fmt.Errorf("acl policy lookup by name failed: %v", err) 1155 } 1156 1157 if policy.ID == "" { 1158 // with no policy ID one will be generated 1159 var err error 1160 policy.ID, err = lib.GenerateUUID(a.srv.checkPolicyUUID) 1161 if err != nil { 1162 return err 1163 } 1164 1165 // validate the name is unique 1166 if nameMatch != nil { 1167 return fmt.Errorf("Invalid Policy: A Policy with Name %q already exists", policy.Name) 1168 } 1169 } else { 1170 // Verify the policy exists 1171 if idMatch == nil { 1172 return fmt.Errorf("cannot find policy %s", policy.ID) 1173 } 1174 1175 // Verify that the name isn't changing or that the name is not already used 1176 if idMatch.Name != policy.Name && nameMatch != nil { 1177 return fmt.Errorf("Invalid Policy: A policy with name %q already exists", policy.Name) 1178 } 1179 1180 if policy.ID == structs.ACLPolicyGlobalManagementID { 1181 if policy.Datacenters != nil || len(policy.Datacenters) > 0 { 1182 return fmt.Errorf("Changing the Datacenters of the builtin global-management policy is not permitted") 1183 } 1184 1185 if policy.Rules != idMatch.Rules { 1186 return fmt.Errorf("Changing the Rules for the builtin global-management policy is not permitted") 1187 } 1188 } 1189 } 1190 1191 // validate the rules 1192 _, err = acl.NewPolicyFromSource("", 0, policy.Rules, policy.Syntax, a.srv.aclConfig, policy.EnterprisePolicyMeta()) 1193 if err != nil { 1194 return err 1195 } 1196 1197 // validate the enterprise meta 1198 err = state.ACLPolicyUpsertValidateEnterprise(policy, idMatch) 1199 if err != nil { 1200 return err 1201 } 1202 1203 // calculate the hash for this policy 1204 policy.SetHash(true) 1205 1206 req := &structs.ACLPolicyBatchSetRequest{ 1207 Policies: structs.ACLPolicies{policy}, 1208 } 1209 1210 _, err = a.srv.raftApply(structs.ACLPolicySetRequestType, req) 1211 if err != nil { 1212 return fmt.Errorf("Failed to apply policy upsert request: %v", err) 1213 } 1214 1215 // Remove from the cache to prevent stale cache usage 1216 a.srv.acls.cache.RemovePolicy(policy.ID) 1217 1218 if _, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, policy.ID, &policy.EnterpriseMeta); err == nil && policy != nil { 1219 *reply = *policy 1220 } 1221 1222 return nil 1223} 1224 1225func (a *ACL) PolicyDelete(args *structs.ACLPolicyDeleteRequest, reply *string) error { 1226 if err := a.aclPreCheck(); err != nil { 1227 return err 1228 } 1229 1230 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil { 1231 return err 1232 } 1233 1234 if !a.srv.InACLDatacenter() { 1235 args.Datacenter = a.srv.config.ACLDatacenter 1236 } 1237 1238 if done, err := a.srv.ForwardRPC("ACL.PolicyDelete", args, reply); done { 1239 return err 1240 } 1241 1242 defer metrics.MeasureSince([]string{"acl", "policy", "delete"}, time.Now()) 1243 1244 // Verify token is permitted to modify ACLs 1245 var authzContext acl.AuthorizerContext 1246 1247 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil { 1248 return err 1249 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 1250 return acl.ErrPermissionDenied 1251 } 1252 1253 _, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, args.PolicyID, &args.EnterpriseMeta) 1254 if err != nil { 1255 return err 1256 } 1257 1258 if policy == nil { 1259 return nil 1260 } 1261 1262 if policy.ID == structs.ACLPolicyGlobalManagementID { 1263 return fmt.Errorf("Delete operation not permitted on the builtin global-management policy") 1264 } 1265 1266 req := structs.ACLPolicyBatchDeleteRequest{ 1267 PolicyIDs: []string{args.PolicyID}, 1268 } 1269 1270 _, err = a.srv.raftApply(structs.ACLPolicyDeleteRequestType, &req) 1271 if err != nil { 1272 return fmt.Errorf("Failed to apply policy delete request: %v", err) 1273 } 1274 1275 a.srv.acls.cache.RemovePolicy(policy.ID) 1276 1277 *reply = policy.Name 1278 1279 return nil 1280} 1281 1282func (a *ACL) PolicyList(args *structs.ACLPolicyListRequest, reply *structs.ACLPolicyListResponse) error { 1283 if err := a.aclPreCheck(); err != nil { 1284 return err 1285 } 1286 1287 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 1288 return err 1289 } 1290 1291 if done, err := a.srv.ForwardRPC("ACL.PolicyList", args, reply); done { 1292 return err 1293 } 1294 1295 var authzContext acl.AuthorizerContext 1296 1297 authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext) 1298 if err != nil { 1299 return err 1300 } else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 1301 return acl.ErrPermissionDenied 1302 } 1303 1304 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 1305 func(ws memdb.WatchSet, state *state.Store) error { 1306 index, policies, err := state.ACLPolicyList(ws, &args.EnterpriseMeta) 1307 if err != nil { 1308 return err 1309 } 1310 1311 // filter down to just what the requester has permissions to see 1312 a.srv.filterACLWithAuthorizer(authz, &policies) 1313 1314 var stubs structs.ACLPolicyListStubs 1315 for _, policy := range policies { 1316 stubs = append(stubs, policy.Stub()) 1317 } 1318 1319 reply.Index, reply.Policies = index, stubs 1320 return nil 1321 }) 1322} 1323 1324// PolicyResolve is used to retrieve a subset of the policies associated with a given token 1325// The policy ids in the args simply act as a filter on the policy set assigned to the token 1326func (a *ACL) PolicyResolve(args *structs.ACLPolicyBatchGetRequest, reply *structs.ACLPolicyBatchResponse) error { 1327 if err := a.aclPreCheck(); err != nil { 1328 return err 1329 } 1330 1331 if done, err := a.srv.ForwardRPC("ACL.PolicyResolve", args, reply); done { 1332 return err 1333 } 1334 1335 // get full list of policies for this token 1336 identity, policies, err := a.srv.acls.resolveTokenToIdentityAndPolicies(args.Token) 1337 if err != nil { 1338 return err 1339 } 1340 1341 entIdentity, entPolicies, err := a.srv.acls.resolveEnterpriseIdentityAndPolicies(identity) 1342 if err != nil { 1343 return err 1344 } 1345 1346 idMap := make(map[string]*structs.ACLPolicy) 1347 for _, policyID := range identity.PolicyIDs() { 1348 idMap[policyID] = nil 1349 } 1350 if entIdentity != nil { 1351 for _, policyID := range entIdentity.PolicyIDs() { 1352 idMap[policyID] = nil 1353 } 1354 } 1355 1356 for _, policy := range policies { 1357 idMap[policy.ID] = policy 1358 } 1359 for _, policy := range entPolicies { 1360 idMap[policy.ID] = policy 1361 } 1362 1363 for _, policyID := range args.PolicyIDs { 1364 if policy, ok := idMap[policyID]; ok { 1365 // only add non-deleted policies 1366 if policy != nil { 1367 reply.Policies = append(reply.Policies, policy) 1368 } 1369 } else { 1370 // send a permission denied to indicate that the request included 1371 // policy ids not associated with this token 1372 return acl.ErrPermissionDenied 1373 } 1374 } 1375 1376 a.srv.setQueryMeta(&reply.QueryMeta) 1377 1378 return nil 1379} 1380 1381// makeACLETag returns an ETag for the given parent and policy. 1382func makeACLETag(parent string, policy *acl.Policy) string { 1383 return fmt.Sprintf("%s:%s", parent, policy.ID) 1384} 1385 1386// GetPolicy is used to retrieve a compiled policy object with a TTL. Does not 1387// support a blocking query. 1388func (a *ACL) GetPolicy(args *structs.ACLPolicyResolveLegacyRequest, reply *structs.ACLPolicyResolveLegacyResponse) error { 1389 if done, err := a.srv.ForwardRPC("ACL.GetPolicy", args, reply); done { 1390 return err 1391 } 1392 1393 // Verify we are allowed to serve this request 1394 if a.srv.config.ACLDatacenter != a.srv.config.Datacenter { 1395 return acl.ErrDisabled 1396 } 1397 1398 // Get the policy via the cache 1399 parent := a.srv.config.ACLDefaultPolicy 1400 1401 ident, policy, err := a.srv.acls.GetMergedPolicyForToken(args.ACL) 1402 if err != nil { 1403 return err 1404 } 1405 1406 if token, ok := ident.(*structs.ACLToken); ok && token.Type == structs.ACLTokenTypeManagement { 1407 parent = "manage" 1408 } 1409 1410 // translates the structures internals to most closely match what could be expressed in the original rule language 1411 policy = policy.ConvertToLegacy() 1412 1413 // Generate an ETag 1414 etag := makeACLETag(parent, policy) 1415 1416 // Setup the response 1417 reply.ETag = etag 1418 reply.TTL = a.srv.config.ACLTokenTTL 1419 a.srv.setQueryMeta(&reply.QueryMeta) 1420 1421 // Only send the policy on an Etag mis-match 1422 if args.ETag != etag { 1423 reply.Parent = parent 1424 reply.Policy = policy 1425 } 1426 return nil 1427} 1428 1429// ReplicationStatus is used to retrieve the current ACL replication status. 1430func (a *ACL) ReplicationStatus(args *structs.DCSpecificRequest, 1431 reply *structs.ACLReplicationStatus) error { 1432 // This must be sent to the leader, so we fix the args since we are 1433 // re-using a structure where we don't support all the options. 1434 args.RequireConsistent = true 1435 args.AllowStale = false 1436 if done, err := a.srv.ForwardRPC("ACL.ReplicationStatus", args, reply); done { 1437 return err 1438 } 1439 1440 // There's no ACL token required here since this doesn't leak any 1441 // sensitive information, and we don't want people to have to use 1442 // management tokens if they are querying this via a health check. 1443 1444 // Poll the latest status. 1445 a.srv.aclReplicationStatusLock.RLock() 1446 *reply = a.srv.aclReplicationStatus 1447 a.srv.aclReplicationStatusLock.RUnlock() 1448 return nil 1449} 1450 1451func timePointer(t time.Time) *time.Time { 1452 return &t 1453} 1454 1455func (a *ACL) RoleRead(args *structs.ACLRoleGetRequest, reply *structs.ACLRoleResponse) error { 1456 if err := a.aclPreCheck(); err != nil { 1457 return err 1458 } 1459 1460 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 1461 return err 1462 } 1463 1464 if done, err := a.srv.ForwardRPC("ACL.RoleRead", args, reply); done { 1465 return err 1466 } 1467 1468 var authzContext acl.AuthorizerContext 1469 1470 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil { 1471 return err 1472 } else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 1473 return acl.ErrPermissionDenied 1474 } 1475 1476 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 1477 func(ws memdb.WatchSet, state *state.Store) error { 1478 var ( 1479 index uint64 1480 role *structs.ACLRole 1481 err error 1482 ) 1483 if args.RoleID != "" { 1484 index, role, err = state.ACLRoleGetByID(ws, args.RoleID, &args.EnterpriseMeta) 1485 } else { 1486 index, role, err = state.ACLRoleGetByName(ws, args.RoleName, &args.EnterpriseMeta) 1487 } 1488 1489 if err != nil { 1490 return err 1491 } 1492 1493 reply.Index, reply.Role = index, role 1494 return nil 1495 }) 1496} 1497 1498func (a *ACL) RoleBatchRead(args *structs.ACLRoleBatchGetRequest, reply *structs.ACLRoleBatchResponse) error { 1499 if err := a.aclPreCheck(); err != nil { 1500 return err 1501 } 1502 1503 if done, err := a.srv.ForwardRPC("ACL.RoleBatchRead", args, reply); done { 1504 return err 1505 } 1506 1507 authz, err := a.srv.ResolveToken(args.Token) 1508 if err != nil { 1509 return err 1510 } else if authz == nil { 1511 return acl.ErrPermissionDenied 1512 } 1513 1514 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 1515 func(ws memdb.WatchSet, state *state.Store) error { 1516 index, roles, err := state.ACLRoleBatchGet(ws, args.RoleIDs) 1517 if err != nil { 1518 return err 1519 } 1520 1521 a.srv.filterACLWithAuthorizer(authz, &roles) 1522 1523 reply.Index, reply.Roles = index, roles 1524 return nil 1525 }) 1526} 1527 1528func (a *ACL) RoleSet(args *structs.ACLRoleSetRequest, reply *structs.ACLRole) error { 1529 if err := a.aclPreCheck(); err != nil { 1530 return err 1531 } 1532 1533 if err := a.srv.validateEnterpriseRequest(&args.Role.EnterpriseMeta, true); err != nil { 1534 return err 1535 } 1536 1537 if !a.srv.InACLDatacenter() { 1538 args.Datacenter = a.srv.config.ACLDatacenter 1539 } 1540 1541 if done, err := a.srv.ForwardRPC("ACL.RoleSet", args, reply); done { 1542 return err 1543 } 1544 1545 defer metrics.MeasureSince([]string{"acl", "role", "upsert"}, time.Now()) 1546 1547 // Verify token is permitted to modify ACLs 1548 var authzContext acl.AuthorizerContext 1549 1550 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.Role.EnterpriseMeta, &authzContext); err != nil { 1551 return err 1552 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 1553 return acl.ErrPermissionDenied 1554 } 1555 1556 role := &args.Role 1557 state := a.srv.fsm.State() 1558 1559 // Almost all of the checks here are also done in the state store. However, 1560 // we want to prevent the raft operations when we know they are going to fail 1561 // so we still do them here. 1562 1563 // ensure a name is set 1564 if role.Name == "" { 1565 return fmt.Errorf("Invalid Role: no Name is set") 1566 } 1567 1568 if !validRoleName.MatchString(role.Name) { 1569 return fmt.Errorf("Invalid Role: invalid Name. Only alphanumeric characters, '-' and '_' are allowed") 1570 } 1571 1572 var existing *structs.ACLRole 1573 var err error 1574 if role.ID == "" { 1575 // with no role ID one will be generated 1576 role.ID, err = lib.GenerateUUID(a.srv.checkRoleUUID) 1577 if err != nil { 1578 return err 1579 } 1580 1581 // validate the name is unique 1582 if _, existing, err = state.ACLRoleGetByName(nil, role.Name, &role.EnterpriseMeta); err != nil { 1583 return fmt.Errorf("acl role lookup by name failed: %v", err) 1584 } else if existing != nil { 1585 return fmt.Errorf("Invalid Role: A Role with Name %q already exists", role.Name) 1586 } 1587 } else { 1588 if _, err := uuid.ParseUUID(role.ID); err != nil { 1589 return fmt.Errorf("Role ID invalid UUID") 1590 } 1591 1592 // Verify the role exists 1593 _, existing, err = state.ACLRoleGetByID(nil, role.ID, nil) 1594 if err != nil { 1595 return fmt.Errorf("acl role lookup failed: %v", err) 1596 } else if existing == nil { 1597 return fmt.Errorf("cannot find role %s", role.ID) 1598 } 1599 1600 if existing.Name != role.Name { 1601 if _, nameMatch, err := state.ACLRoleGetByName(nil, role.Name, &role.EnterpriseMeta); err != nil { 1602 return fmt.Errorf("acl role lookup by name failed: %v", err) 1603 } else if nameMatch != nil { 1604 return fmt.Errorf("Invalid Role: A role with name %q already exists", role.Name) 1605 } 1606 } 1607 } 1608 1609 // validate the enterprise meta 1610 if err := state.ACLRoleUpsertValidateEnterprise(role, existing); err != nil { 1611 return err 1612 } 1613 1614 policyIDs := make(map[string]struct{}) 1615 var policies []structs.ACLRolePolicyLink 1616 1617 // Validate all the policy names and convert them to policy IDs 1618 for _, link := range role.Policies { 1619 if link.ID == "" { 1620 _, policy, err := state.ACLPolicyGetByName(nil, link.Name, &role.EnterpriseMeta) 1621 if err != nil { 1622 return fmt.Errorf("Error looking up policy for name %q: %v", link.Name, err) 1623 } 1624 if policy == nil { 1625 return fmt.Errorf("No such ACL policy with name %q", link.Name) 1626 } 1627 link.ID = policy.ID 1628 } 1629 1630 // Do not store the policy name within raft/memdb as the policy could be renamed in the future. 1631 link.Name = "" 1632 1633 // dedup policy links by id 1634 if _, ok := policyIDs[link.ID]; !ok { 1635 policies = append(policies, link) 1636 policyIDs[link.ID] = struct{}{} 1637 } 1638 } 1639 role.Policies = policies 1640 1641 for _, svcid := range role.ServiceIdentities { 1642 if svcid.ServiceName == "" { 1643 return fmt.Errorf("Service identity is missing the service name field on this role") 1644 } 1645 if !isValidServiceIdentityName(svcid.ServiceName) { 1646 return fmt.Errorf("Service identity %q has an invalid name. Only alphanumeric characters, '-' and '_' are allowed", svcid.ServiceName) 1647 } 1648 } 1649 role.ServiceIdentities = dedupeServiceIdentities(role.ServiceIdentities) 1650 1651 for _, nodeid := range role.NodeIdentities { 1652 if nodeid.NodeName == "" { 1653 return fmt.Errorf("Node identity is missing the node name field on this role") 1654 } 1655 if nodeid.Datacenter == "" { 1656 return fmt.Errorf("Node identity is missing the datacenter field on this role") 1657 } 1658 if !isValidNodeIdentityName(nodeid.NodeName) { 1659 return fmt.Errorf("Node identity has an invalid name. Only alphanumeric characters, '-' and '_' are allowed") 1660 } 1661 } 1662 role.NodeIdentities = dedupeNodeIdentities(role.NodeIdentities) 1663 1664 // calculate the hash for this role 1665 role.SetHash(true) 1666 1667 req := &structs.ACLRoleBatchSetRequest{ 1668 Roles: structs.ACLRoles{role}, 1669 } 1670 1671 _, err = a.srv.raftApply(structs.ACLRoleSetRequestType, req) 1672 if err != nil { 1673 return fmt.Errorf("Failed to apply role upsert request: %v", err) 1674 } 1675 1676 // Remove from the cache to prevent stale cache usage 1677 a.srv.acls.cache.RemoveRole(role.ID) 1678 1679 if _, role, err := a.srv.fsm.State().ACLRoleGetByID(nil, role.ID, &role.EnterpriseMeta); err == nil && role != nil { 1680 *reply = *role 1681 } 1682 1683 return nil 1684} 1685 1686func (a *ACL) RoleDelete(args *structs.ACLRoleDeleteRequest, reply *string) error { 1687 if err := a.aclPreCheck(); err != nil { 1688 return err 1689 } 1690 1691 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil { 1692 return err 1693 } 1694 1695 if !a.srv.InACLDatacenter() { 1696 args.Datacenter = a.srv.config.ACLDatacenter 1697 } 1698 1699 if done, err := a.srv.ForwardRPC("ACL.RoleDelete", args, reply); done { 1700 return err 1701 } 1702 1703 defer metrics.MeasureSince([]string{"acl", "role", "delete"}, time.Now()) 1704 1705 // Verify token is permitted to modify ACLs 1706 var authzContext acl.AuthorizerContext 1707 1708 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil { 1709 return err 1710 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 1711 return acl.ErrPermissionDenied 1712 } 1713 1714 _, role, err := a.srv.fsm.State().ACLRoleGetByID(nil, args.RoleID, &args.EnterpriseMeta) 1715 if err != nil { 1716 return err 1717 } 1718 1719 if role == nil { 1720 return nil 1721 } 1722 1723 req := structs.ACLRoleBatchDeleteRequest{ 1724 RoleIDs: []string{args.RoleID}, 1725 } 1726 1727 _, err = a.srv.raftApply(structs.ACLRoleDeleteRequestType, &req) 1728 if err != nil { 1729 return fmt.Errorf("Failed to apply role delete request: %v", err) 1730 } 1731 1732 a.srv.acls.cache.RemoveRole(role.ID) 1733 1734 *reply = role.Name 1735 1736 return nil 1737} 1738 1739func (a *ACL) RoleList(args *structs.ACLRoleListRequest, reply *structs.ACLRoleListResponse) error { 1740 if err := a.aclPreCheck(); err != nil { 1741 return err 1742 } 1743 1744 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 1745 return err 1746 } 1747 1748 if done, err := a.srv.ForwardRPC("ACL.RoleList", args, reply); done { 1749 return err 1750 } 1751 1752 var authzContext acl.AuthorizerContext 1753 1754 authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext) 1755 if err != nil { 1756 return err 1757 } else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 1758 return acl.ErrPermissionDenied 1759 } 1760 1761 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 1762 func(ws memdb.WatchSet, state *state.Store) error { 1763 index, roles, err := state.ACLRoleList(ws, args.Policy, &args.EnterpriseMeta) 1764 if err != nil { 1765 return err 1766 } 1767 1768 a.srv.filterACLWithAuthorizer(authz, &roles) 1769 1770 reply.Index, reply.Roles = index, roles 1771 return nil 1772 }) 1773} 1774 1775// RoleResolve is used to retrieve a subset of the roles associated with a given token 1776// The role ids in the args simply act as a filter on the role set assigned to the token 1777func (a *ACL) RoleResolve(args *structs.ACLRoleBatchGetRequest, reply *structs.ACLRoleBatchResponse) error { 1778 if err := a.aclPreCheck(); err != nil { 1779 return err 1780 } 1781 1782 if done, err := a.srv.ForwardRPC("ACL.RoleResolve", args, reply); done { 1783 return err 1784 } 1785 1786 // get full list of roles for this token 1787 identity, roles, err := a.srv.acls.resolveTokenToIdentityAndRoles(args.Token) 1788 if err != nil { 1789 return err 1790 } 1791 1792 entIdentity, entRoles, err := a.srv.acls.resolveEnterpriseIdentityAndRoles(identity) 1793 if err != nil { 1794 return err 1795 } 1796 1797 idMap := make(map[string]*structs.ACLRole) 1798 for _, roleID := range identity.RoleIDs() { 1799 idMap[roleID] = nil 1800 } 1801 if entIdentity != nil { 1802 for _, roleID := range entIdentity.RoleIDs() { 1803 idMap[roleID] = nil 1804 } 1805 } 1806 1807 for _, role := range roles { 1808 idMap[role.ID] = role 1809 } 1810 for _, role := range entRoles { 1811 idMap[role.ID] = role 1812 } 1813 1814 for _, roleID := range args.RoleIDs { 1815 if role, ok := idMap[roleID]; ok { 1816 // only add non-deleted roles 1817 if role != nil { 1818 reply.Roles = append(reply.Roles, role) 1819 } 1820 } else { 1821 // send a permission denied to indicate that the request included 1822 // role ids not associated with this token 1823 return acl.ErrPermissionDenied 1824 } 1825 } 1826 1827 a.srv.setQueryMeta(&reply.QueryMeta) 1828 1829 return nil 1830} 1831 1832var errAuthMethodsRequireTokenReplication = errors.New("Token replication is required for auth methods to function") 1833 1834func (a *ACL) BindingRuleRead(args *structs.ACLBindingRuleGetRequest, reply *structs.ACLBindingRuleResponse) error { 1835 if err := a.aclPreCheck(); err != nil { 1836 return err 1837 } 1838 1839 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 1840 return err 1841 } 1842 1843 if !a.srv.LocalTokensEnabled() { 1844 return errAuthMethodsRequireTokenReplication 1845 } 1846 1847 if done, err := a.srv.ForwardRPC("ACL.BindingRuleRead", args, reply); done { 1848 return err 1849 } 1850 1851 var authzContext acl.AuthorizerContext 1852 1853 authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext) 1854 if err != nil { 1855 return err 1856 } else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 1857 return acl.ErrPermissionDenied 1858 } 1859 1860 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 1861 func(ws memdb.WatchSet, state *state.Store) error { 1862 index, rule, err := state.ACLBindingRuleGetByID(ws, args.BindingRuleID, &args.EnterpriseMeta) 1863 1864 if err != nil { 1865 return err 1866 } 1867 1868 reply.Index, reply.BindingRule = index, rule 1869 return nil 1870 }) 1871} 1872 1873func (a *ACL) BindingRuleSet(args *structs.ACLBindingRuleSetRequest, reply *structs.ACLBindingRule) error { 1874 if err := a.aclPreCheck(); err != nil { 1875 return err 1876 } 1877 1878 if err := a.srv.validateEnterpriseRequest(&args.BindingRule.EnterpriseMeta, true); err != nil { 1879 return err 1880 } 1881 1882 if !a.srv.LocalTokensEnabled() { 1883 return errAuthMethodsRequireTokenReplication 1884 } 1885 1886 if done, err := a.srv.ForwardRPC("ACL.BindingRuleSet", args, reply); done { 1887 return err 1888 } 1889 1890 defer metrics.MeasureSince([]string{"acl", "bindingrule", "upsert"}, time.Now()) 1891 1892 var authzContext acl.AuthorizerContext 1893 1894 // Verify token is permitted to modify ACLs 1895 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.BindingRule.EnterpriseMeta, &authzContext); err != nil { 1896 return err 1897 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 1898 return acl.ErrPermissionDenied 1899 } 1900 1901 var existing *structs.ACLBindingRule 1902 rule := &args.BindingRule 1903 state := a.srv.fsm.State() 1904 1905 if rule.ID == "" { 1906 // with no binding rule ID one will be generated 1907 var err error 1908 1909 rule.ID, err = lib.GenerateUUID(a.srv.checkBindingRuleUUID) 1910 if err != nil { 1911 return err 1912 } 1913 } else { 1914 if _, err := uuid.ParseUUID(rule.ID); err != nil { 1915 return fmt.Errorf("Binding Rule ID invalid UUID") 1916 } 1917 1918 // Verify the role exists 1919 var err error 1920 // specifically disregarding the enterprise meta here 1921 _, existing, err = state.ACLBindingRuleGetByID(nil, rule.ID, nil) 1922 if err != nil { 1923 return fmt.Errorf("acl binding rule lookup failed: %v", err) 1924 } else if existing == nil { 1925 return fmt.Errorf("cannot find binding rule %s", rule.ID) 1926 } 1927 1928 if rule.AuthMethod == "" { 1929 rule.AuthMethod = existing.AuthMethod 1930 } else if existing.AuthMethod != rule.AuthMethod { 1931 return fmt.Errorf("the AuthMethod field of an Binding Rule is immutable") 1932 } 1933 } 1934 1935 if rule.AuthMethod == "" { 1936 return fmt.Errorf("Invalid Binding Rule: no AuthMethod is set") 1937 } 1938 1939 // this is done early here to produce better errors 1940 if err := state.ACLBindingRuleUpsertValidateEnterprise(rule, existing); err != nil { 1941 return err 1942 } 1943 1944 methodIdx, method, err := state.ACLAuthMethodGetByName(nil, rule.AuthMethod, &args.BindingRule.EnterpriseMeta) 1945 if err != nil { 1946 return fmt.Errorf("acl auth method lookup failed: %v", err) 1947 } else if method == nil { 1948 return fmt.Errorf("cannot find auth method with name %q", rule.AuthMethod) 1949 } 1950 validator, err := a.srv.loadAuthMethodValidator(methodIdx, method) 1951 if err != nil { 1952 return err 1953 } 1954 1955 // Create a blank placeholder identity for use in validation below. 1956 blankID := validator.NewIdentity() 1957 1958 if rule.Selector != "" { 1959 if _, err := bexpr.CreateEvaluatorForType(rule.Selector, nil, blankID.SelectableFields); err != nil { 1960 return fmt.Errorf("invalid Binding Rule: Selector is invalid: %v", err) 1961 } 1962 } 1963 1964 if rule.BindType == "" { 1965 return fmt.Errorf("Invalid Binding Rule: no BindType is set") 1966 } 1967 1968 if rule.BindName == "" { 1969 return fmt.Errorf("Invalid Binding Rule: no BindName is set") 1970 } 1971 1972 switch rule.BindType { 1973 case structs.BindingRuleBindTypeService: 1974 case structs.BindingRuleBindTypeNode: 1975 case structs.BindingRuleBindTypeRole: 1976 default: 1977 return fmt.Errorf("Invalid Binding Rule: unknown BindType %q", rule.BindType) 1978 } 1979 1980 if valid, err := validateBindingRuleBindName(rule.BindType, rule.BindName, blankID.ProjectedVarNames()); err != nil { 1981 return fmt.Errorf("Invalid Binding Rule: invalid BindName: %v", err) 1982 } else if !valid { 1983 return fmt.Errorf("Invalid Binding Rule: invalid BindName") 1984 } 1985 1986 req := &structs.ACLBindingRuleBatchSetRequest{ 1987 BindingRules: structs.ACLBindingRules{rule}, 1988 } 1989 1990 _, err = a.srv.raftApply(structs.ACLBindingRuleSetRequestType, req) 1991 if err != nil { 1992 return fmt.Errorf("Failed to apply binding rule upsert request: %v", err) 1993 } 1994 1995 if _, rule, err := a.srv.fsm.State().ACLBindingRuleGetByID(nil, rule.ID, &rule.EnterpriseMeta); err == nil && rule != nil { 1996 *reply = *rule 1997 } 1998 1999 return nil 2000} 2001 2002func (a *ACL) BindingRuleDelete(args *structs.ACLBindingRuleDeleteRequest, reply *bool) error { 2003 if err := a.aclPreCheck(); err != nil { 2004 return err 2005 } 2006 2007 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil { 2008 return err 2009 } 2010 2011 if !a.srv.LocalTokensEnabled() { 2012 return errAuthMethodsRequireTokenReplication 2013 } 2014 2015 if done, err := a.srv.ForwardRPC("ACL.BindingRuleDelete", args, reply); done { 2016 return err 2017 } 2018 2019 defer metrics.MeasureSince([]string{"acl", "bindingrule", "delete"}, time.Now()) 2020 2021 var authzContext acl.AuthorizerContext 2022 2023 // Verify token is permitted to modify ACLs 2024 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil { 2025 return err 2026 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 2027 return acl.ErrPermissionDenied 2028 } 2029 2030 _, rule, err := a.srv.fsm.State().ACLBindingRuleGetByID(nil, args.BindingRuleID, &args.EnterpriseMeta) 2031 if err != nil { 2032 return err 2033 } 2034 2035 if rule == nil { 2036 return nil 2037 } 2038 2039 req := structs.ACLBindingRuleBatchDeleteRequest{ 2040 BindingRuleIDs: []string{args.BindingRuleID}, 2041 } 2042 2043 _, err = a.srv.raftApply(structs.ACLBindingRuleDeleteRequestType, &req) 2044 if err != nil { 2045 return fmt.Errorf("Failed to apply binding rule delete request: %v", err) 2046 } 2047 2048 *reply = true 2049 2050 return nil 2051} 2052 2053func (a *ACL) BindingRuleList(args *structs.ACLBindingRuleListRequest, reply *structs.ACLBindingRuleListResponse) error { 2054 if err := a.aclPreCheck(); err != nil { 2055 return err 2056 } 2057 2058 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 2059 return err 2060 } 2061 2062 if !a.srv.LocalTokensEnabled() { 2063 return errAuthMethodsRequireTokenReplication 2064 } 2065 2066 if done, err := a.srv.ForwardRPC("ACL.BindingRuleList", args, reply); done { 2067 return err 2068 } 2069 2070 var authzContext acl.AuthorizerContext 2071 2072 authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext) 2073 if err != nil { 2074 return err 2075 } else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 2076 return acl.ErrPermissionDenied 2077 } 2078 2079 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 2080 func(ws memdb.WatchSet, state *state.Store) error { 2081 index, rules, err := state.ACLBindingRuleList(ws, args.AuthMethod, &args.EnterpriseMeta) 2082 if err != nil { 2083 return err 2084 } 2085 2086 a.srv.filterACLWithAuthorizer(authz, &rules) 2087 2088 reply.Index, reply.BindingRules = index, rules 2089 return nil 2090 }) 2091} 2092 2093func (a *ACL) AuthMethodRead(args *structs.ACLAuthMethodGetRequest, reply *structs.ACLAuthMethodResponse) error { 2094 if err := a.aclPreCheck(); err != nil { 2095 return err 2096 } 2097 2098 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 2099 return err 2100 } 2101 2102 if !a.srv.LocalTokensEnabled() { 2103 return errAuthMethodsRequireTokenReplication 2104 } 2105 2106 if done, err := a.srv.ForwardRPC("ACL.AuthMethodRead", args, reply); done { 2107 return err 2108 } 2109 2110 var authzContext acl.AuthorizerContext 2111 2112 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil { 2113 return err 2114 } else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 2115 return acl.ErrPermissionDenied 2116 } 2117 2118 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 2119 func(ws memdb.WatchSet, state *state.Store) error { 2120 index, method, err := state.ACLAuthMethodGetByName(ws, args.AuthMethodName, &args.EnterpriseMeta) 2121 2122 if err != nil { 2123 return err 2124 } 2125 2126 if method != nil { 2127 _ = a.enterpriseAuthMethodTypeValidation(method.Type) 2128 } 2129 2130 reply.Index, reply.AuthMethod = index, method 2131 return nil 2132 }) 2133} 2134 2135func (a *ACL) AuthMethodSet(args *structs.ACLAuthMethodSetRequest, reply *structs.ACLAuthMethod) error { 2136 if err := a.aclPreCheck(); err != nil { 2137 return err 2138 } 2139 2140 if err := a.srv.validateEnterpriseRequest(&args.AuthMethod.EnterpriseMeta, true); err != nil { 2141 return err 2142 } 2143 2144 if !a.srv.LocalTokensEnabled() { 2145 return errAuthMethodsRequireTokenReplication 2146 } 2147 2148 if done, err := a.srv.ForwardRPC("ACL.AuthMethodSet", args, reply); done { 2149 return err 2150 } 2151 2152 defer metrics.MeasureSince([]string{"acl", "authmethod", "upsert"}, time.Now()) 2153 2154 // Verify token is permitted to modify ACLs 2155 var authzContext acl.AuthorizerContext 2156 2157 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.AuthMethod.EnterpriseMeta, &authzContext); err != nil { 2158 return err 2159 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 2160 return acl.ErrPermissionDenied 2161 } 2162 2163 method := &args.AuthMethod 2164 state := a.srv.fsm.State() 2165 2166 // ensure a name is set 2167 if method.Name == "" { 2168 return fmt.Errorf("Invalid Auth Method: no Name is set") 2169 } 2170 if !validAuthMethod.MatchString(method.Name) { 2171 return fmt.Errorf("Invalid Auth Method: invalid Name. Only alphanumeric characters, '-' and '_' are allowed") 2172 } 2173 2174 if err := a.enterpriseAuthMethodTypeValidation(method.Type); err != nil { 2175 return err 2176 } 2177 2178 // Check to see if the method exists first. 2179 _, existing, err := state.ACLAuthMethodGetByName(nil, method.Name, &method.EnterpriseMeta) 2180 if err != nil { 2181 return fmt.Errorf("acl auth method lookup failed: %v", err) 2182 } 2183 2184 if existing != nil { 2185 if method.Type == "" { 2186 method.Type = existing.Type 2187 } else if existing.Type != method.Type { 2188 return fmt.Errorf("the Type field of an Auth Method is immutable") 2189 } 2190 } 2191 2192 if !authmethod.IsRegisteredType(method.Type) { 2193 return fmt.Errorf("Invalid Auth Method: Type should be one of: %v", authmethod.Types()) 2194 } 2195 2196 if method.MaxTokenTTL != 0 { 2197 if method.MaxTokenTTL > a.srv.config.ACLTokenMaxExpirationTTL { 2198 return fmt.Errorf("MaxTokenTTL %s cannot be more than %s", 2199 method.MaxTokenTTL, a.srv.config.ACLTokenMaxExpirationTTL) 2200 } else if method.MaxTokenTTL < a.srv.config.ACLTokenMinExpirationTTL { 2201 return fmt.Errorf("MaxTokenTTL %s cannot be less than %s", 2202 method.MaxTokenTTL, a.srv.config.ACLTokenMinExpirationTTL) 2203 } 2204 } 2205 2206 switch method.TokenLocality { 2207 case "local", "": 2208 case "global": 2209 if !a.srv.InACLDatacenter() { 2210 return fmt.Errorf("Invalid Auth Method: TokenLocality 'global' can only be used in the primary datacenter") 2211 } 2212 default: 2213 return fmt.Errorf("Invalid Auth Method: TokenLocality should be one of 'local' or 'global'") 2214 } 2215 2216 // Instantiate a validator but do not cache it yet. This will validate the 2217 // configuration. 2218 validator, err := authmethod.NewValidator(a.srv.logger, method) 2219 if err != nil { 2220 return fmt.Errorf("Invalid Auth Method: %v", err) 2221 } 2222 2223 if err := enterpriseAuthMethodValidation(method, validator); err != nil { 2224 return err 2225 } 2226 2227 if err := a.srv.fsm.State().ACLAuthMethodUpsertValidateEnterprise(method, existing); err != nil { 2228 return err 2229 } 2230 2231 req := &structs.ACLAuthMethodBatchSetRequest{ 2232 AuthMethods: structs.ACLAuthMethods{method}, 2233 } 2234 2235 _, err = a.srv.raftApply(structs.ACLAuthMethodSetRequestType, req) 2236 if err != nil { 2237 return fmt.Errorf("Failed to apply auth method upsert request: %v", err) 2238 } 2239 2240 if _, method, err := a.srv.fsm.State().ACLAuthMethodGetByName(nil, method.Name, &method.EnterpriseMeta); err == nil && method != nil { 2241 *reply = *method 2242 } 2243 2244 return nil 2245} 2246 2247func (a *ACL) AuthMethodDelete(args *structs.ACLAuthMethodDeleteRequest, reply *bool) error { 2248 if err := a.aclPreCheck(); err != nil { 2249 return err 2250 } 2251 2252 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, true); err != nil { 2253 return err 2254 } 2255 2256 if !a.srv.LocalTokensEnabled() { 2257 return errAuthMethodsRequireTokenReplication 2258 } 2259 2260 if done, err := a.srv.ForwardRPC("ACL.AuthMethodDelete", args, reply); done { 2261 return err 2262 } 2263 2264 defer metrics.MeasureSince([]string{"acl", "authmethod", "delete"}, time.Now()) 2265 2266 // Verify token is permitted to modify ACLs 2267 var authzContext acl.AuthorizerContext 2268 2269 if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil { 2270 return err 2271 } else if authz == nil || authz.ACLWrite(&authzContext) != acl.Allow { 2272 return acl.ErrPermissionDenied 2273 } 2274 2275 _, method, err := a.srv.fsm.State().ACLAuthMethodGetByName(nil, args.AuthMethodName, &args.EnterpriseMeta) 2276 if err != nil { 2277 return err 2278 } 2279 2280 if method == nil { 2281 return nil 2282 } 2283 2284 if err := a.enterpriseAuthMethodTypeValidation(method.Type); err != nil { 2285 return err 2286 } 2287 2288 req := structs.ACLAuthMethodBatchDeleteRequest{ 2289 AuthMethodNames: []string{args.AuthMethodName}, 2290 EnterpriseMeta: args.EnterpriseMeta, 2291 } 2292 2293 _, err = a.srv.raftApply(structs.ACLAuthMethodDeleteRequestType, &req) 2294 if err != nil { 2295 return fmt.Errorf("Failed to apply auth method delete request: %v", err) 2296 } 2297 2298 *reply = true 2299 2300 return nil 2301} 2302 2303func (a *ACL) AuthMethodList(args *structs.ACLAuthMethodListRequest, reply *structs.ACLAuthMethodListResponse) error { 2304 if err := a.aclPreCheck(); err != nil { 2305 return err 2306 } 2307 2308 if err := a.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil { 2309 return err 2310 } 2311 2312 if !a.srv.LocalTokensEnabled() { 2313 return errAuthMethodsRequireTokenReplication 2314 } 2315 2316 if done, err := a.srv.ForwardRPC("ACL.AuthMethodList", args, reply); done { 2317 return err 2318 } 2319 2320 var authzContext acl.AuthorizerContext 2321 2322 authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext) 2323 if err != nil { 2324 return err 2325 } else if authz == nil || authz.ACLRead(&authzContext) != acl.Allow { 2326 return acl.ErrPermissionDenied 2327 } 2328 2329 return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, 2330 func(ws memdb.WatchSet, state *state.Store) error { 2331 index, methods, err := state.ACLAuthMethodList(ws, &args.EnterpriseMeta) 2332 if err != nil { 2333 return err 2334 } 2335 2336 a.srv.filterACLWithAuthorizer(authz, &methods) 2337 2338 var stubs structs.ACLAuthMethodListStubs 2339 for _, method := range methods { 2340 _ = a.enterpriseAuthMethodTypeValidation(method.Type) 2341 stubs = append(stubs, method.Stub()) 2342 } 2343 2344 reply.Index, reply.AuthMethods = index, stubs 2345 return nil 2346 }) 2347} 2348 2349func (a *ACL) Login(args *structs.ACLLoginRequest, reply *structs.ACLToken) error { 2350 if err := a.aclPreCheck(); err != nil { 2351 return err 2352 } 2353 2354 if !a.srv.LocalTokensEnabled() { 2355 return errAuthMethodsRequireTokenReplication 2356 } 2357 2358 if args.Auth == nil { 2359 return fmt.Errorf("Invalid Login request: Missing auth parameters") 2360 } 2361 2362 if err := a.srv.validateEnterpriseRequest(&args.Auth.EnterpriseMeta, true); err != nil { 2363 return err 2364 } 2365 2366 if args.Token != "" { // This shouldn't happen. 2367 return errors.New("do not provide a token when logging in") 2368 } 2369 2370 if done, err := a.srv.ForwardRPC("ACL.Login", args, reply); done { 2371 return err 2372 } 2373 2374 defer metrics.MeasureSince([]string{"acl", "login"}, time.Now()) 2375 2376 auth := args.Auth 2377 2378 // 1. take args.Data.AuthMethod to get an AuthMethod Validator 2379 idx, method, err := a.srv.fsm.State().ACLAuthMethodGetByName(nil, auth.AuthMethod, &auth.EnterpriseMeta) 2380 if err != nil { 2381 return err 2382 } else if method == nil { 2383 return fmt.Errorf("%w: auth method %q not found", acl.ErrNotFound, auth.AuthMethod) 2384 } 2385 2386 if err := a.enterpriseAuthMethodTypeValidation(method.Type); err != nil { 2387 return err 2388 } 2389 2390 validator, err := a.srv.loadAuthMethodValidator(idx, method) 2391 if err != nil { 2392 return err 2393 } 2394 2395 // 2. Send args.Data.BearerToken to method validator and get back a fields map 2396 verifiedIdentity, err := validator.ValidateLogin(context.Background(), auth.BearerToken) 2397 if err != nil { 2398 return err 2399 } 2400 2401 return a.tokenSetFromAuthMethod( 2402 method, 2403 &auth.EnterpriseMeta, 2404 "token created via login", 2405 auth.Meta, 2406 validator, 2407 verifiedIdentity, 2408 &structs.ACLTokenSetRequest{ 2409 Datacenter: args.Datacenter, 2410 WriteRequest: args.WriteRequest, 2411 }, 2412 reply, 2413 ) 2414} 2415 2416func (a *ACL) tokenSetFromAuthMethod( 2417 method *structs.ACLAuthMethod, 2418 entMeta *structs.EnterpriseMeta, 2419 tokenDescriptionPrefix string, 2420 tokenMetadata map[string]string, 2421 validator authmethod.Validator, 2422 verifiedIdentity *authmethod.Identity, 2423 createReq *structs.ACLTokenSetRequest, // this should be prepopulated with datacenter+writerequest 2424 reply *structs.ACLToken, 2425) error { 2426 // This always will return a valid pointer 2427 targetMeta, err := computeTargetEnterpriseMeta(method, verifiedIdentity) 2428 if err != nil { 2429 return err 2430 } 2431 2432 // 3. send map through role bindings 2433 bindings, err := a.srv.evaluateRoleBindings(validator, verifiedIdentity, entMeta, targetMeta) 2434 if err != nil { 2435 return err 2436 } 2437 2438 // We try to prevent the creation of a useless token without taking a trip 2439 // through the state store if we can. 2440 if bindings == nil || (len(bindings.serviceIdentities) == 0 && len(bindings.nodeIdentities) == 0 && len(bindings.roles) == 0) { 2441 return acl.ErrPermissionDenied 2442 } 2443 2444 // TODO(sso): add a CapturedField to ACLAuthMethod that would pluck fields from the returned identity and stuff into `auth.Meta`. 2445 2446 description := tokenDescriptionPrefix 2447 loginMeta, err := encodeLoginMeta(tokenMetadata) 2448 if err != nil { 2449 return err 2450 } 2451 if loginMeta != "" { 2452 description += ": " + loginMeta 2453 } 2454 2455 // 4. create token 2456 createReq.ACLToken = structs.ACLToken{ 2457 Description: description, 2458 Local: true, 2459 AuthMethod: method.Name, 2460 ServiceIdentities: bindings.serviceIdentities, 2461 NodeIdentities: bindings.nodeIdentities, 2462 Roles: bindings.roles, 2463 ExpirationTTL: method.MaxTokenTTL, 2464 EnterpriseMeta: *targetMeta, 2465 } 2466 2467 if method.TokenLocality == "global" { 2468 if !a.srv.InACLDatacenter() { 2469 return errors.New("creating global tokens via auth methods is only permitted in the primary datacenter") 2470 } 2471 createReq.ACLToken.Local = false 2472 } 2473 2474 createReq.ACLToken.ACLAuthMethodEnterpriseMeta.FillWithEnterpriseMeta(entMeta) 2475 2476 // 5. return token information like a TokenCreate would 2477 err = a.tokenSetInternal(createReq, reply, true) 2478 2479 // If we were in a slight race with a role delete operation then we may 2480 // still end up failing to insert an unprivileged token in the state 2481 // machine instead. Return the same error as earlier so it doesn't 2482 // actually matter which one prevents the insertion. 2483 if err != nil && err.Error() == state.ErrTokenHasNoPrivileges.Error() { 2484 return acl.ErrPermissionDenied 2485 } 2486 2487 return err 2488} 2489 2490func encodeLoginMeta(meta map[string]string) (string, error) { 2491 if len(meta) == 0 { 2492 return "", nil 2493 } 2494 2495 d, err := json.Marshal(meta) 2496 if err != nil { 2497 return "", err 2498 } 2499 return string(d), nil 2500} 2501 2502func (a *ACL) Logout(args *structs.ACLLogoutRequest, reply *bool) error { 2503 if err := a.aclPreCheck(); err != nil { 2504 return err 2505 } 2506 2507 if !a.srv.LocalTokensEnabled() { 2508 return errAuthMethodsRequireTokenReplication 2509 } 2510 2511 if args.Token == "" { 2512 return acl.ErrNotFound 2513 } 2514 2515 if done, err := a.srv.ForwardRPC("ACL.Logout", args, reply); done { 2516 return err 2517 } 2518 2519 defer metrics.MeasureSince([]string{"acl", "logout"}, time.Now()) 2520 2521 _, token, err := a.srv.fsm.State().ACLTokenGetBySecret(nil, args.Token, nil) 2522 if err != nil { 2523 return err 2524 2525 } else if token == nil { 2526 return acl.ErrNotFound 2527 2528 } else if token.AuthMethod == "" { 2529 // Can't "logout" of a token that wasn't a result of login. 2530 return acl.ErrPermissionDenied 2531 2532 } else if !a.srv.InACLDatacenter() && !token.Local { 2533 // global token writes must be forwarded to the primary DC 2534 args.Datacenter = a.srv.config.ACLDatacenter 2535 return a.srv.forwardDC("ACL.Logout", a.srv.config.ACLDatacenter, args, reply) 2536 } 2537 2538 // No need to check expiration time because it's being deleted. 2539 2540 req := &structs.ACLTokenBatchDeleteRequest{ 2541 TokenIDs: []string{token.AccessorID}, 2542 } 2543 2544 _, err = a.srv.raftApply(structs.ACLTokenDeleteRequestType, req) 2545 if err != nil { 2546 return fmt.Errorf("Failed to apply token delete request: %v", err) 2547 } 2548 2549 // Purge the identity from the cache to prevent using the previous definition of the identity 2550 a.srv.acls.cache.RemoveIdentity(tokenSecretCacheID(token.SecretID)) 2551 2552 *reply = true 2553 2554 return nil 2555} 2556 2557func (a *ACL) Authorize(args *structs.RemoteACLAuthorizationRequest, reply *[]structs.ACLAuthorizationResponse) error { 2558 if err := a.aclPreCheck(); err != nil { 2559 return err 2560 } 2561 2562 if done, err := a.srv.ForwardRPC("ACL.Authorize", args, reply); done { 2563 return err 2564 } 2565 2566 authz, err := a.srv.ResolveToken(args.Token) 2567 if err != nil { 2568 return err 2569 } else if authz == nil { 2570 return fmt.Errorf("Failed to initialize authorizer") 2571 } 2572 2573 responses, err := structs.CreateACLAuthorizationResponses(authz, args.Requests) 2574 if err != nil { 2575 return err 2576 } 2577 2578 *reply = responses 2579 return nil 2580} 2581