Allowed/Denied parameters support for globs (#2438)

* Add check for globbed strings

* Add tests for the acl globbing

* Fix bad test case
This commit is contained in:
Brian Kassouf 2017-03-03 14:50:55 -08:00 committed by GitHub
parent 111fbc5747
commit e62f5dbc31
4 changed files with 70 additions and 3 deletions

View File

@ -255,3 +255,22 @@ func StrListDelete(s []string, d string) []string {
return s
}
func GlobbedStringsMatch(item, val string) bool {
if len(item) < 2 {
return val == item
}
hasPrefix := strings.HasPrefix(item, "*")
hasSuffix := strings.HasSuffix(item, "*")
if hasPrefix && hasSuffix {
return strings.Contains(val, item[1:len(item)-1])
} else if hasPrefix {
return strings.HasSuffix(val, item[1:])
} else if hasSuffix {
return strings.HasPrefix(val, item[:len(item)-1])
}
return val == item
}

View File

@ -279,3 +279,39 @@ $$`,
t.Fatalf("bad: expected:\n%#v\nactual:\n%#v", jsonExpected, actual)
}
}
func TestGlobbedStringsMatch(t *testing.T) {
type tCase struct {
item string
val string
expect bool
}
tCases := []tCase{
tCase{"", "", true},
tCase{"*", "*", true},
tCase{"**", "**", true},
tCase{"*t", "t", true},
tCase{"*t", "test", true},
tCase{"t*", "test", true},
tCase{"*test", "test", true},
tCase{"*test", "a test", true},
tCase{"test", "a test", false},
tCase{"*test", "tests", false},
tCase{"test*", "test", true},
tCase{"test*", "testsss", true},
tCase{"test**", "testsss", false},
tCase{"test**", "test*", true},
tCase{"**test", "*test", true},
tCase{"TEST", "test", false},
tCase{"test", "test", true},
}
for _, tc := range tCases {
actual := GlobbedStringsMatch(tc.item, tc.val)
if actual != tc.expect {
t.Fatalf("Bad testcase %#v, expected %b, got %b", tc, tc.expect, actual)
}
}
}

View File

@ -5,6 +5,7 @@ import (
"strings"
"github.com/armon/go-radix"
"github.com/hashicorp/vault/helper/strutil"
"github.com/hashicorp/vault/logical"
)
@ -348,7 +349,14 @@ func valueInParameterList(v interface{}, list []interface{}) bool {
func valueInSlice(v interface{}, list []interface{}) bool {
for _, el := range list {
if reflect.DeepEqual(el, v) {
if reflect.TypeOf(el).String() == "string" && reflect.TypeOf(v).String() == "string" {
item := el.(string)
val := v.(string)
if strutil.GlobbedStringsMatch(item, val) {
return true
}
} else if reflect.DeepEqual(el, v) {
return true
}
}

View File

@ -366,6 +366,7 @@ func TestACL_ValuePermissions(t *testing.T) {
{"dev/ops", []string{"allow"}, []interface{}{"good"}, true},
{"dev/ops", []string{"allow"}, []interface{}{"bad"}, false},
{"foo/bar", []string{"deny"}, []interface{}{"bad"}, false},
{"foo/bar", []string{"deny"}, []interface{}{"bad glob"}, false},
{"foo/bar", []string{"deny"}, []interface{}{"good"}, true},
{"foo/bar", []string{"allow"}, []interface{}{"good"}, true},
{"foo/baz", []string{"aLLow"}, []interface{}{"good"}, true},
@ -379,6 +380,9 @@ func TestACL_ValuePermissions(t *testing.T) {
{"fizz/buzz", []string{"allow_multi"}, []interface{}{"good"}, true},
{"fizz/buzz", []string{"allow_multi"}, []interface{}{"good1"}, true},
{"fizz/buzz", []string{"allow_multi"}, []interface{}{"good2"}, true},
{"fizz/buzz", []string{"allow_multi"}, []interface{}{"glob good2"}, false},
{"fizz/buzz", []string{"allow_multi"}, []interface{}{"glob good3"}, true},
{"fizz/buzz", []string{"allow_multi"}, []interface{}{"bad"}, false},
{"fizz/buzz", []string{"allow_multi"}, []interface{}{"bad"}, false},
{"fizz/buzz", []string{"allow_multi", "allow"}, []interface{}{"good1", "good"}, true},
{"fizz/buzz", []string{"deny_multi"}, []interface{}{"bad2"}, false},
@ -686,7 +690,7 @@ path "dev/*" {
path "foo/bar" {
policy = "write"
denied_parameters = {
"deny" = ["bad"]
"deny" = ["bad*"]
}
}
path "foo/baz" {
@ -701,7 +705,7 @@ path "foo/baz" {
path "fizz/buzz" {
policy = "write"
allowed_parameters = {
"allow_multi" = ["good", "good1", "good2"]
"allow_multi" = ["good", "good1", "good2", "*good3"]
"allow" = ["good"]
}
denied_parameters = {