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