diff --git a/agent/consul/acl.go b/agent/consul/acl.go index b475bf1596..4e8c885380 100644 --- a/agent/consul/acl.go +++ b/agent/consul/acl.go @@ -133,11 +133,12 @@ func tokenSecretCacheID(token string) string { return "token-secret:" + token } -type ACLResolverDelegate interface { +type ACLResolverBackend interface { ACLDatacenter() string ResolveIdentityFromToken(token string) (bool, structs.ACLIdentity, error) ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error) ResolveRoleFromID(roleID string) (bool, *structs.ACLRole, error) + // TODO: separate methods for each RPC call (there are 4) RPC(method string, args interface{}, reply interface{}) error EnterpriseACLResolverDelegate } @@ -160,8 +161,9 @@ type ACLResolverConfig struct { // CacheConfig is a pass through configuration for ACL cache limits CacheConfig *structs.ACLCachesConfig - // Delegate that implements some helper functionality that is server/client specific - Delegate ACLResolverDelegate + // Backend is used to retrieve data from the state store, or perform RPCs + // to fetch data from other Datacenters. + Backend ACLResolverBackend // DisableDuration is the length of time to leave ACLs disabled when an RPC // request to a server indicates that the ACL system is disabled. If set to @@ -219,9 +221,9 @@ type ACLResolverSettings struct { // ACLResolver is the type to handle all your token and policy resolution needs. // // Supports: -// - Resolving tokens locally via the ACLResolverDelegate -// - Resolving policies locally via the ACLResolverDelegate -// - Resolving roles locally via the ACLResolverDelegate +// - Resolving tokens locally via the ACLResolverBackend +// - Resolving policies locally via the ACLResolverBackend +// - Resolving roles locally via the ACLResolverBackend // - Resolving legacy tokens remotely via an ACL.GetPolicy RPC // - Resolving tokens remotely via an ACL.TokenRead RPC // - Resolving policies remotely via an ACL.PolicyResolve RPC @@ -245,8 +247,8 @@ type ACLResolver struct { config ACLResolverSettings logger hclog.Logger - delegate ACLResolverDelegate - aclConf *acl.Config + backend ACLResolverBackend + aclConf *acl.Config tokens *token.Store @@ -298,7 +300,7 @@ func NewACLResolver(config *ACLResolverConfig) (*ACLResolver, error) { if config == nil { return nil, fmt.Errorf("ACL Resolver must be initialized with a config") } - if config.Delegate == nil { + if config.Backend == nil { return nil, fmt.Errorf("ACL Resolver must be initialized with a valid delegate") } @@ -331,7 +333,7 @@ func NewACLResolver(config *ACLResolverConfig) (*ACLResolver, error) { return &ACLResolver{ config: config.Config, logger: config.Logger.Named(logging.ACL), - delegate: config.Delegate, + backend: config.Backend, aclConf: config.ACLConfig, cache: cache, disableDuration: config.DisableDuration, @@ -349,7 +351,7 @@ func (r *ACLResolver) fetchAndCacheIdentityFromToken(token string, cached *struc cacheID := tokenSecretCacheID(token) req := structs.ACLTokenGetRequest{ - Datacenter: r.delegate.ACLDatacenter(), + Datacenter: r.backend.ACLDatacenter(), TokenID: token, TokenIDType: structs.ACLTokenSecret, QueryOptions: structs.QueryOptions{ @@ -359,7 +361,7 @@ func (r *ACLResolver) fetchAndCacheIdentityFromToken(token string, cached *struc } var resp structs.ACLTokenResponse - err := r.delegate.RPC("ACL.TokenRead", &req, &resp) + err := r.backend.RPC("ACL.TokenRead", &req, &resp) if err == nil { if resp.Token == nil { r.cache.PutIdentity(cacheID, nil) @@ -396,7 +398,7 @@ func (r *ACLResolver) fetchAndCacheIdentityFromToken(token string, cached *struc // we initiate an RPC for the value. func (r *ACLResolver) resolveIdentityFromToken(token string) (structs.ACLIdentity, error) { // Attempt to resolve locally first (local results are not cached) - if done, identity, err := r.delegate.ResolveIdentityFromToken(token); done { + if done, identity, err := r.backend.ResolveIdentityFromToken(token); done { return identity, err } @@ -437,7 +439,7 @@ func (r *ACLResolver) resolveIdentityFromToken(token string) (structs.ACLIdentit func (r *ACLResolver) fetchAndCachePoliciesForIdentity(identity structs.ACLIdentity, policyIDs []string, cached map[string]*structs.PolicyCacheEntry) (map[string]*structs.ACLPolicy, error) { req := structs.ACLPolicyBatchGetRequest{ - Datacenter: r.delegate.ACLDatacenter(), + Datacenter: r.backend.ACLDatacenter(), PolicyIDs: policyIDs, QueryOptions: structs.QueryOptions{ Token: identity.SecretToken(), @@ -446,7 +448,7 @@ func (r *ACLResolver) fetchAndCachePoliciesForIdentity(identity structs.ACLIdent } var resp structs.ACLPolicyBatchResponse - err := r.delegate.RPC("ACL.PolicyResolve", &req, &resp) + err := r.backend.RPC("ACL.PolicyResolve", &req, &resp) if err == nil { out := make(map[string]*structs.ACLPolicy) for _, policy := range resp.Policies { @@ -492,7 +494,7 @@ func (r *ACLResolver) fetchAndCachePoliciesForIdentity(identity structs.ACLIdent func (r *ACLResolver) fetchAndCacheRolesForIdentity(identity structs.ACLIdentity, roleIDs []string, cached map[string]*structs.RoleCacheEntry) (map[string]*structs.ACLRole, error) { req := structs.ACLRoleBatchGetRequest{ - Datacenter: r.delegate.ACLDatacenter(), + Datacenter: r.backend.ACLDatacenter(), RoleIDs: roleIDs, QueryOptions: structs.QueryOptions{ Token: identity.SecretToken(), @@ -501,7 +503,7 @@ func (r *ACLResolver) fetchAndCacheRolesForIdentity(identity structs.ACLIdentity } var resp structs.ACLRoleBatchResponse - err := r.delegate.RPC("ACL.RoleResolve", &req, &resp) + err := r.backend.RPC("ACL.RoleResolve", &req, &resp) if err == nil { out := make(map[string]*structs.ACLRole) for _, role := range resp.Roles { @@ -774,7 +776,7 @@ func (r *ACLResolver) collectPoliciesForIdentity(identity structs.ACLIdentity, p } for _, policyID := range policyIDs { - if done, policy, err := r.delegate.ResolvePolicyFromID(policyID); done { + if done, policy, err := r.backend.ResolvePolicyFromID(policyID); done { if err != nil && !acl.IsErrNotFound(err) { return nil, err } @@ -871,7 +873,7 @@ func (r *ACLResolver) collectRolesForIdentity(identity structs.ACLIdentity, role expCacheMap := make(map[string]*structs.RoleCacheEntry) for _, roleID := range roleIDs { - if done, role, err := r.delegate.ResolveRoleFromID(roleID); done { + if done, role, err := r.backend.ResolveRoleFromID(roleID); done { if err != nil && !acl.IsErrNotFound(err) { return nil, err } diff --git a/agent/consul/acl_client.go b/agent/consul/acl_client.go index 36f3f19a79..2378776c83 100644 --- a/agent/consul/acl_client.go +++ b/agent/consul/acl_client.go @@ -5,7 +5,7 @@ import ( "github.com/hashicorp/consul/agent/structs" ) -var clientACLCacheConfig *structs.ACLCachesConfig = &structs.ACLCachesConfig{ +var clientACLCacheConfig = &structs.ACLCachesConfig{ // The ACL cache configuration on client agents is more conservative than // on the servers. It is assumed that individual client agents will have // fewer distinct identities accessing the client than a server would @@ -23,23 +23,28 @@ var clientACLCacheConfig *structs.ACLCachesConfig = &structs.ACLCachesConfig{ Roles: 128, } -func (c *Client) ACLDatacenter() string { - // For resolution running on clients, servers within the current datacenter +type clientACLResolverBackend struct { + // TODO: un-embed + *Client +} + +func (c *clientACLResolverBackend) ACLDatacenter() string { + // For resolution running on clients servers within the current datacenter // must be queried first to pick up local tokens. return c.config.Datacenter } -func (c *Client) ResolveIdentityFromToken(token string) (bool, structs.ACLIdentity, error) { +func (c *clientACLResolverBackend) ResolveIdentityFromToken(token string) (bool, structs.ACLIdentity, error) { // clients do no local identity resolution at the moment return false, nil, nil } -func (c *Client) ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error) { +func (c *clientACLResolverBackend) ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error) { // clients do no local policy resolution at the moment return false, nil, nil } -func (c *Client) ResolveRoleFromID(roleID string) (bool, *structs.ACLRole, error) { +func (c *clientACLResolverBackend) ResolveRoleFromID(roleID string) (bool, *structs.ACLRole, error) { // clients do no local role resolution at the moment return false, nil, nil } diff --git a/agent/consul/acl_server.go b/agent/consul/acl_server.go index f16b1cc864..497b347d73 100644 --- a/agent/consul/acl_server.go +++ b/agent/consul/acl_server.go @@ -100,9 +100,14 @@ func (s *Server) LocalTokensEnabled() bool { return true } -func (s *Server) ACLDatacenter() string { - // For resolution running on servers the only option - // is to contact the configured ACL Datacenter +type serverACLResolverBackend struct { + // TODO: un-embed + *Server +} + +func (s *serverACLResolverBackend) ACLDatacenter() string { + // For resolution running on servers the only option is to contact the + // configured ACL Datacenter if s.config.PrimaryDatacenter != "" { return s.config.PrimaryDatacenter } @@ -114,6 +119,7 @@ func (s *Server) ACLDatacenter() string { } // ResolveIdentityFromToken retrieves a token's full identity given its secretID. +// TODO: why does some code call this directly instead of using ACLResolver.ResolveTokenToIdentity ? func (s *Server) ResolveIdentityFromToken(token string) (bool, structs.ACLIdentity, error) { // only allow remote RPC resolution when token replication is off and // when not in the ACL datacenter @@ -131,7 +137,7 @@ func (s *Server) ResolveIdentityFromToken(token string) (bool, structs.ACLIdenti return s.InPrimaryDatacenter() || index > 0, nil, acl.ErrNotFound } -func (s *Server) ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error) { +func (s *serverACLResolverBackend) ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error) { index, policy, err := s.fsm.State().ACLPolicyGetByID(nil, policyID, nil) if err != nil { return true, nil, err @@ -145,7 +151,7 @@ func (s *Server) ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, return s.InPrimaryDatacenter() || index > 0, policy, acl.ErrNotFound } -func (s *Server) ResolveRoleFromID(roleID string) (bool, *structs.ACLRole, error) { +func (s *serverACLResolverBackend) ResolveRoleFromID(roleID string) (bool, *structs.ACLRole, error) { index, role, err := s.fsm.State().ACLRoleGetByID(nil, roleID, nil) if err != nil { return true, nil, err diff --git a/agent/consul/acl_test.go b/agent/consul/acl_test.go index d45b1e1973..ee328039bf 100644 --- a/agent/consul/acl_test.go +++ b/agent/consul/acl_test.go @@ -715,7 +715,7 @@ func newTestACLResolver(t *testing.T, delegate *ACLResolverTestDelegate, cb func Roles: 4, }, DisableDuration: aclClientDisabledTTL, - Delegate: delegate, + Backend: delegate, } if cb != nil { diff --git a/agent/consul/client.go b/agent/consul/client.go index 999f986634..369595bc0d 100644 --- a/agent/consul/client.go +++ b/agent/consul/client.go @@ -119,7 +119,7 @@ func NewClient(config *Config, deps Deps) (*Client, error) { aclConfig := ACLResolverConfig{ Config: config.ACLResolverSettings, - Delegate: c, + Backend: &clientACLResolverBackend{Client: c}, Logger: c.logger, DisableDuration: aclClientDisabledTTL, CacheConfig: clientACLCacheConfig, diff --git a/agent/consul/replication.go b/agent/consul/replication.go index 4b6f74c5cd..d4d449aa1f 100644 --- a/agent/consul/replication.go +++ b/agent/consul/replication.go @@ -110,7 +110,7 @@ func NewReplicator(config *ReplicatorConfig) (*Replicator, error) { return nil, fmt.Errorf("Cannot create the Replicator without a config") } if config.Delegate == nil { - return nil, fmt.Errorf("Cannot create the Replicator without a Delegate set in the config") + return nil, fmt.Errorf("Cannot create the Replicator without a Backend set in the config") } if config.Logger == nil { logger := hclog.New(&hclog.LoggerOptions{}) diff --git a/agent/consul/server.go b/agent/consul/server.go index e076af7214..a3a9b75ca5 100644 --- a/agent/consul/server.go +++ b/agent/consul/server.go @@ -450,7 +450,7 @@ func NewServer(config *Config, flat Deps) (*Server, error) { s.aclConfig = newACLConfig(partitionInfo, logger) aclConfig := ACLResolverConfig{ Config: config.ACLResolverSettings, - Delegate: s, + Backend: &serverACLResolverBackend{Server: s}, CacheConfig: serverACLCacheConfig, Logger: logger, ACLConfig: s.aclConfig,