vault: Adding precedence logic for conflicting policy
This commit is contained in:
parent
27d01270c8
commit
eda88c18ff
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue