diff --git a/agent/acl_test.go b/agent/acl_test.go index c085e49a3..7d8039511 100644 --- a/agent/acl_test.go +++ b/agent/acl_test.go @@ -102,10 +102,10 @@ func (a *TestACLAgent) ResolveTokenToIdentity(secretID string) (structs.ACLIdent return a.resolveIdentFn(secretID) } -func (a *TestACLAgent) ResolveTokenAndDefaultMeta(secretID string, entMeta *structs.EnterpriseMeta, authzContext *acl.AuthorizerContext) (acl.Authorizer, error) { +func (a *TestACLAgent) ResolveTokenAndDefaultMeta(secretID string, entMeta *structs.EnterpriseMeta, authzContext *acl.AuthorizerContext) (consul.ACLResolveResult, error) { identity, authz, err := a.ResolveTokenToIdentityAndAuthorizer(secretID) if err != nil { - return nil, err + return consul.ACLResolveResult{}, err } // Default the EnterpriseMeta based on the Tokens meta or actual defaults @@ -119,7 +119,7 @@ func (a *TestACLAgent) ResolveTokenAndDefaultMeta(secretID string, entMeta *stru // Use the meta to fill in the ACL authorization context entMeta.FillAuthzContext(authzContext) - return authz, err + return consul.ACLResolveResult{Authorizer: authz, ACLIdentity: identity}, err } // All of these are stubs to satisfy the interface diff --git a/agent/agent.go b/agent/agent.go index 41bab89e7..ba587d343 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -174,7 +174,7 @@ type delegate interface { // actions based on the permissions granted to the token. // If either entMeta or authzContext are non-nil they will be populated with the // default partition and namespace from the token. - ResolveTokenAndDefaultMeta(token string, entMeta *structs.EnterpriseMeta, authzContext *acl.AuthorizerContext) (acl.Authorizer, error) + ResolveTokenAndDefaultMeta(token string, entMeta *structs.EnterpriseMeta, authzContext *acl.AuthorizerContext) (consul.ACLResolveResult, error) RPC(method string, args interface{}, reply interface{}) error SnapshotRPC(args *structs.SnapshotRequest, in io.Reader, out io.Writer, replyFn structs.SnapshotReplyFn) error diff --git a/agent/agent_endpoint_test.go b/agent/agent_endpoint_test.go index 8e965db38..70840f950 100644 --- a/agent/agent_endpoint_test.go +++ b/agent/agent_endpoint_test.go @@ -1640,8 +1640,8 @@ type fakeResolveTokenDelegate struct { authorizer acl.Authorizer } -func (f fakeResolveTokenDelegate) ResolveTokenAndDefaultMeta(_ string, _ *structs.EnterpriseMeta, _ *acl.AuthorizerContext) (acl.Authorizer, error) { - return f.authorizer, nil +func (f fakeResolveTokenDelegate) ResolveTokenAndDefaultMeta(_ string, _ *structs.EnterpriseMeta, _ *acl.AuthorizerContext) (consul.ACLResolveResult, error) { + return consul.ACLResolveResult{Authorizer: f.authorizer}, nil } func TestAgent_Reload(t *testing.T) { diff --git a/agent/consul/acl.go b/agent/consul/acl.go index 797bd22e4..d033db1b9 100644 --- a/agent/consul/acl.go +++ b/agent/consul/acl.go @@ -1115,6 +1115,19 @@ func (r *ACLResolver) ResolveTokenToIdentityAndAuthorizer(token string) (structs return identity, acl.NewChainedAuthorizer(chain), nil } +type ACLResolveResult struct { + acl.Authorizer + // TODO: likely we can reduce this interface + structs.ACLIdentity +} + +func (a ACLResolveResult) AccessorID() string { + if a.ACLIdentity == nil { + return "" + } + return a.ACLIdentity.ID() +} + // TODO: rename to AccessorIDFromToken. This method is only used to retrieve the // ACLIdentity.ID, so we don't need to return a full ACLIdentity. We could // return a much smaller type (instad of just a string) to allow for changes @@ -1158,10 +1171,10 @@ func (r *ACLResolver) ACLsEnabled() bool { return true } -func (r *ACLResolver) ResolveTokenAndDefaultMeta(token string, entMeta *structs.EnterpriseMeta, authzContext *acl.AuthorizerContext) (acl.Authorizer, error) { +func (r *ACLResolver) ResolveTokenAndDefaultMeta(token string, entMeta *structs.EnterpriseMeta, authzContext *acl.AuthorizerContext) (ACLResolveResult, error) { identity, authz, err := r.ResolveTokenToIdentityAndAuthorizer(token) if err != nil { - return nil, err + return ACLResolveResult{}, err } if entMeta == nil { @@ -1179,7 +1192,7 @@ func (r *ACLResolver) ResolveTokenAndDefaultMeta(token string, entMeta *structs. // Use the meta to fill in the ACL authorization context entMeta.FillAuthzContext(authzContext) - return authz, err + return ACLResolveResult{Authorizer: authz, ACLIdentity: identity}, err } // aclFilter is used to filter results from our state store based on ACL rules diff --git a/agent/consul/acl_server.go b/agent/consul/acl_server.go index 3802145fa..21b4d9503 100644 --- a/agent/consul/acl_server.go +++ b/agent/consul/acl_server.go @@ -159,13 +159,12 @@ func (s *Server) ResolveRoleFromID(roleID string) (bool, *structs.ACLRole, error return s.InPrimaryDatacenter() || index > 0, role, acl.ErrNotFound } +// TODO: remove func (s *Server) ResolveToken(token string) (acl.Authorizer, error) { _, authz, err := s.ACLResolver.ResolveTokenToIdentityAndAuthorizer(token) return authz, err } -// TODO: Client has an identical implementation, remove duplication - func (s *Server) filterACL(token string, subj interface{}) error { return filterACL(s.ACLResolver, token, subj) } diff --git a/agent/consul/intention_endpoint.go b/agent/consul/intention_endpoint.go index 814d1590a..57d3fc766 100644 --- a/agent/consul/intention_endpoint.go +++ b/agent/consul/intention_endpoint.go @@ -100,6 +100,7 @@ func (s *Intention) Apply(args *structs.IntentionRequest, reply *string) error { } // Get the ACL token for the request for the checks below. + // TODO: use ResolveTokenAndDefaultMeta identity, authz, err := s.srv.ACLResolver.ResolveTokenToIdentityAndAuthorizer(args.Token) if err != nil { return err diff --git a/agent/structs/acl.go b/agent/structs/acl.go index 756cadbb1..42fa55821 100644 --- a/agent/structs/acl.go +++ b/agent/structs/acl.go @@ -89,8 +89,8 @@ var ACLBootstrapNotAllowedErr = errors.New("ACL bootstrap no longer allowed") var ACLBootstrapInvalidResetIndexErr = errors.New("Invalid ACL bootstrap reset index") type ACLIdentity interface { - // ID returns a string that can be used for logging and telemetry. This should not - // contain any secret data used for authentication + // ID returns the accessor ID, a string that can be used for logging and + // telemetry. It is not the secret ID used for authentication. ID() string SecretToken() string PolicyIDs() []string