mirror of https://github.com/status-im/consul.git
ACL error improvements: incomplete bootstrapping and non-existent token (#16105)
* add bootstrapping detail for acl errors * error detail improvements * update acl bootstrapping test coverage * update namespace errors * update test coverage * add changelog * update message for unbootstrapped error * consolidate error message code and update changelog * logout message change
This commit is contained in:
parent
ad7b71dbd7
commit
6f0b226b0d
|
@ -0,0 +1,11 @@
|
||||||
|
```release-note:breaking-change
|
||||||
|
acl errors: Delete and get requests now return descriptive errors when the specified resource cannot be found. Other ACL request errors provide more information about when a resource is missing. Add error for when the ACL system has not been bootstrapped.
|
||||||
|
1. Delete Token/Policy/AuthMethod/Role/BindingRule endpoints now return 404 when the resource cannot be found.
|
||||||
|
- New error formats: "Requested * does not exist: ACL not found", "* not found in namespace $NAMESPACE: ACL not found"
|
||||||
|
3. Read Token/Policy/Role endpoints now return 404 when the resource cannot be found.
|
||||||
|
- New error format: "Cannot find * to delete"
|
||||||
|
4. Logout now returns a 401 error when the supplied token cannot be found
|
||||||
|
- New error format: "Supplied token does not exist"
|
||||||
|
5. Token Self endpoint now returns 404 when the token cannot be found.
|
||||||
|
- New error format: "Supplied token does not exist"
|
||||||
|
```
|
|
@ -140,3 +140,10 @@ func extractAccessorID(authz interface{}) string {
|
||||||
}
|
}
|
||||||
return accessor
|
return accessor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ACLResourceNotExistError(resourceType string, entMeta EnterpriseMeta) error {
|
||||||
|
if ns := entMeta.NamespaceOrEmpty(); ns != "" {
|
||||||
|
return fmt.Errorf("Requested %s not found in namespace %s: %w", resourceType, ns, ErrNotFound)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Requested %s does not exist: %w", resourceType, ErrNotFound)
|
||||||
|
}
|
||||||
|
|
|
@ -162,12 +162,15 @@ func (s *HTTPHandlers) ACLPolicyRead(resp http.ResponseWriter, req *http.Request
|
||||||
var out structs.ACLPolicyResponse
|
var out structs.ACLPolicyResponse
|
||||||
defer setMeta(resp, &out.QueryMeta)
|
defer setMeta(resp, &out.QueryMeta)
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.PolicyRead", &args, &out); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.PolicyRead", &args, &out); err != nil {
|
||||||
|
// should return permission denied error if missing permissions
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if out.Policy == nil {
|
if out.Policy == nil {
|
||||||
// TODO(rb): should this return a normal 404?
|
// if no error was returned above, the policy does not exist
|
||||||
return nil, acl.ErrNotFound
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
|
msg := acl.ACLResourceNotExistError("policy", args.EnterpriseMeta)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: msg.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out.Policy, nil
|
return out.Policy, nil
|
||||||
|
@ -247,6 +250,10 @@ func (s *HTTPHandlers) ACLPolicyDelete(resp http.ResponseWriter, req *http.Reque
|
||||||
|
|
||||||
var ignored string
|
var ignored string
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.PolicyDelete", args, &ignored); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.PolicyDelete", args, &ignored); err != nil {
|
||||||
|
if strings.Contains(err.Error(), acl.ErrNotFound.Error()) {
|
||||||
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: "Cannot find policy to delete"}
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,11 +353,14 @@ func (s *HTTPHandlers) ACLTokenSelf(resp http.ResponseWriter, req *http.Request)
|
||||||
var out structs.ACLTokenResponse
|
var out structs.ACLTokenResponse
|
||||||
defer setMeta(resp, &out.QueryMeta)
|
defer setMeta(resp, &out.QueryMeta)
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.TokenRead", &args, &out); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.TokenRead", &args, &out); err != nil {
|
||||||
|
// should return permission denied error if missing permissions
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if out.Token == nil {
|
if out.Token == nil {
|
||||||
return nil, acl.ErrNotFound
|
// if no error was returned above, the token does not exist
|
||||||
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: "Supplied token does not exist"}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out.Token, nil
|
return out.Token, nil
|
||||||
|
@ -393,7 +403,10 @@ func (s *HTTPHandlers) ACLTokenGet(resp http.ResponseWriter, req *http.Request,
|
||||||
}
|
}
|
||||||
|
|
||||||
if out.Token == nil {
|
if out.Token == nil {
|
||||||
return nil, acl.ErrNotFound
|
// if no error was returned above, the token does not exist
|
||||||
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
|
msg := acl.ACLResourceNotExistError("token", args.EnterpriseMeta)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: msg.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.Expanded {
|
if args.Expanded {
|
||||||
|
@ -449,6 +462,10 @@ func (s *HTTPHandlers) ACLTokenDelete(resp http.ResponseWriter, req *http.Reques
|
||||||
|
|
||||||
var ignored string
|
var ignored string
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.TokenDelete", args, &ignored); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.TokenDelete", args, &ignored); err != nil {
|
||||||
|
if strings.Contains(err.Error(), acl.ErrNotFound.Error()) {
|
||||||
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: "Cannot find token to delete"}
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
|
@ -582,12 +599,15 @@ func (s *HTTPHandlers) ACLRoleRead(resp http.ResponseWriter, req *http.Request,
|
||||||
var out structs.ACLRoleResponse
|
var out structs.ACLRoleResponse
|
||||||
defer setMeta(resp, &out.QueryMeta)
|
defer setMeta(resp, &out.QueryMeta)
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.RoleRead", &args, &out); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.RoleRead", &args, &out); err != nil {
|
||||||
|
// should return permission denied error if missing permissions
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if out.Role == nil {
|
if out.Role == nil {
|
||||||
|
// if not permission denied error is returned above, role does not exist
|
||||||
resp.WriteHeader(http.StatusNotFound)
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
return nil, nil
|
msg := acl.ACLResourceNotExistError("role", args.EnterpriseMeta)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: msg.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out.Role, nil
|
return out.Role, nil
|
||||||
|
@ -640,6 +660,10 @@ func (s *HTTPHandlers) ACLRoleDelete(resp http.ResponseWriter, req *http.Request
|
||||||
|
|
||||||
var ignored string
|
var ignored string
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.RoleDelete", args, &ignored); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.RoleDelete", args, &ignored); err != nil {
|
||||||
|
if strings.Contains(err.Error(), acl.ErrNotFound.Error()) {
|
||||||
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: "Cannot find role to delete"}
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -729,12 +753,15 @@ func (s *HTTPHandlers) ACLBindingRuleRead(resp http.ResponseWriter, req *http.Re
|
||||||
var out structs.ACLBindingRuleResponse
|
var out structs.ACLBindingRuleResponse
|
||||||
defer setMeta(resp, &out.QueryMeta)
|
defer setMeta(resp, &out.QueryMeta)
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.BindingRuleRead", &args, &out); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.BindingRuleRead", &args, &out); err != nil {
|
||||||
|
// should return permission denied error if missing permissions
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if out.BindingRule == nil {
|
if out.BindingRule == nil {
|
||||||
|
// if no error was returned above, the binding rule does not exist
|
||||||
resp.WriteHeader(http.StatusNotFound)
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
return nil, nil
|
msg := acl.ACLResourceNotExistError("binding rule", args.EnterpriseMeta)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: msg.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out.BindingRule, nil
|
return out.BindingRule, nil
|
||||||
|
@ -786,6 +813,10 @@ func (s *HTTPHandlers) ACLBindingRuleDelete(resp http.ResponseWriter, req *http.
|
||||||
|
|
||||||
var ignored bool
|
var ignored bool
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.BindingRuleDelete", args, &ignored); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.BindingRuleDelete", args, &ignored); err != nil {
|
||||||
|
if strings.Contains(err.Error(), acl.ErrNotFound.Error()) {
|
||||||
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: "Cannot find binding rule to delete"}
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -871,12 +902,15 @@ func (s *HTTPHandlers) ACLAuthMethodRead(resp http.ResponseWriter, req *http.Req
|
||||||
var out structs.ACLAuthMethodResponse
|
var out structs.ACLAuthMethodResponse
|
||||||
defer setMeta(resp, &out.QueryMeta)
|
defer setMeta(resp, &out.QueryMeta)
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.AuthMethodRead", &args, &out); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.AuthMethodRead", &args, &out); err != nil {
|
||||||
|
// should return permission denied if missing permissions
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if out.AuthMethod == nil {
|
if out.AuthMethod == nil {
|
||||||
|
// if no error was returned above, the auth method does not exist
|
||||||
resp.WriteHeader(http.StatusNotFound)
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
return nil, nil
|
msg := acl.ACLResourceNotExistError("auth method", args.EnterpriseMeta)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: msg.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
fixupAuthMethodConfig(out.AuthMethod)
|
fixupAuthMethodConfig(out.AuthMethod)
|
||||||
|
@ -932,6 +966,10 @@ func (s *HTTPHandlers) ACLAuthMethodDelete(resp http.ResponseWriter, req *http.R
|
||||||
|
|
||||||
var ignored bool
|
var ignored bool
|
||||||
if err := s.agent.RPC(req.Context(), "ACL.AuthMethodDelete", args, &ignored); err != nil {
|
if err := s.agent.RPC(req.Context(), "ACL.AuthMethodDelete", args, &ignored); err != nil {
|
||||||
|
if strings.Contains(err.Error(), acl.ErrNotFound.Error()) {
|
||||||
|
resp.WriteHeader(http.StatusNotFound)
|
||||||
|
return nil, HTTPError{StatusCode: http.StatusNotFound, Reason: "Cannot find auth method to delete"}
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,7 +1014,7 @@ func (s *HTTPHandlers) ACLLogout(resp http.ResponseWriter, req *http.Request) (i
|
||||||
s.parseToken(req, &args.Token)
|
s.parseToken(req, &args.Token)
|
||||||
|
|
||||||
if args.Token == "" {
|
if args.Token == "" {
|
||||||
return nil, acl.ErrNotFound
|
return nil, HTTPError{StatusCode: http.StatusUnauthorized, Reason: "Supplied token does not exist"}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ignored bool
|
var ignored bool
|
||||||
|
|
|
@ -1845,7 +1845,7 @@ func TestACL_LoginProcedure_HTTP(t *testing.T) {
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
_, err := a.srv.ACLTokenCRUD(resp, req)
|
_, err := a.srv.ACLTokenCRUD(resp, req)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.True(t, acl.IsErrNotFound(err), err.Error())
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2010,7 +2010,7 @@ func TestACLEndpoint_LoginLogout_jwt(t *testing.T) {
|
||||||
// make the request
|
// make the request
|
||||||
_, err = a.srv.ACLTokenCRUD(resp, req)
|
_, err = a.srv.ACLTokenCRUD(resp, req)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Equal(t, acl.ErrNotFound, err)
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,19 +314,22 @@ func (a *ACL) TokenRead(args *structs.ACLTokenGetRequest, reply *structs.ACLToke
|
||||||
// no extra validation is needed here. If you have the secret ID you can read it.
|
// no extra validation is needed here. If you have the secret ID you can read it.
|
||||||
}
|
}
|
||||||
|
|
||||||
if token != nil && token.IsExpired(time.Now()) {
|
|
||||||
token = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if token != nil && token.IsExpired(time.Now()) {
|
||||||
|
return fmt.Errorf("token has expired: %w", acl.ErrNotFound)
|
||||||
|
} else if token == nil {
|
||||||
|
// token does not exist
|
||||||
|
if ns := args.EnterpriseMeta.NamespaceOrEmpty(); ns != "" {
|
||||||
|
return fmt.Errorf("token not found in namespace %s: %w", ns, acl.ErrNotFound)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("token does not exist: %w", acl.ErrNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
reply.Index, reply.Token = index, token
|
reply.Index, reply.Token = index, token
|
||||||
reply.SourceDatacenter = args.Datacenter
|
reply.SourceDatacenter = args.Datacenter
|
||||||
if token == nil {
|
|
||||||
return errNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.Expanded {
|
if args.Expanded {
|
||||||
info, err := a.lookupExpandedTokenInfo(ws, state, token)
|
info, err := a.lookupExpandedTokenInfo(ws, state, token)
|
||||||
|
@ -458,8 +461,13 @@ func (a *ACL) TokenClone(args *structs.ACLTokenSetRequest, reply *structs.ACLTok
|
||||||
_, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.ACLToken.AccessorID, &args.ACLToken.EnterpriseMeta)
|
_, token, err := a.srv.fsm.State().ACLTokenGetByAccessor(nil, args.ACLToken.AccessorID, &args.ACLToken.EnterpriseMeta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if token == nil || token.IsExpired(time.Now()) {
|
} else if token == nil {
|
||||||
return acl.ErrNotFound
|
if ns := args.ACLToken.EnterpriseMeta.NamespaceOrEmpty(); ns != "" {
|
||||||
|
return fmt.Errorf("token not found in namespace %s: %w", ns, acl.ErrNotFound)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("token does not exist: %w", acl.ErrNotFound)
|
||||||
|
} else if token.IsExpired(time.Now()) {
|
||||||
|
return fmt.Errorf("token is expired: %w", acl.ErrNotFound)
|
||||||
} else if !a.srv.InPrimaryDatacenter() && !token.Local {
|
} else if !a.srv.InPrimaryDatacenter() && !token.Local {
|
||||||
// global token writes must be forwarded to the primary DC
|
// global token writes must be forwarded to the primary DC
|
||||||
args.Datacenter = a.srv.config.PrimaryDatacenter
|
args.Datacenter = a.srv.config.PrimaryDatacenter
|
||||||
|
@ -597,8 +605,11 @@ func (a *ACL) TokenDelete(args *structs.ACLTokenDeleteRequest, reply *string) er
|
||||||
args.Datacenter = a.srv.config.PrimaryDatacenter
|
args.Datacenter = a.srv.config.PrimaryDatacenter
|
||||||
return a.srv.forwardDC("ACL.TokenDelete", a.srv.config.PrimaryDatacenter, args, reply)
|
return a.srv.forwardDC("ACL.TokenDelete", a.srv.config.PrimaryDatacenter, args, reply)
|
||||||
} else {
|
} else {
|
||||||
// in Primary Datacenter but the token does not exist - return early as there is nothing to do.
|
// in Primary Datacenter but the token does not exist - return early indicating it wasn't found.
|
||||||
return nil
|
if ns := args.EnterpriseMeta.NamespaceOrEmpty(); ns != "" {
|
||||||
|
return fmt.Errorf("token not found in namespace %s: %w", ns, acl.ErrNotFound)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("token does not exist: %w", acl.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
req := &structs.ACLTokenBatchDeleteRequest{
|
req := &structs.ACLTokenBatchDeleteRequest{
|
||||||
|
@ -979,7 +990,10 @@ func (a *ACL) PolicyDelete(args *structs.ACLPolicyDeleteRequest, reply *string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if policy == nil {
|
if policy == nil {
|
||||||
return nil
|
if ns := args.EnterpriseMeta.NamespaceOrEmpty(); ns != "" {
|
||||||
|
return fmt.Errorf("policy not found in namespace %s: %w", ns, acl.ErrNotFound)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("policy does not exist: %w", acl.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
if policy.ID == structs.ACLPolicyGlobalManagementID {
|
if policy.ID == structs.ACLPolicyGlobalManagementID {
|
||||||
|
@ -1393,7 +1407,10 @@ func (a *ACL) RoleDelete(args *structs.ACLRoleDeleteRequest, reply *string) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
if role == nil {
|
if role == nil {
|
||||||
return nil
|
if ns := args.EnterpriseMeta.NamespaceOrEmpty(); ns != "" {
|
||||||
|
return fmt.Errorf("role not found in namespace %s: %w", ns, acl.ErrNotFound)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("role does not exist: %w", acl.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
req := structs.ACLRoleBatchDeleteRequest{
|
req := structs.ACLRoleBatchDeleteRequest{
|
||||||
|
@ -1706,11 +1723,15 @@ func (a *ACL) BindingRuleDelete(args *structs.ACLBindingRuleDeleteRequest, reply
|
||||||
}
|
}
|
||||||
|
|
||||||
_, rule, err := a.srv.fsm.State().ACLBindingRuleGetByID(nil, args.BindingRuleID, &args.EnterpriseMeta)
|
_, rule, err := a.srv.fsm.State().ACLBindingRuleGetByID(nil, args.BindingRuleID, &args.EnterpriseMeta)
|
||||||
switch {
|
if err != nil {
|
||||||
case err != nil:
|
|
||||||
return err
|
return err
|
||||||
case rule == nil:
|
}
|
||||||
return nil
|
|
||||||
|
if rule == nil {
|
||||||
|
if ns := args.EnterpriseMeta.NamespaceOrEmpty(); ns != "" {
|
||||||
|
return fmt.Errorf("binding rule not found in namespace %s: %w", ns, acl.ErrNotFound)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("binding rule does not exist: %w", acl.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
req := structs.ACLBindingRuleBatchDeleteRequest{
|
req := structs.ACLBindingRuleBatchDeleteRequest{
|
||||||
|
@ -1955,7 +1976,10 @@ func (a *ACL) AuthMethodDelete(args *structs.ACLAuthMethodDeleteRequest, reply *
|
||||||
}
|
}
|
||||||
|
|
||||||
if method == nil {
|
if method == nil {
|
||||||
return nil
|
if ns := args.EnterpriseMeta.NamespaceOrEmpty(); ns != "" {
|
||||||
|
return fmt.Errorf("auth method not found in namespace %s: %w", ns, acl.ErrNotFound)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("auth method does not exist: %w", acl.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.srv.enterpriseAuthMethodTypeValidation(method.Type); err != nil {
|
if err := a.srv.enterpriseAuthMethodTypeValidation(method.Type); err != nil {
|
||||||
|
@ -2082,7 +2106,7 @@ func (a *ACL) Logout(args *structs.ACLLogoutRequest, reply *bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.Token == "" {
|
if args.Token == "" {
|
||||||
return acl.ErrNotFound
|
return fmt.Errorf("no valid token ID provided: %w", acl.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
if done, err := a.srv.ForwardRPC("ACL.Logout", args, reply); done {
|
if done, err := a.srv.ForwardRPC("ACL.Logout", args, reply); done {
|
||||||
|
|
|
@ -214,13 +214,16 @@ func TestACLEndpoint_TokenRead(t *testing.T) {
|
||||||
resp := structs.ACLTokenResponse{}
|
resp := structs.ACLTokenResponse{}
|
||||||
|
|
||||||
retry.Run(t, func(r *retry.R) {
|
retry.Run(t, func(r *retry.R) {
|
||||||
require.NoError(r, aclEp.TokenRead(&req, &resp))
|
time.Sleep(200 * time.Millisecond)
|
||||||
|
err := aclEp.TokenRead(&req, &resp)
|
||||||
|
require.Error(r, err)
|
||||||
|
require.ErrorContains(t, err, "ACL not found")
|
||||||
require.Nil(r, resp.Token)
|
require.Nil(r, resp.Token)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("nil when token does not exist", func(t *testing.T) {
|
t.Run("error when token does not exist", func(t *testing.T) {
|
||||||
fakeID, err := uuid.GenerateUUID()
|
fakeID, err := uuid.GenerateUUID()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -235,7 +238,8 @@ func TestACLEndpoint_TokenRead(t *testing.T) {
|
||||||
|
|
||||||
err = aclEp.TokenRead(&req, &resp)
|
err = aclEp.TokenRead(&req, &resp)
|
||||||
require.Nil(t, resp.Token)
|
require.Nil(t, resp.Token)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("validates ID format", func(t *testing.T) {
|
t.Run("validates ID format", func(t *testing.T) {
|
||||||
|
@ -507,7 +511,7 @@ func TestACLEndpoint_TokenClone(t *testing.T) {
|
||||||
|
|
||||||
err = endpoint.TokenClone(&req, &t2)
|
err = endpoint.TokenClone(&req, &t2)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Equal(t, acl.ErrNotFound, err)
|
require.ErrorContains(t, err, "token is expired")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1647,7 +1651,8 @@ func TestACLEndpoint_TokenDelete(t *testing.T) {
|
||||||
|
|
||||||
// Make sure the token is gone
|
// Make sure the token is gone
|
||||||
tokenResp, err = retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", testToken.AccessorID)
|
tokenResp, err = retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", testToken.AccessorID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
require.Nil(t, tokenResp.Token)
|
require.Nil(t, tokenResp.Token)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1662,7 +1667,8 @@ func TestACLEndpoint_TokenDelete(t *testing.T) {
|
||||||
|
|
||||||
// Make sure the token is not listable (filtered due to expiry)
|
// Make sure the token is not listable (filtered due to expiry)
|
||||||
tokenResp, err := retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", expiringToken.AccessorID)
|
tokenResp, err := retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", expiringToken.AccessorID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, "token has expired")
|
||||||
require.Nil(t, tokenResp.Token)
|
require.Nil(t, tokenResp.Token)
|
||||||
|
|
||||||
// Now try to delete it (this should work).
|
// Now try to delete it (this should work).
|
||||||
|
@ -1679,7 +1685,8 @@ func TestACLEndpoint_TokenDelete(t *testing.T) {
|
||||||
|
|
||||||
// Make sure the token is still gone (this time it's actually gone)
|
// Make sure the token is still gone (this time it's actually gone)
|
||||||
tokenResp, err = retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", expiringToken.AccessorID)
|
tokenResp, err = retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", expiringToken.AccessorID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
require.Nil(t, tokenResp.Token)
|
require.Nil(t, tokenResp.Token)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1697,8 +1704,9 @@ func TestACLEndpoint_TokenDelete(t *testing.T) {
|
||||||
|
|
||||||
// Make sure the token is gone
|
// Make sure the token is gone
|
||||||
tokenResp, err := retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", existingToken.AccessorID)
|
tokenResp, err := retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", existingToken.AccessorID)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
require.Nil(t, tokenResp.Token)
|
require.Nil(t, tokenResp.Token)
|
||||||
require.NoError(t, err)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("can't delete itself", func(t *testing.T) {
|
t.Run("can't delete itself", func(t *testing.T) {
|
||||||
|
@ -1739,12 +1747,14 @@ func TestACLEndpoint_TokenDelete(t *testing.T) {
|
||||||
var resp string
|
var resp string
|
||||||
|
|
||||||
err = acl1.TokenDelete(&req, &resp)
|
err = acl1.TokenDelete(&req, &resp)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorIs(t, err, acl.ErrNotFound)
|
||||||
|
|
||||||
// token should be nil
|
// token should be nil
|
||||||
tokenResp, err := retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", existingToken.AccessorID)
|
tokenResp, err := retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", existingToken.AccessorID)
|
||||||
require.Nil(t, tokenResp.Token)
|
require.Nil(t, tokenResp.Token)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("don't segfault when attempting to delete non existent token in secondary dc", func(t *testing.T) {
|
t.Run("don't segfault when attempting to delete non existent token in secondary dc", func(t *testing.T) {
|
||||||
|
@ -1760,12 +1770,14 @@ func TestACLEndpoint_TokenDelete(t *testing.T) {
|
||||||
var resp string
|
var resp string
|
||||||
|
|
||||||
err = acl2.TokenDelete(&req, &resp)
|
err = acl2.TokenDelete(&req, &resp)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
|
|
||||||
// token should be nil
|
// token should be nil
|
||||||
tokenResp, err := retrieveTestToken(codec2, TestDefaultInitialManagementToken, "dc1", existingToken.AccessorID)
|
tokenResp, err := retrieveTestToken(codec2, TestDefaultInitialManagementToken, "dc1", existingToken.AccessorID)
|
||||||
require.Nil(t, tokenResp.Token)
|
require.Nil(t, tokenResp.Token)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3307,7 +3319,8 @@ func TestACLEndpoint_AuthMethodDelete(t *testing.T) {
|
||||||
|
|
||||||
var ignored bool
|
var ignored bool
|
||||||
err = aclEp.AuthMethodDelete(&req, &ignored)
|
err = aclEp.AuthMethodDelete(&req, &ignored)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3413,7 +3426,8 @@ func TestACLEndpoint_AuthMethodDelete_RuleAndTokenCascade(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, id := range []string{i1_t1.AccessorID, i1_t2.AccessorID} {
|
for _, id := range []string{i1_t1.AccessorID, i1_t2.AccessorID} {
|
||||||
tokResp, err := retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", id)
|
tokResp, err := retrieveTestToken(codec, TestDefaultInitialManagementToken, "dc1", id)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
require.Nil(t, tokResp.Token)
|
require.Nil(t, tokResp.Token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3774,7 +3788,8 @@ func TestACLEndpoint_BindingRuleDelete(t *testing.T) {
|
||||||
|
|
||||||
var ignored bool
|
var ignored bool
|
||||||
err = aclEp.BindingRuleDelete(&req, &ignored)
|
err = aclEp.BindingRuleDelete(&req, &ignored)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4197,7 +4212,8 @@ func TestACLEndpoint_SecureIntroEndpoints_OnlyCreateLocalData(t *testing.T) {
|
||||||
require.Equal(t, "web2", resp2.Token.ServiceIdentities[0].ServiceName)
|
require.Equal(t, "web2", resp2.Token.ServiceIdentities[0].ServiceName)
|
||||||
// absent in dc1
|
// absent in dc1
|
||||||
resp2, err = retrieveTestToken(codec1, TestDefaultInitialManagementToken, "dc1", remoteToken.AccessorID)
|
resp2, err = retrieveTestToken(codec1, TestDefaultInitialManagementToken, "dc1", remoteToken.AccessorID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
require.Nil(t, resp2.Token)
|
require.Nil(t, resp2.Token)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -4256,7 +4272,8 @@ func TestACLEndpoint_SecureIntroEndpoints_OnlyCreateLocalData(t *testing.T) {
|
||||||
require.Equal(t, "web1", resp2.Token.ServiceIdentities[0].ServiceName)
|
require.Equal(t, "web1", resp2.Token.ServiceIdentities[0].ServiceName)
|
||||||
// absent in dc2
|
// absent in dc2
|
||||||
resp2, err = retrieveTestToken(codec2, TestDefaultInitialManagementToken, "dc2", primaryToken.AccessorID)
|
resp2, err = retrieveTestToken(codec2, TestDefaultInitialManagementToken, "dc2", primaryToken.AccessorID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
require.Nil(t, resp2.Token)
|
require.Nil(t, resp2.Token)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -4274,11 +4291,13 @@ func TestACLEndpoint_SecureIntroEndpoints_OnlyCreateLocalData(t *testing.T) {
|
||||||
|
|
||||||
// absent in dc2
|
// absent in dc2
|
||||||
resp2, err := retrieveTestToken(codec2, TestDefaultInitialManagementToken, "dc2", remoteToken.AccessorID)
|
resp2, err := retrieveTestToken(codec2, TestDefaultInitialManagementToken, "dc2", remoteToken.AccessorID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
require.Nil(t, resp2.Token)
|
require.Nil(t, resp2.Token)
|
||||||
// absent in dc1
|
// absent in dc1
|
||||||
resp2, err = retrieveTestToken(codec1, TestDefaultInitialManagementToken, "dc1", remoteToken.AccessorID)
|
resp2, err = retrieveTestToken(codec1, TestDefaultInitialManagementToken, "dc1", remoteToken.AccessorID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
require.Nil(t, resp2.Token)
|
require.Nil(t, resp2.Token)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -4299,7 +4318,8 @@ func TestACLEndpoint_SecureIntroEndpoints_OnlyCreateLocalData(t *testing.T) {
|
||||||
require.Equal(t, "web1", resp2.Token.ServiceIdentities[0].ServiceName)
|
require.Equal(t, "web1", resp2.Token.ServiceIdentities[0].ServiceName)
|
||||||
// absent in dc2
|
// absent in dc2
|
||||||
resp2, err = retrieveTestToken(codec2, TestDefaultInitialManagementToken, "dc2", primaryToken.AccessorID)
|
resp2, err = retrieveTestToken(codec2, TestDefaultInitialManagementToken, "dc2", primaryToken.AccessorID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, acl.ErrNotFound.Error())
|
||||||
require.Nil(t, resp2.Token)
|
require.Nil(t, resp2.Token)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -5458,11 +5478,7 @@ func retrieveTestToken(codec rpc.ClientCodec, initialManagementToken string, dat
|
||||||
|
|
||||||
err := msgpackrpc.CallWithCodec(codec, "ACL.TokenRead", &arg, &out)
|
err := msgpackrpc.CallWithCodec(codec, "ACL.TokenRead", &arg, &out)
|
||||||
|
|
||||||
if err != nil {
|
return &out, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &out, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteTestToken(codec rpc.ClientCodec, initialManagementToken string, datacenter string, tokenAccessor string) error {
|
func deleteTestToken(codec rpc.ClientCodec, initialManagementToken string, datacenter string, tokenAccessor string) error {
|
||||||
|
|
|
@ -754,8 +754,8 @@ func TestACLReplication_TokensRedacted(t *testing.T) {
|
||||||
QueryOptions: structs.QueryOptions{Token: aclfilter.RedactedToken},
|
QueryOptions: structs.QueryOptions{Token: aclfilter.RedactedToken},
|
||||||
}
|
}
|
||||||
err := s2.RPC(context.Background(), "ACL.TokenRead", &req, &tokenResp)
|
err := s2.RPC(context.Background(), "ACL.TokenRead", &req, &tokenResp)
|
||||||
// its not an error for the secret to not be found.
|
require.Error(r, err)
|
||||||
require.NoError(r, err)
|
require.ErrorContains(r, err, "token does not exist")
|
||||||
require.Nil(r, tokenResp.Token)
|
require.Nil(r, tokenResp.Token)
|
||||||
|
|
||||||
var status structs.ACLReplicationStatus
|
var status structs.ACLReplicationStatus
|
||||||
|
|
|
@ -142,7 +142,6 @@ func (s *Server) ResolveIdentityFromToken(token string) (bool, structs.ACLIdenti
|
||||||
if !s.InPrimaryDatacenter() && !s.config.ACLTokenReplication {
|
if !s.InPrimaryDatacenter() && !s.config.ACLTokenReplication {
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
index, aclToken, err := s.fsm.State().ACLTokenGetBySecret(nil, token, nil)
|
index, aclToken, err := s.fsm.State().ACLTokenGetBySecret(nil, token, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, nil, err
|
return true, nil, err
|
||||||
|
@ -150,7 +149,12 @@ func (s *Server) ResolveIdentityFromToken(token string) (bool, structs.ACLIdenti
|
||||||
return true, aclToken, nil
|
return true, aclToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.InPrimaryDatacenter() || index > 0, nil, acl.ErrNotFound
|
defaultErr := acl.ErrNotFound
|
||||||
|
canBootstrap, _, _ := s.fsm.State().CanBootstrapACLToken()
|
||||||
|
if canBootstrap {
|
||||||
|
defaultErr = fmt.Errorf("ACL system must be bootstrapped before making any requests that require authorization: %w", defaultErr)
|
||||||
|
}
|
||||||
|
return s.InPrimaryDatacenter() || index > 0, nil, defaultErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *serverACLResolverBackend) ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error) {
|
func (s *serverACLResolverBackend) ResolvePolicyFromID(policyID string) (bool, *structs.ACLPolicy, error) {
|
||||||
|
|
|
@ -289,6 +289,28 @@ func prepTokenPoliciesInPartition(t *testing.T, acl *ACL, partition string) (pol
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPI_ACLBootstrap(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
c, s := makeNonBootstrappedACLClient(t)
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
acl := c.ACL()
|
||||||
|
s.WaitForLeader(t)
|
||||||
|
|
||||||
|
// not bootstrapped
|
||||||
|
_, _, err := acl.TokenList(nil)
|
||||||
|
require.EqualError(t, err, "Unexpected response code: 403 (ACL system must be bootstrapped before making any requests that require authorization: ACL not found)")
|
||||||
|
// bootstrap
|
||||||
|
mgmtTok, _, err := acl.Bootstrap()
|
||||||
|
require.NoError(t, err)
|
||||||
|
// bootstrapped
|
||||||
|
acl.c.config.Token = mgmtTok.SecretID
|
||||||
|
toks, _, err := acl.TokenList(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
// management and anonymous should be only tokens
|
||||||
|
require.Len(t, toks, 2)
|
||||||
|
}
|
||||||
|
|
||||||
func TestAPI_ACLToken_CreateReadDelete(t *testing.T) {
|
func TestAPI_ACLToken_CreateReadDelete(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
c, s := makeACLClient(t)
|
c, s := makeACLClient(t)
|
||||||
|
|
|
@ -50,6 +50,19 @@ func makeACLClient(t *testing.T) (*Client, *testutil.TestServer) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeNonBootstrappedACLClient(t *testing.T) (*Client, *testutil.TestServer) {
|
||||||
|
return makeClientWithConfig(t,
|
||||||
|
func(clientConfig *Config) {
|
||||||
|
clientConfig.Token = "root"
|
||||||
|
},
|
||||||
|
func(serverConfig *testutil.TestServerConfig) {
|
||||||
|
serverConfig.PrimaryDatacenter = "dc1"
|
||||||
|
serverConfig.ACL.Enabled = true
|
||||||
|
serverConfig.ACL.DefaultPolicy = "deny"
|
||||||
|
serverConfig.Bootstrap = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func makeClientWithCA(t *testing.T) (*Client, *testutil.TestServer) {
|
func makeClientWithCA(t *testing.T) (*Client, *testutil.TestServer) {
|
||||||
return makeClientWithConfig(t,
|
return makeClientWithConfig(t,
|
||||||
func(c *Config) {
|
func(c *Config) {
|
||||||
|
|
|
@ -163,7 +163,7 @@ func GetBindingRuleIDFromPartial(client *api.Client, partialID string) (string,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ruleID == "" {
|
if ruleID == "" {
|
||||||
return "", fmt.Errorf("No such rule ID with prefix: %s", partialID)
|
return "", fmt.Errorf("no such rule ID with prefix: %s: %w", partialID, acl.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ruleID, nil
|
return ruleID, nil
|
||||||
|
|
|
@ -5,13 +5,14 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent"
|
|
||||||
"github.com/hashicorp/consul/api"
|
|
||||||
"github.com/hashicorp/consul/testrpc"
|
|
||||||
"github.com/hashicorp/go-uuid"
|
"github.com/hashicorp/go-uuid"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent"
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
"github.com/hashicorp/consul/testrpc"
|
||||||
|
|
||||||
// activate testing auth method
|
// activate testing auth method
|
||||||
_ "github.com/hashicorp/consul/agent/consul/authmethod/testauth"
|
_ "github.com/hashicorp/consul/agent/consul/authmethod/testauth"
|
||||||
)
|
)
|
||||||
|
@ -70,12 +71,11 @@ func TestAuthMethodDeleteCommand(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
code := cmd.Run(args)
|
code := cmd.Run(args)
|
||||||
require.Equal(t, code, 0)
|
require.Equal(t, 1, code)
|
||||||
require.Empty(t, ui.ErrorWriter.String())
|
require.Contains(t, ui.ErrorWriter.String(), "404 (Cannot find auth method to delete)")
|
||||||
|
|
||||||
output := ui.OutputWriter.String()
|
output := ui.OutputWriter.String()
|
||||||
require.Contains(t, output, fmt.Sprintf("deleted successfully"))
|
require.Empty(t, output)
|
||||||
require.Contains(t, output, "notfound")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
createAuthMethod := func(t *testing.T) string {
|
createAuthMethod := func(t *testing.T) string {
|
||||||
|
|
|
@ -5,11 +5,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent"
|
"github.com/hashicorp/consul/agent"
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/hashicorp/consul/testrpc"
|
"github.com/hashicorp/consul/testrpc"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
// activate testing auth method
|
// activate testing auth method
|
||||||
_ "github.com/hashicorp/consul/agent/consul/authmethod/testauth"
|
_ "github.com/hashicorp/consul/agent/consul/authmethod/testauth"
|
||||||
|
@ -180,4 +181,22 @@ func TestBindingRuleDeleteCommand(t *testing.T) {
|
||||||
require.Equal(t, code, 1)
|
require.Equal(t, code, 1)
|
||||||
require.Contains(t, ui.ErrorWriter.String(), "Error determining binding rule ID")
|
require.Contains(t, ui.ErrorWriter.String(), "Error determining binding rule ID")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("delete notfound", func(t *testing.T) {
|
||||||
|
ui := cli.NewMockUi()
|
||||||
|
cmd := New(ui)
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-http-addr=" + a.HTTPAddr(),
|
||||||
|
"-token=root",
|
||||||
|
"-id=notfound",
|
||||||
|
}
|
||||||
|
|
||||||
|
code := cmd.Run(args)
|
||||||
|
require.Equal(t, 1, code)
|
||||||
|
require.Contains(t, ui.ErrorWriter.String(), "Error determining binding rule ID: no such rule ID with prefix: notfound")
|
||||||
|
|
||||||
|
output := ui.OutputWriter.String()
|
||||||
|
require.Empty(t, output)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent"
|
"github.com/hashicorp/consul/agent"
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/hashicorp/consul/testrpc"
|
"github.com/hashicorp/consul/testrpc"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPolicyDeleteCommand_noTabs(t *testing.T) {
|
func TestPolicyDeleteCommand_noTabs(t *testing.T) {
|
||||||
|
@ -69,5 +70,5 @@ func TestPolicyDeleteCommand(t *testing.T) {
|
||||||
policy.ID,
|
policy.ID,
|
||||||
&api.QueryOptions{Token: "root"},
|
&api.QueryOptions{Token: "root"},
|
||||||
)
|
)
|
||||||
assert.EqualError(t, err, "Unexpected response code: 403 (ACL not found)")
|
assert.EqualError(t, err, "Unexpected response code: 404 (Requested policy does not exist: ACL not found)")
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,5 +70,6 @@ func TestTokenDeleteCommand(t *testing.T) {
|
||||||
token.AccessorID,
|
token.AccessorID,
|
||||||
&api.QueryOptions{Token: "root"},
|
&api.QueryOptions{Token: "root"},
|
||||||
)
|
)
|
||||||
assert.EqualError(t, err, "Unexpected response code: 403 (ACL not found)")
|
assert.ErrorContains(t, err, "Unexpected response code: 403")
|
||||||
|
assert.ErrorContains(t, err, "ACL not found")
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ func TestLogoutCommand(t *testing.T) {
|
||||||
|
|
||||||
code := cmd.Run(args)
|
code := cmd.Run(args)
|
||||||
require.Equal(t, code, 1, "err: %s", ui.ErrorWriter.String())
|
require.Equal(t, code, 1, "err: %s", ui.ErrorWriter.String())
|
||||||
require.Contains(t, ui.ErrorWriter.String(), "403 (ACL not found)")
|
require.Contains(t, ui.ErrorWriter.String(), "401 (Supplied token does not exist)")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("logout of deleted token", func(t *testing.T) {
|
t.Run("logout of deleted token", func(t *testing.T) {
|
||||||
|
@ -185,7 +185,7 @@ func TestLogoutCommand_k8s(t *testing.T) {
|
||||||
|
|
||||||
code := cmd.Run(args)
|
code := cmd.Run(args)
|
||||||
require.Equal(t, code, 1, "err: %s", ui.ErrorWriter.String())
|
require.Equal(t, code, 1, "err: %s", ui.ErrorWriter.String())
|
||||||
require.Contains(t, ui.ErrorWriter.String(), "403 (ACL not found)")
|
require.Contains(t, ui.ErrorWriter.String(), "401 (Supplied token does not exist)")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("logout of deleted token", func(t *testing.T) {
|
t.Run("logout of deleted token", func(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue