2016-12-14 07:21:14 +00:00
|
|
|
package agent
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
rawacl "github.com/hashicorp/consul/acl"
|
pkg refactor
command/agent/* -> agent/*
command/consul/* -> agent/consul/*
command/agent/command{,_test}.go -> command/agent{,_test}.go
command/base/command.go -> command/base.go
command/base/* -> command/*
commands.go -> command/commands.go
The script which did the refactor is:
(
cd $GOPATH/src/github.com/hashicorp/consul
git mv command/agent/command.go command/agent.go
git mv command/agent/command_test.go command/agent_test.go
git mv command/agent/flag_slice_value{,_test}.go command/
git mv command/agent .
git mv command/base/command.go command/base.go
git mv command/base/config_util{,_test}.go command/
git mv commands.go command/
git mv consul agent
rmdir command/base/
gsed -i -e 's|package agent|package command|' command/agent{,_test}.go
gsed -i -e 's|package agent|package command|' command/flag_slice_value{,_test}.go
gsed -i -e 's|package base|package command|' command/base.go command/config_util{,_test}.go
gsed -i -e 's|package main|package command|' command/commands.go
gsed -i -e 's|base.Command|BaseCommand|' command/commands.go
gsed -i -e 's|agent.Command|AgentCommand|' command/commands.go
gsed -i -e 's|\tCommand:|\tBaseCommand:|' command/commands.go
gsed -i -e 's|base\.||' command/commands.go
gsed -i -e 's|command\.||' command/commands.go
gsed -i -e 's|command|c|' main.go
gsed -i -e 's|range Commands|range command.Commands|' main.go
gsed -i -e 's|Commands: Commands|Commands: command.Commands|' main.go
gsed -i -e 's|base\.BoolValue|BoolValue|' command/operator_autopilot_set.go
gsed -i -e 's|base\.DurationValue|DurationValue|' command/operator_autopilot_set.go
gsed -i -e 's|base\.StringValue|StringValue|' command/operator_autopilot_set.go
gsed -i -e 's|base\.UintValue|UintValue|' command/operator_autopilot_set.go
gsed -i -e 's|\bCommand\b|BaseCommand|' command/base.go
gsed -i -e 's|BaseCommand Options|Command Options|' command/base.go
gsed -i -e 's|base.Command|BaseCommand|' command/*.go
gsed -i -e 's|c\.Command|c.BaseCommand|g' command/*.go
gsed -i -e 's|\tCommand:|\tBaseCommand:|' command/*_test.go
gsed -i -e 's|base\.||' command/*_test.go
gsed -i -e 's|\bCommand\b|AgentCommand|' command/agent{,_test}.go
gsed -i -e 's|cmd.AgentCommand|cmd.BaseCommand|' command/agent.go
gsed -i -e 's|cli.AgentCommand = new(Command)|cli.Command = new(AgentCommand)|' command/agent_test.go
gsed -i -e 's|exec.AgentCommand|exec.Command|' command/agent_test.go
gsed -i -e 's|exec.BaseCommand|exec.Command|' command/agent_test.go
gsed -i -e 's|NewTestAgent|agent.NewTestAgent|' command/agent_test.go
gsed -i -e 's|= TestConfig|= agent.TestConfig|' command/agent_test.go
gsed -i -e 's|: RetryJoin|: agent.RetryJoin|' command/agent_test.go
gsed -i -e 's|\.\./\.\./|../|' command/config_util_test.go
gsed -i -e 's|\bverifyUniqueListeners|VerifyUniqueListeners|' agent/config{,_test}.go command/agent.go
gsed -i -e 's|\bserfLANKeyring\b|SerfLANKeyring|g' agent/{agent,keyring,testagent}.go command/agent.go
gsed -i -e 's|\bserfWANKeyring\b|SerfWANKeyring|g' agent/{agent,keyring,testagent}.go command/agent.go
gsed -i -e 's|\bNewAgent\b|agent.New|g' command/agent{,_test}.go
gsed -i -e 's|\bNewAgent|New|' agent/{acl_test,agent,testagent}.go
gsed -i -e 's|\bAgent\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bBool\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bDefaultConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bDevConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bMergeConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bReadConfigPaths\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bParseMetaPair\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bSerfLANKeyring\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bSerfWANKeyring\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|circonus\.agent|circonus|g' command/agent{,_test}.go
gsed -i -e 's|logger\.agent|logger|g' command/agent{,_test}.go
gsed -i -e 's|metrics\.agent|metrics|g' command/agent{,_test}.go
gsed -i -e 's|// agent.Agent|// agent|' command/agent{,_test}.go
gsed -i -e 's|a\.agent\.Config|a.Config|' command/agent{,_test}.go
gsed -i -e 's|agent\.AppendSliceValue|AppendSliceValue|' command/{configtest,validate}.go
gsed -i -e 's|consul/consul|agent/consul|' GNUmakefile
gsed -i -e 's|\.\./test|../../test|' agent/consul/server_test.go
# fix imports
f=$(grep -rl 'github.com/hashicorp/consul/command/agent' * | grep '\.go')
gsed -i -e 's|github.com/hashicorp/consul/command/agent|github.com/hashicorp/consul/agent|' $f
goimports -w $f
f=$(grep -rl 'github.com/hashicorp/consul/consul' * | grep '\.go')
gsed -i -e 's|github.com/hashicorp/consul/consul|github.com/hashicorp/consul/agent/consul|' $f
goimports -w $f
goimports -w command/*.go main.go
)
2017-06-09 22:28:28 +00:00
|
|
|
"github.com/hashicorp/consul/agent/consul/structs"
|
2017-05-12 13:41:13 +00:00
|
|
|
"github.com/hashicorp/consul/testutil"
|
2016-12-15 03:28:09 +00:00
|
|
|
"github.com/hashicorp/consul/types"
|
|
|
|
"github.com/hashicorp/serf/serf"
|
2016-12-14 07:21:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestACL_Bad_Config(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 11:03:59 +00:00
|
|
|
cfg := TestConfig()
|
|
|
|
cfg.ACLDownPolicy = "nope"
|
|
|
|
cfg.DataDir = testutil.TempDir(t, "agent")
|
2016-12-14 07:21:14 +00:00
|
|
|
|
2017-05-31 08:56:19 +00:00
|
|
|
// do not use TestAgent here since we want
|
|
|
|
// the agent to fail during startup.
|
pkg refactor
command/agent/* -> agent/*
command/consul/* -> agent/consul/*
command/agent/command{,_test}.go -> command/agent{,_test}.go
command/base/command.go -> command/base.go
command/base/* -> command/*
commands.go -> command/commands.go
The script which did the refactor is:
(
cd $GOPATH/src/github.com/hashicorp/consul
git mv command/agent/command.go command/agent.go
git mv command/agent/command_test.go command/agent_test.go
git mv command/agent/flag_slice_value{,_test}.go command/
git mv command/agent .
git mv command/base/command.go command/base.go
git mv command/base/config_util{,_test}.go command/
git mv commands.go command/
git mv consul agent
rmdir command/base/
gsed -i -e 's|package agent|package command|' command/agent{,_test}.go
gsed -i -e 's|package agent|package command|' command/flag_slice_value{,_test}.go
gsed -i -e 's|package base|package command|' command/base.go command/config_util{,_test}.go
gsed -i -e 's|package main|package command|' command/commands.go
gsed -i -e 's|base.Command|BaseCommand|' command/commands.go
gsed -i -e 's|agent.Command|AgentCommand|' command/commands.go
gsed -i -e 's|\tCommand:|\tBaseCommand:|' command/commands.go
gsed -i -e 's|base\.||' command/commands.go
gsed -i -e 's|command\.||' command/commands.go
gsed -i -e 's|command|c|' main.go
gsed -i -e 's|range Commands|range command.Commands|' main.go
gsed -i -e 's|Commands: Commands|Commands: command.Commands|' main.go
gsed -i -e 's|base\.BoolValue|BoolValue|' command/operator_autopilot_set.go
gsed -i -e 's|base\.DurationValue|DurationValue|' command/operator_autopilot_set.go
gsed -i -e 's|base\.StringValue|StringValue|' command/operator_autopilot_set.go
gsed -i -e 's|base\.UintValue|UintValue|' command/operator_autopilot_set.go
gsed -i -e 's|\bCommand\b|BaseCommand|' command/base.go
gsed -i -e 's|BaseCommand Options|Command Options|' command/base.go
gsed -i -e 's|base.Command|BaseCommand|' command/*.go
gsed -i -e 's|c\.Command|c.BaseCommand|g' command/*.go
gsed -i -e 's|\tCommand:|\tBaseCommand:|' command/*_test.go
gsed -i -e 's|base\.||' command/*_test.go
gsed -i -e 's|\bCommand\b|AgentCommand|' command/agent{,_test}.go
gsed -i -e 's|cmd.AgentCommand|cmd.BaseCommand|' command/agent.go
gsed -i -e 's|cli.AgentCommand = new(Command)|cli.Command = new(AgentCommand)|' command/agent_test.go
gsed -i -e 's|exec.AgentCommand|exec.Command|' command/agent_test.go
gsed -i -e 's|exec.BaseCommand|exec.Command|' command/agent_test.go
gsed -i -e 's|NewTestAgent|agent.NewTestAgent|' command/agent_test.go
gsed -i -e 's|= TestConfig|= agent.TestConfig|' command/agent_test.go
gsed -i -e 's|: RetryJoin|: agent.RetryJoin|' command/agent_test.go
gsed -i -e 's|\.\./\.\./|../|' command/config_util_test.go
gsed -i -e 's|\bverifyUniqueListeners|VerifyUniqueListeners|' agent/config{,_test}.go command/agent.go
gsed -i -e 's|\bserfLANKeyring\b|SerfLANKeyring|g' agent/{agent,keyring,testagent}.go command/agent.go
gsed -i -e 's|\bserfWANKeyring\b|SerfWANKeyring|g' agent/{agent,keyring,testagent}.go command/agent.go
gsed -i -e 's|\bNewAgent\b|agent.New|g' command/agent{,_test}.go
gsed -i -e 's|\bNewAgent|New|' agent/{acl_test,agent,testagent}.go
gsed -i -e 's|\bAgent\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bBool\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bDefaultConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bDevConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bMergeConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bReadConfigPaths\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bParseMetaPair\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bSerfLANKeyring\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bSerfWANKeyring\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|circonus\.agent|circonus|g' command/agent{,_test}.go
gsed -i -e 's|logger\.agent|logger|g' command/agent{,_test}.go
gsed -i -e 's|metrics\.agent|metrics|g' command/agent{,_test}.go
gsed -i -e 's|// agent.Agent|// agent|' command/agent{,_test}.go
gsed -i -e 's|a\.agent\.Config|a.Config|' command/agent{,_test}.go
gsed -i -e 's|agent\.AppendSliceValue|AppendSliceValue|' command/{configtest,validate}.go
gsed -i -e 's|consul/consul|agent/consul|' GNUmakefile
gsed -i -e 's|\.\./test|../../test|' agent/consul/server_test.go
# fix imports
f=$(grep -rl 'github.com/hashicorp/consul/command/agent' * | grep '\.go')
gsed -i -e 's|github.com/hashicorp/consul/command/agent|github.com/hashicorp/consul/agent|' $f
goimports -w $f
f=$(grep -rl 'github.com/hashicorp/consul/consul' * | grep '\.go')
gsed -i -e 's|github.com/hashicorp/consul/consul|github.com/hashicorp/consul/agent/consul|' $f
goimports -w $f
goimports -w command/*.go main.go
)
2017-06-09 22:28:28 +00:00
|
|
|
_, err := New(cfg)
|
2016-12-14 07:21:14 +00:00
|
|
|
if err == nil || !strings.Contains(err.Error(), "invalid ACL down policy") {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type MockServer struct {
|
|
|
|
getPolicyFn func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MockServer) GetPolicy(args *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
|
|
|
|
if m.getPolicyFn != nil {
|
|
|
|
return m.getPolicyFn(args, reply)
|
|
|
|
}
|
2017-04-21 01:59:42 +00:00
|
|
|
return fmt.Errorf("should not have called GetPolicy")
|
2016-12-14 07:21:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_Version8(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 11:03:59 +00:00
|
|
|
cfg := TestConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(false)
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-14 07:21:14 +00:00
|
|
|
|
|
|
|
m := MockServer{}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// With version 8 enforcement off, this should not get called.
|
|
|
|
m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
|
|
|
|
t.Fatalf("should not have called to server")
|
|
|
|
return nil
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
if token, err := a.resolveToken("nope"); token != nil || err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("bad: %v err: %v", token, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_Disabled(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-22 11:03:59 +00:00
|
|
|
cfg.ACLDisabledTTL = 10 * time.Millisecond
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-14 07:21:14 +00:00
|
|
|
|
|
|
|
m := MockServer{}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch a token without ACLs enabled and make sure the manager sees it.
|
|
|
|
m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
|
|
|
|
return errors.New(aclDisabled)
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
if a.acls.isDisabled() {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should not be disabled yet")
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
if token, err := a.resolveToken("nope"); token != nil || err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("bad: %v err: %v", token, err)
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
if !a.acls.isDisabled() {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should be disabled")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now turn on ACLs and check right away, it should still think ACLs are
|
|
|
|
// disabled since we don't check again right away.
|
|
|
|
m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
|
|
|
|
return errors.New(aclNotFound)
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
if token, err := a.resolveToken("nope"); token != nil || err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("bad: %v err: %v", token, err)
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
if !a.acls.isDisabled() {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should be disabled")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait the waiting period and make sure it checks again. Do a few tries
|
|
|
|
// to make sure we don't think it's disabled.
|
2017-05-22 11:03:59 +00:00
|
|
|
time.Sleep(2 * cfg.ACLDisabledTTL)
|
2016-12-14 07:21:14 +00:00
|
|
|
for i := 0; i < 10; i++ {
|
2017-05-21 07:11:09 +00:00
|
|
|
_, err := a.resolveToken("nope")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err == nil || !strings.Contains(err.Error(), aclNotFound) {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
if a.acls.isDisabled() {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should not be disabled")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_Special_IDs(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2017-05-22 11:03:59 +00:00
|
|
|
cfg.ACLAgentMasterToken = "towel"
|
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-14 07:21:14 +00:00
|
|
|
|
|
|
|
m := MockServer{}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// An empty ID should get mapped to the anonymous token.
|
|
|
|
m.getPolicyFn = func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
|
|
|
|
if req.ACL != "anonymous" {
|
|
|
|
t.Fatalf("bad: %#v", *req)
|
|
|
|
}
|
|
|
|
return errors.New(aclNotFound)
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
_, err := a.resolveToken("")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err == nil || !strings.Contains(err.Error(), aclNotFound) {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// A root ACL request should get rejected and not call the server.
|
|
|
|
m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
|
|
|
|
t.Fatalf("should not have called to server")
|
|
|
|
return nil
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
_, err = a.resolveToken("deny")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err == nil || !strings.Contains(err.Error(), rootDenied) {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The ACL master token should also not call the server, but should give
|
2017-05-30 23:05:21 +00:00
|
|
|
// us a working agent token.
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err := a.resolveToken("towel")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should be able to read agent")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentWrite(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should be able to write agent")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_Down_Deny(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-22 11:03:59 +00:00
|
|
|
cfg.ACLDownPolicy = "deny"
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-14 07:21:14 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-14 07:21:14 +00:00
|
|
|
|
|
|
|
m := MockServer{}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve with ACLs down.
|
|
|
|
m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
|
|
|
|
return fmt.Errorf("ACLs are broken")
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err := a.resolveToken("nope")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_Down_Allow(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-22 11:03:59 +00:00
|
|
|
cfg.ACLDownPolicy = "allow"
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-14 07:21:14 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-14 07:21:14 +00:00
|
|
|
|
|
|
|
m := MockServer{}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve with ACLs down.
|
|
|
|
m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
|
|
|
|
return fmt.Errorf("ACLs are broken")
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err := a.resolveToken("nope")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should allow")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_Down_Extend(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-22 11:03:59 +00:00
|
|
|
cfg.ACLDownPolicy = "extend-cache"
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-14 07:21:14 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-14 07:21:14 +00:00
|
|
|
|
|
|
|
m := MockServer{}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Populate the cache for one of the tokens.
|
|
|
|
m.getPolicyFn = func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
|
|
|
|
*reply = structs.ACLPolicy{
|
|
|
|
Parent: "allow",
|
|
|
|
Policy: &rawacl.Policy{
|
|
|
|
Agents: []*rawacl.AgentPolicy{
|
|
|
|
&rawacl.AgentPolicy{
|
2017-05-22 11:03:59 +00:00
|
|
|
Node: cfg.NodeName,
|
2016-12-14 07:21:14 +00:00
|
|
|
Policy: "read",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err := a.resolveToken("yep")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should allow")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if acl.AgentWrite(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now take down ACLs and make sure a new token fails to resolve.
|
|
|
|
m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
|
|
|
|
return fmt.Errorf("ACLs are broken")
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err = a.resolveToken("nope")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if acl.AgentWrite(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the token from the cache while ACLs are broken, which should
|
|
|
|
// extend.
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err = a.resolveToken("yep")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should allow")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if acl.AgentWrite(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_Cache(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-14 07:21:14 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-14 07:21:14 +00:00
|
|
|
|
|
|
|
m := MockServer{}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Populate the cache for one of the tokens.
|
|
|
|
m.getPolicyFn = func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
|
|
|
|
*reply = structs.ACLPolicy{
|
|
|
|
ETag: "hash1",
|
|
|
|
Parent: "deny",
|
|
|
|
Policy: &rawacl.Policy{
|
|
|
|
Agents: []*rawacl.AgentPolicy{
|
|
|
|
&rawacl.AgentPolicy{
|
2017-05-22 11:03:59 +00:00
|
|
|
Node: cfg.NodeName,
|
2016-12-14 07:21:14 +00:00
|
|
|
Policy: "read",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
TTL: 10 * time.Millisecond,
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err := a.resolveToken("yep")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should allow")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if acl.AgentWrite(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
if acl.NodeRead("nope") {
|
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch right away and make sure it uses the cache.
|
|
|
|
m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
|
|
|
|
t.Fatalf("should not have called to server")
|
|
|
|
return nil
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err = a.resolveToken("yep")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should allow")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if acl.AgentWrite(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
if acl.NodeRead("nope") {
|
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for the TTL to expire and try again. This time the token will be
|
|
|
|
// gone.
|
|
|
|
time.Sleep(20 * time.Millisecond)
|
|
|
|
m.getPolicyFn = func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
|
|
|
|
return errors.New(aclNotFound)
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
_, err = a.resolveToken("yep")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err == nil || !strings.Contains(err.Error(), aclNotFound) {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Page it back in with a new tag and different policy
|
|
|
|
m.getPolicyFn = func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
|
|
|
|
*reply = structs.ACLPolicy{
|
|
|
|
ETag: "hash2",
|
|
|
|
Parent: "deny",
|
|
|
|
Policy: &rawacl.Policy{
|
|
|
|
Agents: []*rawacl.AgentPolicy{
|
|
|
|
&rawacl.AgentPolicy{
|
2017-05-22 11:03:59 +00:00
|
|
|
Node: cfg.NodeName,
|
2016-12-14 07:21:14 +00:00
|
|
|
Policy: "write",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
TTL: 10 * time.Millisecond,
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err = a.resolveToken("yep")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should allow")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentWrite(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should allow")
|
|
|
|
}
|
|
|
|
if acl.NodeRead("nope") {
|
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for the TTL to expire and try again. This will match the tag
|
|
|
|
// and not send the policy back, but we should have the old token
|
|
|
|
// behavior.
|
|
|
|
time.Sleep(20 * time.Millisecond)
|
|
|
|
var didRefresh bool
|
|
|
|
m.getPolicyFn = func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
|
|
|
|
*reply = structs.ACLPolicy{
|
|
|
|
ETag: "hash2",
|
|
|
|
TTL: 10 * time.Millisecond,
|
|
|
|
}
|
|
|
|
didRefresh = true
|
|
|
|
return nil
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
acl, err = a.resolveToken("yep")
|
2016-12-14 07:21:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if acl == nil {
|
|
|
|
t.Fatalf("should not be nil")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentRead(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should allow")
|
|
|
|
}
|
2017-05-22 11:03:59 +00:00
|
|
|
if !acl.AgentWrite(cfg.NodeName) {
|
2016-12-14 07:21:14 +00:00
|
|
|
t.Fatalf("should allow")
|
|
|
|
}
|
|
|
|
if acl.NodeRead("nope") {
|
|
|
|
t.Fatalf("should deny")
|
|
|
|
}
|
|
|
|
if !didRefresh {
|
|
|
|
t.Fatalf("should refresh")
|
|
|
|
}
|
|
|
|
}
|
2016-12-15 03:28:09 +00:00
|
|
|
|
|
|
|
// catalogPolicy supplies some standard policies to help with testing the
|
|
|
|
// catalog-related vet and filter functions.
|
|
|
|
func catalogPolicy(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
|
|
|
|
reply.Policy = &rawacl.Policy{}
|
|
|
|
|
|
|
|
switch req.ACL {
|
|
|
|
|
|
|
|
case "node-ro":
|
|
|
|
reply.Policy.Nodes = append(reply.Policy.Nodes,
|
|
|
|
&rawacl.NodePolicy{Name: "Node", Policy: "read"})
|
|
|
|
|
|
|
|
case "node-rw":
|
|
|
|
reply.Policy.Nodes = append(reply.Policy.Nodes,
|
|
|
|
&rawacl.NodePolicy{Name: "Node", Policy: "write"})
|
|
|
|
|
|
|
|
case "service-ro":
|
|
|
|
reply.Policy.Services = append(reply.Policy.Services,
|
|
|
|
&rawacl.ServicePolicy{Name: "service", Policy: "read"})
|
|
|
|
|
|
|
|
case "service-rw":
|
|
|
|
reply.Policy.Services = append(reply.Policy.Services,
|
|
|
|
&rawacl.ServicePolicy{Name: "service", Policy: "write"})
|
|
|
|
|
|
|
|
case "other-rw":
|
|
|
|
reply.Policy.Services = append(reply.Policy.Services,
|
|
|
|
&rawacl.ServicePolicy{Name: "other", Policy: "write"})
|
|
|
|
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("unknown token %q", req.ACL)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_vetServiceRegister(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-15 03:28:09 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-15 03:28:09 +00:00
|
|
|
|
|
|
|
m := MockServer{catalogPolicy}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a new service, with permission.
|
2017-05-21 07:11:09 +00:00
|
|
|
err := a.vetServiceRegister("service-rw", &structs.NodeService{
|
2016-12-15 03:28:09 +00:00
|
|
|
ID: "my-service",
|
|
|
|
Service: "service",
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a new service without write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetServiceRegister("service-ro", &structs.NodeService{
|
2016-12-15 03:28:09 +00:00
|
|
|
ID: "my-service",
|
|
|
|
Service: "service",
|
|
|
|
})
|
2017-05-09 12:17:21 +00:00
|
|
|
if !isPermissionDenied(err) {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to register over a service without write privs to the existing
|
|
|
|
// service.
|
2017-05-21 07:11:09 +00:00
|
|
|
a.state.AddService(&structs.NodeService{
|
2016-12-15 03:28:09 +00:00
|
|
|
ID: "my-service",
|
|
|
|
Service: "other",
|
|
|
|
}, "")
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetServiceRegister("service-rw", &structs.NodeService{
|
2016-12-15 03:28:09 +00:00
|
|
|
ID: "my-service",
|
|
|
|
Service: "service",
|
|
|
|
})
|
2017-05-09 12:17:21 +00:00
|
|
|
if !isPermissionDenied(err) {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_vetServiceUpdate(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-15 03:28:09 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-15 03:28:09 +00:00
|
|
|
|
|
|
|
m := MockServer{catalogPolicy}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update a service that doesn't exist.
|
2017-05-21 07:11:09 +00:00
|
|
|
err := a.vetServiceUpdate("service-rw", "my-service")
|
2016-12-15 03:28:09 +00:00
|
|
|
if err == nil || !strings.Contains(err.Error(), "Unknown service") {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update with write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
a.state.AddService(&structs.NodeService{
|
2016-12-15 03:28:09 +00:00
|
|
|
ID: "my-service",
|
|
|
|
Service: "service",
|
|
|
|
}, "")
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetServiceUpdate("service-rw", "my-service")
|
2016-12-15 03:28:09 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update without write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetServiceUpdate("service-ro", "my-service")
|
2017-05-09 12:17:21 +00:00
|
|
|
if !isPermissionDenied(err) {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_vetCheckRegister(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-15 03:28:09 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-15 03:28:09 +00:00
|
|
|
|
|
|
|
m := MockServer{catalogPolicy}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a new service check with write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
err := a.vetCheckRegister("service-rw", &structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-check"),
|
|
|
|
ServiceID: "my-service",
|
|
|
|
ServiceName: "service",
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a new service check without write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetCheckRegister("service-ro", &structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-check"),
|
|
|
|
ServiceID: "my-service",
|
|
|
|
ServiceName: "service",
|
|
|
|
})
|
2017-05-09 12:17:21 +00:00
|
|
|
if !isPermissionDenied(err) {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a new node check with write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetCheckRegister("node-rw", &structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-check"),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a new node check without write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetCheckRegister("node-ro", &structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-check"),
|
|
|
|
})
|
2017-05-09 12:17:21 +00:00
|
|
|
if !isPermissionDenied(err) {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to register over a service check without write privs to the
|
|
|
|
// existing service.
|
2017-05-21 07:11:09 +00:00
|
|
|
a.state.AddService(&structs.NodeService{
|
2016-12-15 03:28:09 +00:00
|
|
|
ID: "my-service",
|
|
|
|
Service: "service",
|
|
|
|
}, "")
|
2017-05-21 07:11:09 +00:00
|
|
|
a.state.AddCheck(&structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-check"),
|
|
|
|
ServiceID: "my-service",
|
|
|
|
ServiceName: "other",
|
|
|
|
}, "")
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetCheckRegister("service-rw", &structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-check"),
|
|
|
|
ServiceID: "my-service",
|
|
|
|
ServiceName: "service",
|
|
|
|
})
|
2017-05-09 12:17:21 +00:00
|
|
|
if !isPermissionDenied(err) {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to register over a node check without write privs to the node.
|
2017-05-21 07:11:09 +00:00
|
|
|
a.state.AddCheck(&structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-node-check"),
|
|
|
|
}, "")
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetCheckRegister("service-rw", &structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-node-check"),
|
|
|
|
ServiceID: "my-service",
|
|
|
|
ServiceName: "service",
|
|
|
|
})
|
2017-05-09 12:17:21 +00:00
|
|
|
if !isPermissionDenied(err) {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_vetCheckUpdate(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-15 03:28:09 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-15 03:28:09 +00:00
|
|
|
|
|
|
|
m := MockServer{catalogPolicy}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update a check that doesn't exist.
|
2017-05-21 07:11:09 +00:00
|
|
|
err := a.vetCheckUpdate("node-rw", "my-check")
|
2016-12-15 03:28:09 +00:00
|
|
|
if err == nil || !strings.Contains(err.Error(), "Unknown check") {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update service check with write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
a.state.AddService(&structs.NodeService{
|
2016-12-15 03:28:09 +00:00
|
|
|
ID: "my-service",
|
|
|
|
Service: "service",
|
|
|
|
}, "")
|
2017-05-21 07:11:09 +00:00
|
|
|
a.state.AddCheck(&structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-service-check"),
|
|
|
|
ServiceID: "my-service",
|
|
|
|
ServiceName: "service",
|
|
|
|
}, "")
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetCheckUpdate("service-rw", "my-service-check")
|
2016-12-15 03:28:09 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update service check without write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetCheckUpdate("service-ro", "my-service-check")
|
2017-05-09 12:17:21 +00:00
|
|
|
if !isPermissionDenied(err) {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update node check with write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
a.state.AddCheck(&structs.HealthCheck{
|
2016-12-15 03:28:09 +00:00
|
|
|
CheckID: types.CheckID("my-node-check"),
|
|
|
|
}, "")
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetCheckUpdate("node-rw", "my-node-check")
|
2016-12-15 03:28:09 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update without write privs.
|
2017-05-21 07:11:09 +00:00
|
|
|
err = a.vetCheckUpdate("node-ro", "my-node-check")
|
2017-05-09 12:17:21 +00:00
|
|
|
if !isPermissionDenied(err) {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_filterMembers(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-15 03:28:09 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-15 03:28:09 +00:00
|
|
|
|
|
|
|
m := MockServer{catalogPolicy}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var members []serf.Member
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.filterMembers("node-ro", &members); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if len(members) != 0 {
|
|
|
|
t.Fatalf("bad: %#v", members)
|
|
|
|
}
|
|
|
|
|
|
|
|
members = []serf.Member{
|
|
|
|
serf.Member{Name: "Node 1"},
|
|
|
|
serf.Member{Name: "Nope"},
|
|
|
|
serf.Member{Name: "Node 2"},
|
|
|
|
}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.filterMembers("node-ro", &members); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if len(members) != 2 ||
|
|
|
|
members[0].Name != "Node 1" ||
|
|
|
|
members[1].Name != "Node 2" {
|
|
|
|
t.Fatalf("bad: %#v", members)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_filterServices(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-15 03:28:09 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-15 03:28:09 +00:00
|
|
|
|
|
|
|
m := MockServer{catalogPolicy}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
services := make(map[string]*structs.NodeService)
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.filterServices("node-ro", &services); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
services["my-service"] = &structs.NodeService{ID: "my-service", Service: "service"}
|
|
|
|
services["my-other"] = &structs.NodeService{ID: "my-other", Service: "other"}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.filterServices("service-ro", &services); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if _, ok := services["my-service"]; !ok {
|
|
|
|
t.Fatalf("bad: %#v", services)
|
|
|
|
}
|
|
|
|
if _, ok := services["my-other"]; ok {
|
|
|
|
t.Fatalf("bad: %#v", services)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestACL_filterChecks(t *testing.T) {
|
2017-05-21 07:54:40 +00:00
|
|
|
t.Parallel()
|
2017-05-22 15:20:01 +00:00
|
|
|
cfg := TestACLConfig()
|
2017-05-31 07:21:01 +00:00
|
|
|
cfg.ACLEnforceVersion8 = Bool(true)
|
2016-12-15 03:28:09 +00:00
|
|
|
|
2017-05-22 11:03:59 +00:00
|
|
|
a := NewTestAgent(t.Name(), cfg)
|
2017-05-21 07:11:09 +00:00
|
|
|
defer a.Shutdown()
|
2016-12-15 03:28:09 +00:00
|
|
|
|
|
|
|
m := MockServer{catalogPolicy}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.InjectEndpoint("ACL", &m); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
checks := make(map[types.CheckID]*structs.HealthCheck)
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.filterChecks("node-ro", &checks); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
checks["my-node"] = &structs.HealthCheck{}
|
|
|
|
checks["my-service"] = &structs.HealthCheck{ServiceName: "service"}
|
|
|
|
checks["my-other"] = &structs.HealthCheck{ServiceName: "other"}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.filterChecks("service-ro", &checks); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if _, ok := checks["my-node"]; ok {
|
|
|
|
t.Fatalf("bad: %#v", checks)
|
|
|
|
}
|
|
|
|
if _, ok := checks["my-service"]; !ok {
|
|
|
|
t.Fatalf("bad: %#v", checks)
|
|
|
|
}
|
|
|
|
if _, ok := checks["my-other"]; ok {
|
|
|
|
t.Fatalf("bad: %#v", checks)
|
|
|
|
}
|
|
|
|
|
|
|
|
checks["my-node"] = &structs.HealthCheck{}
|
|
|
|
checks["my-service"] = &structs.HealthCheck{ServiceName: "service"}
|
|
|
|
checks["my-other"] = &structs.HealthCheck{ServiceName: "other"}
|
2017-05-21 07:11:09 +00:00
|
|
|
if err := a.filterChecks("node-ro", &checks); err != nil {
|
2016-12-15 03:28:09 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if _, ok := checks["my-node"]; !ok {
|
|
|
|
t.Fatalf("bad: %#v", checks)
|
|
|
|
}
|
|
|
|
if _, ok := checks["my-service"]; ok {
|
|
|
|
t.Fatalf("bad: %#v", checks)
|
|
|
|
}
|
|
|
|
if _, ok := checks["my-other"]; ok {
|
|
|
|
t.Fatalf("bad: %#v", checks)
|
|
|
|
}
|
|
|
|
}
|