Miscellaneous Fixes (#6896)

Ensure we close the Sentinel Evaluator so as not to leak go routines

Fix a bunch of test logging so that various warnings when starting a test agent go to the ltest logger and not straight to stdout.

Various canned ent meta types always return a valid pointer (no more nils). This allows us to blindly deref + assign in various places.

Update ACL index tracking to ensure oss -> ent upgrades will work as expected.

Update ent meta parsing to include function to disallow wildcarding.
pull/6898/head
Matt Keeler 2019-12-06 14:01:34 -05:00 committed by GitHub
parent a704ebe639
commit 8f0ab0129e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 130 additions and 117 deletions

View File

@ -4,3 +4,5 @@ package acl
// EnterpriseACLConfig stub // EnterpriseACLConfig stub
type EnterpriseACLConfig struct{} type EnterpriseACLConfig struct{}
func (_ *EnterpriseACLConfig) Close() {}

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"os"
"testing" "testing"
"time" "time"
@ -16,6 +15,7 @@ import (
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/logger" "github.com/hashicorp/consul/logger"
"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/types" "github.com/hashicorp/consul/types"
"github.com/hashicorp/serf/serf" "github.com/hashicorp/serf/serf"
@ -55,28 +55,27 @@ type TestACLAgent struct {
// NewTestACLAGent does just enough so that all the code within agent/acl.go can work // NewTestACLAGent does just enough so that all the code within agent/acl.go can work
// Basically it needs a local state for some of the vet* functions, a logger and a delegate. // Basically it needs a local state for some of the vet* functions, a logger and a delegate.
// The key is that we are the delegate so we can control the ResolveToken responses // The key is that we are the delegate so we can control the ResolveToken responses
func NewTestACLAgent(name string, hcl string, resolveFn func(string) (acl.Authorizer, error)) *TestACLAgent { func NewTestACLAgent(t *testing.T, name string, hcl string, resolveFn func(string) (acl.Authorizer, error)) *TestACLAgent {
a := &TestACLAgent{Name: name, HCL: hcl, resolveTokenFn: resolveFn} a := &TestACLAgent{Name: name, HCL: hcl, resolveTokenFn: resolveFn}
hclDataDir := `data_dir = "acl-agent"` hclDataDir := `data_dir = "acl-agent"`
a.Config = TestConfig( logOutput := testutil.TestWriter(t)
logger := log.New(logOutput, a.Name+" - ", log.LstdFlags|log.Lmicroseconds)
a.Config = TestConfig(logger,
config.Source{Name: a.Name, Format: "hcl", Data: a.HCL}, config.Source{Name: a.Name, Format: "hcl", Data: a.HCL},
config.Source{Name: a.Name + ".data_dir", Format: "hcl", Data: hclDataDir}, config.Source{Name: a.Name + ".data_dir", Format: "hcl", Data: hclDataDir},
) )
agent, err := New(a.Config, nil) agent, err := New(a.Config, logger)
if err != nil { if err != nil {
panic(fmt.Sprintf("Error creating agent: %v", err)) panic(fmt.Sprintf("Error creating agent: %v", err))
} }
a.Agent = agent a.Agent = agent
logOutput := a.LogOutput
if logOutput == nil {
logOutput = os.Stderr
}
agent.LogOutput = logOutput agent.LogOutput = logOutput
agent.LogWriter = a.LogWriter agent.LogWriter = a.LogWriter
agent.logger = log.New(logOutput, a.Name+" - ", log.LstdFlags|log.Lmicroseconds) agent.logger = logger
agent.MemSink = metrics.NewInmemSink(1*time.Second, time.Minute) agent.MemSink = metrics.NewInmemSink(1*time.Second, time.Minute)
a.Agent.delegate = a a.Agent.delegate = a
@ -156,7 +155,7 @@ func TestACL_Version8(t *testing.T) {
return nil, fmt.Errorf("should not have called delegate.ResolveToken") return nil, fmt.Errorf("should not have called delegate.ResolveToken")
} }
a := NewTestACLAgent(t.Name(), TestACLConfig()+` a := NewTestACLAgent(t, t.Name(), TestACLConfig()+`
acl_enforce_version_8 = false acl_enforce_version_8 = false
`, resolveFn) `, resolveFn)
@ -171,7 +170,7 @@ func TestACL_Version8(t *testing.T) {
called = true called = true
return nil, acl.ErrNotFound return nil, acl.ErrNotFound
} }
a := NewTestACLAgent(t.Name(), TestACLConfig()+` a := NewTestACLAgent(t, t.Name(), TestACLConfig()+`
acl_enforce_version_8 = true acl_enforce_version_8 = true
`, resolveFn) `, resolveFn)
@ -189,7 +188,7 @@ func TestACL_AgentMasterToken(t *testing.T) {
return nil, fmt.Errorf("should not have called delegate.ResolveToken") return nil, fmt.Errorf("should not have called delegate.ResolveToken")
} }
a := NewTestACLAgent(t.Name(), TestACLConfig(), resolveFn) a := NewTestACLAgent(t, t.Name(), TestACLConfig(), resolveFn)
a.loadTokens(a.config) a.loadTokens(a.config)
authz, err := a.resolveToken("towel") authz, err := a.resolveToken("towel")
require.NotNil(t, authz) require.NotNil(t, authz)
@ -209,7 +208,7 @@ func TestACL_RootAuthorizersDenied(t *testing.T) {
return nil, fmt.Errorf("should not have called delegate.ResolveToken") return nil, fmt.Errorf("should not have called delegate.ResolveToken")
} }
a := NewTestACLAgent(t.Name(), TestACLConfig(), resolveFn) a := NewTestACLAgent(t, t.Name(), TestACLConfig(), resolveFn)
authz, err := a.resolveToken("deny") authz, err := a.resolveToken("deny")
require.Nil(t, authz) require.Nil(t, authz)
require.Error(t, err) require.Error(t, err)
@ -224,8 +223,8 @@ func TestACL_RootAuthorizersDenied(t *testing.T) {
require.True(t, acl.IsErrRootDenied(err)) require.True(t, acl.IsErrRootDenied(err))
} }
func authzFromPolicy(policy *acl.Policy) (acl.Authorizer, error) { func authzFromPolicy(policy *acl.Policy, cfg *acl.EnterpriseACLConfig) (acl.Authorizer, error) {
return acl.NewPolicyAuthorizerWithDefaults(acl.DenyAll(), []*acl.Policy{policy}, nil) return acl.NewPolicyAuthorizerWithDefaults(acl.DenyAll(), []*acl.Policy{policy}, cfg)
} }
// catalogPolicy supplies some standard policies to help with testing the // catalogPolicy supplies some standard policies to help with testing the
@ -240,7 +239,7 @@ func catalogPolicy(token string) (acl.Authorizer, error) {
&acl.NodeRule{Name: "Node", Policy: "read"}, &acl.NodeRule{Name: "Node", Policy: "read"},
}, },
}, },
}) }, nil)
case "node-rw": case "node-rw":
return authzFromPolicy(&acl.Policy{ return authzFromPolicy(&acl.Policy{
PolicyRules: acl.PolicyRules{ PolicyRules: acl.PolicyRules{
@ -248,7 +247,7 @@ func catalogPolicy(token string) (acl.Authorizer, error) {
&acl.NodeRule{Name: "Node", Policy: "write"}, &acl.NodeRule{Name: "Node", Policy: "write"},
}, },
}, },
}) }, nil)
case "service-ro": case "service-ro":
return authzFromPolicy(&acl.Policy{ return authzFromPolicy(&acl.Policy{
PolicyRules: acl.PolicyRules{ PolicyRules: acl.PolicyRules{
@ -256,7 +255,7 @@ func catalogPolicy(token string) (acl.Authorizer, error) {
&acl.ServiceRule{Name: "service", Policy: "read"}, &acl.ServiceRule{Name: "service", Policy: "read"},
}, },
}, },
}) }, nil)
case "service-rw": case "service-rw":
return authzFromPolicy(&acl.Policy{ return authzFromPolicy(&acl.Policy{
PolicyRules: acl.PolicyRules{ PolicyRules: acl.PolicyRules{
@ -264,7 +263,7 @@ func catalogPolicy(token string) (acl.Authorizer, error) {
&acl.ServiceRule{Name: "service", Policy: "write"}, &acl.ServiceRule{Name: "service", Policy: "write"},
}, },
}, },
}) }, nil)
case "other-rw": case "other-rw":
return authzFromPolicy(&acl.Policy{ return authzFromPolicy(&acl.Policy{
PolicyRules: acl.PolicyRules{ PolicyRules: acl.PolicyRules{
@ -272,7 +271,7 @@ func catalogPolicy(token string) (acl.Authorizer, error) {
&acl.ServiceRule{Name: "other", Policy: "write"}, &acl.ServiceRule{Name: "other", Policy: "write"},
}, },
}, },
}) }, nil)
default: default:
return nil, fmt.Errorf("unknown token %q", token) return nil, fmt.Errorf("unknown token %q", token)
} }
@ -280,7 +279,7 @@ func catalogPolicy(token string) (acl.Authorizer, error) {
func TestACL_vetServiceRegister(t *testing.T) { func TestACL_vetServiceRegister(t *testing.T) {
t.Parallel() t.Parallel()
a := NewTestACLAgent(t.Name(), TestACLConfig(), catalogPolicy) a := NewTestACLAgent(t, t.Name(), TestACLConfig(), catalogPolicy)
// Register a new service, with permission. // Register a new service, with permission.
err := a.vetServiceRegister("service-rw", &structs.NodeService{ err := a.vetServiceRegister("service-rw", &structs.NodeService{
@ -311,7 +310,7 @@ func TestACL_vetServiceRegister(t *testing.T) {
func TestACL_vetServiceUpdate(t *testing.T) { func TestACL_vetServiceUpdate(t *testing.T) {
t.Parallel() t.Parallel()
a := NewTestACLAgent(t.Name(), TestACLConfig(), catalogPolicy) a := NewTestACLAgent(t, t.Name(), TestACLConfig(), catalogPolicy)
// Update a service that doesn't exist. // Update a service that doesn't exist.
err := a.vetServiceUpdate("service-rw", "my-service") err := a.vetServiceUpdate("service-rw", "my-service")
@ -334,7 +333,7 @@ func TestACL_vetServiceUpdate(t *testing.T) {
func TestACL_vetCheckRegister(t *testing.T) { func TestACL_vetCheckRegister(t *testing.T) {
t.Parallel() t.Parallel()
a := NewTestACLAgent(t.Name(), TestACLConfig(), catalogPolicy) a := NewTestACLAgent(t, t.Name(), TestACLConfig(), catalogPolicy)
// Register a new service check with write privs. // Register a new service check with write privs.
err := a.vetCheckRegister("service-rw", &structs.HealthCheck{ err := a.vetCheckRegister("service-rw", &structs.HealthCheck{
@ -400,7 +399,7 @@ func TestACL_vetCheckRegister(t *testing.T) {
func TestACL_vetCheckUpdate(t *testing.T) { func TestACL_vetCheckUpdate(t *testing.T) {
t.Parallel() t.Parallel()
a := NewTestACLAgent(t.Name(), TestACLConfig(), catalogPolicy) a := NewTestACLAgent(t, t.Name(), TestACLConfig(), catalogPolicy)
// Update a check that doesn't exist. // Update a check that doesn't exist.
err := a.vetCheckUpdate("node-rw", "my-check") err := a.vetCheckUpdate("node-rw", "my-check")
@ -440,7 +439,7 @@ func TestACL_vetCheckUpdate(t *testing.T) {
func TestACL_filterMembers(t *testing.T) { func TestACL_filterMembers(t *testing.T) {
t.Parallel() t.Parallel()
a := NewTestACLAgent(t.Name(), TestACLConfig(), catalogPolicy) a := NewTestACLAgent(t, t.Name(), TestACLConfig(), catalogPolicy)
var members []serf.Member var members []serf.Member
require.NoError(t, a.filterMembers("node-ro", &members)) require.NoError(t, a.filterMembers("node-ro", &members))
@ -459,7 +458,7 @@ func TestACL_filterMembers(t *testing.T) {
func TestACL_filterServices(t *testing.T) { func TestACL_filterServices(t *testing.T) {
t.Parallel() t.Parallel()
a := NewTestACLAgent(t.Name(), TestACLConfig(), catalogPolicy) a := NewTestACLAgent(t, t.Name(), TestACLConfig(), catalogPolicy)
services := make(map[string]*structs.NodeService) services := make(map[string]*structs.NodeService)
require.NoError(t, a.filterServices("node-ro", &services)) require.NoError(t, a.filterServices("node-ro", &services))
@ -473,7 +472,7 @@ func TestACL_filterServices(t *testing.T) {
func TestACL_filterChecks(t *testing.T) { func TestACL_filterChecks(t *testing.T) {
t.Parallel() t.Parallel()
a := NewTestACLAgent(t.Name(), TestACLConfig(), catalogPolicy) a := NewTestACLAgent(t, t.Name(), TestACLConfig(), catalogPolicy)
checks := make(map[types.CheckID]*structs.HealthCheck) checks := make(map[types.CheckID]*structs.HealthCheck)
require.NoError(t, a.filterChecks("node-ro", &checks)) require.NoError(t, a.filterChecks("node-ro", &checks))

View File

@ -30,6 +30,7 @@ import (
"github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/logger" "github.com/hashicorp/consul/logger"
"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/sdk/testutil/retry"
"github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/testrpc"
"github.com/hashicorp/consul/types" "github.com/hashicorp/consul/types"
@ -1245,7 +1246,7 @@ func TestAgent_Reload(t *testing.T) {
t.Fatal("missing redis service") t.Fatal("missing redis service")
} }
cfg2 := TestConfig(config.Source{ cfg2 := TestConfig(testutil.TestLogger(t), config.Source{
Name: "reload", Name: "reload",
Format: "hcl", Format: "hcl",
Data: ` Data: `

View File

@ -3456,7 +3456,7 @@ func TestAgent_ReloadConfigOutgoingRPCConfig(t *testing.T) {
key_file = "../test/key/ourdomain.key" key_file = "../test/key/ourdomain.key"
verify_server_hostname = true verify_server_hostname = true
` `
c := TestConfig(config.Source{Name: t.Name(), Format: "hcl", Data: hcl}) c := TestConfig(testutil.TestLogger(t), config.Source{Name: t.Name(), Format: "hcl", Data: hcl})
require.NoError(t, a.ReloadConfig(c)) require.NoError(t, a.ReloadConfig(c))
tlsConf = a.tlsConfigurator.OutgoingRPCConfig() tlsConf = a.tlsConfigurator.OutgoingRPCConfig()
require.False(t, tlsConf.InsecureSkipVerify) require.False(t, tlsConf.InsecureSkipVerify)
@ -3495,7 +3495,7 @@ func TestAgent_ReloadConfigIncomingRPCConfig(t *testing.T) {
key_file = "../test/key/ourdomain.key" key_file = "../test/key/ourdomain.key"
verify_server_hostname = true verify_server_hostname = true
` `
c := TestConfig(config.Source{Name: t.Name(), Format: "hcl", Data: hcl}) c := TestConfig(testutil.TestLogger(t), config.Source{Name: t.Name(), Format: "hcl", Data: hcl})
require.NoError(t, a.ReloadConfig(c)) require.NoError(t, a.ReloadConfig(c))
tlsConf, err = tlsConf.GetConfigForClient(nil) tlsConf, err = tlsConf.GetConfigForClient(nil)
require.NoError(t, err) require.NoError(t, err)
@ -3524,7 +3524,7 @@ func TestAgent_ReloadConfigTLSConfigFailure(t *testing.T) {
data_dir = "` + dataDir + `" data_dir = "` + dataDir + `"
verify_incoming = true verify_incoming = true
` `
c := TestConfig(config.Source{Name: t.Name(), Format: "hcl", Data: hcl}) c := TestConfig(testutil.TestLogger(t), config.Source{Name: t.Name(), Format: "hcl", Data: hcl})
require.Error(t, a.ReloadConfig(c)) require.Error(t, a.ReloadConfig(c))
tlsConf, err := tlsConf.GetConfigForClient(nil) tlsConf, err := tlsConf.GetConfigForClient(nil)
require.NoError(t, err) require.NoError(t, err)

View File

@ -223,6 +223,10 @@ func NewACLResolver(config *ACLResolverConfig) (*ACLResolver, error) {
}, nil }, nil
} }
func (r *ACLResolver) Close() {
r.entConf.Close()
}
func (r *ACLResolver) fetchAndCacheTokenLegacy(token string, cached *structs.AuthorizerCacheEntry) (acl.Authorizer, error) { func (r *ACLResolver) fetchAndCacheTokenLegacy(token string, cached *structs.AuthorizerCacheEntry) (acl.Authorizer, error) {
req := structs.ACLPolicyResolveLegacyRequest{ req := structs.ACLPolicyResolveLegacyRequest{
Datacenter: r.delegate.ACLDatacenter(true), Datacenter: r.delegate.ACLDatacenter(true),
@ -1205,8 +1209,11 @@ func (f *aclFilter) filterSessions(sessions *structs.Sessions) {
s := *sessions s := *sessions
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
session := s[i] session := s[i]
// TODO (namespaces) update to call with an actual ent authz context once sessions supports ns
if f.allowSession(session.Node, nil) { var entCtx acl.EnterpriseAuthorizerContext
session.FillAuthzContext(&entCtx)
if f.allowSession(session.Node, &entCtx) {
continue continue
} }
f.logger.Printf("[DEBUG] consul: dropping session %q from result due to ACLs", session.ID) f.logger.Printf("[DEBUG] consul: dropping session %q from result due to ACLs", session.ID)

View File

@ -161,13 +161,12 @@ func (a *ACL) BootstrapTokens(args *structs.DCSpecificRequest, reply *structs.AC
CreateTime: time.Now(), CreateTime: time.Now(),
Local: false, Local: false,
// DEPRECATED (ACL-Legacy-Compat) - This is used so that the bootstrap token is still visible via the v1 acl APIs // DEPRECATED (ACL-Legacy-Compat) - This is used so that the bootstrap token is still visible via the v1 acl APIs
Type: structs.ACLTokenTypeManagement, Type: structs.ACLTokenTypeManagement,
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
}, },
ResetIndex: specifiedIndex, ResetIndex: specifiedIndex,
} }
req.Token.EnterpriseMeta.InitDefault()
req.Token.SetHash(true) req.Token.SetHash(true)
resp, err := a.srv.raftApply(structs.ACLBootstrapRequestType, &req) resp, err := a.srv.raftApply(structs.ACLBootstrapRequestType, &req)

View File

@ -758,7 +758,7 @@ func TestACLReplication_AllTypes(t *testing.T) {
c.ACLsEnabled = true c.ACLsEnabled = true
c.ACLTokenReplication = true c.ACLTokenReplication = true
c.ACLReplicationRate = 100 c.ACLReplicationRate = 100
c.ACLReplicationBurst = 100 c.ACLReplicationBurst = 25
c.ACLReplicationApplyLimit = 1000000 c.ACLReplicationApplyLimit = 1000000
}) })
s2.tokens.UpdateReplicationToken("root", tokenStore.TokenSourceConfig) s2.tokens.UpdateReplicationToken("root", tokenStore.TokenSourceConfig)

View File

@ -214,6 +214,9 @@ func (c *Client) Shutdown() error {
// Close the connection pool // Close the connection pool
c.connPool.Shutdown() c.connPool.Shutdown()
c.acls.Close()
return nil return nil
} }

View File

@ -505,18 +505,18 @@ func (s *Server) initializeACLs(upgrade bool) error {
} }
if policy == nil || policy.Rules != structs.ACLPolicyGlobalManagement { if policy == nil || policy.Rules != structs.ACLPolicyGlobalManagement {
newPolicy := structs.ACLPolicy{ newPolicy := structs.ACLPolicy{
ID: structs.ACLPolicyGlobalManagementID, ID: structs.ACLPolicyGlobalManagementID,
Name: "global-management", Name: "global-management",
Description: "Builtin Policy that grants unlimited access", Description: "Builtin Policy that grants unlimited access",
Rules: structs.ACLPolicyGlobalManagement, Rules: structs.ACLPolicyGlobalManagement,
Syntax: acl.SyntaxCurrent, Syntax: acl.SyntaxCurrent,
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
} }
if policy != nil { if policy != nil {
newPolicy.Name = policy.Name newPolicy.Name = policy.Name
newPolicy.Description = policy.Description newPolicy.Description = policy.Description
} }
newPolicy.EnterpriseMeta.InitDefault()
newPolicy.SetHash(true) newPolicy.SetHash(true)
req := structs.ACLPolicyBatchSetRequest{ req := structs.ACLPolicyBatchSetRequest{
@ -560,10 +560,10 @@ func (s *Server) initializeACLs(upgrade bool) error {
Local: false, Local: false,
// DEPRECATED (ACL-Legacy-Compat) - only needed for compatibility // DEPRECATED (ACL-Legacy-Compat) - only needed for compatibility
Type: structs.ACLTokenTypeManagement, Type: structs.ACLTokenTypeManagement,
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
} }
token.EnterpriseMeta.InitDefault()
token.SetHash(true) token.SetHash(true)
done := false done := false
@ -616,13 +616,13 @@ func (s *Server) initializeACLs(upgrade bool) error {
// the token upgrade routine will take care of upgrading the token if a legacy version exists // the token upgrade routine will take care of upgrading the token if a legacy version exists
if legacyToken == nil { if legacyToken == nil {
token = &structs.ACLToken{ token = &structs.ACLToken{
AccessorID: structs.ACLTokenAnonymousID, AccessorID: structs.ACLTokenAnonymousID,
SecretID: anonymousToken, SecretID: anonymousToken,
Description: "Anonymous Token", Description: "Anonymous Token",
CreateTime: time.Now(), CreateTime: time.Now(),
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
} }
token.SetHash(true) token.SetHash(true)
token.EnterpriseMeta.InitDefault()
req := structs.ACLTokenBatchSetRequest{ req := structs.ACLTokenBatchSetRequest{
Tokens: structs.ACLTokens{token}, Tokens: structs.ACLTokens{token},

View File

@ -847,6 +847,8 @@ func (s *Server) Shutdown() error {
// Close the connection pool // Close the connection pool
s.connPool.Shutdown() s.connPool.Shutdown()
s.acls.Close()
if s.config.NotifyShutdown != nil { if s.config.NotifyShutdown != nil {
s.config.NotifyShutdown() s.config.NotifyShutdown()
} }

View File

@ -230,7 +230,7 @@ func (s *Snapshot) ACLTokens() (memdb.ResultIterator, error) {
// ACLToken is used when restoring from a snapshot. For general inserts, use ACL. // ACLToken is used when restoring from a snapshot. For general inserts, use ACL.
func (s *Restore) ACLToken(token *structs.ACLToken) error { func (s *Restore) ACLToken(token *structs.ACLToken) error {
return s.store.aclTokenInsert(s.tx, token, false) return s.store.aclTokenInsert(s.tx, token)
} }
// ACLPolicies is used when saving a snapshot // ACLPolicies is used when saving a snapshot
@ -243,7 +243,7 @@ func (s *Snapshot) ACLPolicies() (memdb.ResultIterator, error) {
} }
func (s *Restore) ACLPolicy(policy *structs.ACLPolicy) error { func (s *Restore) ACLPolicy(policy *structs.ACLPolicy) error {
return s.store.aclPolicyInsert(s.tx, policy, false) return s.store.aclPolicyInsert(s.tx, policy)
} }
// ACLRoles is used when saving a snapshot // ACLRoles is used when saving a snapshot
@ -256,7 +256,7 @@ func (s *Snapshot) ACLRoles() (memdb.ResultIterator, error) {
} }
func (s *Restore) ACLRole(role *structs.ACLRole) error { func (s *Restore) ACLRole(role *structs.ACLRole) error {
return s.store.aclRoleInsert(s.tx, role, false) return s.store.aclRoleInsert(s.tx, role)
} }
// ACLBindingRules is used when saving a snapshot // ACLBindingRules is used when saving a snapshot
@ -269,7 +269,7 @@ func (s *Snapshot) ACLBindingRules() (memdb.ResultIterator, error) {
} }
func (s *Restore) ACLBindingRule(rule *structs.ACLBindingRule) error { func (s *Restore) ACLBindingRule(rule *structs.ACLBindingRule) error {
return s.store.aclBindingRuleInsert(s.tx, rule, false) return s.store.aclBindingRuleInsert(s.tx, rule)
} }
// ACLAuthMethods is used when saving a snapshot // ACLAuthMethods is used when saving a snapshot
@ -282,7 +282,7 @@ func (s *Snapshot) ACLAuthMethods() (memdb.ResultIterator, error) {
} }
func (s *Restore) ACLAuthMethod(method *structs.ACLAuthMethod) error { func (s *Restore) ACLAuthMethod(method *structs.ACLAuthMethod) error {
return s.store.aclAuthMethodInsert(s.tx, method, false) return s.store.aclAuthMethodInsert(s.tx, method)
} }
// ACLBootstrap is used to perform a one-time ACL bootstrap operation on a // ACLBootstrap is used to perform a one-time ACL bootstrap operation on a
@ -765,7 +765,7 @@ func (s *Store) aclTokenSetTxn(tx *memdb.Txn, idx uint64, token *structs.ACLToke
token.ModifyIndex = idx token.ModifyIndex = idx
} }
return s.aclTokenInsert(tx, token, true) return s.aclTokenInsert(tx, token)
} }
// ACLTokenGetBySecret is used to look up an existing ACL token by its SecretID. // ACLTokenGetBySecret is used to look up an existing ACL token by its SecretID.
@ -1163,7 +1163,7 @@ func (s *Store) aclPolicySetTxn(tx *memdb.Txn, idx uint64, policy *structs.ACLPo
} }
// Insert the ACL // Insert the ACL
return s.aclPolicyInsert(tx, policy, true) return s.aclPolicyInsert(tx, policy)
} }
func (s *Store) ACLPolicyGetByID(ws memdb.WatchSet, id string, entMeta *structs.EnterpriseMeta) (uint64, *structs.ACLPolicy, error) { func (s *Store) ACLPolicyGetByID(ws memdb.WatchSet, id string, entMeta *structs.EnterpriseMeta) (uint64, *structs.ACLPolicy, error) {
@ -1379,7 +1379,7 @@ func (s *Store) aclRoleSetTxn(tx *memdb.Txn, idx uint64, role *structs.ACLRole,
role.ModifyIndex = idx role.ModifyIndex = idx
} }
return s.aclRoleInsert(tx, role, true) return s.aclRoleInsert(tx, role)
} }
type aclRoleGetFn func(*memdb.Txn, string, *structs.EnterpriseMeta) (<-chan struct{}, interface{}, error) type aclRoleGetFn func(*memdb.Txn, string, *structs.EnterpriseMeta) (<-chan struct{}, interface{}, error)
@ -1588,7 +1588,7 @@ func (s *Store) aclBindingRuleSetTxn(tx *memdb.Txn, idx uint64, rule *structs.AC
return fmt.Errorf("failed inserting acl binding rule: auth method not found") return fmt.Errorf("failed inserting acl binding rule: auth method not found")
} }
return s.aclBindingRuleInsert(tx, rule, true) return s.aclBindingRuleInsert(tx, rule)
} }
func (s *Store) ACLBindingRuleGetByID(ws memdb.WatchSet, id string, entMeta *structs.EnterpriseMeta) (uint64, *structs.ACLBindingRule, error) { func (s *Store) ACLBindingRuleGetByID(ws memdb.WatchSet, id string, entMeta *structs.EnterpriseMeta) (uint64, *structs.ACLBindingRule, error) {
@ -1771,7 +1771,7 @@ func (s *Store) aclAuthMethodSetTxn(tx *memdb.Txn, idx uint64, method *structs.A
method.ModifyIndex = idx method.ModifyIndex = idx
} }
return s.aclAuthMethodInsert(tx, method, true) return s.aclAuthMethodInsert(tx, method)
} }
func (s *Store) ACLAuthMethodGetByName(ws memdb.WatchSet, name string, entMeta *structs.EnterpriseMeta) (uint64, *structs.ACLAuthMethod, error) { func (s *Store) ACLAuthMethodGetByName(ws memdb.WatchSet, name string, entMeta *structs.EnterpriseMeta) (uint64, *structs.ACLAuthMethod, error) {

View File

@ -206,15 +206,13 @@ func authMethodsTableSchema() *memdb.TableSchema {
///// ACL Policy Functions ///// ///// ACL Policy Functions /////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
func (s *Store) aclPolicyInsert(tx *memdb.Txn, policy *structs.ACLPolicy, updateIndexes bool) error { func (s *Store) aclPolicyInsert(tx *memdb.Txn, policy *structs.ACLPolicy) error {
if err := tx.Insert("acl-policies", policy); err != nil { if err := tx.Insert("acl-policies", policy); err != nil {
return fmt.Errorf("failed inserting acl policy: %v", err) return fmt.Errorf("failed inserting acl policy: %v", err)
} }
if updateIndexes { if err := indexUpdateMaxTxn(tx, policy.ModifyIndex, "acl-policies"); err != nil {
if err := tx.Insert("index", &IndexEntry{"acl-policies", policy.ModifyIndex}); err != nil { return fmt.Errorf("failed updating acl policies index: %v", err)
return fmt.Errorf("failed updating acl policies index: %v", err)
}
} }
return nil return nil
@ -239,7 +237,7 @@ func (s *Store) aclPolicyDeleteWithPolicy(tx *memdb.Txn, policy *structs.ACLPoli
} }
// update the overall acl-policies index // update the overall acl-policies index
if err := tx.Insert("index", &IndexEntry{"acl-policies", idx}); err != nil { if err := indexUpdateMaxTxn(tx, idx, "acl-policies"); err != nil {
return fmt.Errorf("failed updating acl policies index: %v", err) return fmt.Errorf("failed updating acl policies index: %v", err)
} }
return nil return nil
@ -261,17 +259,15 @@ func (s *Store) ACLPolicyUpsertValidateEnterprise(*structs.ACLPolicy, *structs.A
///// ACL Token Functions ///// ///// ACL Token Functions /////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
func (s *Store) aclTokenInsert(tx *memdb.Txn, token *structs.ACLToken, updateIndexes bool) error { func (s *Store) aclTokenInsert(tx *memdb.Txn, token *structs.ACLToken) error {
// insert the token into memdb // insert the token into memdb
if err := tx.Insert("acl-tokens", token); err != nil { if err := tx.Insert("acl-tokens", token); err != nil {
return fmt.Errorf("failed inserting acl token: %v", err) return fmt.Errorf("failed inserting acl token: %v", err)
} }
if updateIndexes { // update the overall acl-tokens index
// update the overall acl-tokens index if err := indexUpdateMaxTxn(tx, token.ModifyIndex, "acl-tokens"); err != nil {
if err := tx.Insert("index", &IndexEntry{"acl-tokens", token.ModifyIndex}); err != nil { return fmt.Errorf("failed updating acl tokens index: %v", err)
return fmt.Errorf("failed updating acl tokens index: %v", err)
}
} }
return nil return nil
@ -312,7 +308,7 @@ func (s *Store) aclTokenDeleteWithToken(tx *memdb.Txn, token *structs.ACLToken,
} }
// update the overall acl-tokens index // update the overall acl-tokens index
if err := tx.Insert("index", &IndexEntry{"acl-tokens", idx}); err != nil { if err := indexUpdateMaxTxn(tx, idx, "acl-tokens"); err != nil {
return fmt.Errorf("failed updating acl tokens index: %v", err) return fmt.Errorf("failed updating acl tokens index: %v", err)
} }
return nil return nil
@ -334,17 +330,15 @@ func (s *Store) ACLTokenUpsertValidateEnterprise(token *structs.ACLToken, existi
///// ACL Role Functions ///// ///// ACL Role Functions /////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
func (s *Store) aclRoleInsert(tx *memdb.Txn, role *structs.ACLRole, updateIndexes bool) error { func (s *Store) aclRoleInsert(tx *memdb.Txn, role *structs.ACLRole) error {
// insert the role into memdb // insert the role into memdb
if err := tx.Insert("acl-roles", role); err != nil { if err := tx.Insert("acl-roles", role); err != nil {
return fmt.Errorf("failed inserting acl role: %v", err) return fmt.Errorf("failed inserting acl role: %v", err)
} }
if updateIndexes { // update the overall acl-roles index
// update the overall acl-roles index if err := indexUpdateMaxTxn(tx, role.ModifyIndex, "acl-roles"); err != nil {
if err := tx.Insert("index", &IndexEntry{"acl-roles", role.ModifyIndex}); err != nil { return fmt.Errorf("failed updating acl roles index: %v", err)
return fmt.Errorf("failed updating acl roles index: %v", err)
}
} }
return nil return nil
} }
@ -372,7 +366,7 @@ func (s *Store) aclRoleDeleteWithRole(tx *memdb.Txn, role *structs.ACLRole, idx
} }
// update the overall acl-roles index // update the overall acl-roles index
if err := tx.Insert("index", &IndexEntry{"acl-roles", idx}); err != nil { if err := indexUpdateMaxTxn(tx, idx, "acl-roles"); err != nil {
return fmt.Errorf("failed updating acl policies index: %v", err) return fmt.Errorf("failed updating acl policies index: %v", err)
} }
return nil return nil
@ -394,17 +388,15 @@ func (s *Store) ACLRoleUpsertValidateEnterprise(role *structs.ACLRole, existing
///// ACL Binding Rule Functions ///// ///// ACL Binding Rule Functions /////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
func (s *Store) aclBindingRuleInsert(tx *memdb.Txn, rule *structs.ACLBindingRule, updateIndexes bool) error { func (s *Store) aclBindingRuleInsert(tx *memdb.Txn, rule *structs.ACLBindingRule) error {
// insert the role into memdb // insert the role into memdb
if err := tx.Insert("acl-binding-rules", rule); err != nil { if err := tx.Insert("acl-binding-rules", rule); err != nil {
return fmt.Errorf("failed inserting acl role: %v", err) return fmt.Errorf("failed inserting acl role: %v", err)
} }
if updateIndexes { // update the overall acl-binding-rules index
// update the overall acl-binding-rules index if err := indexUpdateMaxTxn(tx, rule.ModifyIndex, "acl-binding-rules"); err != nil {
if err := tx.Insert("index", &IndexEntry{"acl-binding-rules", rule.ModifyIndex}); err != nil { return fmt.Errorf("failed updating acl binding-rules index: %v", err)
return fmt.Errorf("failed updating acl binding-rules index: %v", err)
}
} }
return nil return nil
@ -429,7 +421,7 @@ func (s *Store) aclBindingRuleDeleteWithRule(tx *memdb.Txn, rule *structs.ACLBin
} }
// update the overall acl-binding-rules index // update the overall acl-binding-rules index
if err := tx.Insert("index", &IndexEntry{"acl-binding-rules", idx}); err != nil { if err := indexUpdateMaxTxn(tx, idx, "acl-binding-rules"); err != nil {
return fmt.Errorf("failed updating acl binding rules index: %v", err) return fmt.Errorf("failed updating acl binding rules index: %v", err)
} }
return nil return nil
@ -451,17 +443,15 @@ func (s *Store) ACLBindingRuleUpsertValidateEnterprise(rule *structs.ACLBindingR
///// ACL Auth Method Functions ///// ///// ACL Auth Method Functions /////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
func (s *Store) aclAuthMethodInsert(tx *memdb.Txn, method *structs.ACLAuthMethod, updateIndexes bool) error { func (s *Store) aclAuthMethodInsert(tx *memdb.Txn, method *structs.ACLAuthMethod) error {
// insert the role into memdb // insert the role into memdb
if err := tx.Insert("acl-auth-methods", method); err != nil { if err := tx.Insert("acl-auth-methods", method); err != nil {
return fmt.Errorf("failed inserting acl role: %v", err) return fmt.Errorf("failed inserting acl role: %v", err)
} }
if updateIndexes { // update the overall acl-auth-methods index
// update the overall acl-auth-methods index if err := indexUpdateMaxTxn(tx, method.ModifyIndex, "acl-auth-methods"); err != nil {
if err := tx.Insert("index", &IndexEntry{"acl-auth-methods", method.ModifyIndex}); err != nil { return fmt.Errorf("failed updating acl auth methods index: %v", err)
return fmt.Errorf("failed updating acl auth methods index: %v", err)
}
} }
return nil return nil
@ -482,7 +472,7 @@ func (s *Store) aclAuthMethodDeleteWithMethod(tx *memdb.Txn, method *structs.ACL
} }
// update the overall acl-auth-methods index // update the overall acl-auth-methods index
if err := tx.Insert("index", &IndexEntry{"acl-auth-methods", idx}); err != nil { if err := indexUpdateMaxTxn(tx, idx, "acl-auth-methods"); err != nil {
return fmt.Errorf("failed updating acl auth methods index: %v", err) return fmt.Errorf("failed updating acl auth methods index: %v", err)
} }
return nil return nil

View File

@ -20,6 +20,10 @@ func (s *HTTPServer) parseEntMeta(req *http.Request, entMeta *structs.Enterprise
return nil return nil
} }
func (s *HTTPServer) parseEntMetaNoWildcard(req *http.Request, _ *structs.EnterpriseMeta) error {
return s.parseEntMeta(req, nil)
}
func (s *HTTPServer) rewordUnknownEnterpriseFieldError(err error) error { func (s *HTTPServer) rewordUnknownEnterpriseFieldError(err error) error {
if err == nil { if err == nil {
return nil return nil

View File

@ -452,7 +452,7 @@ func (t *ACLToken) SetHash(force bool) []byte {
srvid.AddToHash(hash) srvid.AddToHash(hash)
} }
t.EnterpriseMeta.addToHash(hash) t.EnterpriseMeta.addToHash(hash, false)
// Finalize the hash // Finalize the hash
hashVal := hash.Sum(nil) hashVal := hash.Sum(nil)
@ -645,7 +645,7 @@ func (p *ACLPolicy) SetHash(force bool) []byte {
hash.Write([]byte(dc)) hash.Write([]byte(dc))
} }
p.EnterpriseMeta.addToHash(hash) p.EnterpriseMeta.addToHash(hash, false)
// Finalize the hash // Finalize the hash
hashVal := hash.Sum(nil) hashVal := hash.Sum(nil)
@ -879,7 +879,7 @@ func (r *ACLRole) SetHash(force bool) []byte {
srvid.AddToHash(hash) srvid.AddToHash(hash)
} }
r.EnterpriseMeta.addToHash(hash) r.EnterpriseMeta.addToHash(hash, false)
// Finalize the hash // Finalize the hash
hashVal := hash.Sum(nil) hashVal := hash.Sum(nil)

View File

@ -8,6 +8,8 @@ import (
"github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl"
) )
var emptyEnterpriseMeta = EnterpriseMeta{}
// EnterpriseMeta stub // EnterpriseMeta stub
type EnterpriseMeta struct{} type EnterpriseMeta struct{}
@ -15,30 +17,27 @@ func (m *EnterpriseMeta) estimateSize() int {
return 0 return 0
} }
func (m *EnterpriseMeta) addToHash(hasher hash.Hash) { func (m *EnterpriseMeta) addToHash(_ hash.Hash, _ bool) {
// do nothing // do nothing
} }
// WildcardEnterpriseMeta stub
func WildcardEnterpriseMeta() *EnterpriseMeta {
return nil
}
// ReplicationEnterpriseMeta stub // ReplicationEnterpriseMeta stub
func ReplicationEnterpriseMeta() *EnterpriseMeta { func ReplicationEnterpriseMeta() *EnterpriseMeta {
return nil return &emptyEnterpriseMeta
} }
// DefaultEnterpriseMeta stub // DefaultEnterpriseMeta stub
func DefaultEnterpriseMeta() *EnterpriseMeta { func DefaultEnterpriseMeta() *EnterpriseMeta {
return nil return &emptyEnterpriseMeta
} }
// InitDefault stub // WildcardEnterpriseMeta stub
func (m *EnterpriseMeta) InitDefault() {} func WildcardEnterpriseMeta() *EnterpriseMeta {
return &emptyEnterpriseMeta
}
// FillAuthzContext stub // FillAuthzContext stub
func (m *EnterpriseMeta) FillAuthzContext(*acl.EnterpriseAuthorizerContext) {} func (_ *EnterpriseMeta) FillAuthzContext(_ *acl.EnterpriseAuthorizerContext) {}
// FillAuthzContext stub // FillAuthzContext stub
func (d *DirEntry) FillAuthzContext(*acl.EnterpriseAuthorizerContext) {} func (d *DirEntry) FillAuthzContext(*acl.EnterpriseAuthorizerContext) {}

View File

@ -156,9 +156,15 @@ func (a *TestAgent) Start() (err error) {
hclDataDir = `data_dir = "` + d + `"` hclDataDir = `data_dir = "` + d + `"`
} }
logOutput := a.LogOutput
if logOutput == nil {
logOutput = os.Stderr
}
agentLogger := log.New(logOutput, a.Name+" - ", log.LstdFlags|log.Lmicroseconds)
portsConfig, returnPortsFn := randomPortsSource(a.UseTLS) portsConfig, returnPortsFn := randomPortsSource(a.UseTLS)
a.returnPortsFn = returnPortsFn a.returnPortsFn = returnPortsFn
a.Config = TestConfig( a.Config = TestConfig(agentLogger,
portsConfig, portsConfig,
config.Source{Name: a.Name, Format: "hcl", Data: a.HCL}, config.Source{Name: a.Name, Format: "hcl", Data: a.HCL},
config.Source{Name: a.Name + ".data_dir", Format: "hcl", Data: hclDataDir}, config.Source{Name: a.Name + ".data_dir", Format: "hcl", Data: hclDataDir},
@ -191,12 +197,6 @@ func (a *TestAgent) Start() (err error) {
} }
} }
logOutput := a.LogOutput
if logOutput == nil {
logOutput = os.Stderr
}
agentLogger := log.New(logOutput, a.Name+" - ", log.LstdFlags|log.Lmicroseconds)
agent, err := New(a.Config, agentLogger) agent, err := New(a.Config, agentLogger)
if err != nil { if err != nil {
cleanupTmpDir() cleanupTmpDir()
@ -411,7 +411,7 @@ func NodeID() string {
// TestConfig returns a unique default configuration for testing an // TestConfig returns a unique default configuration for testing an
// agent. // agent.
func TestConfig(sources ...config.Source) *config.RuntimeConfig { func TestConfig(logger *log.Logger, sources ...config.Source) *config.RuntimeConfig {
nodeID := NodeID() nodeID := NodeID()
testsrc := config.Source{ testsrc := config.Source{
Name: "test", Name: "test",
@ -450,7 +450,7 @@ func TestConfig(sources ...config.Source) *config.RuntimeConfig {
} }
for _, w := range b.Warnings { for _, w := range b.Warnings {
fmt.Println("WARNING:", w) logger.Printf("[WARN] %s", w)
} }
// Effectively disables the delay after root rotation before requesting CSRs // Effectively disables the delay after root rotation before requesting CSRs

View File

@ -5,4 +5,5 @@ package sentinel
type Evaluator interface { type Evaluator interface {
Compile(policy string) error Compile(policy string) error
Execute(policy string, enforcementLevel string, data map[string]interface{}) bool Execute(policy string, enforcementLevel string, data map[string]interface{}) bool
Close()
} }

View File

@ -12,6 +12,8 @@ type rpcFn func(string, interface{}, interface{}) error
// WaitForLeader ensures we have a leader and a node registration. // WaitForLeader ensures we have a leader and a node registration.
func WaitForLeader(t *testing.T, rpc rpcFn, dc string) { func WaitForLeader(t *testing.T, rpc rpcFn, dc string) {
t.Helper()
var out structs.IndexedNodes var out structs.IndexedNodes
retry.Run(t, func(r *retry.R) { retry.Run(t, func(r *retry.R) {
args := &structs.DCSpecificRequest{Datacenter: dc} args := &structs.DCSpecificRequest{Datacenter: dc}
@ -29,6 +31,8 @@ func WaitForLeader(t *testing.T, rpc rpcFn, dc string) {
// WaitUntilNoLeader ensures no leader is present, useful for testing lost leadership. // WaitUntilNoLeader ensures no leader is present, useful for testing lost leadership.
func WaitUntilNoLeader(t *testing.T, rpc rpcFn, dc string) { func WaitUntilNoLeader(t *testing.T, rpc rpcFn, dc string) {
t.Helper()
var out structs.IndexedNodes var out structs.IndexedNodes
retry.Run(t, func(r *retry.R) { retry.Run(t, func(r *retry.R) {
args := &structs.DCSpecificRequest{Datacenter: dc} args := &structs.DCSpecificRequest{Datacenter: dc}
@ -56,6 +60,8 @@ func WaitForAntiEntropySync() waitOption {
// WaitForTestAgent ensures we have a node with serfHealth check registered // WaitForTestAgent ensures we have a node with serfHealth check registered
func WaitForTestAgent(t *testing.T, rpc rpcFn, dc string, options ...waitOption) { func WaitForTestAgent(t *testing.T, rpc rpcFn, dc string, options ...waitOption) {
t.Helper()
var nodes structs.IndexedNodes var nodes structs.IndexedNodes
var checks structs.IndexedHealthChecks var checks structs.IndexedHealthChecks