github.phpd.cn/hashicorp/consul@v1.4.5/agent/consul/acl.go (about) 1 package consul 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "sync" 8 "time" 9 10 "github.com/armon/go-metrics" 11 "github.com/hashicorp/consul/acl" 12 "github.com/hashicorp/consul/agent/structs" 13 "github.com/hashicorp/consul/api" 14 "github.com/hashicorp/consul/sentinel" 15 "golang.org/x/sync/singleflight" 16 "golang.org/x/time/rate" 17 ) 18 19 // These must be kept in sync with the constants in command/agent/acl.go. 20 const ( 21 // anonymousToken is the token ID we re-write to if there is no token ID 22 // provided. 23 anonymousToken = "anonymous" 24 25 // redactedToken is shown in structures with embedded tokens when they 26 // are not allowed to be displayed. 27 redactedToken = "<hidden>" 28 29 // aclUpgradeBatchSize controls how many tokens we look at during each round of upgrading. Individual raft logs 30 // will be further capped using the aclBatchUpsertSize. This limit just prevents us from creating a single slice 31 // with all tokens in it. 32 aclUpgradeBatchSize = 128 33 34 // aclUpgradeRateLimit is the number of batch upgrade requests per second. 35 aclUpgradeRateLimit rate.Limit = 1.0 36 37 // aclBatchDeleteSize is the number of deletions to send in a single batch operation. 4096 should produce a batch that is <150KB 38 // in size but should be sufficiently large to handle 1 replication round in a single batch 39 aclBatchDeleteSize = 4096 40 41 // aclBatchUpsertSize is the target size in bytes we want to submit for a batch upsert request. We estimate the size at runtime 42 // due to the data being more variable in its size. 43 aclBatchUpsertSize = 256 * 1024 44 45 // DEPRECATED (ACL-Legacy-Compat) aclModeCheck* are all only for legacy usage 46 // aclModeCheckMinInterval is the minimum amount of time between checking if the 47 // agent should be using the new or legacy ACL system. All the places it is 48 // currently used will backoff as it detects that it is remaining in legacy mode. 49 // However the initial min value is kept small so that new cluster creation 50 // can enter into new ACL mode quickly. 51 aclModeCheckMinInterval = 50 * time.Millisecond 52 53 // aclModeCheckMaxInterval controls the maximum interval for how often the agent 54 // checks if it should be using the new or legacy ACL system. 55 aclModeCheckMaxInterval = 30 * time.Second 56 57 // Maximum number of re-resolution requests to be made if the token is modified between 58 // resolving the token and resolving its policies that would remove one of its policies. 59 tokenPolicyResolutionMaxRetries = 5 60 ) 61 62 func minTTL(a time.Duration, b time.Duration) time.Duration { 63 if a < b { 64 return a 65 } 66 return b 67 } 68 69 type ACLRemoteError struct { 70 Err error 71 } 72 73 func (e ACLRemoteError) Error() string { 74 return fmt.Sprintf("Error communicating with the ACL Datacenter: %v", e.Err) 75 } 76 77 func IsACLRemoteError(err error) bool { 78 _, ok := err.(ACLRemoteError) 79 return ok 80 } 81 82 type ACLResolverDelegate interface { 83 ACLsEnabled() bool 84 ACLDatacenter(legacy bool) string 85 UseLegacyACLs() bool 86 ResolveIdentityFromToken(token string) (bool, structs.ACLIdentity, error) 87 ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error) 88 RPC(method string, args interface{}, reply interface{}) error 89 } 90 91 type policyTokenError struct { 92 Err error 93 token string 94 } 95 96 func (e policyTokenError) Error() string { 97 return e.Err.Error() 98 } 99 100 // ACLResolverConfig holds all the configuration necessary to create an ACLResolver 101 type ACLResolverConfig struct { 102 Config *Config 103 Logger *log.Logger 104 105 // CacheConfig is a pass through configuration for ACL cache limits 106 CacheConfig *structs.ACLCachesConfig 107 108 // Delegate that implements some helper functionality that is server/client specific 109 Delegate ACLResolverDelegate 110 111 // AutoDisable indicates that RPC responses should be checked and if they indicate ACLs are disabled 112 // remotely then disable them locally as well. This is particularly useful for the client agent 113 // so that it can detect when the servers have gotten ACLs enabled. 114 AutoDisable bool 115 116 Sentinel sentinel.Evaluator 117 } 118 119 // ACLResolver is the type to handle all your token and policy resolution needs. 120 // 121 // Supports: 122 // - Resolving tokens locally via the ACLResolverDelegate 123 // - Resolving policies locally via the ACLResolverDelegate 124 // - Resolving legacy tokens remotely via a ACL.GetPolicy RPC 125 // - Resolving tokens remotely via an ACL.TokenRead RPC 126 // - Resolving policies remotely via an ACL.PolicyResolve RPC 127 // 128 // Remote Resolution: 129 // Remote resolution can be done syncrhonously or asynchronously depending 130 // on the ACLDownPolicy in the Config passed to the resolver. 131 // 132 // When the down policy is set to async-cache and we have already cached values 133 // then go routines will be spawned to perform the RPCs in the background 134 // and then will update the cache with either the positive or negative result. 135 // 136 // When the down policy is set to extend-cache or the token/policy is not already 137 // cached then the same go routines are spawned to do the RPCs in the background. 138 // However in this mode channels are created to receive the results of the RPC 139 // and are registered with the resolver. Those channels are immediately read/blocked 140 // upon. 141 // 142 type ACLResolver struct { 143 config *Config 144 logger *log.Logger 145 146 delegate ACLResolverDelegate 147 sentinel sentinel.Evaluator 148 149 cache *structs.ACLCaches 150 identityGroup singleflight.Group 151 policyGroup singleflight.Group 152 legacyGroup singleflight.Group 153 154 down acl.Authorizer 155 156 autoDisable bool 157 disabled time.Time 158 disabledLock sync.RWMutex 159 } 160 161 func NewACLResolver(config *ACLResolverConfig) (*ACLResolver, error) { 162 if config == nil { 163 return nil, fmt.Errorf("ACL Resolver must be initialized with a config") 164 } 165 166 if config.Config == nil { 167 return nil, fmt.Errorf("ACLResolverConfig.Config must not be nil") 168 } 169 170 if config.Delegate == nil { 171 return nil, fmt.Errorf("ACL Resolver must be initialized with a valid delegate") 172 } 173 174 if config.Logger == nil { 175 config.Logger = log.New(os.Stderr, "", log.LstdFlags) 176 } 177 178 cache, err := structs.NewACLCaches(config.CacheConfig) 179 if err != nil { 180 return nil, err 181 } 182 183 var down acl.Authorizer 184 switch config.Config.ACLDownPolicy { 185 case "allow": 186 down = acl.AllowAll() 187 case "deny": 188 down = acl.DenyAll() 189 case "async-cache", "extend-cache": 190 // Leave the down policy as nil to signal this. 191 default: 192 return nil, fmt.Errorf("invalid ACL down policy %q", config.Config.ACLDownPolicy) 193 } 194 195 return &ACLResolver{ 196 config: config.Config, 197 logger: config.Logger, 198 delegate: config.Delegate, 199 sentinel: config.Sentinel, 200 cache: cache, 201 autoDisable: config.AutoDisable, 202 down: down, 203 }, nil 204 } 205 206 func (r *ACLResolver) fetchAndCacheTokenLegacy(token string, cached *structs.AuthorizerCacheEntry) (acl.Authorizer, error) { 207 req := structs.ACLPolicyResolveLegacyRequest{ 208 Datacenter: r.delegate.ACLDatacenter(true), 209 ACL: token, 210 } 211 212 cacheTTL := r.config.ACLTokenTTL 213 if cached != nil { 214 cacheTTL = cached.TTL 215 } 216 217 var reply structs.ACLPolicyResolveLegacyResponse 218 err := r.delegate.RPC("ACL.GetPolicy", &req, &reply) 219 if err == nil { 220 parent := acl.RootAuthorizer(reply.Parent) 221 if parent == nil { 222 var authorizer acl.Authorizer 223 if cached != nil { 224 authorizer = cached.Authorizer 225 } 226 r.cache.PutAuthorizerWithTTL(token, authorizer, cacheTTL) 227 return authorizer, acl.ErrInvalidParent 228 } 229 230 var policies []*acl.Policy 231 policy := reply.Policy 232 if policy != nil { 233 policies = append(policies, policy.ConvertFromLegacy()) 234 } 235 236 authorizer, err := acl.NewPolicyAuthorizer(parent, policies, r.sentinel) 237 238 r.cache.PutAuthorizerWithTTL(token, authorizer, reply.TTL) 239 return authorizer, err 240 } 241 242 if acl.IsErrNotFound(err) { 243 // Make sure to remove from the cache if it was deleted 244 r.cache.PutAuthorizerWithTTL(token, nil, cacheTTL) 245 return nil, acl.ErrNotFound 246 247 } 248 249 // some other RPC error 250 switch r.config.ACLDownPolicy { 251 case "allow": 252 r.cache.PutAuthorizerWithTTL(token, acl.AllowAll(), cacheTTL) 253 return acl.AllowAll(), nil 254 case "async-cache", "extend-cache": 255 if cached != nil { 256 r.cache.PutAuthorizerWithTTL(token, cached.Authorizer, cacheTTL) 257 return cached.Authorizer, nil 258 } 259 fallthrough 260 default: 261 r.cache.PutAuthorizerWithTTL(token, acl.DenyAll(), cacheTTL) 262 return acl.DenyAll(), nil 263 } 264 } 265 266 func (r *ACLResolver) resolveTokenLegacy(token string) (acl.Authorizer, error) { 267 defer metrics.MeasureSince([]string{"acl", "resolveTokenLegacy"}, time.Now()) 268 269 // Attempt to resolve locally first (local results are not cached) 270 // This is only useful for servers where either legacy replication is being 271 // done or the server is within the primary datacenter. 272 if done, identity, err := r.delegate.ResolveIdentityFromToken(token); done { 273 if err == nil && identity != nil { 274 policies, err := r.resolvePoliciesForIdentity(identity) 275 if err != nil { 276 return nil, err 277 } 278 279 return policies.Compile(acl.RootAuthorizer(r.config.ACLDefaultPolicy), r.cache, r.sentinel) 280 } 281 282 return nil, err 283 } 284 285 // Look in the cache prior to making a RPC request 286 entry := r.cache.GetAuthorizer(token) 287 288 if entry != nil && entry.Age() <= minTTL(entry.TTL, r.config.ACLTokenTTL) { 289 metrics.IncrCounter([]string{"acl", "token", "cache_hit"}, 1) 290 if entry.Authorizer != nil { 291 return entry.Authorizer, nil 292 } 293 return nil, acl.ErrNotFound 294 } 295 296 metrics.IncrCounter([]string{"acl", "token", "cache_miss"}, 1) 297 298 // Resolve the token in the background and wait on the result if we must 299 waitChan := r.legacyGroup.DoChan(token, func() (interface{}, error) { 300 authorizer, err := r.fetchAndCacheTokenLegacy(token, entry) 301 return authorizer, err 302 }) 303 304 waitForResult := entry == nil || r.config.ACLDownPolicy != "async-cache" 305 if !waitForResult { 306 // waitForResult being false requires the cacheEntry to not be nil 307 if entry.Authorizer != nil { 308 return entry.Authorizer, nil 309 } 310 return nil, acl.ErrNotFound 311 } 312 313 // block waiting for the async RPC to finish. 314 res := <-waitChan 315 316 var authorizer acl.Authorizer 317 if res.Val != nil { // avoid a nil-not-nil bug 318 authorizer = res.Val.(acl.Authorizer) 319 } 320 321 return authorizer, res.Err 322 } 323 324 func (r *ACLResolver) fetchAndCacheIdentityFromToken(token string, cached *structs.IdentityCacheEntry) (structs.ACLIdentity, error) { 325 req := structs.ACLTokenGetRequest{ 326 Datacenter: r.delegate.ACLDatacenter(false), 327 TokenID: token, 328 TokenIDType: structs.ACLTokenSecret, 329 QueryOptions: structs.QueryOptions{ 330 Token: token, 331 AllowStale: true, 332 }, 333 } 334 335 var resp structs.ACLTokenResponse 336 err := r.delegate.RPC("ACL.TokenRead", &req, &resp) 337 if err == nil { 338 if resp.Token == nil { 339 r.cache.PutIdentity(token, nil) 340 return nil, acl.ErrNotFound 341 } else { 342 r.cache.PutIdentity(token, resp.Token) 343 return resp.Token, nil 344 } 345 } 346 347 if acl.IsErrNotFound(err) { 348 // Make sure to remove from the cache if it was deleted 349 r.cache.PutIdentity(token, nil) 350 return nil, acl.ErrNotFound 351 352 } 353 354 // some other RPC error 355 if cached != nil && (r.config.ACLDownPolicy == "extend-cache" || r.config.ACLDownPolicy == "async-cache") { 356 // extend the cache 357 r.cache.PutIdentity(token, cached.Identity) 358 return cached.Identity, nil 359 } 360 361 r.cache.PutIdentity(token, nil) 362 return nil, err 363 } 364 365 func (r *ACLResolver) resolveIdentityFromToken(token string) (structs.ACLIdentity, error) { 366 // Attempt to resolve locally first (local results are not cached) 367 if done, identity, err := r.delegate.ResolveIdentityFromToken(token); done { 368 return identity, err 369 } 370 371 // Check the cache before making any RPC requests 372 cacheEntry := r.cache.GetIdentity(token) 373 if cacheEntry != nil && cacheEntry.Age() <= r.config.ACLTokenTTL { 374 metrics.IncrCounter([]string{"acl", "token", "cache_hit"}, 1) 375 return cacheEntry.Identity, nil 376 } 377 378 metrics.IncrCounter([]string{"acl", "token", "cache_miss"}, 1) 379 380 // Background a RPC request and wait on it if we must 381 waitChan := r.identityGroup.DoChan(token, func() (interface{}, error) { 382 identity, err := r.fetchAndCacheIdentityFromToken(token, cacheEntry) 383 return identity, err 384 }) 385 386 waitForResult := cacheEntry == nil || r.config.ACLDownPolicy != "async-cache" 387 if !waitForResult { 388 // waitForResult being false requires the cacheEntry to not be nil 389 return cacheEntry.Identity, nil 390 } 391 392 // block on the read here, this is why we don't need chan buffering 393 res := <-waitChan 394 395 var identity structs.ACLIdentity 396 if res.Val != nil { // avoid a nil-not-nil bug 397 identity = res.Val.(structs.ACLIdentity) 398 } 399 400 if res.Err != nil && !acl.IsErrNotFound(res.Err) { 401 return identity, ACLRemoteError{Err: res.Err} 402 } 403 return identity, res.Err 404 } 405 406 func (r *ACLResolver) fetchAndCachePoliciesForIdentity(identity structs.ACLIdentity, policyIDs []string, cached map[string]*structs.PolicyCacheEntry) (map[string]*structs.ACLPolicy, error) { 407 req := structs.ACLPolicyBatchGetRequest{ 408 Datacenter: r.delegate.ACLDatacenter(false), 409 PolicyIDs: policyIDs, 410 QueryOptions: structs.QueryOptions{ 411 Token: identity.SecretToken(), 412 AllowStale: true, 413 }, 414 } 415 416 var resp structs.ACLPolicyBatchResponse 417 err := r.delegate.RPC("ACL.PolicyResolve", &req, &resp) 418 if err == nil { 419 out := make(map[string]*structs.ACLPolicy) 420 for _, policy := range resp.Policies { 421 out[policy.ID] = policy 422 } 423 424 for _, policyID := range policyIDs { 425 if policy, ok := out[policyID]; ok { 426 r.cache.PutPolicy(policyID, policy) 427 } else { 428 r.cache.PutPolicy(policyID, nil) 429 } 430 } 431 return out, nil 432 } 433 434 if acl.IsErrNotFound(err) { 435 // make sure to indicate that this identity is no longer valid within 436 // the cache 437 r.cache.PutIdentity(identity.SecretToken(), nil) 438 439 // Do not touch the policy cache. Getting a top level ACL not found error 440 // only indicates that the secret token used in the request 441 // no longer exists 442 return nil, &policyTokenError{acl.ErrNotFound, identity.SecretToken()} 443 } 444 445 if acl.IsErrPermissionDenied(err) { 446 // invalidate our ID cache so that identity resolution will take place 447 // again in the future 448 r.cache.RemoveIdentity(identity.SecretToken()) 449 450 // Do not remove from the policy cache for permission denied 451 // what this does indicate is that our view of the token is out of date 452 return nil, &policyTokenError{acl.ErrPermissionDenied, identity.SecretToken()} 453 } 454 455 // other RPC error - use cache if available 456 457 extendCache := r.config.ACLDownPolicy == "extend-cache" || r.config.ACLDownPolicy == "async-cache" 458 459 out := make(map[string]*structs.ACLPolicy) 460 insufficientCache := false 461 for _, policyID := range policyIDs { 462 if entry, ok := cached[policyID]; extendCache && ok { 463 r.cache.PutPolicy(policyID, entry.Policy) 464 if entry.Policy != nil { 465 out[policyID] = entry.Policy 466 } 467 } else { 468 r.cache.PutPolicy(policyID, nil) 469 insufficientCache = true 470 } 471 } 472 if insufficientCache { 473 return nil, ACLRemoteError{Err: err} 474 } 475 return out, nil 476 } 477 478 func (r *ACLResolver) filterPoliciesByScope(policies structs.ACLPolicies) structs.ACLPolicies { 479 var out structs.ACLPolicies 480 for _, policy := range policies { 481 if len(policy.Datacenters) == 0 { 482 out = append(out, policy) 483 continue 484 } 485 486 for _, dc := range policy.Datacenters { 487 if dc == r.config.Datacenter { 488 out = append(out, policy) 489 continue 490 } 491 } 492 } 493 494 return out 495 } 496 497 func (r *ACLResolver) resolvePoliciesForIdentity(identity structs.ACLIdentity) (structs.ACLPolicies, error) { 498 policyIDs := identity.PolicyIDs() 499 if len(policyIDs) == 0 { 500 policy := identity.EmbeddedPolicy() 501 if policy != nil { 502 return []*structs.ACLPolicy{policy}, nil 503 } 504 505 // In this case the default policy will be all that is in effect. 506 return nil, nil 507 } 508 509 // For the new ACLs policy replication is mandatory for correct operation on servers. Therefore 510 // we only attempt to resolve policies locally 511 policies := make([]*structs.ACLPolicy, 0, len(policyIDs)) 512 513 // Get all associated policies 514 var missing []string 515 var expired []*structs.ACLPolicy 516 expCacheMap := make(map[string]*structs.PolicyCacheEntry) 517 518 for _, policyID := range policyIDs { 519 if done, policy, err := r.delegate.ResolvePolicyFromID(policyID); done { 520 if err != nil && !acl.IsErrNotFound(err) { 521 return nil, err 522 } 523 524 if policy != nil { 525 policies = append(policies, policy) 526 } else { 527 r.logger.Printf("[WARN] acl: policy %q not found for identity %q", policyID, identity.ID()) 528 } 529 530 continue 531 } 532 533 // create the missing list which we can execute an RPC to get all the missing policies at once 534 entry := r.cache.GetPolicy(policyID) 535 if entry == nil { 536 missing = append(missing, policyID) 537 continue 538 } 539 540 if entry.Policy == nil { 541 // this happens when we cache a negative response for the policies existence 542 continue 543 } 544 545 if entry.Age() >= r.config.ACLPolicyTTL { 546 expired = append(expired, entry.Policy) 547 expCacheMap[policyID] = entry 548 } else { 549 policies = append(policies, entry.Policy) 550 } 551 } 552 553 // Hot-path if we have no missing or expired policies 554 if len(missing)+len(expired) == 0 { 555 return r.filterPoliciesByScope(policies), nil 556 } 557 558 hasMissing := len(missing) > 0 559 560 fetchIDs := missing 561 for _, policy := range expired { 562 fetchIDs = append(fetchIDs, policy.ID) 563 } 564 565 // Background a RPC request and wait on it if we must 566 waitChan := r.policyGroup.DoChan(identity.SecretToken(), func() (interface{}, error) { 567 policies, err := r.fetchAndCachePoliciesForIdentity(identity, fetchIDs, expCacheMap) 568 return policies, err 569 }) 570 571 waitForResult := hasMissing || r.config.ACLDownPolicy != "async-cache" 572 if !waitForResult { 573 // waitForResult being false requires that all the policies were cached already 574 policies = append(policies, expired...) 575 return r.filterPoliciesByScope(policies), nil 576 } 577 578 res := <-waitChan 579 580 if res.Err != nil { 581 return nil, res.Err 582 } 583 584 if res.Val != nil { 585 foundPolicies := res.Val.(map[string]*structs.ACLPolicy) 586 587 for _, policy := range foundPolicies { 588 policies = append(policies, policy) 589 } 590 } 591 592 return r.filterPoliciesByScope(policies), nil 593 } 594 595 func (r *ACLResolver) resolveTokenToPolicies(token string) (structs.ACLPolicies, error) { 596 _, policies, err := r.resolveTokenToIdentityAndPolicies(token) 597 return policies, err 598 } 599 600 func (r *ACLResolver) resolveTokenToIdentityAndPolicies(token string) (structs.ACLIdentity, structs.ACLPolicies, error) { 601 var lastErr error 602 var lastIdentity structs.ACLIdentity 603 604 for i := 0; i < tokenPolicyResolutionMaxRetries; i++ { 605 // Resolve the token to an ACLIdentity 606 identity, err := r.resolveIdentityFromToken(token) 607 if err != nil { 608 return nil, nil, err 609 } else if identity == nil { 610 return nil, nil, acl.ErrNotFound 611 } 612 613 lastIdentity = identity 614 615 policies, err := r.resolvePoliciesForIdentity(identity) 616 if err == nil { 617 return identity, policies, nil 618 } 619 lastErr = err 620 621 if tokenErr, ok := err.(*policyTokenError); ok { 622 if acl.IsErrNotFound(err) && tokenErr.token == identity.SecretToken() { 623 // token was deleted while resolving policies 624 return nil, nil, acl.ErrNotFound 625 } 626 627 // other types of policyTokenErrors should cause retrying the whole token 628 // resolution process 629 } else { 630 return identity, nil, err 631 } 632 } 633 634 return lastIdentity, nil, lastErr 635 } 636 637 func (r *ACLResolver) disableACLsWhenUpstreamDisabled(err error) error { 638 if !r.autoDisable || err == nil || !acl.IsErrDisabled(err) { 639 return err 640 } 641 642 r.logger.Printf("[DEBUG] acl: ACLs disabled on upstream servers, will check again after %s", r.config.ACLDisabledTTL) 643 r.disabledLock.Lock() 644 r.disabled = time.Now().Add(r.config.ACLDisabledTTL) 645 r.disabledLock.Unlock() 646 647 return err 648 } 649 650 func (r *ACLResolver) ResolveToken(token string) (acl.Authorizer, error) { 651 if !r.ACLsEnabled() { 652 return nil, nil 653 } 654 655 if acl.RootAuthorizer(token) != nil { 656 return nil, acl.ErrRootDenied 657 } 658 659 // handle the anonymous token 660 if token == "" { 661 token = anonymousToken 662 } 663 664 if r.delegate.UseLegacyACLs() { 665 authorizer, err := r.resolveTokenLegacy(token) 666 return authorizer, r.disableACLsWhenUpstreamDisabled(err) 667 } 668 669 defer metrics.MeasureSince([]string{"acl", "ResolveToken"}, time.Now()) 670 671 policies, err := r.resolveTokenToPolicies(token) 672 if err != nil { 673 r.disableACLsWhenUpstreamDisabled(err) 674 if IsACLRemoteError(err) { 675 r.logger.Printf("[ERR] consul.acl: %v", err) 676 return r.down, nil 677 } 678 679 return nil, err 680 } 681 682 // Build the Authorizer 683 authorizer, err := policies.Compile(acl.RootAuthorizer(r.config.ACLDefaultPolicy), r.cache, r.sentinel) 684 return authorizer, err 685 686 } 687 688 func (r *ACLResolver) ACLsEnabled() bool { 689 // Whether we desire ACLs to be enabled according to configuration 690 if !r.delegate.ACLsEnabled() { 691 return false 692 } 693 694 if r.autoDisable { 695 // Whether ACLs are disabled according to RPCs failing with a ACLs Disabled error 696 r.disabledLock.RLock() 697 defer r.disabledLock.RUnlock() 698 return !time.Now().Before(r.disabled) 699 } 700 701 return true 702 } 703 704 func (r *ACLResolver) GetMergedPolicyForToken(token string) (*acl.Policy, error) { 705 policies, err := r.resolveTokenToPolicies(token) 706 if err != nil { 707 return nil, err 708 } 709 if len(policies) == 0 { 710 return nil, acl.ErrNotFound 711 } 712 713 return policies.Merge(r.cache, r.sentinel) 714 } 715 716 // aclFilter is used to filter results from our state store based on ACL rules 717 // configured for the provided token. 718 type aclFilter struct { 719 authorizer acl.Authorizer 720 logger *log.Logger 721 enforceVersion8 bool 722 } 723 724 // newACLFilter constructs a new aclFilter. 725 func newACLFilter(authorizer acl.Authorizer, logger *log.Logger, enforceVersion8 bool) *aclFilter { 726 if logger == nil { 727 logger = log.New(os.Stderr, "", log.LstdFlags) 728 } 729 return &aclFilter{ 730 authorizer: authorizer, 731 logger: logger, 732 enforceVersion8: enforceVersion8, 733 } 734 } 735 736 // allowNode is used to determine if a node is accessible for an ACL. 737 func (f *aclFilter) allowNode(node string) bool { 738 if !f.enforceVersion8 { 739 return true 740 } 741 return f.authorizer.NodeRead(node) 742 } 743 744 // allowService is used to determine if a service is accessible for an ACL. 745 func (f *aclFilter) allowService(service string) bool { 746 if service == "" { 747 return true 748 } 749 750 if !f.enforceVersion8 && service == structs.ConsulServiceID { 751 return true 752 } 753 return f.authorizer.ServiceRead(service) 754 } 755 756 // allowSession is used to determine if a session for a node is accessible for 757 // an ACL. 758 func (f *aclFilter) allowSession(node string) bool { 759 if !f.enforceVersion8 { 760 return true 761 } 762 return f.authorizer.SessionRead(node) 763 } 764 765 // filterHealthChecks is used to filter a set of health checks down based on 766 // the configured ACL rules for a token. 767 func (f *aclFilter) filterHealthChecks(checks *structs.HealthChecks) { 768 hc := *checks 769 for i := 0; i < len(hc); i++ { 770 check := hc[i] 771 if f.allowNode(check.Node) && f.allowService(check.ServiceName) { 772 continue 773 } 774 f.logger.Printf("[DEBUG] consul: dropping check %q from result due to ACLs", check.CheckID) 775 hc = append(hc[:i], hc[i+1:]...) 776 i-- 777 } 778 *checks = hc 779 } 780 781 // filterServices is used to filter a set of services based on ACLs. 782 func (f *aclFilter) filterServices(services structs.Services) { 783 for svc := range services { 784 if f.allowService(svc) { 785 continue 786 } 787 f.logger.Printf("[DEBUG] consul: dropping service %q from result due to ACLs", svc) 788 delete(services, svc) 789 } 790 } 791 792 // filterServiceNodes is used to filter a set of nodes for a given service 793 // based on the configured ACL rules. 794 func (f *aclFilter) filterServiceNodes(nodes *structs.ServiceNodes) { 795 sn := *nodes 796 for i := 0; i < len(sn); i++ { 797 node := sn[i] 798 if f.allowNode(node.Node) && f.allowService(node.ServiceName) { 799 continue 800 } 801 f.logger.Printf("[DEBUG] consul: dropping node %q from result due to ACLs", node.Node) 802 sn = append(sn[:i], sn[i+1:]...) 803 i-- 804 } 805 *nodes = sn 806 } 807 808 // filterNodeServices is used to filter services on a given node base on ACLs. 809 func (f *aclFilter) filterNodeServices(services **structs.NodeServices) { 810 if *services == nil { 811 return 812 } 813 814 if !f.allowNode((*services).Node.Node) { 815 *services = nil 816 return 817 } 818 819 for svc := range (*services).Services { 820 if f.allowService(svc) { 821 continue 822 } 823 f.logger.Printf("[DEBUG] consul: dropping service %q from result due to ACLs", svc) 824 delete((*services).Services, svc) 825 } 826 } 827 828 // filterCheckServiceNodes is used to filter nodes based on ACL rules. 829 func (f *aclFilter) filterCheckServiceNodes(nodes *structs.CheckServiceNodes) { 830 csn := *nodes 831 for i := 0; i < len(csn); i++ { 832 node := csn[i] 833 if f.allowNode(node.Node.Node) && f.allowService(node.Service.Service) { 834 continue 835 } 836 f.logger.Printf("[DEBUG] consul: dropping node %q from result due to ACLs", node.Node.Node) 837 csn = append(csn[:i], csn[i+1:]...) 838 i-- 839 } 840 *nodes = csn 841 } 842 843 // filterSessions is used to filter a set of sessions based on ACLs. 844 func (f *aclFilter) filterSessions(sessions *structs.Sessions) { 845 s := *sessions 846 for i := 0; i < len(s); i++ { 847 session := s[i] 848 if f.allowSession(session.Node) { 849 continue 850 } 851 f.logger.Printf("[DEBUG] consul: dropping session %q from result due to ACLs", session.ID) 852 s = append(s[:i], s[i+1:]...) 853 i-- 854 } 855 *sessions = s 856 } 857 858 // filterCoordinates is used to filter nodes in a coordinate dump based on ACL 859 // rules. 860 func (f *aclFilter) filterCoordinates(coords *structs.Coordinates) { 861 c := *coords 862 for i := 0; i < len(c); i++ { 863 node := c[i].Node 864 if f.allowNode(node) { 865 continue 866 } 867 f.logger.Printf("[DEBUG] consul: dropping node %q from result due to ACLs", node) 868 c = append(c[:i], c[i+1:]...) 869 i-- 870 } 871 *coords = c 872 } 873 874 // filterIntentions is used to filter intentions based on ACL rules. 875 // We prune entries the user doesn't have access to, and we redact any tokens 876 // if the user doesn't have a management token. 877 func (f *aclFilter) filterIntentions(ixns *structs.Intentions) { 878 // Management tokens can see everything with no filtering. 879 if f.authorizer.ACLRead() { 880 return 881 } 882 883 // Otherwise, we need to see what the token has access to. 884 ret := make(structs.Intentions, 0, len(*ixns)) 885 for _, ixn := range *ixns { 886 // If no prefix ACL applies to this then filter it, since 887 // we know at this point the user doesn't have a management 888 // token, otherwise see what the policy says. 889 prefix, ok := ixn.GetACLPrefix() 890 if !ok || !f.authorizer.IntentionRead(prefix) { 891 f.logger.Printf("[DEBUG] consul: dropping intention %q from result due to ACLs", ixn.ID) 892 continue 893 } 894 895 ret = append(ret, ixn) 896 } 897 898 *ixns = ret 899 } 900 901 // filterNodeDump is used to filter through all parts of a node dump and 902 // remove elements the provided ACL token cannot access. 903 func (f *aclFilter) filterNodeDump(dump *structs.NodeDump) { 904 nd := *dump 905 for i := 0; i < len(nd); i++ { 906 info := nd[i] 907 908 // Filter nodes 909 if node := info.Node; !f.allowNode(node) { 910 f.logger.Printf("[DEBUG] consul: dropping node %q from result due to ACLs", node) 911 nd = append(nd[:i], nd[i+1:]...) 912 i-- 913 continue 914 } 915 916 // Filter services 917 for j := 0; j < len(info.Services); j++ { 918 svc := info.Services[j].Service 919 if f.allowService(svc) { 920 continue 921 } 922 f.logger.Printf("[DEBUG] consul: dropping service %q from result due to ACLs", svc) 923 info.Services = append(info.Services[:j], info.Services[j+1:]...) 924 j-- 925 } 926 927 // Filter checks 928 for j := 0; j < len(info.Checks); j++ { 929 chk := info.Checks[j] 930 if f.allowService(chk.ServiceName) { 931 continue 932 } 933 f.logger.Printf("[DEBUG] consul: dropping check %q from result due to ACLs", chk.CheckID) 934 info.Checks = append(info.Checks[:j], info.Checks[j+1:]...) 935 j-- 936 } 937 } 938 *dump = nd 939 } 940 941 // filterNodes is used to filter through all parts of a node list and remove 942 // elements the provided ACL token cannot access. 943 func (f *aclFilter) filterNodes(nodes *structs.Nodes) { 944 n := *nodes 945 for i := 0; i < len(n); i++ { 946 node := n[i].Node 947 if f.allowNode(node) { 948 continue 949 } 950 f.logger.Printf("[DEBUG] consul: dropping node %q from result due to ACLs", node) 951 n = append(n[:i], n[i+1:]...) 952 i-- 953 } 954 *nodes = n 955 } 956 957 // redactPreparedQueryTokens will redact any tokens unless the client has a 958 // management token. This eases the transition to delegated authority over 959 // prepared queries, since it was easy to capture management tokens in Consul 960 // 0.6.3 and earlier, and we don't want to willy-nilly show those. This does 961 // have the limitation of preventing delegated non-management users from seeing 962 // captured tokens, but they can at least see whether or not a token is set. 963 func (f *aclFilter) redactPreparedQueryTokens(query **structs.PreparedQuery) { 964 // Management tokens can see everything with no filtering. 965 if f.authorizer.ACLWrite() { 966 return 967 } 968 969 // Let the user see if there's a blank token, otherwise we need 970 // to redact it, since we know they don't have a management 971 // token. 972 if (*query).Token != "" { 973 // Redact the token, using a copy of the query structure 974 // since we could be pointed at a live instance from the 975 // state store so it's not safe to modify it. Note that 976 // this clone will still point to things like underlying 977 // arrays in the original, but for modifying just the 978 // token it will be safe to use. 979 clone := *(*query) 980 clone.Token = redactedToken 981 *query = &clone 982 } 983 } 984 985 // filterPreparedQueries is used to filter prepared queries based on ACL rules. 986 // We prune entries the user doesn't have access to, and we redact any tokens 987 // if the user doesn't have a management token. 988 func (f *aclFilter) filterPreparedQueries(queries *structs.PreparedQueries) { 989 // Management tokens can see everything with no filtering. 990 if f.authorizer.ACLWrite() { 991 return 992 } 993 994 // Otherwise, we need to see what the token has access to. 995 ret := make(structs.PreparedQueries, 0, len(*queries)) 996 for _, query := range *queries { 997 // If no prefix ACL applies to this query then filter it, since 998 // we know at this point the user doesn't have a management 999 // token, otherwise see what the policy says. 1000 prefix, ok := query.GetACLPrefix() 1001 if !ok || !f.authorizer.PreparedQueryRead(prefix) { 1002 f.logger.Printf("[DEBUG] consul: dropping prepared query %q from result due to ACLs", query.ID) 1003 continue 1004 } 1005 1006 // Redact any tokens if necessary. We make a copy of just the 1007 // pointer so we don't mess with the caller's slice. 1008 final := query 1009 f.redactPreparedQueryTokens(&final) 1010 ret = append(ret, final) 1011 } 1012 *queries = ret 1013 } 1014 1015 func (f *aclFilter) redactTokenSecret(token **structs.ACLToken) { 1016 if token == nil || *token == nil || f == nil || f.authorizer.ACLWrite() { 1017 return 1018 } 1019 clone := *(*token) 1020 clone.SecretID = redactedToken 1021 *token = &clone 1022 } 1023 1024 func (f *aclFilter) redactTokenSecrets(tokens *structs.ACLTokens) { 1025 ret := make(structs.ACLTokens, 0, len(*tokens)) 1026 for _, token := range *tokens { 1027 final := token 1028 f.redactTokenSecret(&final) 1029 ret = append(ret, final) 1030 } 1031 *tokens = ret 1032 } 1033 1034 func (r *ACLResolver) filterACLWithAuthorizer(authorizer acl.Authorizer, subj interface{}) error { 1035 if authorizer == nil { 1036 return nil 1037 } 1038 // Create the filter 1039 filt := newACLFilter(authorizer, r.logger, r.config.ACLEnforceVersion8) 1040 1041 switch v := subj.(type) { 1042 case *structs.CheckServiceNodes: 1043 filt.filterCheckServiceNodes(v) 1044 1045 case *structs.IndexedCheckServiceNodes: 1046 filt.filterCheckServiceNodes(&v.Nodes) 1047 1048 case *structs.IndexedCoordinates: 1049 filt.filterCoordinates(&v.Coordinates) 1050 1051 case *structs.IndexedHealthChecks: 1052 filt.filterHealthChecks(&v.HealthChecks) 1053 1054 case *structs.IndexedIntentions: 1055 filt.filterIntentions(&v.Intentions) 1056 1057 case *structs.IndexedNodeDump: 1058 filt.filterNodeDump(&v.Dump) 1059 1060 case *structs.IndexedNodes: 1061 filt.filterNodes(&v.Nodes) 1062 1063 case *structs.IndexedNodeServices: 1064 filt.filterNodeServices(&v.NodeServices) 1065 1066 case *structs.IndexedServiceNodes: 1067 filt.filterServiceNodes(&v.ServiceNodes) 1068 1069 case *structs.IndexedServices: 1070 filt.filterServices(v.Services) 1071 1072 case *structs.IndexedSessions: 1073 filt.filterSessions(&v.Sessions) 1074 1075 case *structs.IndexedPreparedQueries: 1076 filt.filterPreparedQueries(&v.Queries) 1077 1078 case **structs.PreparedQuery: 1079 filt.redactPreparedQueryTokens(v) 1080 1081 case *structs.ACLTokens: 1082 filt.redactTokenSecrets(v) 1083 1084 case **structs.ACLToken: 1085 filt.redactTokenSecret(v) 1086 1087 default: 1088 panic(fmt.Errorf("Unhandled type passed to ACL filter: %#v", subj)) 1089 } 1090 1091 return nil 1092 } 1093 1094 // filterACL is used to filter results from our service catalog based on the 1095 // rules configured for the provided token. 1096 func (r *ACLResolver) filterACL(token string, subj interface{}) error { 1097 // Get the ACL from the token 1098 authorizer, err := r.ResolveToken(token) 1099 if err != nil { 1100 return err 1101 } 1102 1103 // Fast path if ACLs are not enabled 1104 if authorizer == nil { 1105 return nil 1106 } 1107 1108 return r.filterACLWithAuthorizer(authorizer, subj) 1109 } 1110 1111 // vetRegisterWithACL applies the given ACL's policy to the catalog update and 1112 // determines if it is allowed. Since the catalog register request is so 1113 // dynamic, this is a pretty complex algorithm and was worth breaking out of the 1114 // endpoint. The NodeServices record for the node must be supplied, and can be 1115 // nil. 1116 // 1117 // This is a bit racy because we have to check the state store outside of a 1118 // transaction. It's the best we can do because we don't want to flow ACL 1119 // checking down there. The node information doesn't change in practice, so this 1120 // will be fine. If we expose ways to change node addresses in a later version, 1121 // then we should split the catalog API at the node and service level so we can 1122 // address this race better (even then it would be super rare, and would at 1123 // worst let a service update revert a recent node update, so it doesn't open up 1124 // too much abuse). 1125 func vetRegisterWithACL(rule acl.Authorizer, subj *structs.RegisterRequest, 1126 ns *structs.NodeServices) error { 1127 // Fast path if ACLs are not enabled. 1128 if rule == nil { 1129 return nil 1130 } 1131 1132 // This gets called potentially from a few spots so we save it and 1133 // return the structure we made if we have it. 1134 var memo map[string]interface{} 1135 scope := func() map[string]interface{} { 1136 if memo != nil { 1137 return memo 1138 } 1139 1140 node := &api.Node{ 1141 ID: string(subj.ID), 1142 Node: subj.Node, 1143 Address: subj.Address, 1144 Datacenter: subj.Datacenter, 1145 TaggedAddresses: subj.TaggedAddresses, 1146 Meta: subj.NodeMeta, 1147 } 1148 1149 var service *api.AgentService 1150 if subj.Service != nil { 1151 service = &api.AgentService{ 1152 ID: subj.Service.ID, 1153 Service: subj.Service.Service, 1154 Tags: subj.Service.Tags, 1155 Meta: subj.Service.Meta, 1156 Address: subj.Service.Address, 1157 Port: subj.Service.Port, 1158 EnableTagOverride: subj.Service.EnableTagOverride, 1159 } 1160 } 1161 1162 memo = sentinel.ScopeCatalogUpsert(node, service) 1163 return memo 1164 } 1165 1166 // Vet the node info. This allows service updates to re-post the required 1167 // node info for each request without having to have node "write" 1168 // privileges. 1169 needsNode := ns == nil || subj.ChangesNode(ns.Node) 1170 1171 if needsNode && !rule.NodeWrite(subj.Node, scope) { 1172 return acl.ErrPermissionDenied 1173 } 1174 1175 // Vet the service change. This includes making sure they can register 1176 // the given service, and that we can write to any existing service that 1177 // is being modified by id (if any). 1178 if subj.Service != nil { 1179 if !rule.ServiceWrite(subj.Service.Service, scope) { 1180 return acl.ErrPermissionDenied 1181 } 1182 1183 if ns != nil { 1184 other, ok := ns.Services[subj.Service.ID] 1185 1186 // This is effectively a delete, so we DO NOT apply the 1187 // sentinel scope to the service we are overwriting, just 1188 // the regular ACL policy. 1189 if ok && !rule.ServiceWrite(other.Service, nil) { 1190 return acl.ErrPermissionDenied 1191 } 1192 } 1193 } 1194 1195 // Make sure that the member was flattened before we got there. This 1196 // keeps us from having to verify this check as well. 1197 if subj.Check != nil { 1198 return fmt.Errorf("check member must be nil") 1199 } 1200 1201 // Vet the checks. Node-level checks require node write, and 1202 // service-level checks require service write. 1203 for _, check := range subj.Checks { 1204 // Make sure that the node matches - we don't allow you to mix 1205 // checks from other nodes because we'd have to pull a bunch 1206 // more state store data to check this. If ACLs are enabled then 1207 // we simply require them to match in a given request. There's a 1208 // note in state_store.go to ban this down there in Consul 0.8, 1209 // but it's good to leave this here because it's required for 1210 // correctness wrt. ACLs. 1211 if check.Node != subj.Node { 1212 return fmt.Errorf("Node '%s' for check '%s' doesn't match register request node '%s'", 1213 check.Node, check.CheckID, subj.Node) 1214 } 1215 1216 // Node-level check. 1217 if check.ServiceID == "" { 1218 if !rule.NodeWrite(subj.Node, scope) { 1219 return acl.ErrPermissionDenied 1220 } 1221 continue 1222 } 1223 1224 // Service-level check, check the common case where it 1225 // matches the service part of this request, which has 1226 // already been vetted above, and might be being registered 1227 // along with its checks. 1228 if subj.Service != nil && subj.Service.ID == check.ServiceID { 1229 continue 1230 } 1231 1232 // Service-level check for some other service. Make sure they've 1233 // got write permissions for that service. 1234 if ns == nil { 1235 return fmt.Errorf("Unknown service '%s' for check '%s'", check.ServiceID, check.CheckID) 1236 } 1237 1238 other, ok := ns.Services[check.ServiceID] 1239 if !ok { 1240 return fmt.Errorf("Unknown service '%s' for check '%s'", check.ServiceID, check.CheckID) 1241 } 1242 1243 // We are only adding a check here, so we don't add the scope, 1244 // since the sentinel policy doesn't apply to adding checks at 1245 // this time. 1246 if !rule.ServiceWrite(other.Service, nil) { 1247 return acl.ErrPermissionDenied 1248 } 1249 } 1250 1251 return nil 1252 } 1253 1254 // vetDeregisterWithACL applies the given ACL's policy to the catalog update and 1255 // determines if it is allowed. Since the catalog deregister request is so 1256 // dynamic, this is a pretty complex algorithm and was worth breaking out of the 1257 // endpoint. The NodeService for the referenced service must be supplied, and can 1258 // be nil; similar for the HealthCheck for the referenced health check. 1259 func vetDeregisterWithACL(rule acl.Authorizer, subj *structs.DeregisterRequest, 1260 ns *structs.NodeService, nc *structs.HealthCheck) error { 1261 1262 // Fast path if ACLs are not enabled. 1263 if rule == nil { 1264 return nil 1265 } 1266 1267 // We don't apply sentinel in this path, since at this time sentinel 1268 // only applies to create and update operations. 1269 1270 // This order must match the code in applyRegister() in fsm.go since it 1271 // also evaluates things in this order, and will ignore fields based on 1272 // this precedence. This lets us also ignore them from an ACL perspective. 1273 if subj.ServiceID != "" { 1274 if ns == nil { 1275 return fmt.Errorf("Unknown service '%s'", subj.ServiceID) 1276 } 1277 if !rule.ServiceWrite(ns.Service, nil) { 1278 return acl.ErrPermissionDenied 1279 } 1280 } else if subj.CheckID != "" { 1281 if nc == nil { 1282 return fmt.Errorf("Unknown check '%s'", subj.CheckID) 1283 } 1284 if nc.ServiceID != "" { 1285 if !rule.ServiceWrite(nc.ServiceName, nil) { 1286 return acl.ErrPermissionDenied 1287 } 1288 } else { 1289 if !rule.NodeWrite(subj.Node, nil) { 1290 return acl.ErrPermissionDenied 1291 } 1292 } 1293 } else { 1294 if !rule.NodeWrite(subj.Node, nil) { 1295 return acl.ErrPermissionDenied 1296 } 1297 } 1298 1299 return nil 1300 } 1301 1302 // vetNodeTxnOp applies the given ACL policy to a node transaction operation. 1303 func vetNodeTxnOp(op *structs.TxnNodeOp, rule acl.Authorizer) error { 1304 // Fast path if ACLs are not enabled. 1305 if rule == nil { 1306 return nil 1307 } 1308 1309 node := op.Node 1310 1311 n := &api.Node{ 1312 Node: node.Node, 1313 ID: string(node.ID), 1314 Address: node.Address, 1315 Datacenter: node.Datacenter, 1316 TaggedAddresses: node.TaggedAddresses, 1317 Meta: node.Meta, 1318 } 1319 1320 // Sentinel doesn't apply to deletes, only creates/updates, so we don't need the scopeFn. 1321 var scope func() map[string]interface{} 1322 if op.Verb != api.NodeDelete && op.Verb != api.NodeDeleteCAS { 1323 scope = func() map[string]interface{} { 1324 return sentinel.ScopeCatalogUpsert(n, nil) 1325 } 1326 } 1327 1328 if rule != nil && !rule.NodeWrite(node.Node, scope) { 1329 return acl.ErrPermissionDenied 1330 } 1331 1332 return nil 1333 } 1334 1335 // vetServiceTxnOp applies the given ACL policy to a service transaction operation. 1336 func vetServiceTxnOp(op *structs.TxnServiceOp, rule acl.Authorizer) error { 1337 // Fast path if ACLs are not enabled. 1338 if rule == nil { 1339 return nil 1340 } 1341 1342 service := op.Service 1343 1344 n := &api.Node{Node: op.Node} 1345 svc := &api.AgentService{ 1346 ID: service.ID, 1347 Service: service.Service, 1348 Tags: service.Tags, 1349 Meta: service.Meta, 1350 Address: service.Address, 1351 Port: service.Port, 1352 EnableTagOverride: service.EnableTagOverride, 1353 } 1354 var scope func() map[string]interface{} 1355 if op.Verb != api.ServiceDelete && op.Verb != api.ServiceDeleteCAS { 1356 scope = func() map[string]interface{} { 1357 return sentinel.ScopeCatalogUpsert(n, svc) 1358 } 1359 } 1360 if !rule.ServiceWrite(service.Service, scope) { 1361 return acl.ErrPermissionDenied 1362 } 1363 1364 return nil 1365 } 1366 1367 // vetCheckTxnOp applies the given ACL policy to a check transaction operation. 1368 func vetCheckTxnOp(op *structs.TxnCheckOp, rule acl.Authorizer) error { 1369 // Fast path if ACLs are not enabled. 1370 if rule == nil { 1371 return nil 1372 } 1373 1374 n := &api.Node{Node: op.Check.Node} 1375 svc := &api.AgentService{ 1376 ID: op.Check.ServiceID, 1377 Service: op.Check.ServiceID, 1378 Tags: op.Check.ServiceTags, 1379 } 1380 var scope func() map[string]interface{} 1381 if op.Check.ServiceID == "" { 1382 // Node-level check. 1383 if op.Verb == api.CheckDelete || op.Verb == api.CheckDeleteCAS { 1384 scope = func() map[string]interface{} { 1385 return sentinel.ScopeCatalogUpsert(n, svc) 1386 } 1387 } 1388 if !rule.NodeWrite(op.Check.Node, scope) { 1389 return acl.ErrPermissionDenied 1390 } 1391 } else { 1392 // Service-level check. 1393 if op.Verb == api.CheckDelete || op.Verb == api.CheckDeleteCAS { 1394 scope = func() map[string]interface{} { 1395 return sentinel.ScopeCatalogUpsert(n, svc) 1396 } 1397 } 1398 if !rule.ServiceWrite(op.Check.ServiceName, scope) { 1399 return acl.ErrPermissionDenied 1400 } 1401 } 1402 1403 return nil 1404 }