Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update token language to distinguish Accessor and Secret ID usage #16044

Merged
merged 9 commits into from
Feb 7, 2023
3 changes: 3 additions & 0 deletions .changelog/16044.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:deprecation
cli: The `-id` flag on acl token operations has been changed to `-accessor-id` for clarity in documentation. The `-id` flag will continue to work, but operators should use `-accessor-id` in the future.
```
7 changes: 0 additions & 7 deletions acl/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@ import (
"strings"
)

type SyntaxVersion int

const (
SyntaxCurrent SyntaxVersion = iota
SyntaxLegacy
)

const (
PolicyDeny = "deny"
PolicyRead = "read"
Expand Down
40 changes: 19 additions & 21 deletions agent/acl_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ func (s *HTTPHandlers) ACLTokenCRUD(resp http.ResponseWriter, req *http.Request)
return nil, aclDisabled
}

var fn func(resp http.ResponseWriter, req *http.Request, tokenID string) (interface{}, error)
var fn func(resp http.ResponseWriter, req *http.Request, tokenAccessorID string) (interface{}, error)

switch req.Method {
case "GET":
Expand All @@ -311,16 +311,16 @@ func (s *HTTPHandlers) ACLTokenCRUD(resp http.ResponseWriter, req *http.Request)
return nil, MethodNotAllowedError{req.Method, []string{"GET", "PUT", "DELETE"}}
}

tokenID := strings.TrimPrefix(req.URL.Path, "/v1/acl/token/")
if strings.HasSuffix(tokenID, "/clone") && req.Method == "PUT" {
tokenID = tokenID[:len(tokenID)-6]
tokenAccessorID := strings.TrimPrefix(req.URL.Path, "/v1/acl/token/")
if strings.HasSuffix(tokenAccessorID, "/clone") && req.Method == "PUT" {
tokenAccessorID = tokenAccessorID[:len(tokenAccessorID)-6]
fn = s.ACLTokenClone
}
if tokenID == "" && req.Method != "PUT" {
return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "Missing token ID"}
if tokenAccessorID == "" && req.Method != "PUT" {
return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "Missing token AccessorID"}
}

return fn(resp, req, tokenID)
return fn(resp, req, tokenAccessorID)
}

func (s *HTTPHandlers) ACLTokenSelf(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
Expand All @@ -336,7 +336,7 @@ func (s *HTTPHandlers) ACLTokenSelf(resp http.ResponseWriter, req *http.Request)
return nil, nil
}

// copy the token parameter to the ID
// copy the token secret parameter to the ID
args.TokenID = args.Token

if args.Datacenter == "" {
Expand Down Expand Up @@ -364,10 +364,10 @@ func (s *HTTPHandlers) ACLTokenCreate(resp http.ResponseWriter, req *http.Reques
return s.aclTokenSetInternal(req, "", true)
}

func (s *HTTPHandlers) ACLTokenGet(resp http.ResponseWriter, req *http.Request, tokenID string) (interface{}, error) {
func (s *HTTPHandlers) ACLTokenGet(resp http.ResponseWriter, req *http.Request, tokenAccessorID string) (interface{}, error) {
args := structs.ACLTokenGetRequest{
Datacenter: s.agent.config.Datacenter,
TokenID: tokenID,
TokenID: tokenAccessorID,
TokenIDType: structs.ACLTokenAccessor,
}

Expand Down Expand Up @@ -407,11 +407,11 @@ func (s *HTTPHandlers) ACLTokenGet(resp http.ResponseWriter, req *http.Request,
return out.Token, nil
}

func (s *HTTPHandlers) ACLTokenSet(_ http.ResponseWriter, req *http.Request, tokenID string) (interface{}, error) {
return s.aclTokenSetInternal(req, tokenID, false)
func (s *HTTPHandlers) ACLTokenSet(_ http.ResponseWriter, req *http.Request, tokenAccessorID string) (interface{}, error) {
return s.aclTokenSetInternal(req, tokenAccessorID, false)
}

func (s *HTTPHandlers) aclTokenSetInternal(req *http.Request, tokenID string, create bool) (interface{}, error) {
func (s *HTTPHandlers) aclTokenSetInternal(req *http.Request, tokenAccessorID string, create bool) (interface{}, error) {
args := structs.ACLTokenSetRequest{
Datacenter: s.agent.config.Datacenter,
Create: create,
Expand All @@ -425,10 +425,8 @@ func (s *HTTPHandlers) aclTokenSetInternal(req *http.Request, tokenID string, cr
return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: fmt.Sprintf("Token decoding failed: %v", err)}
}

if !create {
if args.ACLToken.AccessorID != tokenID {
return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "Token Accessor ID in URL and payload do not match"}
}
if !create && args.ACLToken.AccessorID != tokenAccessorID {
return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "Token Accessor ID in URL and payload do not match"}
}

var out structs.ACLToken
Expand All @@ -439,10 +437,10 @@ func (s *HTTPHandlers) aclTokenSetInternal(req *http.Request, tokenID string, cr
return &out, nil
}

func (s *HTTPHandlers) ACLTokenDelete(resp http.ResponseWriter, req *http.Request, tokenID string) (interface{}, error) {
func (s *HTTPHandlers) ACLTokenDelete(resp http.ResponseWriter, req *http.Request, tokenAccessorID string) (interface{}, error) {
args := structs.ACLTokenDeleteRequest{
Datacenter: s.agent.config.Datacenter,
TokenID: tokenID,
TokenID: tokenAccessorID,
}
s.parseToken(req, &args.Token)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
Expand All @@ -456,7 +454,7 @@ func (s *HTTPHandlers) ACLTokenDelete(resp http.ResponseWriter, req *http.Reques
return true, nil
}

func (s *HTTPHandlers) ACLTokenClone(resp http.ResponseWriter, req *http.Request, tokenID string) (interface{}, error) {
func (s *HTTPHandlers) ACLTokenClone(resp http.ResponseWriter, req *http.Request, tokenAccessorID string) (interface{}, error) {
if s.checkACLDisabled() {
return nil, aclDisabled
}
Expand All @@ -475,7 +473,7 @@ func (s *HTTPHandlers) ACLTokenClone(resp http.ResponseWriter, req *http.Request
s.parseToken(req, &args.Token)

// Set this for the ID to clone
args.ACLToken.AccessorID = tokenID
args.ACLToken.AccessorID = tokenAccessorID

var out structs.ACLToken
if err := s.agent.RPC(req.Context(), "ACL.TokenClone", args, &out); err != nil {
Expand Down
8 changes: 4 additions & 4 deletions agent/acl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type TestACLAgent struct {

// NewTestACLAgent does just enough so that all the code within agent/acl.go can work
// Basically it needs a local state for some of the vet* functions, a logger and a delegate.
// The key is that we are the delegate so we can control the ResolveToken responses
// The key is that we are the delegate so we can control the ResolveTokenSecret responses
func NewTestACLAgent(t *testing.T, name string, hcl string, resolveAuthz authzResolver, resolveIdent identResolver) *TestACLAgent {
t.Helper()

Expand Down Expand Up @@ -89,17 +89,17 @@ func NewTestACLAgent(t *testing.T, name string, hcl string, resolveAuthz authzRe
return a
}

func (a *TestACLAgent) ResolveToken(secretID string) (acl.Authorizer, error) {
func (a *TestACLAgent) ResolveTokenSecret(secretID string) (acl.Authorizer, error) {
if a.resolveAuthzFn == nil {
return nil, fmt.Errorf("ResolveToken call is unexpected - no authz resolver callback set")
return nil, fmt.Errorf("ResolveTokenSecret call is unexpected - no authz resolver callback set")
}

_, authz, err := a.resolveAuthzFn(secretID)
return authz, err
}

func (a *TestACLAgent) ResolveTokenAndDefaultMeta(secretID string, entMeta *acl.EnterpriseMeta, authzContext *acl.AuthorizerContext) (resolver.Result, error) {
authz, err := a.ResolveToken(secretID)
authz, err := a.ResolveTokenSecret(secretID)
if err != nil {
return resolver.Result{}, err
}
Expand Down
2 changes: 1 addition & 1 deletion agent/agent_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4418,7 +4418,7 @@ func testAgent_RegisterServiceDeregisterService_Sidecar(t *testing.T, extraHCL s
}
`,
enableACL: true,
policies: ``, // No token rules means no valid token
policies: ``, // No policy means no valid token
wantNS: nil,
wantErr: "Permission denied",
},
Expand Down
30 changes: 15 additions & 15 deletions agent/consul/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ var ACLSummaries = []prometheus.SummaryDefinition{

// These must be kept in sync with the constants in command/agent/acl.go.
const (
// anonymousToken is the token ID we re-write to if there is no token ID
// anonymousToken is the token SecretID we re-write to if there is no token ID
// provided.
anonymousToken = "anonymous"

Expand Down Expand Up @@ -993,35 +993,35 @@ func (r *ACLResolver) resolveLocallyManagedToken(token string) (structs.ACLIdent
return r.resolveLocallyManagedEnterpriseToken(token)
}

// ResolveToken to an acl.Authorizer and structs.ACLIdentity. The acl.Authorizer
// can be used to check permissions granted to the token, and the ACLIdentity
// describes the token and any defaults applied to it.
func (r *ACLResolver) ResolveToken(token string) (resolver.Result, error) {
// ResolveTokenSecret to an acl.Authorizer and structs.ACLIdentity. The acl.Authorizer
// can be used to check permissions granted to the token using its secret, and the
// ACLIdentity describes the token and any defaults applied to it.
func (r *ACLResolver) ResolveTokenSecret(tokenSecretID string) (resolver.Result, error) {
if !r.ACLsEnabled() {
return resolver.Result{Authorizer: acl.ManageAll()}, nil
}

if acl.RootAuthorizer(token) != nil {
if acl.RootAuthorizer(tokenSecretID) != nil {
return resolver.Result{}, acl.ErrRootDenied
}

// handle the anonymous token
if token == "" {
token = anonymousToken
if tokenSecretID == "" {
tokenSecretID = anonymousToken
}

if ident, authz, ok := r.resolveLocallyManagedToken(token); ok {
if ident, authz, ok := r.resolveLocallyManagedToken(tokenSecretID); ok {
return resolver.Result{Authorizer: authz, ACLIdentity: ident}, nil
}

defer metrics.MeasureSince([]string{"acl", "ResolveToken"}, time.Now())

identity, policies, err := r.resolveTokenToIdentityAndPolicies(token)
identity, policies, err := r.resolveTokenToIdentityAndPolicies(tokenSecretID)
if err != nil {
r.handleACLDisabledError(err)
if IsACLRemoteError(err) {
r.logger.Error("Error resolving token", "error", err)
ident := &missingIdentity{reason: "primary-dc-down", token: token}
ident := &missingIdentity{reason: "primary-dc-down", token: tokenSecretID}
return resolver.Result{Authorizer: r.down, ACLIdentity: ident}, nil
}

Expand Down Expand Up @@ -1074,11 +1074,11 @@ func (r *ACLResolver) ACLsEnabled() bool {
}

func (r *ACLResolver) ResolveTokenAndDefaultMeta(
token string,
tokenSecretID string,
entMeta *acl.EnterpriseMeta,
authzContext *acl.AuthorizerContext,
) (resolver.Result, error) {
result, err := r.ResolveToken(token)
result, err := r.ResolveTokenSecret(tokenSecretID)
if err != nil {
return resolver.Result{}, err
}
Expand Down Expand Up @@ -1119,9 +1119,9 @@ func filterACLWithAuthorizer(logger hclog.Logger, authorizer acl.Authorizer, sub
// filterACL uses the ACLResolver to resolve the token in an acl.Authorizer,
// then uses the acl.Authorizer to filter subj. Any entities in subj that are
// not authorized for read access will be removed from subj.
func filterACL(r *ACLResolver, token string, subj interface{}) error {
func filterACL(r *ACLResolver, tokenSecretID string, subj interface{}) error {
// Get the ACL from the token
authorizer, err := r.ResolveToken(token)
authorizer, err := r.ResolveTokenSecret(tokenSecretID)
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions agent/consul/acl_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ func (a *ACL) TokenBatchRead(args *structs.ACLTokenBatchGetRequest, reply *struc
return err
}

authz, err := a.srv.ResolveToken(args.Token)
authz, err := a.srv.ResolveTokenSecret(args.Token)
if err != nil {
return err
}
Expand Down Expand Up @@ -796,7 +796,7 @@ func (a *ACL) PolicyBatchRead(args *structs.ACLPolicyBatchGetRequest, reply *str
return err
}

authz, err := a.srv.ResolveToken(args.Token)
authz, err := a.srv.ResolveTokenSecret(args.Token)
if err != nil {
return err
}
Expand Down Expand Up @@ -1182,7 +1182,7 @@ func (a *ACL) RoleBatchRead(args *structs.ACLRoleBatchGetRequest, reply *structs
return err
}

authz, err := a.srv.ResolveToken(args.Token)
authz, err := a.srv.ResolveTokenSecret(args.Token)
if err != nil {
return err
}
Expand Down Expand Up @@ -2115,7 +2115,7 @@ func (a *ACL) Authorize(args *structs.RemoteACLAuthorizationRequest, reply *[]st
return err
}

authz, err := a.srv.ResolveToken(args.Token)
authz, err := a.srv.ResolveTokenSecret(args.Token)
if err != nil {
return err
}
Expand Down
16 changes: 8 additions & 8 deletions agent/consul/acl_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ func TestACLEndpoint_TokenSet(t *testing.T) {

a := ACL{srv: srv}

var tokenID string
var accessorID string

t.Run("Create it", func(t *testing.T) {
req := structs.ACLTokenSetRequest{
Expand Down Expand Up @@ -563,15 +563,15 @@ func TestACLEndpoint_TokenSet(t *testing.T) {
require.Equal(t, "foo", token.NodeIdentities[0].NodeName)
require.Equal(t, "dc1", token.NodeIdentities[0].Datacenter)

tokenID = token.AccessorID
accessorID = token.AccessorID
})

t.Run("Update it", func(t *testing.T) {
req := structs.ACLTokenSetRequest{
Datacenter: "dc1",
ACLToken: structs.ACLToken{
Description: "new-description",
AccessorID: tokenID,
AccessorID: accessorID,
},
WriteRequest: structs.WriteRequest{Token: TestDefaultInitialManagementToken},
}
Expand Down Expand Up @@ -1085,7 +1085,7 @@ func TestACLEndpoint_TokenSet(t *testing.T) {
require.Equal(t, token.AccessorID, resp.AccessorID)
requireTimeEquals(t, &expectExpTime, resp.ExpirationTime)

tokenID = token.AccessorID
accessorID = token.AccessorID
})

var expTime time.Time
Expand Down Expand Up @@ -1118,7 +1118,7 @@ func TestACLEndpoint_TokenSet(t *testing.T) {
require.Equal(t, token.AccessorID, resp.AccessorID)
requireTimeEquals(t, &expTime, resp.ExpirationTime)

tokenID = token.AccessorID
accessorID = token.AccessorID
})

// do not insert another test at this point: these tests need to be serial
Expand All @@ -1128,7 +1128,7 @@ func TestACLEndpoint_TokenSet(t *testing.T) {
Datacenter: "dc1",
ACLToken: structs.ACLToken{
Description: "new-description",
AccessorID: tokenID,
AccessorID: accessorID,
ExpirationTime: timePointer(expTime.Add(-1 * time.Second)),
},
WriteRequest: structs.WriteRequest{Token: TestDefaultInitialManagementToken},
Expand All @@ -1147,7 +1147,7 @@ func TestACLEndpoint_TokenSet(t *testing.T) {
Datacenter: "dc1",
ACLToken: structs.ACLToken{
Description: "new-description-1",
AccessorID: tokenID,
AccessorID: accessorID,
},
WriteRequest: structs.WriteRequest{Token: TestDefaultInitialManagementToken},
}
Expand All @@ -1174,7 +1174,7 @@ func TestACLEndpoint_TokenSet(t *testing.T) {
Datacenter: "dc1",
ACLToken: structs.ACLToken{
Description: "new-description-2",
AccessorID: tokenID,
AccessorID: accessorID,
ExpirationTime: &expTime,
},
WriteRequest: structs.WriteRequest{Token: TestDefaultInitialManagementToken},
Expand Down
4 changes: 2 additions & 2 deletions agent/consul/acl_replication.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,10 @@ func (s *Server) updateLocalACLType(ctx context.Context, logger hclog.Logger, tr
return false, nil
}

func (s *Server) fetchACLTokensBatch(tokenIDs []string) (*structs.ACLTokenBatchResponse, error) {
func (s *Server) fetchACLTokensBatch(tokenAccessorIDs []string) (*structs.ACLTokenBatchResponse, error) {
req := structs.ACLTokenBatchGetRequest{
Datacenter: s.config.PrimaryDatacenter,
AccessorIDs: tokenIDs,
AccessorIDs: tokenAccessorIDs,
QueryOptions: structs.QueryOptions{
AllowStale: true,
Token: s.tokens.ReplicationToken(),
Expand Down
Loading