acl: Simplify parent ACL, adding root policies
This commit is contained in:
parent
9e16caa497
commit
32e1f8e259
12
acl/acl.go
12
acl/acl.go
|
@ -49,6 +49,18 @@ func DenyAll() ACL {
|
|||
return denyAll
|
||||
}
|
||||
|
||||
// RootACL returns a possible ACL if the ID matches a root policy
|
||||
func RootACL(id string) ACL {
|
||||
switch id {
|
||||
case "allow":
|
||||
return allowAll
|
||||
case "deny":
|
||||
return denyAll
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// PolicyACL is used to wrap a set of ACL policies to provide
|
||||
// the ACL interface.
|
||||
type PolicyACL struct {
|
||||
|
|
|
@ -4,6 +4,18 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestRootACL(t *testing.T) {
|
||||
if RootACL("allow") != AllowAll() {
|
||||
t.Fatalf("Bad root")
|
||||
}
|
||||
if RootACL("deny") != DenyAll() {
|
||||
t.Fatalf("Bad root")
|
||||
}
|
||||
if RootACL("foo") != nil {
|
||||
t.Fatalf("bad root")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStaticACL(t *testing.T) {
|
||||
all := AllowAll()
|
||||
if _, ok := all.(*StaticACL); !ok {
|
||||
|
|
29
acl/cache.go
29
acl/cache.go
|
@ -7,9 +7,9 @@ import (
|
|||
"github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// FaultFunc is a function used to fault in the rules for an
|
||||
// ACL given it's ID
|
||||
type FaultFunc func(id string) (string, error)
|
||||
// FaultFunc is a function used to fault in the parent,
|
||||
// rules for an ACL given it's ID
|
||||
type FaultFunc func(id string) (string, string, error)
|
||||
|
||||
// aclEntry allows us to store the ACL with it's policy ID
|
||||
type aclEntry struct {
|
||||
|
@ -19,15 +19,14 @@ type aclEntry struct {
|
|||
|
||||
// Cache is used to implement policy and ACL caching
|
||||
type Cache struct {
|
||||
aclCache *lru.Cache // Cache id -> acl
|
||||
faultfn FaultFunc
|
||||
parent ACL
|
||||
aclCache *lru.Cache // Cache id -> acl
|
||||
policyCache *lru.Cache // Cache policy -> acl
|
||||
ruleCache *lru.Cache // Cache rules -> policy
|
||||
}
|
||||
|
||||
// NewCache contructs a new policy and ACL cache of a given size
|
||||
func NewCache(size int, parent ACL, faultfn FaultFunc) (*Cache, error) {
|
||||
func NewCache(size int, faultfn FaultFunc) (*Cache, error) {
|
||||
if size <= 0 {
|
||||
return nil, fmt.Errorf("Must provide positive cache size")
|
||||
}
|
||||
|
@ -35,9 +34,8 @@ func NewCache(size int, parent ACL, faultfn FaultFunc) (*Cache, error) {
|
|||
pc, _ := lru.New(size)
|
||||
ac, _ := lru.New(size)
|
||||
c := &Cache{
|
||||
aclCache: ac,
|
||||
faultfn: faultfn,
|
||||
parent: parent,
|
||||
aclCache: ac,
|
||||
policyCache: pc,
|
||||
ruleCache: rc,
|
||||
}
|
||||
|
@ -84,7 +82,7 @@ func (c *Cache) GetACLPolicy(id string) (*Policy, error) {
|
|||
}
|
||||
|
||||
// Fault in the rules
|
||||
rules, err := c.faultfn(id)
|
||||
_, rules, err := c.faultfn(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -103,7 +101,7 @@ func (c *Cache) GetACL(id string) (ACL, error) {
|
|||
}
|
||||
|
||||
// Get the rules
|
||||
rules, err := c.faultfn(id)
|
||||
parentID, rules, err := c.faultfn(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -120,8 +118,17 @@ func (c *Cache) GetACL(id string) (ACL, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Get the parent ACL
|
||||
parent := RootACL(parentID)
|
||||
if parent == nil {
|
||||
parent, err = c.GetACL(parentID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Compile the ACL
|
||||
acl, err := New(c.parent, policy)
|
||||
acl, err := New(parent, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
func TestCache_GetPolicy(t *testing.T) {
|
||||
c, err := NewCache(1, AllowAll(), nil)
|
||||
c, err := NewCache(1, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -45,11 +45,11 @@ func TestCache_GetACL(t *testing.T) {
|
|||
"foo": testSimplePolicy,
|
||||
"bar": testSimplePolicy2,
|
||||
}
|
||||
faultfn := func(id string) (string, error) {
|
||||
return policies[id], nil
|
||||
faultfn := func(id string) (string, string, error) {
|
||||
return "deny", policies[id], nil
|
||||
}
|
||||
|
||||
c, err := NewCache(1, DenyAll(), faultfn)
|
||||
c, err := NewCache(1, faultfn)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -96,11 +96,11 @@ func TestCache_ClearACL(t *testing.T) {
|
|||
"foo": testSimplePolicy,
|
||||
"bar": testSimplePolicy,
|
||||
}
|
||||
faultfn := func(id string) (string, error) {
|
||||
return policies[id], nil
|
||||
faultfn := func(id string) (string, string, error) {
|
||||
return "deny", policies[id], nil
|
||||
}
|
||||
|
||||
c, err := NewCache(1, DenyAll(), faultfn)
|
||||
c, err := NewCache(1, faultfn)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -131,11 +131,11 @@ func TestCache_Purge(t *testing.T) {
|
|||
"foo": testSimplePolicy,
|
||||
"bar": testSimplePolicy,
|
||||
}
|
||||
faultfn := func(id string) (string, error) {
|
||||
return policies[id], nil
|
||||
faultfn := func(id string) (string, string, error) {
|
||||
return "deny", policies[id], nil
|
||||
}
|
||||
|
||||
c, err := NewCache(1, DenyAll(), faultfn)
|
||||
c, err := NewCache(1, faultfn)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -164,10 +164,10 @@ func TestCache_GetACLPolicy(t *testing.T) {
|
|||
"foo": testSimplePolicy,
|
||||
"bar": testSimplePolicy,
|
||||
}
|
||||
faultfn := func(id string) (string, error) {
|
||||
return policies[id], nil
|
||||
faultfn := func(id string) (string, string, error) {
|
||||
return "deny", policies[id], nil
|
||||
}
|
||||
c, err := NewCache(1, DenyAll(), faultfn)
|
||||
c, err := NewCache(1, faultfn)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -201,6 +201,37 @@ func TestCache_GetACLPolicy(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCache_GetACL_Parent(t *testing.T) {
|
||||
faultfn := func(id string) (string, string, error) {
|
||||
switch id {
|
||||
case "foo":
|
||||
// Foo inherits from bar
|
||||
return "bar", testSimplePolicy, nil
|
||||
case "bar":
|
||||
return "deny", testSimplePolicy2, nil
|
||||
}
|
||||
t.Fatalf("bad case")
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
c, err := NewCache(1, faultfn)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
acl, err := c.GetACL("foo")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if !acl.KeyRead("bar/test") {
|
||||
t.Fatalf("should allow")
|
||||
}
|
||||
if !acl.KeyRead("foo/test") {
|
||||
t.Fatalf("should allow")
|
||||
}
|
||||
}
|
||||
|
||||
var testSimplePolicy = `
|
||||
key "foo/" {
|
||||
policy = "read"
|
||||
|
|
Loading…
Reference in New Issue