2015-03-17 22:53:29 +00:00
|
|
|
package vault
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
2016-03-10 18:36:54 +00:00
|
|
|
"strings"
|
2015-03-17 22:53:29 +00:00
|
|
|
"testing"
|
2017-02-27 19:42:00 +00:00
|
|
|
"time"
|
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
|
2017-02-27 19:42:00 +00:00
|
|
|
# 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"
|
2017-02-27 19:42:00 +00:00
|
|
|
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
|
2017-02-27 19:42:00 +00:00
|
|
|
# Also tests reverse string/int handling to the above
|
2016-03-10 18:36:54 +00:00
|
|
|
path "foo/bar" {
|
|
|
|
capabilities = ["create", "sudo"]
|
2017-02-27 19:42:00 +00:00
|
|
|
min_wrapping_ttl = "300s"
|
|
|
|
max_wrapping_ttl = 3600
|
2016-03-10 18:36:54 +00:00
|
|
|
}
|
2016-10-28 17:18:31 +00:00
|
|
|
|
2017-01-20 00:40:19 +00:00
|
|
|
# Check that only allowed_parameters are being added to foobar
|
2016-10-28 17:18:31 +00:00
|
|
|
path "foo/bar" {
|
|
|
|
capabilities = ["create", "sudo"]
|
2017-02-16 02:12:26 +00:00
|
|
|
allowed_parameters = {
|
|
|
|
"zip" = []
|
|
|
|
"zap" = []
|
2016-10-28 17:18:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-20 00:40:19 +00:00
|
|
|
# Check that only denied_parameters are being added to bazbar
|
2016-10-28 17:18:31 +00:00
|
|
|
path "baz/bar" {
|
|
|
|
capabilities = ["create", "sudo"]
|
2017-02-16 02:12:26 +00:00
|
|
|
denied_parameters = {
|
|
|
|
"zip" = []
|
|
|
|
"zap" = []
|
2016-10-28 17:18:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# 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" = []
|
2016-10-28 17:18:31 +00:00
|
|
|
}
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
}
|
2017-11-02 11:18:49 +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"]
|
|
|
|
}
|
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{
|
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "",
|
2017-02-16 02:12:26 +00:00
|
|
|
Policy: "deny",
|
|
|
|
Capabilities: []string{
|
2016-01-07 20:10:05 +00:00
|
|
|
"deny",
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
Permissions: &ACLPermissions{CapabilitiesBitmap: DenyCapabilityInt},
|
2019-01-23 18:55:40 +00:00
|
|
|
IsPrefix: true,
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "stage/",
|
2017-02-16 02:12:26 +00:00
|
|
|
Policy: "sudo",
|
|
|
|
Capabilities: []string{
|
2016-01-07 20:10:05 +00:00
|
|
|
"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),
|
|
|
|
},
|
2019-01-23 18:55:40 +00:00
|
|
|
IsPrefix: true,
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "prod/version",
|
2017-02-16 02:12:26 +00:00
|
|
|
Policy: "read",
|
|
|
|
Capabilities: []string{
|
2016-01-07 20:10:05 +00:00
|
|
|
"read",
|
|
|
|
"list",
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
Permissions: &ACLPermissions{CapabilitiesBitmap: (ReadCapabilityInt | ListCapabilityInt)},
|
2019-01-23 18:55:40 +00:00
|
|
|
IsPrefix: false,
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "foo/bar",
|
2017-02-16 02:12:26 +00:00
|
|
|
Policy: "read",
|
|
|
|
Capabilities: []string{
|
2016-01-07 20:10:05 +00:00
|
|
|
"read",
|
|
|
|
"list",
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-02-27 19:42:00 +00:00
|
|
|
MinWrappingTTLHCL: 300,
|
|
|
|
MaxWrappingTTLHCL: "1h",
|
2017-10-23 18:59:37 +00:00
|
|
|
Permissions: &ACLPermissions{
|
2017-02-27 19:42:00 +00:00
|
|
|
CapabilitiesBitmap: (ReadCapabilityInt | ListCapabilityInt),
|
|
|
|
MinWrappingTTL: 300 * time.Second,
|
|
|
|
MaxWrappingTTL: 3600 * time.Second,
|
|
|
|
},
|
2019-01-23 18:55:40 +00:00
|
|
|
IsPrefix: false,
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "foo/bar",
|
2017-02-16 02:12:26 +00:00
|
|
|
Policy: "",
|
|
|
|
Capabilities: []string{
|
2016-01-07 20:10:05 +00:00
|
|
|
"create",
|
|
|
|
"sudo",
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-02-27 19:42:00 +00:00
|
|
|
MinWrappingTTLHCL: "300s",
|
|
|
|
MaxWrappingTTLHCL: 3600,
|
2017-10-23 18:59:37 +00:00
|
|
|
Permissions: &ACLPermissions{
|
2017-02-27 19:42:00 +00:00
|
|
|
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
|
|
|
|
MinWrappingTTL: 300 * time.Second,
|
|
|
|
MaxWrappingTTL: 3600 * time.Second,
|
|
|
|
},
|
2019-01-23 18:55:40 +00:00
|
|
|
IsPrefix: false,
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "foo/bar",
|
2017-02-16 02:12:26 +00:00
|
|
|
Policy: "",
|
|
|
|
Capabilities: []string{
|
2016-10-28 17:18:31 +00:00
|
|
|
"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 18:55:40 +00:00
|
|
|
IsPrefix: false,
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "baz/bar",
|
2017-02-16 02:12:26 +00:00
|
|
|
Policy: "",
|
|
|
|
Capabilities: []string{
|
2016-10-28 17:18:31 +00:00
|
|
|
"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 18:55:40 +00:00
|
|
|
IsPrefix: false,
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "biz/bar",
|
2017-02-16 02:12:26 +00:00
|
|
|
Policy: "",
|
|
|
|
Capabilities: []string{
|
2016-10-28 17:18:31 +00:00
|
|
|
"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 18:55:40 +00:00
|
|
|
IsPrefix: false,
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-10-23 18:59:37 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +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}},
|
|
|
|
},
|
2019-01-23 18:55:40 +00:00
|
|
|
IsPrefix: false,
|
2017-01-20 02:13:39 +00:00
|
|
|
},
|
2017-11-02 11:18:49 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "test/req",
|
2017-11-02 11:18:49 +00:00
|
|
|
Policy: "",
|
|
|
|
Capabilities: []string{
|
|
|
|
"create",
|
|
|
|
"sudo",
|
|
|
|
},
|
|
|
|
RequiredParametersHCL: []string{"foo"},
|
|
|
|
Permissions: &ACLPermissions{
|
|
|
|
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
|
|
|
|
RequiredParameters: []string{"foo"},
|
|
|
|
},
|
2019-01-23 18:55:40 +00:00
|
|
|
IsPrefix: false,
|
2017-11-02 11:18:49 +00:00
|
|
|
},
|
2018-09-18 03:03:00 +00:00
|
|
|
&PathRules{
|
2019-01-23 20:04:49 +00:00
|
|
|
Path: "test/mfa",
|
2018-09-18 03:03:00 +00:00
|
|
|
Policy: "",
|
|
|
|
Capabilities: []string{
|
|
|
|
"create",
|
|
|
|
"sudo",
|
|
|
|
},
|
|
|
|
MFAMethodsHCL: []string{
|
|
|
|
"my_totp",
|
|
|
|
"my_totp2",
|
|
|
|
},
|
|
|
|
Permissions: &ACLPermissions{
|
|
|
|
CapabilitiesBitmap: (CreateCapabilityInt | SudoCapabilityInt),
|
|
|
|
MFAMethods: []string{
|
|
|
|
"my_totp",
|
|
|
|
"my_totp2",
|
|
|
|
},
|
|
|
|
},
|
2019-01-23 18:55:40 +00:00
|
|
|
IsPrefix: false,
|
2018-09-18 03:03:00 +00:00
|
|
|
},
|
2015-03-17 22:53:29 +00:00
|
|
|
}
|
2018-09-18 03:03:00 +00:00
|
|
|
|
2015-03-17 22:53:29 +00:00
|
|
|
if !reflect.DeepEqual(p.Paths, expect) {
|
2016-03-10 18:36:54 +00:00
|
|
|
t.Errorf("expected \n\n%#v\n\n to be \n\n%#v\n\n", p.Paths, expect)
|
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
|
|
|
|
2018-04-06 00:43: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)
|
|
|
|
}
|
|
|
|
|
2018-04-06 00:43:29 +00:00
|
|
|
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-01-07 20:10:05 +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-01-07 20:10:05 +00:00
|
|
|
}
|
2016-03-10 18:36:54 +00:00
|
|
|
`))
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected error")
|
|
|
|
}
|
2016-01-07 20:10:05 +00:00
|
|
|
|
2018-04-06 00:43:29 +00:00
|
|
|
if !strings.Contains(err.Error(), `path "/": invalid policy "banana"`) {
|
2016-03-10 18:36:54 +00:00
|
|
|
t.Errorf("bad error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-27 19:42:00 +00:00
|
|
|
func TestPolicy_ParseBadWrapping(t *testing.T) {
|
2018-09-18 03:03:00 +00:00
|
|
|
_, err := ParseACLPolicy(namespace.RootNamespace, strings.TrimSpace(`
|
2017-02-27 19:42:00 +00:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2018-04-06 00:43:29 +00:00
|
|
|
if !strings.Contains(err.Error(), `path "/": invalid capability "banana"`) {
|
2016-03-10 18:36:54 +00:00
|
|
|
t.Errorf("bad error: %s", err)
|
|
|
|
}
|
2016-01-07 20:10:05 +00:00
|
|
|
}
|