From d03f849e496b6ceecb56e5e3c8dbf45d458c196c Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Fri, 22 Oct 2021 04:41:35 -0700 Subject: [PATCH] acl: Expand ServiceRead logic to look at service-exports for cross-partition --- acl/authorizer.go | 3 +++ acl/authorizer_test.go | 5 +++++ acl/chained_authorizer.go | 6 ++++++ acl/chained_authorizer_test.go | 3 +++ acl/policy_authorizer.go | 4 ++++ acl/static_authorizer.go | 7 +++++++ agent/consul/acl.go | 7 ++++++- 7 files changed, 34 insertions(+), 1 deletion(-) diff --git a/acl/authorizer.go b/acl/authorizer.go index 43d50544bf..427eb1a162 100644 --- a/acl/authorizer.go +++ b/acl/authorizer.go @@ -149,6 +149,9 @@ type Authorizer interface { // service ServiceWrite(string, *AuthorizerContext) EnforcementDecision + // ServiceWriteAny checks for permission to read any service + ServiceWriteAny(*AuthorizerContext) EnforcementDecision + // SessionRead checks for permission to read sessions for a given node. SessionRead(string, *AuthorizerContext) EnforcementDecision diff --git a/acl/authorizer_test.go b/acl/authorizer_test.go index d74029f239..7d32a78bf7 100644 --- a/acl/authorizer_test.go +++ b/acl/authorizer_test.go @@ -185,6 +185,11 @@ func (m *mockAuthorizer) ServiceWrite(segment string, ctx *AuthorizerContext) En return ret.Get(0).(EnforcementDecision) } +func (m *mockAuthorizer) ServiceWriteAny(ctx *AuthorizerContext) EnforcementDecision { + ret := m.Called(ctx) + return ret.Get(0).(EnforcementDecision) +} + // SessionRead checks for permission to read sessions for a given node. func (m *mockAuthorizer) SessionRead(segment string, ctx *AuthorizerContext) EnforcementDecision { ret := m.Called(segment, ctx) diff --git a/acl/chained_authorizer.go b/acl/chained_authorizer.go index 1b3aed4978..33a05f9f1e 100644 --- a/acl/chained_authorizer.go +++ b/acl/chained_authorizer.go @@ -235,6 +235,12 @@ func (c *ChainedAuthorizer) ServiceWrite(name string, entCtx *AuthorizerContext) }) } +func (c *ChainedAuthorizer) ServiceWriteAny(entCtx *AuthorizerContext) EnforcementDecision { + return c.executeChain(func(authz Authorizer) EnforcementDecision { + return authz.ServiceWriteAny(entCtx) + }) +} + // SessionRead checks for permission to read sessions for a given node. func (c *ChainedAuthorizer) SessionRead(node string, entCtx *AuthorizerContext) EnforcementDecision { return c.executeChain(func(authz Authorizer) EnforcementDecision { diff --git a/acl/chained_authorizer_test.go b/acl/chained_authorizer_test.go index 7a1aba2396..ac4880ba09 100644 --- a/acl/chained_authorizer_test.go +++ b/acl/chained_authorizer_test.go @@ -89,6 +89,9 @@ func (authz testAuthorizer) ServiceReadAll(*AuthorizerContext) EnforcementDecisi func (authz testAuthorizer) ServiceWrite(string, *AuthorizerContext) EnforcementDecision { return EnforcementDecision(authz) } +func (authz testAuthorizer) ServiceWriteAny(*AuthorizerContext) EnforcementDecision { + return EnforcementDecision(authz) +} func (authz testAuthorizer) SessionRead(string, *AuthorizerContext) EnforcementDecision { return EnforcementDecision(authz) } diff --git a/acl/policy_authorizer.go b/acl/policy_authorizer.go index 8cce120eb6..0e9496bf78 100644 --- a/acl/policy_authorizer.go +++ b/acl/policy_authorizer.go @@ -767,6 +767,10 @@ func (p *policyAuthorizer) ServiceWrite(name string, _ *AuthorizerContext) Enfor return Default } +func (p *policyAuthorizer) ServiceWriteAny(_ *AuthorizerContext) EnforcementDecision { + return p.anyAllowed(p.serviceRules, AccessWrite) +} + // SessionRead checks for permission to read sessions for a given node. func (p *policyAuthorizer) SessionRead(node string, _ *AuthorizerContext) EnforcementDecision { if rule, ok := getPolicy(node, p.sessionRules); ok { diff --git a/acl/static_authorizer.go b/acl/static_authorizer.go index f257d6b68a..2837b8f0ac 100644 --- a/acl/static_authorizer.go +++ b/acl/static_authorizer.go @@ -219,6 +219,13 @@ func (s *staticAuthorizer) ServiceWrite(string, *AuthorizerContext) EnforcementD return Deny } +func (s *staticAuthorizer) ServiceWriteAny(*AuthorizerContext) EnforcementDecision { + if s.defaultAllow { + return Allow + } + return Deny +} + func (s *staticAuthorizer) SessionRead(string, *AuthorizerContext) EnforcementDecision { if s.defaultAllow { return Allow diff --git a/agent/consul/acl.go b/agent/consul/acl.go index 2bbe961d16..73a181becf 100644 --- a/agent/consul/acl.go +++ b/agent/consul/acl.go @@ -1090,8 +1090,13 @@ func (r *ACLResolver) ResolveTokenToIdentityAndAuthorizer(token string) (structs // Build the Authorizer var chain []acl.Authorizer + var conf acl.Config + if r.aclConf != nil { + conf = *r.aclConf + } + conf.LocalPartition = identity.EnterpriseMetadata().PartitionOrDefault() - authz, err := policies.Compile(r.cache, r.aclConf) + authz, err := policies.Compile(r.cache, &conf) if err != nil { return nil, nil, err }