Bulk acl message fixup oss (#12470)
* First pass for helper for bulk changes Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Convert ACLRead and ACLWrite to new form Signed-off-by: Mark Anderson <manderson@hashicorp.com> * AgentRead and AgentWRite Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Fix EventWrite Signed-off-by: Mark Anderson <manderson@hashicorp.com> * KeyRead, KeyWrite, KeyList Signed-off-by: Mark Anderson <manderson@hashicorp.com> * KeyRing Signed-off-by: Mark Anderson <manderson@hashicorp.com> * NodeRead NodeWrite Signed-off-by: Mark Anderson <manderson@hashicorp.com> * OperatorRead and OperatorWrite Signed-off-by: Mark Anderson <manderson@hashicorp.com> * PreparedQuery Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Intention partial Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Fix ServiceRead, Write ,etc Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Error check ServiceRead? Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Fix Sessionread/Write Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Fixup snapshot ACL Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Error fixups for txn Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Add changelog Signed-off-by: Mark Anderson <manderson@hashicorp.com> * Fixup review comments Signed-off-by: Mark Anderson <manderson@hashicorp.com>
This commit is contained in:
parent
a313b61fe9
commit
5591cb1e11
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:enhancement
|
||||||
|
acl: Provide fuller detail in the error messsage when an ACL denies access.
|
||||||
|
```
|
|
@ -161,6 +161,279 @@ type Authorizer interface {
|
||||||
|
|
||||||
// Embedded Interface for Consul Enterprise specific ACL enforcement
|
// Embedded Interface for Consul Enterprise specific ACL enforcement
|
||||||
enterpriseAuthorizer
|
enterpriseAuthorizer
|
||||||
|
|
||||||
|
// ToAllowAuthorizer is needed until we can use ResolveResult in all the places this interface is used.
|
||||||
|
ToAllowAuthorizer() AllowAuthorizer
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowAuthorizer is a wrapper to expose the *Allowed methods.
|
||||||
|
// This and the ToAllowAuthorizer function exist to tide us over until the ResolveResult struct
|
||||||
|
// is moved into acl.
|
||||||
|
type AllowAuthorizer struct {
|
||||||
|
Authorizer
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLReadAllowed checks for permission to list all the ACLs
|
||||||
|
func (a AllowAuthorizer) ACLReadAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.ACLRead(ctx) != Allow {
|
||||||
|
return PermissionDeniedByACLUnnamed(a, ctx, ResourceACL, AccessRead)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLWriteAllowed checks for permission to manipulate ACLs
|
||||||
|
func (a AllowAuthorizer) ACLWriteAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.ACLWrite(ctx) != Allow {
|
||||||
|
return PermissionDeniedByACLUnnamed(a, ctx, ResourceACL, AccessWrite)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AgentReadAllowed checks for permission to read from agent endpoints for a
|
||||||
|
// given node.
|
||||||
|
func (a AllowAuthorizer) AgentReadAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.AgentRead(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceAgent, AccessRead, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AgentWriteAllowed checks for permission to make changes via agent endpoints
|
||||||
|
// for a given node.
|
||||||
|
func (a AllowAuthorizer) AgentWriteAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.AgentWrite(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceAgent, AccessWrite, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventReadAllowed determines if a specific event can be queried.
|
||||||
|
func (a AllowAuthorizer) EventReadAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.EventRead(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceEvent, AccessRead, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventWriteAllowed determines if a specific event may be fired.
|
||||||
|
func (a AllowAuthorizer) EventWriteAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.EventWrite(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceEvent, AccessWrite, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntentionDefaultAllowAllowed determines the default authorized behavior
|
||||||
|
// when no intentions match a Connect request.
|
||||||
|
func (a AllowAuthorizer) IntentionDefaultAllowAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.IntentionDefaultAllow(ctx) != Allow {
|
||||||
|
// This is a bit nuanced, in that this isn't set by a rule, but inherited globally
|
||||||
|
// TODO(acl-error-enhancements) revisit when we have full accessor info
|
||||||
|
return PermissionDeniedError{Cause: "Denied by intention default"}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntentionReadAllowed determines if a specific intention can be read.
|
||||||
|
func (a AllowAuthorizer) IntentionReadAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.IntentionRead(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceIntention, AccessRead, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntentionWriteAllowed determines if a specific intention can be
|
||||||
|
// created, modified, or deleted.
|
||||||
|
func (a AllowAuthorizer) IntentionWriteAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.IntentionWrite(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceIntention, AccessWrite, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyListAllowed checks for permission to list keys under a prefix
|
||||||
|
func (a AllowAuthorizer) KeyListAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.KeyList(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceKey, AccessList, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyReadAllowed checks for permission to read a given key
|
||||||
|
func (a AllowAuthorizer) KeyReadAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.KeyRead(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceKey, AccessRead, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyWriteAllowed checks for permission to write a given key
|
||||||
|
func (a AllowAuthorizer) KeyWriteAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.KeyWrite(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceKey, AccessWrite, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyWritePrefixAllowed checks for permission to write to an
|
||||||
|
// entire key prefix. This means there must be no sub-policies
|
||||||
|
// that deny a write.
|
||||||
|
func (a AllowAuthorizer) KeyWritePrefixAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.KeyWritePrefix(name, ctx) != Allow {
|
||||||
|
// TODO(acl-error-enhancements) revisit this message; we may need to do some extra plumbing inside of KeyWritePrefix to
|
||||||
|
// return properly detailed information.
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceKey, AccessWrite, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyringReadAllowed determines if the encryption keyring used in
|
||||||
|
// the gossip layer can be read.
|
||||||
|
func (a AllowAuthorizer) KeyringReadAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.KeyringRead(ctx) != Allow {
|
||||||
|
return PermissionDeniedByACLUnnamed(a, ctx, ResourceKeyring, AccessRead)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyringWriteAllowed determines if the keyring can be manipulated
|
||||||
|
func (a AllowAuthorizer) KeyringWriteAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.KeyringWrite(ctx) != Allow {
|
||||||
|
return PermissionDeniedByACLUnnamed(a, ctx, ResourceKeyring, AccessWrite)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MeshReadAllowed determines if the read-only Consul mesh functions
|
||||||
|
// can be used.
|
||||||
|
func (a AllowAuthorizer) MeshReadAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.MeshRead(ctx) != Allow {
|
||||||
|
return PermissionDeniedByACLUnnamed(a, ctx, ResourceMesh, AccessRead)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MeshWriteAllowed determines if the state-changing Consul mesh
|
||||||
|
// functions can be used.
|
||||||
|
func (a AllowAuthorizer) MeshWriteAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.MeshWrite(ctx) != Allow {
|
||||||
|
return PermissionDeniedByACLUnnamed(a, ctx, ResourceMesh, AccessWrite)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeReadAllowed checks for permission to read (discover) a given node.
|
||||||
|
func (a AllowAuthorizer) NodeReadAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.NodeRead(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceNode, AccessRead, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeReadAllAllowed checks for permission to read (discover) all nodes.
|
||||||
|
func (a AllowAuthorizer) NodeReadAllAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.NodeReadAll(ctx) != Allow {
|
||||||
|
// This is only used to gate certain UI functions right now (e.g metrics)
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceNode, AccessRead, "all nodes")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeWriteAllowed checks for permission to create or update (register) a
|
||||||
|
// given node.
|
||||||
|
func (a AllowAuthorizer) NodeWriteAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.NodeWrite(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceNode, AccessWrite, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperatorReadAllowed determines if the read-only Consul operator functions
|
||||||
|
// can be used.
|
||||||
|
func (a AllowAuthorizer) OperatorReadAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.OperatorRead(ctx) != Allow {
|
||||||
|
return PermissionDeniedByACLUnnamed(a, ctx, ResourceOperator, AccessRead)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperatorWriteAllowed determines if the state-changing Consul operator
|
||||||
|
// functions can be used.
|
||||||
|
func (a AllowAuthorizer) OperatorWriteAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.OperatorWrite(ctx) != Allow {
|
||||||
|
return PermissionDeniedByACLUnnamed(a, ctx, ResourceOperator, AccessWrite)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PreparedQueryReadAllowed determines if a specific prepared query can be read
|
||||||
|
// to show its contents (this is not used for execution).
|
||||||
|
func (a AllowAuthorizer) PreparedQueryReadAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.PreparedQueryRead(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceQuery, AccessRead, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PreparedQueryWriteAllowed determines if a specific prepared query can be
|
||||||
|
// created, modified, or deleted.
|
||||||
|
func (a AllowAuthorizer) PreparedQueryWriteAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.PreparedQueryWrite(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceQuery, AccessWrite, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceReadAllowed checks for permission to read a given service
|
||||||
|
func (a AllowAuthorizer) ServiceReadAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.ServiceRead(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceService, AccessRead, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceReadAllAllowed checks for permission to read all services
|
||||||
|
func (a AllowAuthorizer) ServiceReadAllAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.ServiceReadAll(ctx) != Allow {
|
||||||
|
// This is only used to gate certain UI functions right now (e.g metrics)
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceService, AccessRead, "all services") // read
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceWriteAllowed checks for permission to create or update a given
|
||||||
|
// service
|
||||||
|
func (a AllowAuthorizer) ServiceWriteAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.ServiceWrite(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceService, AccessWrite, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionReadAllowed checks for permission to read sessions for a given node.
|
||||||
|
func (a AllowAuthorizer) SessionReadAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.SessionRead(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceSession, AccessRead, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionWriteAllowed checks for permission to create sessions for a given
|
||||||
|
// node.
|
||||||
|
func (a AllowAuthorizer) SessionWriteAllowed(name string, ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.SessionWrite(name, ctx) != Allow {
|
||||||
|
return PermissionDeniedByACL(a, ctx, ResourceSession, AccessWrite, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SnapshotAllowed checks for permission to take and restore snapshots.
|
||||||
|
func (a AllowAuthorizer) SnapshotAllowed(ctx *AuthorizerContext) error {
|
||||||
|
if a.Authorizer.Snapshot(ctx) != Allow {
|
||||||
|
// Implementation of this currently just checks acl write
|
||||||
|
return PermissionDeniedByACLUnnamed(a, ctx, ResourceACL, AccessWrite)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Enforce(authz Authorizer, rsc Resource, segment string, access string, ctx *AuthorizerContext) (EnforcementDecision, error) {
|
func Enforce(authz Authorizer, rsc Resource, segment string, access string, ctx *AuthorizerContext) (EnforcementDecision, error) {
|
||||||
|
|
|
@ -204,6 +204,10 @@ func (m *mockAuthorizer) Snapshot(ctx *AuthorizerContext) EnforcementDecision {
|
||||||
return ret.Get(0).(EnforcementDecision)
|
return ret.Get(0).(EnforcementDecision)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *mockAuthorizer) ToAllowAuthorizer() AllowAuthorizer {
|
||||||
|
return AllowAuthorizer{Authorizer: p}
|
||||||
|
}
|
||||||
|
|
||||||
func TestACL_Enforce(t *testing.T) {
|
func TestACL_Enforce(t *testing.T) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
method string
|
method string
|
||||||
|
|
|
@ -256,3 +256,7 @@ func (c *ChainedAuthorizer) Snapshot(entCtx *AuthorizerContext) EnforcementDecis
|
||||||
return authz.Snapshot(entCtx)
|
return authz.Snapshot(entCtx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ChainedAuthorizer) ToAllowAuthorizer() AllowAuthorizer {
|
||||||
|
return AllowAuthorizer{Authorizer: c}
|
||||||
|
}
|
||||||
|
|
|
@ -99,6 +99,10 @@ func (authz testAuthorizer) Snapshot(*AuthorizerContext) EnforcementDecision {
|
||||||
return EnforcementDecision(authz)
|
return EnforcementDecision(authz)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (authz testAuthorizer) ToAllowAuthorizer() AllowAuthorizer {
|
||||||
|
return AllowAuthorizer{Authorizer: &authz}
|
||||||
|
}
|
||||||
|
|
||||||
func TestChainedAuthorizer(t *testing.T) {
|
func TestChainedAuthorizer(t *testing.T) {
|
||||||
t.Run("No Authorizers", func(t *testing.T) {
|
t.Run("No Authorizers", func(t *testing.T) {
|
||||||
authz := NewChainedAuthorizer([]Authorizer{})
|
authz := NewChainedAuthorizer([]Authorizer{})
|
||||||
|
|
|
@ -106,7 +106,7 @@ func (e PermissionDeniedError) Error() string {
|
||||||
fmt.Fprintf(&message, " lacks permission '%s:%s'", e.Resource, e.AccessLevel.String())
|
fmt.Fprintf(&message, " lacks permission '%s:%s'", e.Resource, e.AccessLevel.String())
|
||||||
|
|
||||||
if e.ResourceID.Name != "" {
|
if e.ResourceID.Name != "" {
|
||||||
fmt.Fprintf(&message, " %s", e.ResourceID.ToString())
|
fmt.Fprintf(&message, " on %s", e.ResourceID.ToString())
|
||||||
}
|
}
|
||||||
return message.String()
|
return message.String()
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestPermissionDeniedError(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
err: PermissionDeniedByACL(&auth1, nil, ResourceService, AccessRead, "foobar"),
|
err: PermissionDeniedByACL(&auth1, nil, ResourceService, AccessRead, "foobar"),
|
||||||
expected: "Permission denied: provided accessor lacks permission 'service:read' foobar",
|
expected: "Permission denied: provided accessor lacks permission 'service:read' on foobar",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
err: PermissionDeniedByACLUnnamed(&auth1, nil, ResourceService, AccessRead),
|
err: PermissionDeniedByACLUnnamed(&auth1, nil, ResourceService, AccessRead),
|
||||||
|
|
|
@ -787,3 +787,7 @@ func (p *policyAuthorizer) SessionWrite(node string, _ *AuthorizerContext) Enfor
|
||||||
}
|
}
|
||||||
return Default
|
return Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *policyAuthorizer) ToAllowAuthorizer() AllowAuthorizer {
|
||||||
|
return AllowAuthorizer{Authorizer: p}
|
||||||
|
}
|
||||||
|
|
|
@ -240,6 +240,10 @@ func (s *staticAuthorizer) Snapshot(_ *AuthorizerContext) EnforcementDecision {
|
||||||
return Deny
|
return Deny
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *staticAuthorizer) ToAllowAuthorizer() AllowAuthorizer {
|
||||||
|
return AllowAuthorizer{Authorizer: s}
|
||||||
|
}
|
||||||
|
|
||||||
// AllowAll returns an Authorizer that allows all operations
|
// AllowAll returns an Authorizer that allows all operations
|
||||||
func AllowAll() Authorizer {
|
func AllowAll() Authorizer {
|
||||||
return allowAll
|
return allowAll
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package acl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RequirePermissionDeniedError(t testing.TB, err error, _ Authorizer, _ *AuthorizerContext, resource Resource, accessLevel AccessLevel, resourceID string) {
|
||||||
|
t.Helper()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("An error is expected but got nil.")
|
||||||
|
}
|
||||||
|
if v, ok := err.(PermissionDeniedError); ok {
|
||||||
|
require.Equal(t, v.Resource, resource)
|
||||||
|
require.Equal(t, v.AccessLevel, accessLevel)
|
||||||
|
require.Equal(t, v.ResourceID.Name, resourceID)
|
||||||
|
} else {
|
||||||
|
t.Fatalf("Expected a permission denied error got %T %vp", err, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RequirePermissionDeniedMessage(t testing.TB, msg string, auth Authorizer, _ *AuthorizerContext, resource Resource, accessLevel AccessLevel, resourceID string) {
|
||||||
|
require.NotEmpty(t, msg, "expected non-empty error message")
|
||||||
|
|
||||||
|
var resourceIDFound string
|
||||||
|
if auth == nil {
|
||||||
|
expr := "^Permission denied" + `: provided accessor lacks permission '(\S*):(\S*)' on (.*)\s*$`
|
||||||
|
re, _ := regexp.Compile(expr)
|
||||||
|
matched := re.FindStringSubmatch(msg)
|
||||||
|
|
||||||
|
require.Equal(t, string(resource), matched[1], "resource")
|
||||||
|
require.Equal(t, accessLevel.String(), matched[2], "access level")
|
||||||
|
resourceIDFound = matched[3]
|
||||||
|
} else {
|
||||||
|
expr := "^Permission denied" + `: accessor '(\S*)' lacks permission '(\S*):(\S*)' on (.*)\s*$`
|
||||||
|
re, _ := regexp.Compile(expr)
|
||||||
|
matched := re.FindStringSubmatch(msg)
|
||||||
|
|
||||||
|
require.Equal(t, auth, matched[1], "auth")
|
||||||
|
require.Equal(t, string(resource), matched[2], "resource")
|
||||||
|
require.Equal(t, accessLevel.String(), matched[3], "access level")
|
||||||
|
resourceIDFound = matched[4]
|
||||||
|
}
|
||||||
|
// AuthorizerContext information should be checked here
|
||||||
|
require.Contains(t, resourceIDFound, resourceID, "resource id")
|
||||||
|
}
|
41
agent/acl.go
41
agent/acl.go
|
@ -43,15 +43,15 @@ func (a *Agent) vetServiceRegisterWithAuthorizer(authz acl.Authorizer, service *
|
||||||
|
|
||||||
// Vet the service itself.
|
// Vet the service itself.
|
||||||
service.FillAuthzContext(&authzContext)
|
service.FillAuthzContext(&authzContext)
|
||||||
if authz.ServiceWrite(service.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(service.Service, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceService, acl.AccessWrite, service.Service)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vet any service that might be getting overwritten.
|
// Vet any service that might be getting overwritten.
|
||||||
if existing := a.State.Service(service.CompoundServiceID()); existing != nil {
|
if existing := a.State.Service(service.CompoundServiceID()); existing != nil {
|
||||||
existing.FillAuthzContext(&authzContext)
|
existing.FillAuthzContext(&authzContext)
|
||||||
if authz.ServiceWrite(existing.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(existing.Service, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceService, acl.AccessWrite, existing.Service)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ func (a *Agent) vetServiceRegisterWithAuthorizer(authz acl.Authorizer, service *
|
||||||
// since it can be discovered as an instance of that service.
|
// since it can be discovered as an instance of that service.
|
||||||
if service.Kind == structs.ServiceKindConnectProxy {
|
if service.Kind == structs.ServiceKindConnectProxy {
|
||||||
service.FillAuthzContext(&authzContext)
|
service.FillAuthzContext(&authzContext)
|
||||||
if authz.ServiceWrite(service.Proxy.DestinationServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(service.Proxy.DestinationServiceName, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceService, acl.AccessWrite, service.Proxy.DestinationServiceName)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +73,9 @@ func (a *Agent) vetServiceUpdateWithAuthorizer(authz acl.Authorizer, serviceID s
|
||||||
// Vet any changes based on the existing services's info.
|
// Vet any changes based on the existing services's info.
|
||||||
if existing := a.State.Service(serviceID); existing != nil {
|
if existing := a.State.Service(serviceID); existing != nil {
|
||||||
existing.FillAuthzContext(&authzContext)
|
existing.FillAuthzContext(&authzContext)
|
||||||
if authz.ServiceWrite(existing.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(existing.Service, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceService, acl.AccessWrite, existing.Service)
|
return err
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Take care if modifying this error message.
|
// Take care if modifying this error message.
|
||||||
|
@ -95,13 +96,13 @@ func (a *Agent) vetCheckRegisterWithAuthorizer(authz acl.Authorizer, check *stru
|
||||||
|
|
||||||
// Vet the check itself.
|
// Vet the check itself.
|
||||||
if len(check.ServiceName) > 0 {
|
if len(check.ServiceName) > 0 {
|
||||||
if authz.ServiceWrite(check.ServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(check.ServiceName, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceService, acl.AccessWrite, check.ServiceName)
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// N.B. Should this authzContext be derived from a.AgentEnterpriseMeta()
|
// N.B. Should this authzContext be derived from a.AgentEnterpriseMeta()
|
||||||
if authz.NodeWrite(a.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(a.config.NodeName, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceNode, acl.AccessWrite, a.config.NodeName)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,13 +110,13 @@ func (a *Agent) vetCheckRegisterWithAuthorizer(authz acl.Authorizer, check *stru
|
||||||
if existing := a.State.Check(check.CompoundCheckID()); existing != nil {
|
if existing := a.State.Check(check.CompoundCheckID()); existing != nil {
|
||||||
if len(existing.ServiceName) > 0 {
|
if len(existing.ServiceName) > 0 {
|
||||||
// N.B. Should this authzContext be derived from existing.EnterpriseMeta?
|
// N.B. Should this authzContext be derived from existing.EnterpriseMeta?
|
||||||
if authz.ServiceWrite(existing.ServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(existing.ServiceName, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceService, acl.AccessWrite, existing.ServiceName)
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// N.B. Should this authzContext be derived from a.AgentEnterpriseMeta()
|
// N.B. Should this authzContext be derived from a.AgentEnterpriseMeta()
|
||||||
if authz.NodeWrite(a.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(a.config.NodeName, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceNode, acl.AccessWrite, a.config.NodeName)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,12 +131,12 @@ func (a *Agent) vetCheckUpdateWithAuthorizer(authz acl.Authorizer, checkID struc
|
||||||
// Vet any changes based on the existing check's info.
|
// Vet any changes based on the existing check's info.
|
||||||
if existing := a.State.Check(checkID); existing != nil {
|
if existing := a.State.Check(checkID); existing != nil {
|
||||||
if len(existing.ServiceName) > 0 {
|
if len(existing.ServiceName) > 0 {
|
||||||
if authz.ServiceWrite(existing.ServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(existing.ServiceName, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceService, acl.AccessWrite, existing.ServiceName)
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if authz.NodeWrite(a.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(a.config.NodeName, &authzContext); err != nil {
|
||||||
return acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceNode, acl.AccessWrite, a.config.NodeName)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -60,8 +60,8 @@ func (s *HTTPHandlers) AgentSelf(resp http.ResponseWriter, req *http.Request) (i
|
||||||
// Authorize using the agent's own enterprise meta, not the token.
|
// Authorize using the agent's own enterprise meta, not the token.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.AgentRead(s.agent.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().AgentReadAllowed(s.agent.config.NodeName, &authzContext); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var cs lib.CoordinateSet
|
var cs lib.CoordinateSet
|
||||||
|
@ -150,8 +150,8 @@ func (s *HTTPHandlers) AgentMetrics(resp http.ResponseWriter, req *http.Request)
|
||||||
// Authorize using the agent's own enterprise meta, not the token.
|
// Authorize using the agent's own enterprise meta, not the token.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.AgentRead(s.agent.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().AgentReadAllowed(s.agent.config.NodeName, &authzContext); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
}
|
}
|
||||||
if enablePrometheusOutput(req) {
|
if enablePrometheusOutput(req) {
|
||||||
if s.agent.config.Telemetry.PrometheusOpts.Expiration < 1 {
|
if s.agent.config.Telemetry.PrometheusOpts.Expiration < 1 {
|
||||||
|
@ -187,8 +187,8 @@ func (s *HTTPHandlers) AgentMetricsStream(resp http.ResponseWriter, req *http.Re
|
||||||
// Authorize using the agent's own enterprise meta, not the token.
|
// Authorize using the agent's own enterprise meta, not the token.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.AgentRead(s.agent.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().AgentReadAllowed(s.agent.config.NodeName, &authzContext); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
flusher, ok := resp.(http.Flusher)
|
flusher, ok := resp.(http.Flusher)
|
||||||
|
@ -240,8 +240,8 @@ func (s *HTTPHandlers) AgentReload(resp http.ResponseWriter, req *http.Request)
|
||||||
// Authorize using the agent's own enterprise meta, not the token.
|
// Authorize using the agent's own enterprise meta, not the token.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.AgentWrite(s.agent.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().AgentWriteAllowed(s.agent.config.NodeName, &authzContext); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, s.agent.ReloadConfig()
|
return nil, s.agent.ReloadConfig()
|
||||||
|
@ -440,8 +440,8 @@ func (s *HTTPHandlers) AgentService(resp http.ResponseWriter, req *http.Request)
|
||||||
}
|
}
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
svc.FillAuthzContext(&authzContext)
|
svc.FillAuthzContext(&authzContext)
|
||||||
if authz.ServiceRead(svc.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(svc.Service, &authzContext); err != nil {
|
||||||
return "", nil, acl.ErrPermissionDenied
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the content hash over the response, minus the hash field
|
// Calculate the content hash over the response, minus the hash field
|
||||||
|
@ -621,8 +621,9 @@ func (s *HTTPHandlers) AgentJoin(resp http.ResponseWriter, req *http.Request) (i
|
||||||
// Authorize using the agent's own enterprise meta, not the token.
|
// Authorize using the agent's own enterprise meta, not the token.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.AgentWrite(s.agent.config.NodeName, &authzContext) != acl.Allow {
|
|
||||||
return nil, acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceAgent, acl.AccessWrite, s.agent.config.NodeName)
|
if err := authz.ToAllowAuthorizer().AgentWriteAllowed(s.agent.config.NodeName, &authzContext); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the request partition and default to that of the agent.
|
// Get the request partition and default to that of the agent.
|
||||||
|
@ -666,8 +667,8 @@ func (s *HTTPHandlers) AgentLeave(resp http.ResponseWriter, req *http.Request) (
|
||||||
// Authorize using the agent's own enterprise meta, not the token.
|
// Authorize using the agent's own enterprise meta, not the token.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.AgentWrite(s.agent.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().AgentWriteAllowed(s.agent.config.NodeName, &authzContext); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.agent.Leave(); err != nil {
|
if err := s.agent.Leave(); err != nil {
|
||||||
|
@ -685,8 +686,8 @@ func (s *HTTPHandlers) AgentForceLeave(resp http.ResponseWriter, req *http.Reque
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// TODO(partitions): should this be possible in a partition?
|
// TODO(partitions): should this be possible in a partition?
|
||||||
if authz.OperatorWrite(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorWriteAllowed(nil); err != nil {
|
||||||
return nil, acl.PermissionDeniedByACLUnnamed(authz, nil, acl.ResourceOperator, acl.AccessWrite)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the request partition and default to that of the agent.
|
// Get the request partition and default to that of the agent.
|
||||||
|
@ -1007,8 +1008,8 @@ func (s *HTTPHandlers) AgentHealthServiceByID(resp http.ResponseWriter, req *htt
|
||||||
dc := s.agent.config.Datacenter
|
dc := s.agent.config.Datacenter
|
||||||
|
|
||||||
if service := s.agent.State.Service(sid); service != nil {
|
if service := s.agent.State.Service(sid); service != nil {
|
||||||
if authz.ServiceRead(service.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(service.Service, &authzContext); err != nil {
|
||||||
return nil, acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceService, acl.AccessRead, service.Service)
|
return nil, err
|
||||||
}
|
}
|
||||||
code, status, healthChecks := agentHealthService(sid, s)
|
code, status, healthChecks := agentHealthService(sid, s)
|
||||||
if returnTextPlain(req) {
|
if returnTextPlain(req) {
|
||||||
|
@ -1060,8 +1061,8 @@ func (s *HTTPHandlers) AgentHealthServiceByName(resp http.ResponseWriter, req *h
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if authz.ServiceRead(serviceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(serviceName, &authzContext); err != nil {
|
||||||
return nil, acl.PermissionDeniedByACL(authz, &authzContext, acl.ResourceService, acl.AccessRead, serviceName)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.validateRequestPartition(resp, &entMeta) {
|
if !s.validateRequestPartition(resp, &entMeta) {
|
||||||
|
@ -1374,8 +1375,8 @@ func (s *HTTPHandlers) AgentNodeMaintenance(resp http.ResponseWriter, req *http.
|
||||||
|
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.NodeWrite(s.agent.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(s.agent.config.NodeName, &authzContext); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if enable {
|
if enable {
|
||||||
|
@ -1399,8 +1400,8 @@ func (s *HTTPHandlers) AgentMonitor(resp http.ResponseWriter, req *http.Request)
|
||||||
// Authorize using the agent's own enterprise meta, not the token.
|
// Authorize using the agent's own enterprise meta, not the token.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.AgentRead(s.agent.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().AgentReadAllowed(s.agent.config.NodeName, &authzContext); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the provided loglevel.
|
// Get the provided loglevel.
|
||||||
|
@ -1482,8 +1483,8 @@ func (s *HTTPHandlers) AgentToken(resp http.ResponseWriter, req *http.Request) (
|
||||||
// Authorize using the agent's own enterprise meta, not the token.
|
// Authorize using the agent's own enterprise meta, not the token.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
s.agent.AgentEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.AgentWrite(s.agent.config.NodeName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().AgentWriteAllowed(s.agent.config.NodeName, &authzContext); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// The body is just the token, but it's in a JSON object so we can add
|
// The body is just the token, but it's in a JSON object so we can add
|
||||||
|
@ -1683,8 +1684,8 @@ func (s *HTTPHandlers) AgentHost(resp http.ResponseWriter, req *http.Request) (i
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(partitions): should this be possible in a partition?
|
// TODO(partitions): should this be possible in a partition?
|
||||||
if authz.OperatorRead(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorReadAllowed(nil); err != nil {
|
||||||
return nil, acl.PermissionDeniedByACLUnnamed(authz, nil, acl.ResourceOperator, acl.AccessRead)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return debug.CollectHostInfo(), nil
|
return debug.CollectHostInfo(), nil
|
||||||
|
|
|
@ -65,8 +65,8 @@ func (a *Agent) ConnectAuthorize(token string,
|
||||||
return returnErr(err)
|
return returnErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if authz.ServiceWrite(req.Target, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(req.Target, &authzContext); err != nil {
|
||||||
return returnErr(acl.ErrPermissionDenied)
|
return returnErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !uriService.MatchesPartition(req.TargetPartition()) {
|
if !uriService.MatchesPartition(req.TargetPartition()) {
|
||||||
|
|
|
@ -286,8 +286,8 @@ func (a *ACL) TokenRead(args *structs.ACLTokenGetRequest, reply *structs.ACLToke
|
||||||
// secrets will be redacted
|
// secrets will be redacted
|
||||||
if authz, err = a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err = a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLRead(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,8 +354,8 @@ func (a *ACL) TokenClone(args *structs.ACLTokenSetRequest, reply *structs.ACLTok
|
||||||
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.ACLToken.EnterpriseMeta, &authzContext)
|
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.ACLToken.EnterpriseMeta, &authzContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, 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)
|
||||||
|
@ -425,8 +425,8 @@ func (a *ACL) TokenSet(args *structs.ACLTokenSetRequest, reply *structs.ACLToken
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.ACLToken.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.ACLToken.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.tokenSetInternal(args, reply, false)
|
return a.tokenSetInternal(args, reply, false)
|
||||||
|
@ -830,8 +830,8 @@ func (a *ACL) TokenDelete(args *structs.ACLTokenDeleteRequest, reply *string) er
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := uuid.ParseUUID(args.TokenID); err != nil {
|
if _, err := uuid.ParseUUID(args.TokenID); err != nil {
|
||||||
|
@ -919,8 +919,8 @@ func (a *ACL) TokenList(args *structs.ACLTokenListRequest, reply *structs.ACLTok
|
||||||
// merge the token default meta into the requests meta
|
// merge the token default meta into the requests meta
|
||||||
args.EnterpriseMeta.Merge(&requestMeta)
|
args.EnterpriseMeta.Merge(&requestMeta)
|
||||||
args.EnterpriseMeta.FillAuthzContext(&authzContext)
|
args.EnterpriseMeta.FillAuthzContext(&authzContext)
|
||||||
if authz.ACLRead(&authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var methodMeta *structs.EnterpriseMeta
|
var methodMeta *structs.EnterpriseMeta
|
||||||
|
@ -1026,8 +1026,8 @@ func (a *ACL) PolicyRead(args *structs.ACLPolicyGetRequest, reply *structs.ACLPo
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLRead(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||||
|
@ -1107,8 +1107,8 @@ func (a *ACL) PolicySet(args *structs.ACLPolicySetRequest, reply *structs.ACLPol
|
||||||
|
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.Policy.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.Policy.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
policy := &args.Policy
|
policy := &args.Policy
|
||||||
|
@ -1237,8 +1237,8 @@ func (a *ACL) PolicyDelete(args *structs.ACLPolicyDeleteRequest, reply *string)
|
||||||
|
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, args.PolicyID, &args.EnterpriseMeta)
|
_, policy, err := a.srv.fsm.State().ACLPolicyGetByID(nil, args.PolicyID, &args.EnterpriseMeta)
|
||||||
|
@ -1288,8 +1288,8 @@ func (a *ACL) PolicyList(args *structs.ACLPolicyListRequest, reply *structs.ACLP
|
||||||
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLRead(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||||
|
@ -1412,8 +1412,8 @@ func (a *ACL) RoleRead(args *structs.ACLRoleGetRequest, reply *structs.ACLRoleRe
|
||||||
|
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLRead(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||||
|
@ -1493,8 +1493,8 @@ func (a *ACL) RoleSet(args *structs.ACLRoleSetRequest, reply *structs.ACLRole) e
|
||||||
|
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.Role.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.Role.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
role := &args.Role
|
role := &args.Role
|
||||||
|
@ -1651,8 +1651,8 @@ func (a *ACL) RoleDelete(args *structs.ACLRoleDeleteRequest, reply *string) erro
|
||||||
|
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, role, err := a.srv.fsm.State().ACLRoleGetByID(nil, args.RoleID, &args.EnterpriseMeta)
|
_, role, err := a.srv.fsm.State().ACLRoleGetByID(nil, args.RoleID, &args.EnterpriseMeta)
|
||||||
|
@ -1698,8 +1698,8 @@ func (a *ACL) RoleList(args *structs.ACLRoleListRequest, reply *structs.ACLRoleL
|
||||||
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLRead(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||||
|
@ -1797,8 +1797,8 @@ func (a *ACL) BindingRuleRead(args *structs.ACLBindingRuleGetRequest, reply *str
|
||||||
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLRead(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||||
|
@ -1840,8 +1840,8 @@ func (a *ACL) BindingRuleSet(args *structs.ACLBindingRuleSetRequest, reply *stru
|
||||||
// Verify token is permitted to modify ACLs
|
// Verify token is permitted to modify ACLs
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.BindingRule.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.BindingRule.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var existing *structs.ACLBindingRule
|
var existing *structs.ACLBindingRule
|
||||||
|
@ -1969,8 +1969,8 @@ func (a *ACL) BindingRuleDelete(args *structs.ACLBindingRuleDeleteRequest, reply
|
||||||
// Verify token is permitted to modify ACLs
|
// Verify token is permitted to modify ACLs
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, rule, err := a.srv.fsm.State().ACLBindingRuleGetByID(nil, args.BindingRuleID, &args.EnterpriseMeta)
|
_, rule, err := a.srv.fsm.State().ACLBindingRuleGetByID(nil, args.BindingRuleID, &args.EnterpriseMeta)
|
||||||
|
@ -2017,8 +2017,8 @@ func (a *ACL) BindingRuleList(args *structs.ACLBindingRuleListRequest, reply *st
|
||||||
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLRead(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||||
|
@ -2056,8 +2056,8 @@ func (a *ACL) AuthMethodRead(args *structs.ACLAuthMethodGetRequest, reply *struc
|
||||||
|
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLRead(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||||
|
@ -2101,8 +2101,8 @@ func (a *ACL) AuthMethodSet(args *structs.ACLAuthMethodSetRequest, reply *struct
|
||||||
|
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.AuthMethod.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.AuthMethod.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
method := &args.AuthMethod
|
method := &args.AuthMethod
|
||||||
|
@ -2213,8 +2213,8 @@ func (a *ACL) AuthMethodDelete(args *structs.ACLAuthMethodDeleteRequest, reply *
|
||||||
|
|
||||||
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
if authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLWrite(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLWriteAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, method, err := a.srv.fsm.State().ACLAuthMethodGetByName(nil, args.AuthMethodName, &args.EnterpriseMeta)
|
_, method, err := a.srv.fsm.State().ACLAuthMethodGetByName(nil, args.AuthMethodName, &args.EnterpriseMeta)
|
||||||
|
@ -2267,8 +2267,8 @@ func (a *ACL) AuthMethodList(args *structs.ACLAuthMethodListRequest, reply *stru
|
||||||
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
authz, err := a.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, &authzContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if authz.ACLRead(&authzContext) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().ACLReadAllowed(&authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||||
|
|
|
@ -192,15 +192,15 @@ func servicePreApply(service *structs.NodeService, authz acl.Authorizer, authzCt
|
||||||
// later if version 0.8 is enabled, so we can eventually just
|
// later if version 0.8 is enabled, so we can eventually just
|
||||||
// delete this and do all the ACL checks down there.
|
// delete this and do all the ACL checks down there.
|
||||||
if service.Service != structs.ConsulServiceName {
|
if service.Service != structs.ConsulServiceName {
|
||||||
if authz.ServiceWrite(service.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(service.Service, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proxies must have write permission on their destination
|
// Proxies must have write permission on their destination
|
||||||
if service.Kind == structs.ServiceKindConnectProxy {
|
if service.Kind == structs.ServiceKindConnectProxy {
|
||||||
if authz.ServiceWrite(service.Proxy.DestinationServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(service.Proxy.DestinationServiceName, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,16 +241,18 @@ func vetRegisterWithACL(
|
||||||
// privileges.
|
// privileges.
|
||||||
needsNode := ns == nil || subj.ChangesNode(ns.Node)
|
needsNode := ns == nil || subj.ChangesNode(ns.Node)
|
||||||
|
|
||||||
if needsNode && authz.NodeWrite(subj.Node, &authzContext) != acl.Allow {
|
if needsNode {
|
||||||
return acl.ErrPermissionDenied
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(subj.Node, &authzContext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vet the service change. This includes making sure they can register
|
// Vet the service change. This includes making sure they can register
|
||||||
// the given service, and that we can write to any existing service that
|
// the given service, and that we can write to any existing service that
|
||||||
// is being modified by id (if any).
|
// is being modified by id (if any).
|
||||||
if subj.Service != nil {
|
if subj.Service != nil {
|
||||||
if authz.ServiceWrite(subj.Service.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(subj.Service.Service, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ns != nil {
|
if ns != nil {
|
||||||
|
@ -263,7 +265,7 @@ func vetRegisterWithACL(
|
||||||
var secondaryCtx acl.AuthorizerContext
|
var secondaryCtx acl.AuthorizerContext
|
||||||
other.FillAuthzContext(&secondaryCtx)
|
other.FillAuthzContext(&secondaryCtx)
|
||||||
|
|
||||||
if authz.ServiceWrite(other.Service, &secondaryCtx) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(other.Service, &secondaryCtx); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return acl.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,8 +295,8 @@ func vetRegisterWithACL(
|
||||||
|
|
||||||
// Node-level check.
|
// Node-level check.
|
||||||
if check.ServiceID == "" {
|
if check.ServiceID == "" {
|
||||||
if authz.NodeWrite(subj.Node, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(subj.Node, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -324,8 +326,8 @@ func vetRegisterWithACL(
|
||||||
var secondaryCtx acl.AuthorizerContext
|
var secondaryCtx acl.AuthorizerContext
|
||||||
other.FillAuthzContext(&secondaryCtx)
|
other.FillAuthzContext(&secondaryCtx)
|
||||||
|
|
||||||
if authz.ServiceWrite(other.Service, &secondaryCtx) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(other.Service, &secondaryCtx); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +410,8 @@ func vetDeregisterWithACL(
|
||||||
// Allow service deregistration if the token has write permission for the node.
|
// Allow service deregistration if the token has write permission for the node.
|
||||||
// This accounts for cases where the agent no longer has a token with write permission
|
// This accounts for cases where the agent no longer has a token with write permission
|
||||||
// on the service to deregister it.
|
// on the service to deregister it.
|
||||||
if authz.NodeWrite(subj.Node, &authzContext) == acl.Allow {
|
nodeWriteErr := authz.ToAllowAuthorizer().NodeWriteAllowed(subj.Node, &authzContext)
|
||||||
|
if nodeWriteErr == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,8 +426,8 @@ func vetDeregisterWithACL(
|
||||||
|
|
||||||
ns.FillAuthzContext(&authzContext)
|
ns.FillAuthzContext(&authzContext)
|
||||||
|
|
||||||
if authz.ServiceWrite(ns.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(ns.Service, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
} else if subj.CheckID != "" {
|
} else if subj.CheckID != "" {
|
||||||
if nc == nil {
|
if nc == nil {
|
||||||
|
@ -434,18 +437,18 @@ func vetDeregisterWithACL(
|
||||||
nc.FillAuthzContext(&authzContext)
|
nc.FillAuthzContext(&authzContext)
|
||||||
|
|
||||||
if nc.ServiceID != "" {
|
if nc.ServiceID != "" {
|
||||||
if authz.ServiceWrite(nc.ServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(nc.ServiceName, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if authz.NodeWrite(subj.Node, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(subj.Node, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Since NodeWrite is not given - otherwise the earlier check
|
// Since NodeWrite is not given - otherwise the earlier check
|
||||||
// would've returned already - we can deny here.
|
// would've returned already - we can deny here.
|
||||||
return acl.ErrPermissionDenied
|
return nodeWriteErr
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -647,6 +650,8 @@ func (c *Catalog) ServiceNodes(args *structs.ServiceSpecificRequest, reply *stru
|
||||||
// If we're doing a connect query, we need read access to the service
|
// If we're doing a connect query, we need read access to the service
|
||||||
// we're trying to find proxies for, so check that.
|
// we're trying to find proxies for, so check that.
|
||||||
if args.Connect {
|
if args.Connect {
|
||||||
|
// TODO(acl-error-enhancements) can this be improved? What happens if we returned an error here?
|
||||||
|
// Is this similar to filters where we might want to return a hint?
|
||||||
if authz.ServiceRead(args.ServiceName, &authzContext) != acl.Allow {
|
if authz.ServiceRead(args.ServiceName, &authzContext) != acl.Allow {
|
||||||
// Just return nil, which will return an empty response (tested)
|
// Just return nil, which will return an empty response (tested)
|
||||||
return nil
|
return nil
|
||||||
|
@ -862,8 +867,8 @@ func (c *Catalog) GatewayServices(args *structs.ServiceSpecificRequest, reply *s
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if authz.ServiceRead(args.ServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(args.ServiceName, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.srv.blockingQuery(
|
return c.srv.blockingQuery(
|
||||||
|
@ -926,8 +931,8 @@ func (c *Catalog) VirtualIPForService(args *structs.ServiceSpecificRequest, repl
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if authz.ServiceRead(args.ServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(args.ServiceName, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
state := c.srv.fsm.State()
|
state := c.srv.fsm.State()
|
||||||
|
|
|
@ -90,7 +90,7 @@ func (c *ConfigEntry) Apply(args *structs.ConfigEntryRequest, reply *bool) error
|
||||||
}
|
}
|
||||||
|
|
||||||
if !args.Entry.CanWrite(authz) {
|
if !args.Entry.CanWrite(authz) {
|
||||||
return acl.ErrPermissionDenied
|
return acl.ErrPermissionDenied // TODO(acl-error-enhancements) Better errors await refactoring of CanWrite above.
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.Op != structs.ConfigEntryUpsert && args.Op != structs.ConfigEntryUpsertCAS {
|
if args.Op != structs.ConfigEntryUpsert && args.Op != structs.ConfigEntryUpsertCAS {
|
||||||
|
@ -439,8 +439,8 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.ServiceRead(args.Name, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(args.Name, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -65,8 +65,8 @@ func (s *ConnectCA) ConfigurationGet(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorWrite(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorWriteAllowed(nil); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
state := s.srv.fsm.State()
|
state := s.srv.fsm.State()
|
||||||
|
@ -97,8 +97,8 @@ func (s *ConnectCA) ConfigurationSet(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorWrite(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorWriteAllowed(nil); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.srv.caManager.UpdateConfiguration(args)
|
return s.srv.caManager.UpdateConfiguration(args)
|
||||||
|
@ -175,8 +175,8 @@ func (s *ConnectCA) Sign(
|
||||||
if isService {
|
if isService {
|
||||||
entMeta.Merge(serviceID.GetEnterpriseMeta())
|
entMeta.Merge(serviceID.GetEnterpriseMeta())
|
||||||
entMeta.FillAuthzContext(&authzContext)
|
entMeta.FillAuthzContext(&authzContext)
|
||||||
if authz.ServiceWrite(serviceID.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(serviceID.Service, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the DC in the service URI matches us. We might relax this
|
// Verify that the DC in the service URI matches us. We might relax this
|
||||||
|
@ -187,8 +187,8 @@ func (s *ConnectCA) Sign(
|
||||||
}
|
}
|
||||||
} else if isAgent {
|
} else if isAgent {
|
||||||
agentID.GetEnterpriseMeta().FillAuthzContext(&authzContext)
|
agentID.GetEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if authz.NodeWrite(agentID.Agent, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(agentID.Agent, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,8 +223,8 @@ func (s *ConnectCA) SignIntermediate(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorWrite(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorWriteAllowed(nil); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, _ := s.srv.caManager.getCAProvider()
|
provider, _ := s.srv.caManager.getCAProvider()
|
||||||
|
|
|
@ -152,8 +152,8 @@ func (c *Coordinate) Update(args *structs.CoordinateUpdateRequest, reply *struct
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if authz.NodeWrite(args.Node, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(args.Node, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the coordinate to the map of pending updates.
|
// Add the coordinate to the map of pending updates.
|
||||||
|
@ -245,8 +245,8 @@ func (c *Coordinate) Node(args *structs.NodeSpecificRequest, reply *structs.Inde
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if authz.NodeRead(args.Node, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeReadAllowed(args.Node, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.srv.blockingQuery(&args.QueryOptions,
|
return c.srv.blockingQuery(&args.QueryOptions,
|
||||||
|
|
|
@ -36,8 +36,8 @@ func (c *DiscoveryChain) Get(args *structs.DiscoveryChainRequest, reply *structs
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.ServiceRead(args.Name, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(args.Name, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.Name == "" {
|
if args.Name == "" {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"github.com/armon/go-metrics/prometheus"
|
"github.com/armon/go-metrics/prometheus"
|
||||||
memdb "github.com/hashicorp/go-memdb"
|
memdb "github.com/hashicorp/go-memdb"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
|
||||||
"github.com/hashicorp/consul/agent/consul/state"
|
"github.com/hashicorp/consul/agent/consul/state"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
)
|
)
|
||||||
|
@ -63,8 +62,8 @@ func (c *FederationState) Apply(args *structs.FederationStateRequest, reply *boo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorWrite(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorWriteAllowed(nil); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.State == nil || args.State.Datacenter == "" {
|
if args.State == nil || args.State.Datacenter == "" {
|
||||||
|
@ -109,8 +108,8 @@ func (c *FederationState) Get(args *structs.FederationStateQuery, reply *structs
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorRead(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorReadAllowed(nil); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.srv.blockingQuery(
|
return c.srv.blockingQuery(
|
||||||
|
@ -148,8 +147,8 @@ func (c *FederationState) List(args *structs.DCSpecificRequest, reply *structs.I
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorRead(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorReadAllowed(nil); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.srv.blockingQuery(
|
return c.srv.blockingQuery(
|
||||||
|
|
|
@ -220,6 +220,7 @@ func (h *Health) ServiceNodes(args *structs.ServiceSpecificRequest, reply *struc
|
||||||
// If we're doing a connect or ingress query, we need read access to the service
|
// If we're doing a connect or ingress query, we need read access to the service
|
||||||
// we're trying to find proxies for, so check that.
|
// we're trying to find proxies for, so check that.
|
||||||
if args.Connect || args.Ingress {
|
if args.Connect || args.Ingress {
|
||||||
|
// TODO(acl-error-enhancements) Look for ways to percolate this information up to give any feedback to the user.
|
||||||
if authz.ServiceRead(args.ServiceName, &authzContext) != acl.Allow {
|
if authz.ServiceRead(args.ServiceName, &authzContext) != acl.Allow {
|
||||||
// Just return nil, which will return an empty response (tested)
|
// Just return nil, which will return an empty response (tested)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -610,11 +610,13 @@ func (s *Intention) Match(args *structs.IntentionQueryRequest, reply *structs.In
|
||||||
// matching, if you have it on the dest then perform a dest type match.
|
// matching, if you have it on the dest then perform a dest type match.
|
||||||
for _, entry := range args.Match.Entries {
|
for _, entry := range args.Match.Entries {
|
||||||
entry.FillAuthzContext(&authzContext)
|
entry.FillAuthzContext(&authzContext)
|
||||||
if prefix := entry.Name; prefix != "" && authz.IntentionRead(prefix, &authzContext) != acl.Allow {
|
if prefix := entry.Name; prefix != "" {
|
||||||
|
if err := authz.ToAllowAuthorizer().IntentionReadAllowed(prefix, &authzContext); err != nil {
|
||||||
accessorID := authz.AccessorID()
|
accessorID := authz.AccessorID()
|
||||||
// todo(kit) Migrate intention access denial logging over to audit logging when we implement it
|
// todo(kit) Migrate intention access denial logging over to audit logging when we implement it
|
||||||
s.logger.Warn("Operation on intention prefix denied due to ACLs", "prefix", prefix, "accessorID", accessorID)
|
s.logger.Warn("Operation on intention prefix denied due to ACLs", "prefix", prefix, "accessorID", accessorID)
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,11 +735,11 @@ func (s *Intention) Check(args *structs.IntentionQueryRequest, reply *structs.In
|
||||||
if prefix, ok := query.GetACLPrefix(); ok {
|
if prefix, ok := query.GetACLPrefix(); ok {
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
query.FillAuthzContext(&authzContext)
|
query.FillAuthzContext(&authzContext)
|
||||||
if authz.ServiceRead(prefix, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(prefix, &authzContext); err != nil {
|
||||||
accessorID := authz.AccessorID()
|
accessorID := authz.AccessorID()
|
||||||
// todo(kit) Migrate intention access denial logging over to audit logging when we implement it
|
// todo(kit) Migrate intention access denial logging over to audit logging when we implement it
|
||||||
s.logger.Warn("test on intention denied due to ACLs", "prefix", prefix, "accessorID", accessorID)
|
s.logger.Warn("test on intention denied due to ACLs", "prefix", prefix, "accessorID", accessorID)
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,8 +163,8 @@ func (m *Internal) ServiceTopology(args *structs.ServiceSpecificRequest, reply *
|
||||||
if err := m.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
|
if err := m.srv.validateEnterpriseRequest(&args.EnterpriseMeta, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.ServiceRead(args.ServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(args.ServiceName, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.srv.blockingQuery(
|
return m.srv.blockingQuery(
|
||||||
|
@ -272,8 +272,8 @@ func (m *Internal) GatewayServiceDump(args *structs.ServiceSpecificRequest, repl
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need read access to the gateway we're trying to find services for, so check that first.
|
// We need read access to the gateway we're trying to find services for, so check that first.
|
||||||
if authz.ServiceRead(args.ServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(args.ServiceName, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.srv.blockingQuery(
|
err = m.srv.blockingQuery(
|
||||||
|
@ -356,8 +356,8 @@ func (m *Internal) GatewayIntentions(args *structs.IntentionQueryRequest, reply
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need read access to the gateway we're trying to find intentions for, so check that first.
|
// We need read access to the gateway we're trying to find intentions for, so check that first.
|
||||||
if authz.ServiceRead(args.Match.Entries[0].Name, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceReadAllowed(args.Match.Entries[0].Name, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.srv.blockingQuery(
|
return m.srv.blockingQuery(
|
||||||
|
@ -428,10 +428,10 @@ func (m *Internal) EventFire(args *structs.EventFireRequest,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if authz.EventWrite(args.Name, nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().EventWriteAllowed(args.Name, nil); err != nil {
|
||||||
accessorID := authz.AccessorID()
|
accessorID := authz.AccessorID()
|
||||||
m.logger.Warn("user event blocked by ACLs", "event", args.Name, "accessorID", accessorID)
|
m.logger.Warn("user event blocked by ACLs", "event", args.Name, "accessorID", accessorID)
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the query meta data
|
// Set the query meta data
|
||||||
|
@ -464,16 +464,16 @@ func (m *Internal) KeyringOperation(
|
||||||
}
|
}
|
||||||
switch args.Operation {
|
switch args.Operation {
|
||||||
case structs.KeyringList:
|
case structs.KeyringList:
|
||||||
if authz.KeyringRead(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().KeyringReadAllowed(nil); err != nil {
|
||||||
return fmt.Errorf("Reading keyring denied by ACLs")
|
return err
|
||||||
}
|
}
|
||||||
case structs.KeyringInstall:
|
case structs.KeyringInstall:
|
||||||
fallthrough
|
fallthrough
|
||||||
case structs.KeyringUse:
|
case structs.KeyringUse:
|
||||||
fallthrough
|
fallthrough
|
||||||
case structs.KeyringRemove:
|
case structs.KeyringRemove:
|
||||||
if authz.KeyringWrite(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().KeyringWriteAllowed(nil); err != nil {
|
||||||
return fmt.Errorf("Modifying keyring denied due to ACLs")
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic("Invalid keyring operation")
|
panic("Invalid keyring operation")
|
||||||
|
|
|
@ -44,8 +44,8 @@ func kvsPreApply(logger hclog.Logger, srv *Server, authz acl.Authorizer, op api.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
dirEnt.FillAuthzContext(&authzContext)
|
dirEnt.FillAuthzContext(&authzContext)
|
||||||
|
|
||||||
if authz.KeyWritePrefix(dirEnt.Key, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().KeyWritePrefixAllowed(dirEnt.Key, &authzContext); err != nil {
|
||||||
return false, acl.ErrPermissionDenied
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case api.KVGet, api.KVGetTree:
|
case api.KVGet, api.KVGetTree:
|
||||||
|
@ -58,16 +58,16 @@ func kvsPreApply(logger hclog.Logger, srv *Server, authz acl.Authorizer, op api.
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
dirEnt.FillAuthzContext(&authzContext)
|
dirEnt.FillAuthzContext(&authzContext)
|
||||||
|
|
||||||
if authz.KeyRead(dirEnt.Key, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().KeyReadAllowed(dirEnt.Key, &authzContext); err != nil {
|
||||||
return false, acl.ErrPermissionDenied
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
dirEnt.FillAuthzContext(&authzContext)
|
dirEnt.FillAuthzContext(&authzContext)
|
||||||
|
|
||||||
if authz.KeyWrite(dirEnt.Key, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().KeyWriteAllowed(dirEnt.Key, &authzContext); err != nil {
|
||||||
return false, acl.ErrPermissionDenied
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +155,8 @@ func (k *KVS) Get(args *structs.KeyRequest, reply *structs.IndexedDirEntries) er
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.KeyRead(args.Key, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().KeyReadAllowed(args.Key, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ent == nil {
|
if ent == nil {
|
||||||
|
@ -187,8 +187,10 @@ func (k *KVS) List(args *structs.KeyRequest, reply *structs.IndexedDirEntries) e
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if k.srv.config.ACLEnableKeyListPolicy && authz.KeyList(args.Key, &authzContext) != acl.Allow {
|
if k.srv.config.ACLEnableKeyListPolicy {
|
||||||
return acl.ErrPermissionDenied
|
if err := authz.ToAllowAuthorizer().KeyListAllowed(args.Key, &authzContext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return k.srv.blockingQuery(
|
return k.srv.blockingQuery(
|
||||||
|
@ -240,8 +242,10 @@ func (k *KVS) ListKeys(args *structs.KeyListRequest, reply *structs.IndexedKeyLi
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if k.srv.config.ACLEnableKeyListPolicy && authz.KeyList(args.Prefix, &authzContext) != acl.Allow {
|
if k.srv.config.ACLEnableKeyListPolicy {
|
||||||
return acl.ErrPermissionDenied
|
if err := authz.ToAllowAuthorizer().KeyListAllowed(args.Prefix, &authzContext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return k.srv.blockingQuery(
|
return k.srv.blockingQuery(
|
||||||
|
|
|
@ -2,11 +2,9 @@ package consul
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
autopilot "github.com/hashicorp/raft-autopilot"
|
autopilot "github.com/hashicorp/raft-autopilot"
|
||||||
"github.com/hashicorp/serf/serf"
|
"github.com/hashicorp/serf/serf"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,8 +22,9 @@ func (op *Operator) AutopilotGetConfiguration(args *structs.DCSpecificRequest, r
|
||||||
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorRead(nil) != acl.Allow {
|
|
||||||
return acl.PermissionDeniedByACLUnnamed(authz, nil, acl.ResourceOperator, acl.AccessRead)
|
if err := authz.ToAllowAuthorizer().OperatorReadAllowed(nil); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
state := op.srv.fsm.State()
|
state := op.srv.fsm.State()
|
||||||
|
@ -56,8 +55,9 @@ func (op *Operator) AutopilotSetConfiguration(args *structs.AutopilotSetConfigRe
|
||||||
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorWrite(nil) != acl.Allow {
|
|
||||||
return acl.PermissionDeniedByACLUnnamed(authz, nil, acl.ResourceOperator, acl.AccessWrite)
|
if err := authz.ToAllowAuthorizer().OperatorWriteAllowed(nil); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the update
|
// Apply the update
|
||||||
|
@ -91,8 +91,9 @@ func (op *Operator) ServerHealth(args *structs.DCSpecificRequest, reply *structs
|
||||||
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorRead(nil) != acl.Allow {
|
|
||||||
return acl.PermissionDeniedByACLUnnamed(authz, nil, acl.ResourceOperator, acl.AccessRead)
|
if err := authz.ToAllowAuthorizer().OperatorReadAllowed(nil); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
state := op.srv.autopilot.GetState()
|
state := op.srv.autopilot.GetState()
|
||||||
|
@ -158,8 +159,9 @@ func (op *Operator) AutopilotState(args *structs.DCSpecificRequest, reply *autop
|
||||||
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorRead(nil) != acl.Allow {
|
|
||||||
return acl.PermissionDeniedByACLUnnamed(authz, nil, acl.ResourceOperator, acl.AccessRead)
|
if err := authz.ToAllowAuthorizer().OperatorReadAllowed(nil); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
state := op.srv.autopilot.GetState()
|
state := op.srv.autopilot.GetState()
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"github.com/hashicorp/raft"
|
"github.com/hashicorp/raft"
|
||||||
"github.com/hashicorp/serf/serf"
|
"github.com/hashicorp/serf/serf"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
|
||||||
"github.com/hashicorp/consul/agent/metadata"
|
"github.com/hashicorp/consul/agent/metadata"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
)
|
)
|
||||||
|
@ -23,8 +22,8 @@ func (op *Operator) RaftGetConfiguration(args *structs.DCSpecificRequest, reply
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorRead(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorReadAllowed(nil); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can't fetch the leader and the configuration atomically with
|
// We can't fetch the leader and the configuration atomically with
|
||||||
|
@ -88,8 +87,8 @@ func (op *Operator) RaftRemovePeerByAddress(args *structs.RaftRemovePeerRequest,
|
||||||
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorWrite(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorWriteAllowed(nil); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since this is an operation designed for humans to use, we will return
|
// Since this is an operation designed for humans to use, we will return
|
||||||
|
@ -141,8 +140,8 @@ func (op *Operator) RaftRemovePeerByID(args *structs.RaftRemovePeerRequest, repl
|
||||||
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
if err := op.srv.validateEnterpriseToken(authz.Identity()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if authz.OperatorWrite(nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().OperatorWriteAllowed(nil); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since this is an operation designed for humans to use, we will return
|
// Since this is an operation designed for humans to use, we will return
|
||||||
|
|
|
@ -86,9 +86,9 @@ func (p *PreparedQuery) Apply(args *structs.PreparedQueryRequest, reply *string)
|
||||||
// need to make sure they have write access for whatever they are
|
// need to make sure they have write access for whatever they are
|
||||||
// proposing.
|
// proposing.
|
||||||
if prefix, ok := args.Query.GetACLPrefix(); ok {
|
if prefix, ok := args.Query.GetACLPrefix(); ok {
|
||||||
if authz.PreparedQueryWrite(prefix, nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().PreparedQueryWriteAllowed(prefix, nil); err != nil {
|
||||||
p.logger.Warn("Operation on prepared query denied due to ACLs", "query", args.Query.ID)
|
p.logger.Warn("Operation on prepared query denied due to ACLs", "query", args.Query.ID)
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,9 +106,9 @@ func (p *PreparedQuery) Apply(args *structs.PreparedQueryRequest, reply *string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if prefix, ok := query.GetACLPrefix(); ok {
|
if prefix, ok := query.GetACLPrefix(); ok {
|
||||||
if authz.PreparedQueryWrite(prefix, nil) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().PreparedQueryWriteAllowed(prefix, nil); err != nil {
|
||||||
p.logger.Warn("Operation on prepared query denied due to ACLs", "query", args.Query.ID)
|
p.logger.Warn("Operation on prepared query denied due to ACLs", "query", args.Query.ID)
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,13 +82,13 @@ func (s *Session) Apply(args *structs.SessionRequest, reply *string) error {
|
||||||
if existing == nil {
|
if existing == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if authz.SessionWrite(existing.Node, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().SessionWriteAllowed(existing.Node, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case structs.SessionCreate:
|
case structs.SessionCreate:
|
||||||
if authz.SessionWrite(args.Session.Node, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().SessionWriteAllowed(args.Session.Node, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -303,8 +303,8 @@ func (s *Session) Renew(args *structs.SessionSpecificRequest,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if authz.SessionWrite(session.Node, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().SessionWriteAllowed(session.Node, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the session TTL timer.
|
// Reset the session TTL timer.
|
||||||
|
|
|
@ -18,7 +18,6 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/consul-net-rpc/go-msgpack/codec"
|
"github.com/hashicorp/consul-net-rpc/go-msgpack/codec"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
|
||||||
"github.com/hashicorp/consul/agent/pool"
|
"github.com/hashicorp/consul/agent/pool"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
"github.com/hashicorp/consul/snapshot"
|
"github.com/hashicorp/consul/snapshot"
|
||||||
|
@ -62,8 +61,8 @@ func (s *Server) dispatchSnapshotRequest(args *structs.SnapshotRequest, in io.Re
|
||||||
// all the ACLs and you could escalate from there.
|
// all the ACLs and you could escalate from there.
|
||||||
if authz, err := s.ResolveToken(args.Token); err != nil {
|
if authz, err := s.ResolveToken(args.Token); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if authz.Snapshot(nil) != acl.Allow {
|
} else if err := authz.ToAllowAuthorizer().SnapshotAllowed(nil); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch the operation.
|
// Dispatch the operation.
|
||||||
|
|
|
@ -113,8 +113,8 @@ func vetNodeTxnOp(op *structs.TxnNodeOp, authz acl.Authorizer) error {
|
||||||
var authzContext acl.AuthorizerContext
|
var authzContext acl.AuthorizerContext
|
||||||
op.FillAuthzContext(&authzContext)
|
op.FillAuthzContext(&authzContext)
|
||||||
|
|
||||||
if authz.NodeWrite(op.Node.Node, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(op.Node.Node, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -126,13 +126,13 @@ func vetCheckTxnOp(op *structs.TxnCheckOp, authz acl.Authorizer) error {
|
||||||
|
|
||||||
if op.Check.ServiceID == "" {
|
if op.Check.ServiceID == "" {
|
||||||
// Node-level check.
|
// Node-level check.
|
||||||
if authz.NodeWrite(op.Check.Node, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeWriteAllowed(op.Check.Node, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Service-level check.
|
// Service-level check.
|
||||||
if authz.ServiceWrite(op.Check.ServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(op.Check.ServiceName, &authzContext); err != nil {
|
||||||
return acl.ErrPermissionDenied
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -554,57 +554,64 @@ func TestTxn_Apply_ACLDeny(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the transaction's return value.
|
// Verify the transaction's return value.
|
||||||
var expected structs.TxnResponse
|
var outPos int
|
||||||
for i, op := range arg.Ops {
|
for i, op := range arg.Ops {
|
||||||
|
err := out.Errors[outPos]
|
||||||
switch {
|
switch {
|
||||||
case op.KV != nil:
|
case op.KV != nil:
|
||||||
switch op.KV.Verb {
|
switch op.KV.Verb {
|
||||||
case api.KVGet, api.KVGetTree:
|
case api.KVGet, api.KVGetTree:
|
||||||
// These get filtered but won't result in an error.
|
// These get filtered but won't result in an error.
|
||||||
|
case api.KVSet, api.KVDelete, api.KVDeleteCAS, api.KVDeleteTree, api.KVCAS, api.KVLock, api.KVUnlock, api.KVCheckNotExists:
|
||||||
|
require.Equal(t, err.OpIndex, i)
|
||||||
|
acl.RequirePermissionDeniedMessage(t, err.What, nil, nil, acl.ResourceKey, acl.AccessWrite, "nope")
|
||||||
|
outPos++
|
||||||
default:
|
default:
|
||||||
expected.Errors = append(expected.Errors, &structs.TxnError{
|
require.Equal(t, err.OpIndex, i)
|
||||||
OpIndex: i,
|
acl.RequirePermissionDeniedMessage(t, err.What, nil, nil, acl.ResourceKey, acl.AccessRead, "nope")
|
||||||
What: acl.ErrPermissionDenied.Error(),
|
outPos++
|
||||||
})
|
|
||||||
}
|
}
|
||||||
case op.Node != nil:
|
case op.Node != nil:
|
||||||
switch op.Node.Verb {
|
switch op.Node.Verb {
|
||||||
case api.NodeGet:
|
case api.NodeGet:
|
||||||
// These get filtered but won't result in an error.
|
// These get filtered but won't result in an error.
|
||||||
|
case api.NodeSet, api.NodeDelete, api.NodeDeleteCAS, api.NodeCAS:
|
||||||
|
require.Equal(t, err.OpIndex, i)
|
||||||
|
acl.RequirePermissionDeniedMessage(t, err.What, nil, nil, acl.ResourceNode, acl.AccessWrite, "nope")
|
||||||
|
outPos++
|
||||||
default:
|
default:
|
||||||
expected.Errors = append(expected.Errors, &structs.TxnError{
|
require.Equal(t, err.OpIndex, i)
|
||||||
OpIndex: i,
|
acl.RequirePermissionDeniedMessage(t, err.What, nil, nil, acl.ResourceNode, acl.AccessRead, "nope")
|
||||||
What: acl.ErrPermissionDenied.Error(),
|
outPos++
|
||||||
})
|
|
||||||
}
|
}
|
||||||
case op.Service != nil:
|
case op.Service != nil:
|
||||||
switch op.Service.Verb {
|
switch op.Service.Verb {
|
||||||
case api.ServiceGet:
|
case api.ServiceGet:
|
||||||
// These get filtered but won't result in an error.
|
// These get filtered but won't result in an error.
|
||||||
|
case api.ServiceSet, api.ServiceCAS, api.ServiceDelete, api.ServiceDeleteCAS:
|
||||||
|
require.Equal(t, err.OpIndex, i)
|
||||||
|
acl.RequirePermissionDeniedMessage(t, err.What, nil, nil, acl.ResourceService, acl.AccessWrite, "nope")
|
||||||
|
outPos++
|
||||||
default:
|
default:
|
||||||
expected.Errors = append(expected.Errors, &structs.TxnError{
|
require.Equal(t, err.OpIndex, i)
|
||||||
OpIndex: i,
|
acl.RequirePermissionDeniedMessage(t, err.What, nil, nil, acl.ResourceService, acl.AccessRead, "nope")
|
||||||
What: acl.ErrPermissionDenied.Error(),
|
outPos++
|
||||||
})
|
|
||||||
}
|
}
|
||||||
case op.Check != nil:
|
case op.Check != nil:
|
||||||
switch op.Check.Verb {
|
switch op.Check.Verb {
|
||||||
case api.CheckGet:
|
case api.CheckGet:
|
||||||
// These get filtered but won't result in an error.
|
// These get filtered but won't result in an error.
|
||||||
|
case api.CheckSet, api.CheckCAS, api.CheckDelete, api.CheckDeleteCAS:
|
||||||
|
require.Equal(t, err.OpIndex, i)
|
||||||
|
acl.RequirePermissionDeniedMessage(t, err.What, nil, nil, acl.ResourceNode, acl.AccessWrite, "nope")
|
||||||
|
outPos++
|
||||||
default:
|
default:
|
||||||
expected.Errors = append(expected.Errors, &structs.TxnError{
|
require.Equal(t, err.OpIndex, i)
|
||||||
OpIndex: i,
|
acl.RequirePermissionDeniedMessage(t, err.What, nil, nil, acl.ResourceNode, acl.AccessRead, "nope")
|
||||||
What: acl.ErrPermissionDenied.Error(),
|
outPos++
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(t, expected, out)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTxn_Apply_LockDelay(t *testing.T) {
|
func TestTxn_Apply_LockDelay(t *testing.T) {
|
||||||
|
@ -927,10 +934,9 @@ func TestTxn_Read_ACLDeny(t *testing.T) {
|
||||||
var out structs.TxnReadResponse
|
var out structs.TxnReadResponse
|
||||||
err := msgpackrpc.CallWithCodec(codec, "Txn.Read", &arg, &out)
|
err := msgpackrpc.CallWithCodec(codec, "Txn.Read", &arg, &out)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, structs.TxnErrors{
|
acl.RequirePermissionDeniedMessage(t, out.Errors[0].What, nil, nil, acl.ResourceKey, acl.AccessRead, "nope")
|
||||||
{OpIndex: 0, What: acl.ErrPermissionDenied.Error()},
|
acl.RequirePermissionDeniedMessage(t, out.Errors[1].What, nil, nil, acl.ResourceKey, acl.AccessRead, "nope")
|
||||||
{OpIndex: 1, What: acl.ErrPermissionDenied.Error()},
|
|
||||||
}, out.Errors)
|
|
||||||
require.Empty(t, out.Results)
|
require.Empty(t, out.Results)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,6 +273,7 @@ func (s *HTTPHandlers) handler(enableDebug bool) http.Handler {
|
||||||
// If the token provided does not have the necessary permissions,
|
// If the token provided does not have the necessary permissions,
|
||||||
// write a forbidden response
|
// write a forbidden response
|
||||||
// TODO(partitions): should this be possible in a partition?
|
// TODO(partitions): should this be possible in a partition?
|
||||||
|
// TODO((acl-error-enhancements)): We should return error details somehow here.
|
||||||
if authz.OperatorRead(nil) != acl.Allow {
|
if authz.OperatorRead(nil) != acl.Allow {
|
||||||
resp.WriteHeader(http.StatusForbidden)
|
resp.WriteHeader(http.StatusForbidden)
|
||||||
return
|
return
|
||||||
|
|
|
@ -642,8 +642,11 @@ func (s *HTTPHandlers) UIMetricsProxy(resp http.ResponseWriter, req *http.Reques
|
||||||
wildcardEntMeta := structs.WildcardEnterpriseMetaInPartition(structs.WildcardSpecifier)
|
wildcardEntMeta := structs.WildcardEnterpriseMetaInPartition(structs.WildcardSpecifier)
|
||||||
wildcardEntMeta.FillAuthzContext(&authzContext)
|
wildcardEntMeta.FillAuthzContext(&authzContext)
|
||||||
|
|
||||||
if authz.NodeReadAll(&authzContext) != acl.Allow || authz.ServiceReadAll(&authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().NodeReadAllAllowed(&authzContext); err != nil {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := authz.ToAllowAuthorizer().ServiceReadAllAllowed(&authzContext); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log := s.agent.logger.Named(logging.UIMetricsProxy)
|
log := s.agent.logger.Named(logging.UIMetricsProxy)
|
||||||
|
|
|
@ -1156,7 +1156,10 @@ func TestServer_DeltaAggregatedResources_v3_ACLEnforcement(t *testing.T) {
|
||||||
case err := <-errCh:
|
case err := <-errCh:
|
||||||
if tt.wantDenied {
|
if tt.wantDenied {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Contains(t, err.Error(), "permission denied")
|
status, ok := status.FromError(err)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, codes.PermissionDenied, status.Code())
|
||||||
|
require.Contains(t, err.Error(), "Permission denied")
|
||||||
mgr.AssertWatchCancelled(t, sid)
|
mgr.AssertWatchCancelled(t, sid)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -266,7 +266,7 @@ func (s *Server) authorize(ctx context.Context, cfgSnap *proxycfg.ConfigSnapshot
|
||||||
if acl.IsErrNotFound(err) {
|
if acl.IsErrNotFound(err) {
|
||||||
return status.Errorf(codes.Unauthenticated, "unauthenticated: %v", err)
|
return status.Errorf(codes.Unauthenticated, "unauthenticated: %v", err)
|
||||||
} else if acl.IsErrPermissionDenied(err) {
|
} else if acl.IsErrPermissionDenied(err) {
|
||||||
return status.Errorf(codes.PermissionDenied, "permission denied: %v", err)
|
return status.Error(codes.PermissionDenied, err.Error())
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return status.Errorf(codes.Internal, "error resolving acl token: %v", err)
|
return status.Errorf(codes.Internal, "error resolving acl token: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -275,13 +275,13 @@ func (s *Server) authorize(ctx context.Context, cfgSnap *proxycfg.ConfigSnapshot
|
||||||
switch cfgSnap.Kind {
|
switch cfgSnap.Kind {
|
||||||
case structs.ServiceKindConnectProxy:
|
case structs.ServiceKindConnectProxy:
|
||||||
cfgSnap.ProxyID.EnterpriseMeta.FillAuthzContext(&authzContext)
|
cfgSnap.ProxyID.EnterpriseMeta.FillAuthzContext(&authzContext)
|
||||||
if authz.ServiceWrite(cfgSnap.Proxy.DestinationServiceName, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(cfgSnap.Proxy.DestinationServiceName, &authzContext); err != nil {
|
||||||
return status.Errorf(codes.PermissionDenied, "permission denied")
|
return status.Errorf(codes.PermissionDenied, err.Error())
|
||||||
}
|
}
|
||||||
case structs.ServiceKindMeshGateway, structs.ServiceKindTerminatingGateway, structs.ServiceKindIngressGateway:
|
case structs.ServiceKindMeshGateway, structs.ServiceKindTerminatingGateway, structs.ServiceKindIngressGateway:
|
||||||
cfgSnap.ProxyID.EnterpriseMeta.FillAuthzContext(&authzContext)
|
cfgSnap.ProxyID.EnterpriseMeta.FillAuthzContext(&authzContext)
|
||||||
if authz.ServiceWrite(cfgSnap.Service, &authzContext) != acl.Allow {
|
if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(cfgSnap.Service, &authzContext); err != nil {
|
||||||
return status.Errorf(codes.PermissionDenied, "permission denied")
|
return status.Errorf(codes.PermissionDenied, err.Error())
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return status.Errorf(codes.Internal, "Invalid service kind")
|
return status.Errorf(codes.Internal, "Invalid service kind")
|
||||||
|
|
Loading…
Reference in New Issue