mirror of https://github.com/status-im/consul.git
acl: extract a backend type for the ACLResolverBackend
This is a small step to isolate the functionality that is used for the ACLResolver from the large Client and Server structs.
This commit is contained in:
parent
19a67d8768
commit
737c0097e0
|
@ -133,11 +133,12 @@ func tokenSecretCacheID(token string) string {
|
||||||
return "token-secret:" + token
|
return "token-secret:" + token
|
||||||
}
|
}
|
||||||
|
|
||||||
type ACLResolverDelegate interface {
|
type ACLResolverBackend interface {
|
||||||
ACLDatacenter() string
|
ACLDatacenter() string
|
||||||
ResolveIdentityFromToken(token string) (bool, structs.ACLIdentity, error)
|
ResolveIdentityFromToken(token string) (bool, structs.ACLIdentity, error)
|
||||||
ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error)
|
ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error)
|
||||||
ResolveRoleFromID(roleID string) (bool, *structs.ACLRole, 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
|
RPC(method string, args interface{}, reply interface{}) error
|
||||||
EnterpriseACLResolverDelegate
|
EnterpriseACLResolverDelegate
|
||||||
}
|
}
|
||||||
|
@ -160,8 +161,9 @@ type ACLResolverConfig struct {
|
||||||
// CacheConfig is a pass through configuration for ACL cache limits
|
// CacheConfig is a pass through configuration for ACL cache limits
|
||||||
CacheConfig *structs.ACLCachesConfig
|
CacheConfig *structs.ACLCachesConfig
|
||||||
|
|
||||||
// Delegate that implements some helper functionality that is server/client specific
|
// Backend is used to retrieve data from the state store, or perform RPCs
|
||||||
Delegate ACLResolverDelegate
|
// to fetch data from other Datacenters.
|
||||||
|
Backend ACLResolverBackend
|
||||||
|
|
||||||
// DisableDuration is the length of time to leave ACLs disabled when an RPC
|
// 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
|
// 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.
|
// ACLResolver is the type to handle all your token and policy resolution needs.
|
||||||
//
|
//
|
||||||
// Supports:
|
// Supports:
|
||||||
// - Resolving tokens locally via the ACLResolverDelegate
|
// - Resolving tokens locally via the ACLResolverBackend
|
||||||
// - Resolving policies locally via the ACLResolverDelegate
|
// - Resolving policies locally via the ACLResolverBackend
|
||||||
// - Resolving roles locally via the ACLResolverDelegate
|
// - Resolving roles locally via the ACLResolverBackend
|
||||||
// - Resolving legacy tokens remotely via an ACL.GetPolicy RPC
|
// - Resolving legacy tokens remotely via an ACL.GetPolicy RPC
|
||||||
// - Resolving tokens remotely via an ACL.TokenRead RPC
|
// - Resolving tokens remotely via an ACL.TokenRead RPC
|
||||||
// - Resolving policies remotely via an ACL.PolicyResolve RPC
|
// - Resolving policies remotely via an ACL.PolicyResolve RPC
|
||||||
|
@ -245,7 +247,7 @@ type ACLResolver struct {
|
||||||
config ACLResolverSettings
|
config ACLResolverSettings
|
||||||
logger hclog.Logger
|
logger hclog.Logger
|
||||||
|
|
||||||
delegate ACLResolverDelegate
|
backend ACLResolverBackend
|
||||||
aclConf *acl.Config
|
aclConf *acl.Config
|
||||||
|
|
||||||
tokens *token.Store
|
tokens *token.Store
|
||||||
|
@ -298,7 +300,7 @@ func NewACLResolver(config *ACLResolverConfig) (*ACLResolver, error) {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return nil, fmt.Errorf("ACL Resolver must be initialized with a config")
|
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")
|
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{
|
return &ACLResolver{
|
||||||
config: config.Config,
|
config: config.Config,
|
||||||
logger: config.Logger.Named(logging.ACL),
|
logger: config.Logger.Named(logging.ACL),
|
||||||
delegate: config.Delegate,
|
backend: config.Backend,
|
||||||
aclConf: config.ACLConfig,
|
aclConf: config.ACLConfig,
|
||||||
cache: cache,
|
cache: cache,
|
||||||
disableDuration: config.DisableDuration,
|
disableDuration: config.DisableDuration,
|
||||||
|
@ -349,7 +351,7 @@ func (r *ACLResolver) fetchAndCacheIdentityFromToken(token string, cached *struc
|
||||||
cacheID := tokenSecretCacheID(token)
|
cacheID := tokenSecretCacheID(token)
|
||||||
|
|
||||||
req := structs.ACLTokenGetRequest{
|
req := structs.ACLTokenGetRequest{
|
||||||
Datacenter: r.delegate.ACLDatacenter(),
|
Datacenter: r.backend.ACLDatacenter(),
|
||||||
TokenID: token,
|
TokenID: token,
|
||||||
TokenIDType: structs.ACLTokenSecret,
|
TokenIDType: structs.ACLTokenSecret,
|
||||||
QueryOptions: structs.QueryOptions{
|
QueryOptions: structs.QueryOptions{
|
||||||
|
@ -359,7 +361,7 @@ func (r *ACLResolver) fetchAndCacheIdentityFromToken(token string, cached *struc
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp structs.ACLTokenResponse
|
var resp structs.ACLTokenResponse
|
||||||
err := r.delegate.RPC("ACL.TokenRead", &req, &resp)
|
err := r.backend.RPC("ACL.TokenRead", &req, &resp)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if resp.Token == nil {
|
if resp.Token == nil {
|
||||||
r.cache.PutIdentity(cacheID, 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.
|
// we initiate an RPC for the value.
|
||||||
func (r *ACLResolver) resolveIdentityFromToken(token string) (structs.ACLIdentity, error) {
|
func (r *ACLResolver) resolveIdentityFromToken(token string) (structs.ACLIdentity, error) {
|
||||||
// Attempt to resolve locally first (local results are not cached)
|
// 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
|
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) {
|
func (r *ACLResolver) fetchAndCachePoliciesForIdentity(identity structs.ACLIdentity, policyIDs []string, cached map[string]*structs.PolicyCacheEntry) (map[string]*structs.ACLPolicy, error) {
|
||||||
req := structs.ACLPolicyBatchGetRequest{
|
req := structs.ACLPolicyBatchGetRequest{
|
||||||
Datacenter: r.delegate.ACLDatacenter(),
|
Datacenter: r.backend.ACLDatacenter(),
|
||||||
PolicyIDs: policyIDs,
|
PolicyIDs: policyIDs,
|
||||||
QueryOptions: structs.QueryOptions{
|
QueryOptions: structs.QueryOptions{
|
||||||
Token: identity.SecretToken(),
|
Token: identity.SecretToken(),
|
||||||
|
@ -446,7 +448,7 @@ func (r *ACLResolver) fetchAndCachePoliciesForIdentity(identity structs.ACLIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp structs.ACLPolicyBatchResponse
|
var resp structs.ACLPolicyBatchResponse
|
||||||
err := r.delegate.RPC("ACL.PolicyResolve", &req, &resp)
|
err := r.backend.RPC("ACL.PolicyResolve", &req, &resp)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
out := make(map[string]*structs.ACLPolicy)
|
out := make(map[string]*structs.ACLPolicy)
|
||||||
for _, policy := range resp.Policies {
|
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) {
|
func (r *ACLResolver) fetchAndCacheRolesForIdentity(identity structs.ACLIdentity, roleIDs []string, cached map[string]*structs.RoleCacheEntry) (map[string]*structs.ACLRole, error) {
|
||||||
req := structs.ACLRoleBatchGetRequest{
|
req := structs.ACLRoleBatchGetRequest{
|
||||||
Datacenter: r.delegate.ACLDatacenter(),
|
Datacenter: r.backend.ACLDatacenter(),
|
||||||
RoleIDs: roleIDs,
|
RoleIDs: roleIDs,
|
||||||
QueryOptions: structs.QueryOptions{
|
QueryOptions: structs.QueryOptions{
|
||||||
Token: identity.SecretToken(),
|
Token: identity.SecretToken(),
|
||||||
|
@ -501,7 +503,7 @@ func (r *ACLResolver) fetchAndCacheRolesForIdentity(identity structs.ACLIdentity
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp structs.ACLRoleBatchResponse
|
var resp structs.ACLRoleBatchResponse
|
||||||
err := r.delegate.RPC("ACL.RoleResolve", &req, &resp)
|
err := r.backend.RPC("ACL.RoleResolve", &req, &resp)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
out := make(map[string]*structs.ACLRole)
|
out := make(map[string]*structs.ACLRole)
|
||||||
for _, role := range resp.Roles {
|
for _, role := range resp.Roles {
|
||||||
|
@ -774,7 +776,7 @@ func (r *ACLResolver) collectPoliciesForIdentity(identity structs.ACLIdentity, p
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, policyID := range policyIDs {
|
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) {
|
if err != nil && !acl.IsErrNotFound(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -871,7 +873,7 @@ func (r *ACLResolver) collectRolesForIdentity(identity structs.ACLIdentity, role
|
||||||
expCacheMap := make(map[string]*structs.RoleCacheEntry)
|
expCacheMap := make(map[string]*structs.RoleCacheEntry)
|
||||||
|
|
||||||
for _, roleID := range roleIDs {
|
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) {
|
if err != nil && !acl.IsErrNotFound(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"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
|
// The ACL cache configuration on client agents is more conservative than
|
||||||
// on the servers. It is assumed that individual client agents will have
|
// on the servers. It is assumed that individual client agents will have
|
||||||
// fewer distinct identities accessing the client than a server would
|
// fewer distinct identities accessing the client than a server would
|
||||||
|
@ -23,23 +23,28 @@ var clientACLCacheConfig *structs.ACLCachesConfig = &structs.ACLCachesConfig{
|
||||||
Roles: 128,
|
Roles: 128,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ACLDatacenter() string {
|
type clientACLResolverBackend struct {
|
||||||
// For resolution running on clients, servers within the current datacenter
|
// 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.
|
// must be queried first to pick up local tokens.
|
||||||
return c.config.Datacenter
|
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
|
// clients do no local identity resolution at the moment
|
||||||
return false, nil, nil
|
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
|
// clients do no local policy resolution at the moment
|
||||||
return false, nil, nil
|
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
|
// clients do no local role resolution at the moment
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,9 +100,14 @@ func (s *Server) LocalTokensEnabled() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ACLDatacenter() string {
|
type serverACLResolverBackend struct {
|
||||||
// For resolution running on servers the only option
|
// TODO: un-embed
|
||||||
// is to contact the configured ACL Datacenter
|
*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 != "" {
|
if s.config.PrimaryDatacenter != "" {
|
||||||
return 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.
|
// 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) {
|
func (s *Server) ResolveIdentityFromToken(token string) (bool, structs.ACLIdentity, error) {
|
||||||
// only allow remote RPC resolution when token replication is off and
|
// only allow remote RPC resolution when token replication is off and
|
||||||
// when not in the ACL datacenter
|
// 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
|
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)
|
index, policy, err := s.fsm.State().ACLPolicyGetByID(nil, policyID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, nil, err
|
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
|
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)
|
index, role, err := s.fsm.State().ACLRoleGetByID(nil, roleID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, nil, err
|
return true, nil, err
|
||||||
|
|
|
@ -715,7 +715,7 @@ func newTestACLResolver(t *testing.T, delegate *ACLResolverTestDelegate, cb func
|
||||||
Roles: 4,
|
Roles: 4,
|
||||||
},
|
},
|
||||||
DisableDuration: aclClientDisabledTTL,
|
DisableDuration: aclClientDisabledTTL,
|
||||||
Delegate: delegate,
|
Backend: delegate,
|
||||||
}
|
}
|
||||||
|
|
||||||
if cb != nil {
|
if cb != nil {
|
||||||
|
|
|
@ -119,7 +119,7 @@ func NewClient(config *Config, deps Deps) (*Client, error) {
|
||||||
|
|
||||||
aclConfig := ACLResolverConfig{
|
aclConfig := ACLResolverConfig{
|
||||||
Config: config.ACLResolverSettings,
|
Config: config.ACLResolverSettings,
|
||||||
Delegate: c,
|
Backend: &clientACLResolverBackend{Client: c},
|
||||||
Logger: c.logger,
|
Logger: c.logger,
|
||||||
DisableDuration: aclClientDisabledTTL,
|
DisableDuration: aclClientDisabledTTL,
|
||||||
CacheConfig: clientACLCacheConfig,
|
CacheConfig: clientACLCacheConfig,
|
||||||
|
|
|
@ -110,7 +110,7 @@ func NewReplicator(config *ReplicatorConfig) (*Replicator, error) {
|
||||||
return nil, fmt.Errorf("Cannot create the Replicator without a config")
|
return nil, fmt.Errorf("Cannot create the Replicator without a config")
|
||||||
}
|
}
|
||||||
if config.Delegate == nil {
|
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 {
|
if config.Logger == nil {
|
||||||
logger := hclog.New(&hclog.LoggerOptions{})
|
logger := hclog.New(&hclog.LoggerOptions{})
|
||||||
|
|
|
@ -450,7 +450,7 @@ func NewServer(config *Config, flat Deps) (*Server, error) {
|
||||||
s.aclConfig = newACLConfig(partitionInfo, logger)
|
s.aclConfig = newACLConfig(partitionInfo, logger)
|
||||||
aclConfig := ACLResolverConfig{
|
aclConfig := ACLResolverConfig{
|
||||||
Config: config.ACLResolverSettings,
|
Config: config.ACLResolverSettings,
|
||||||
Delegate: s,
|
Backend: &serverACLResolverBackend{Server: s},
|
||||||
CacheConfig: serverACLCacheConfig,
|
CacheConfig: serverACLCacheConfig,
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
ACLConfig: s.aclConfig,
|
ACLConfig: s.aclConfig,
|
||||||
|
|
Loading…
Reference in New Issue