open-vault/vault/policy_test.go

432 lines
9.7 KiB
Go
Raw Normal View History

2015-03-17 22:53:29 +00:00
package vault
import (
2016-03-10 18:36:54 +00:00
"strings"
2015-03-17 22:53:29 +00:00
"testing"
"time"
2018-09-18 03:03:00 +00:00
"github.com/go-test/deep"
2018-09-18 03:03:00 +00:00
"github.com/hashicorp/vault/helper/namespace"
2015-03-17 22:53:29 +00:00
)
2016-03-10 18:36:54 +00:00
var rawPolicy = strings.TrimSpace(`
# Developer policy
name = "dev"
# Deny all paths by default
path "*" {
policy = "deny"
}
# Allow full access to staging
path "stage/*" {
policy = "sudo"
}
# Limited read privilege to production
path "prod/version" {
policy = "read"
}
# Read access to foobar
# Also tests stripping of leading slash and parsing of min/max as string and
# integer
2016-03-10 18:36:54 +00:00
path "/foo/bar" {
policy = "read"
min_wrapping_ttl = 300
max_wrapping_ttl = "1h"
2016-03-10 18:36:54 +00:00
}
# Add capabilities for creation and sudo to foobar
# This will be separate; they are combined when compiled into an ACL
# Also tests reverse string/int handling to the above
2016-03-10 18:36:54 +00:00
path "foo/bar" {
capabilities = ["create", "sudo"]
min_wrapping_ttl = "300s"
max_wrapping_ttl = 3600
2016-03-10 18:36:54 +00:00
}
# Check that only allowed_parameters are being added to foobar
path "foo/bar" {
capabilities = ["create", "sudo"]
2017-02-16 02:12:26 +00:00
allowed_parameters = {
"zip" = []
"zap" = []
}
}
# Check that only denied_parameters are being added to bazbar
path "baz/bar" {
capabilities = ["create", "sudo"]
2017-02-16 02:12:26 +00:00
denied_parameters = {
"zip" = []
"zap" = []
}
}
# Check that both allowed and denied parameters are being added to bizbar
path "biz/bar" {
capabilities = ["create", "sudo"]
2017-02-16 02:12:26 +00:00
allowed_parameters = {
"zim" = []
"zam" = []
}
denied_parameters = {
"zip" = []
"zap" = []
}
}
2017-01-20 02:13:39 +00:00
path "test/types" {
capabilities = ["create", "sudo"]
2017-02-16 02:12:26 +00:00
allowed_parameters = {
"map" = [{"good" = "one"}]
"int" = [1, 2]
}
denied_parameters = {
"string" = ["test"]
"bool" = [false]
2017-01-20 02:13:39 +00:00
}
}
path "test/req" {
capabilities = ["create", "sudo"]
required_parameters = ["foo"]
}
2018-09-18 03:03:00 +00:00
path "test/mfa" {
capabilities = ["create", "sudo"]
mfa_methods = ["my_totp", "my_totp2"]
}
path "test/+/segment" {
capabilities = ["create", "sudo"]
}
path "test/segment/at/end/+" {
capabilities = ["create", "sudo"]
}
path "test/segment/at/end/v2/+/" {
capabilities = ["create", "sudo"]
}
path "test/+/wildcard/+/*" {
capabilities = ["create", "sudo"]
}
path "test/+/wildcard/+/end*" {
capabilities = ["create", "sudo"]
}
2016-03-10 18:36:54 +00:00
`)
2015-03-17 22:53:29 +00:00
func TestPolicy_Parse(t *testing.T) {
2018-09-18 03:03:00 +00:00
p, err := ParseACLPolicy(namespace.RootNamespace, rawPolicy)
2015-03-17 22:53:29 +00:00
if err != nil {
t.Fatalf("err: %v", err)
}
if p.Name != "dev" {
2016-03-10 18:36:54 +00:00
t.Fatalf("bad name: %q", p.Name)
2015-03-17 22:53:29 +00:00
}
2017-10-23 18:59:37 +00:00
expect := []*PathRules{
2019-01-23 22:19:06 +00:00
{
Path: "",
2017-02-16 02:12:26 +00:00
Policy: "deny",
Capabilities: []string{
"deny",
2017-01-20 02:13:39 +00:00
},
2017-10-23 18:59:37 +00:00
Permissions: &ACLPermissions{CapabilitiesBitmap: DenyCapabilityInt},
IsPrefix: true,
2017-01-20 02:13:39 +00:00
},
2019-01-23 22:19:06 +00:00
{
Path: "stage/",
2017-02-16 02:12:26 +00:00
Policy: "sudo",
Capabilities: []string{
"create",
"read",
"update",
"delete",
"list",
"sudo",
2017-01-20 02:13:39 +00:00
},
2017-10-23 18:59:37 +00:00
Permissions: &ACLPermissions{
2017-01-20 02:13:39 +00:00
CapabilitiesBitmap: (CreateCapabilityInt | ReadCapabilityInt | UpdateCapabilityInt | DeleteCapabilityInt | ListCapabilityInt | SudoCapabilityInt),
},
IsPrefix: true,
2017-01-20 02:13:39 +00:00
},
2019-01-23 22:19:06 +00:00
{
Path: "prod/version",
2017-02-16 02:12:26 +00:00
Policy: "read",
Capabilities: []string{
"read",
"list",
2017-01-20 02:13:39 +00:00
},
2017-10-23 18:59:37 +00:00
Permissions: &ACLPermissions{CapabilitiesBitmap: (ReadCapabilityInt | ListCapabilityInt)},
2017-01-20 02:13:39 +00:00
},
2019-01-23 22:19:06 +00:00
{
Path: "foo/bar",
2017-02-16 02:12:26 +00:00
Policy: "read",
Capabilities: []string{
"read",
"list",
2017-01-20 02:13:39 +00:00
},
MinWrappingTTLHCL: 300,
MaxWrappingTTLHCL: "1h",
2017-10-23 18:59:37 +00:00
Permissions: &ACLPermissions{
CapabilitiesBitmap: (ReadCapabilityInt | ListCapabilityInt),
MinWrappingTTL: 300 * time.Second,
MaxWrappingTTL: 3600 * time.Second,
},
2017-01-20 02:13:39 +00:00
},
2019-01-23 22:19:06 +00:00
{
Path: "foo/bar",
2017-02-16 02:12:26 +00:00
Capabilities: []string{
"create",
"sudo",
2017-01-20 02:13:39 +00:00
},
MinWrappingTTLHCL: "300s",
MaxWrappingTTLHCL: 3600,
2017-10-23 18:59:37 +00:00
Permissions: &ACLPermissions{
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
MinWrappingTTL: 300 * time.Second,
MaxWrappingTTL: 3600 * time.Second,
},
2017-01-20 02:13:39 +00:00
},
2019-01-23 22:19:06 +00:00
{
Path: "foo/bar",
2017-02-16 02:12:26 +00:00
Capabilities: []string{
"create",
"sudo",
2017-01-20 02:13:39 +00:00
},
2017-02-16 02:12:26 +00:00
AllowedParametersHCL: map[string][]interface{}{"zip": {}, "zap": {}},
2017-10-23 18:59:37 +00:00
Permissions: &ACLPermissions{
2017-01-20 02:13:39 +00:00
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
AllowedParameters: map[string][]interface{}{"zip": {}, "zap": {}},
},
},
2019-01-23 22:19:06 +00:00
{
Path: "baz/bar",
2017-02-16 02:12:26 +00:00
Capabilities: []string{
"create",
"sudo",
2017-01-20 02:13:39 +00:00
},
2017-02-16 02:12:26 +00:00
DeniedParametersHCL: map[string][]interface{}{"zip": []interface{}{}, "zap": []interface{}{}},
2017-10-23 18:59:37 +00:00
Permissions: &ACLPermissions{
2017-01-20 02:13:39 +00:00
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
DeniedParameters: map[string][]interface{}{"zip": []interface{}{}, "zap": []interface{}{}},
},
},
2019-01-23 22:19:06 +00:00
{
Path: "biz/bar",
2017-02-16 02:12:26 +00:00
Capabilities: []string{
"create",
"sudo",
2017-01-20 02:13:39 +00:00
},
2017-02-16 02:12:26 +00:00
AllowedParametersHCL: map[string][]interface{}{"zim": {}, "zam": {}},
DeniedParametersHCL: map[string][]interface{}{"zip": {}, "zap": {}},
2017-10-23 18:59:37 +00:00
Permissions: &ACLPermissions{
2017-01-20 02:13:39 +00:00
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
AllowedParameters: map[string][]interface{}{"zim": {}, "zam": {}},
DeniedParameters: map[string][]interface{}{"zip": {}, "zap": {}},
},
},
2019-01-23 22:19:06 +00:00
{
Path: "test/types",
2017-02-16 02:12:26 +00:00
Policy: "",
Capabilities: []string{
2017-01-20 02:13:39 +00:00
"create",
"sudo",
},
2017-02-16 02:12:26 +00:00
AllowedParametersHCL: map[string][]interface{}{"map": []interface{}{map[string]interface{}{"good": "one"}}, "int": []interface{}{1, 2}},
DeniedParametersHCL: map[string][]interface{}{"string": []interface{}{"test"}, "bool": []interface{}{false}},
2017-10-23 18:59:37 +00:00
Permissions: &ACLPermissions{
2017-01-20 02:13:39 +00:00
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
AllowedParameters: map[string][]interface{}{"map": []interface{}{map[string]interface{}{"good": "one"}}, "int": []interface{}{1, 2}},
DeniedParameters: map[string][]interface{}{"string": []interface{}{"test"}, "bool": []interface{}{false}},
},
IsPrefix: false,
2017-01-20 02:13:39 +00:00
},
2019-01-23 22:19:06 +00:00
{
Path: "test/req",
Capabilities: []string{
"create",
"sudo",
},
RequiredParametersHCL: []string{"foo"},
Permissions: &ACLPermissions{
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
RequiredParameters: []string{"foo"},
},
},
2019-01-23 22:19:06 +00:00
{
Path: "test/mfa",
2018-09-18 03:03:00 +00:00
Capabilities: []string{
"create",
"sudo",
},
MFAMethodsHCL: []string{
"my_totp",
"my_totp2",
},
Permissions: &ACLPermissions{
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
MFAMethods: []string{
"my_totp",
"my_totp2",
},
},
},
{
Path: "test/+/segment",
Capabilities: []string{
"create",
"sudo",
},
Permissions: &ACLPermissions{
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
},
HasSegmentWildcards: true,
},
{
Path: "test/segment/at/end/+",
Capabilities: []string{
"create",
"sudo",
},
Permissions: &ACLPermissions{
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
},
HasSegmentWildcards: true,
},
{
Path: "test/segment/at/end/v2/+/",
Capabilities: []string{
"create",
"sudo",
},
Permissions: &ACLPermissions{
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
},
HasSegmentWildcards: true,
},
{
Path: "test/+/wildcard/+/*",
Capabilities: []string{
"create",
"sudo",
},
Permissions: &ACLPermissions{
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
},
HasSegmentWildcards: true,
},
{
Path: "test/+/wildcard/+/end*",
Capabilities: []string{
"create",
"sudo",
},
Permissions: &ACLPermissions{
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
},
HasSegmentWildcards: true,
2018-09-18 03:03:00 +00:00
},
2015-03-17 22:53:29 +00:00
}
2018-09-18 03:03:00 +00:00
if diff := deep.Equal(p.Paths, expect); diff != nil {
t.Error(diff)
2015-03-17 22:53:29 +00:00
}
}
2016-03-10 18:36:54 +00:00
func TestPolicy_ParseBadRoot(t *testing.T) {
2018-09-18 03:03:00 +00:00
_, err := ParseACLPolicy(namespace.RootNamespace, strings.TrimSpace(`
2016-03-10 18:36:54 +00:00
name = "test"
bad = "foo"
nope = "yes"
`))
if err == nil {
t.Fatalf("expected error")
}
2015-03-17 22:53:29 +00:00
if !strings.Contains(err.Error(), `invalid key "bad" on line 2`) {
2016-03-10 18:36:54 +00:00
t.Errorf("bad error: %q", err)
}
if !strings.Contains(err.Error(), `invalid key "nope" on line 3`) {
2016-03-10 18:36:54 +00:00
t.Errorf("bad error: %q", err)
}
2015-03-17 22:53:29 +00:00
}
2016-03-10 18:36:54 +00:00
func TestPolicy_ParseBadPath(t *testing.T) {
2018-11-13 18:30:42 +00:00
// The wrong spelling is intended here
2018-09-18 03:03:00 +00:00
_, err := ParseACLPolicy(namespace.RootNamespace, strings.TrimSpace(`
2016-03-10 18:36:54 +00:00
path "/" {
capabilities = ["read"]
2018-11-13 18:22:56 +00:00
capabilites = ["read"]
2015-03-17 22:53:29 +00:00
}
2016-03-10 18:36:54 +00:00
`))
if err == nil {
t.Fatalf("expected error")
}
2015-03-17 22:53:29 +00:00
2018-11-13 18:22:56 +00:00
if !strings.Contains(err.Error(), `invalid key "capabilites" on line 3`) {
2016-03-10 18:36:54 +00:00
t.Errorf("bad error: %s", err)
}
2015-03-17 22:53:29 +00:00
}
2016-03-10 18:36:54 +00:00
func TestPolicy_ParseBadPolicy(t *testing.T) {
2018-09-18 03:03:00 +00:00
_, err := ParseACLPolicy(namespace.RootNamespace, strings.TrimSpace(`
2016-03-10 18:36:54 +00:00
path "/" {
policy = "banana"
}
2016-03-10 18:36:54 +00:00
`))
if err == nil {
t.Fatalf("expected error")
}
if !strings.Contains(err.Error(), `path "/": invalid policy "banana"`) {
2016-03-10 18:36:54 +00:00
t.Errorf("bad error: %s", err)
}
}
func TestPolicy_ParseBadWrapping(t *testing.T) {
2018-09-18 03:03:00 +00:00
_, err := ParseACLPolicy(namespace.RootNamespace, strings.TrimSpace(`
path "/" {
policy = "read"
min_wrapping_ttl = 400
max_wrapping_ttl = 200
}
`))
if err == nil {
t.Fatalf("expected error")
}
if !strings.Contains(err.Error(), `max_wrapping_ttl cannot be less than min_wrapping_ttl`) {
t.Errorf("bad error: %s", err)
}
}
2016-03-10 18:36:54 +00:00
func TestPolicy_ParseBadCapabilities(t *testing.T) {
2018-09-18 03:03:00 +00:00
_, err := ParseACLPolicy(namespace.RootNamespace, strings.TrimSpace(`
2016-03-10 18:36:54 +00:00
path "/" {
capabilities = ["read", "banana"]
}
`))
if err == nil {
t.Fatalf("expected error")
}
if !strings.Contains(err.Error(), `path "/": invalid capability "banana"`) {
2016-03-10 18:36:54 +00:00
t.Errorf("bad error: %s", err)
}
}
func TestPolicy_ParseBadSegmentWildcard(t *testing.T) {
_, err := ParseACLPolicy(namespace.RootNamespace, strings.TrimSpace(`
path "foo/+*" {
capabilities = ["read"]
}
`))
if err == nil {
t.Fatalf("expected error")
}
if !strings.Contains(err.Error(), `path "foo/+*": invalid use of wildcards ('+*' is forbidden)`) {
t.Errorf("bad error: %s", err)
}
}