vault: Adding precedence logic for conflicting policy

This commit is contained in:
Armon Dadgar 2015-07-05 17:30:19 -06:00
parent 27d01270c8
commit eda88c18ff
2 changed files with 76 additions and 9 deletions

View File

@ -14,15 +14,6 @@ const (
PathPolicySudo = "sudo"
)
var (
pathPolicyLevel = map[string]int{
PathPolicyDeny: 0,
PathPolicyRead: 1,
PathPolicyWrite: 2,
PathPolicySudo: 3,
}
)
// Policy is used to represent the policy specified by
// an ACL configuration.
type Policy struct {
@ -38,6 +29,46 @@ type PathPolicy struct {
Glob bool
}
// TakesPrecedence is used when multiple policies
// collide on a path to determine which policy takes
// precendence.
func (p *PathPolicy) TakesPrecedence(other *PathPolicy) bool {
// Handle the full merge matrix
switch p.Policy {
case PathPolicyDeny:
// Deny always takes precendence
return true
case PathPolicyRead:
// Read never takes precedence
return false
case PathPolicyWrite:
switch other.Policy {
case PathPolicyRead:
return true
case PathPolicyDeny, PathPolicyWrite, PathPolicySudo:
return false
default:
panic("missing case")
}
case PathPolicySudo:
switch other.Policy {
case PathPolicyRead, PathPolicyWrite:
return true
case PathPolicyDeny, PathPolicySudo:
return false
default:
panic("missing case")
}
default:
panic("missing case")
}
return false
}
// Parse is used to parse the specified ACL rules into an
// intermediary set of policies, before being compiled into
// the ACL

View File

@ -5,6 +5,42 @@ import (
"testing"
)
func TestPolicy_TakesPrecedence(t *testing.T) {
type tcase struct {
a, b string
precedence bool
}
tests := []tcase{
tcase{PathPolicyDeny, PathPolicyDeny, true},
tcase{PathPolicyDeny, PathPolicyRead, true},
tcase{PathPolicyDeny, PathPolicyWrite, true},
tcase{PathPolicyDeny, PathPolicySudo, true},
tcase{PathPolicyRead, PathPolicyDeny, false},
tcase{PathPolicyRead, PathPolicyRead, false},
tcase{PathPolicyRead, PathPolicyWrite, false},
tcase{PathPolicyRead, PathPolicySudo, false},
tcase{PathPolicyWrite, PathPolicyDeny, false},
tcase{PathPolicyWrite, PathPolicyRead, true},
tcase{PathPolicyWrite, PathPolicyWrite, false},
tcase{PathPolicyWrite, PathPolicySudo, false},
tcase{PathPolicySudo, PathPolicyDeny, false},
tcase{PathPolicySudo, PathPolicyRead, true},
tcase{PathPolicySudo, PathPolicyWrite, true},
tcase{PathPolicySudo, PathPolicySudo, false},
}
for idx, test := range tests {
a := &PathPolicy{Policy: test.a}
b := &PathPolicy{Policy: test.b}
if out := a.TakesPrecedence(b); out != test.precedence {
t.Fatalf("bad: idx %d expect: %v out: %v",
idx, test.precedence, out)
}
}
}
func TestPolicy_Parse(t *testing.T) {
p, err := Parse(rawPolicy)
if err != nil {