acl: Support ACL checks, adding new root policy

This commit is contained in:
Armon Dadgar 2014-08-12 15:09:01 -07:00
parent bac1527281
commit 02e71c70c5
2 changed files with 79 additions and 3 deletions

View File

@ -5,29 +5,47 @@ import (
)
var (
// allowAll is a singleton policy which allows all actions
// allowAll is a singleton policy which allows all
// non-management actions
allowAll ACL
// denyAll is a singleton policy which denies all actions
denyAll ACL
// manageAll is a singleton policy which allows all
// actions, including management
manageAll ACL
)
func init() {
// Setup the singletons
allowAll = &StaticACL{defaultAllow: true}
denyAll = &StaticACL{defaultAllow: false}
allowAll = &StaticACL{
allowManage: false,
defaultAllow: true,
}
denyAll = &StaticACL{
allowManage: false,
defaultAllow: false,
}
manageAll = &StaticACL{
allowManage: true,
defaultAllow: true,
}
}
// ACL is the interface for policy enforcement.
type ACL interface {
KeyRead(string) bool
KeyWrite(string) bool
ACLList() bool
ACLModify() bool
}
// StaticACL is used to implement a base ACL policy. It either
// allows or denies all requests. This can be used as a parent
// ACL to act in a blacklist or whitelist mode.
type StaticACL struct {
allowManage bool
defaultAllow bool
}
@ -39,6 +57,14 @@ func (s *StaticACL) KeyWrite(string) bool {
return s.defaultAllow
}
func (s *StaticACL) ACLList() bool {
return s.allowManage
}
func (s *StaticACL) ACLModify() bool {
return s.allowManage
}
// AllowAll returns an ACL rule that allows all operations
func AllowAll() ACL {
return allowAll
@ -49,6 +75,11 @@ func DenyAll() ACL {
return denyAll
}
// ManageAll returns an ACL rule that can manage all resources
func ManageAll() ACL {
return manageAll
}
// RootACL returns a possible ACL if the ID matches a root policy
func RootACL(id string) ACL {
switch id {
@ -56,6 +87,8 @@ func RootACL(id string) ACL {
return allowAll
case "deny":
return denyAll
case "manage":
return manageAll
default:
return nil
}
@ -122,3 +155,13 @@ func (p *PolicyACL) KeyWrite(key string) bool {
// No matching rule, use the parent.
return p.parent.KeyWrite(key)
}
// ACLList checks if listing of ACLs is allowed
func (p *PolicyACL) ACLList() bool {
return p.ACLList()
}
// ACLModify checks if modification of ACLs is allowed
func (p *PolicyACL) ACLModify() bool {
return p.ACLModify()
}

View File

@ -11,6 +11,9 @@ func TestRootACL(t *testing.T) {
if RootACL("deny") != DenyAll() {
t.Fatalf("Bad root")
}
if RootACL("manage") != ManageAll() {
t.Fatalf("Bad root")
}
if RootACL("foo") != nil {
t.Fatalf("bad root")
}
@ -27,12 +30,23 @@ func TestStaticACL(t *testing.T) {
t.Fatalf("expected static")
}
manage := ManageAll()
if _, ok := none.(*StaticACL); !ok {
t.Fatalf("expected static")
}
if !all.KeyRead("foobar") {
t.Fatalf("should allow")
}
if !all.KeyWrite("foobar") {
t.Fatalf("should allow")
}
if all.ACLList() {
t.Fatalf("should not allow")
}
if all.ACLModify() {
t.Fatalf("should not allow")
}
if none.KeyRead("foobar") {
t.Fatalf("should not allow")
@ -40,6 +54,25 @@ func TestStaticACL(t *testing.T) {
if none.KeyWrite("foobar") {
t.Fatalf("should not allow")
}
if none.ACLList() {
t.Fatalf("should not noneow")
}
if none.ACLModify() {
t.Fatalf("should not noneow")
}
if !manage.KeyRead("foobar") {
t.Fatalf("should allow")
}
if !manage.KeyWrite("foobar") {
t.Fatalf("should allow")
}
if !manage.ACLList() {
t.Fatalf("should allow")
}
if !manage.ACLModify() {
t.Fatalf("should allow")
}
}
func TestPolicyACL(t *testing.T) {