open-nomad/nomad/consul_policy_test.go

203 lines
5 KiB
Go

package nomad
import (
"testing"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/nomad/command/agent/consul"
"github.com/hashicorp/nomad/helper/testlog"
"github.com/stretchr/testify/require"
)
func TestConsulPolicy_ParseConsulPolicy(t *testing.T) {
t.Parallel()
try := func(t *testing.T, text string, expPolicy *ConsulPolicy, expErr string) {
policy, err := ParseConsulPolicy(text)
if expErr != "" {
require.EqualError(t, err, expErr)
require.True(t, policy.IsEmpty())
} else {
require.NoError(t, err)
require.Equal(t, expPolicy, policy)
}
}
t.Run("service", func(t *testing.T) {
text := `service "web" { policy = "read" }`
exp := &ConsulPolicy{
Services: []*ConsulServiceRule{{Name: "web", Policy: "read"}},
ServicePrefixes: []*ConsulServiceRule(nil),
}
try(t, text, exp, "")
})
t.Run("service_prefix", func(t *testing.T) {
text := `service_prefix "data" { policy = "write" }`
exp := &ConsulPolicy{
Services: []*ConsulServiceRule(nil),
ServicePrefixes: []*ConsulServiceRule{{Name: "data", Policy: "write"}},
}
try(t, text, exp, "")
})
t.Run("empty", func(t *testing.T) {
text := ``
expErr := "consul policy contains no service rules"
try(t, text, nil, expErr)
})
t.Run("malformed", func(t *testing.T) {
text := `this is not valid HCL!`
expErr := "failed to parse ACL policy: At 1:22: illegal char"
try(t, text, nil, expErr)
})
}
func TestConsulPolicy_IsEmpty(t *testing.T) {
t.Parallel()
try := func(t *testing.T, cp *ConsulPolicy, exp bool) {
result := cp.IsEmpty()
require.Equal(t, exp, result)
}
t.Run("nil", func(t *testing.T) {
cp := (*ConsulPolicy)(nil)
try(t, cp, true)
})
t.Run("empty slices", func(t *testing.T) {
cp := &ConsulPolicy{
Services: []*ConsulServiceRule(nil),
ServicePrefixes: []*ConsulServiceRule(nil),
}
try(t, cp, true)
})
t.Run("services nonempty", func(t *testing.T) {
cp := &ConsulPolicy{
Services: []*ConsulServiceRule{{Name: "example", Policy: "write"}},
}
try(t, cp, false)
})
t.Run("service_prefixes nonempty", func(t *testing.T) {
cp := &ConsulPolicy{
ServicePrefixes: []*ConsulServiceRule{{Name: "pre", Policy: "read"}},
}
try(t, cp, false)
})
}
func TestConsulACLsAPI_allowsServiceWrite(t *testing.T) {
t.Parallel()
try := func(t *testing.T, task string, cp *ConsulPolicy, exp bool) {
result := cp.allowsServiceWrite(task)
require.Equal(t, exp, result)
}
makeCP := func(services [][2]string, prefixes [][2]string) *ConsulPolicy {
serviceRules := make([]*ConsulServiceRule, 0, len(services))
for _, service := range services {
serviceRules = append(serviceRules, &ConsulServiceRule{Name: service[0], Policy: service[1]})
}
prefixRules := make([]*ConsulServiceRule, 0, len(prefixes))
for _, prefix := range prefixes {
prefixRules = append(prefixRules, &ConsulServiceRule{Name: prefix[0], Policy: prefix[1]})
}
return &ConsulPolicy{Services: serviceRules, ServicePrefixes: prefixRules}
}
t.Run("matching service policy write", func(t *testing.T) {
try(t, "task1", makeCP(
[][2]string{{"task1", "write"}},
nil,
), true)
})
t.Run("matching service policy read", func(t *testing.T) {
try(t, "task1", makeCP(
[][2]string{{"task1", "read"}},
nil,
), false)
})
t.Run("wildcard service policy write", func(t *testing.T) {
try(t, "task1", makeCP(
[][2]string{{"*", "write"}},
nil,
), true)
})
t.Run("wrong service policy write", func(t *testing.T) {
try(t, "other1", makeCP(
[][2]string{{"task1", "write"}},
nil,
), false)
})
t.Run("matching prefix policy write", func(t *testing.T) {
try(t, "task-one", makeCP(
nil,
[][2]string{{"task-", "write"}},
), true)
})
t.Run("matching prefix policy read", func(t *testing.T) {
try(t, "task-one", makeCP(
nil,
[][2]string{{"task-", "read"}},
), false)
})
t.Run("empty prefix policy write", func(t *testing.T) {
try(t, "task-one", makeCP(
nil,
[][2]string{{"", "write"}},
), true)
})
t.Run("late matching service", func(t *testing.T) {
try(t, "task1", makeCP(
[][2]string{{"task0", "write"}, {"task1", "write"}},
nil,
), true)
})
t.Run("late matching prefix", func(t *testing.T) {
try(t, "task-one", makeCP(
nil,
[][2]string{{"foo-", "write"}, {"task-", "write"}},
), true)
})
}
func TestConsulACLsAPI_hasSufficientPolicy(t *testing.T) {
t.Parallel()
try := func(t *testing.T, task string, token *api.ACLToken, exp bool) {
logger := testlog.HCLogger(t)
cAPI := &consulACLsAPI{
aclClient: consul.NewMockACLsAPI(logger),
logger: logger,
}
result, err := cAPI.hasSufficientPolicy(task, token)
require.NoError(t, err)
require.Equal(t, exp, result)
}
t.Run("no useful policy or role", func(t *testing.T) {
try(t, "service1", consul.ExampleOperatorToken0, false)
})
t.Run("working policy only", func(t *testing.T) {
try(t, "service1", consul.ExampleOperatorToken1, true)
})
t.Run("working role only", func(t *testing.T) {
try(t, "service1", consul.ExampleOperatorToken4, true)
})
}