From 9b4f316b210a47d09068df9e9123f5c2cab3c3c5 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Thu, 1 Dec 2016 20:31:50 -0800 Subject: [PATCH] Sorts all the ACl policy handlers for easier navigation (no functional changes). --- acl/acl.go | 316 ++++++++++++++++++++++----------------------- acl/acl_test.go | 176 ++++++++++++------------- acl/policy_test.go | 174 ++++++++++++------------- 3 files changed, 333 insertions(+), 333 deletions(-) diff --git a/acl/acl.go b/acl/acl.go index f0180d60e7..2a09ad6b15 100644 --- a/acl/acl.go +++ b/acl/acl.go @@ -35,6 +35,18 @@ func init() { // ACL is the interface for policy enforcement. type ACL interface { + // ACLList checks for permission to list all the ACLs + ACLList() bool + + // ACLModify checks for permission to manipulate ACLs + ACLModify() bool + + // EventRead determines if a specific event can be queried. + EventRead(string) bool + + // EventWrite determines if a specific event may be fired. + EventWrite(string) bool + // KeyRead checks for permission to read a given key KeyRead(string) bool @@ -46,26 +58,6 @@ type ACL interface { // that deny a write. KeyWritePrefix(string) bool - // ServiceWrite checks for permission to read a given service - ServiceWrite(string) bool - - // ServiceRead checks for permission to read a given service - ServiceRead(string) bool - - // EventRead determines if a specific event can be queried. - EventRead(string) bool - - // EventWrite determines if a specific event may be fired. - EventWrite(string) bool - - // PrepardQueryRead determines if a specific prepared query can be read - // to show its contents (this is not used for execution). - PreparedQueryRead(string) bool - - // PreparedQueryWrite determines if a specific prepared query can be - // created, modified, or deleted. - PreparedQueryWrite(string) bool - // KeyringRead determines if the encryption keyring used in // the gossip layer can be read. KeyringRead() bool @@ -81,11 +73,19 @@ type ACL interface { // functions can be used. OperatorWrite() bool - // ACLList checks for permission to list all the ACLs - ACLList() bool + // PrepardQueryRead determines if a specific prepared query can be read + // to show its contents (this is not used for execution). + PreparedQueryRead(string) bool - // ACLModify checks for permission to manipulate ACLs - ACLModify() bool + // PreparedQueryWrite determines if a specific prepared query can be + // created, modified, or deleted. + PreparedQueryWrite(string) bool + + // ServiceRead checks for permission to read a given service + ServiceRead(string) bool + + // ServiceWrite checks for permission to read a given service + ServiceWrite(string) bool // Snapshot checks for permission to take and restore snapshots. Snapshot() bool @@ -99,24 +99,12 @@ type StaticACL struct { defaultAllow bool } -func (s *StaticACL) KeyRead(string) bool { - return s.defaultAllow +func (s *StaticACL) ACLList() bool { + return s.allowManage } -func (s *StaticACL) KeyWrite(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) KeyWritePrefix(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) ServiceRead(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) ServiceWrite(string) bool { - return s.defaultAllow +func (s *StaticACL) ACLModify() bool { + return s.allowManage } func (s *StaticACL) EventRead(string) bool { @@ -127,11 +115,15 @@ func (s *StaticACL) EventWrite(string) bool { return s.defaultAllow } -func (s *StaticACL) PreparedQueryRead(string) bool { +func (s *StaticACL) KeyRead(string) bool { return s.defaultAllow } -func (s *StaticACL) PreparedQueryWrite(string) bool { +func (s *StaticACL) KeyWrite(string) bool { + return s.defaultAllow +} + +func (s *StaticACL) KeyWritePrefix(string) bool { return s.defaultAllow } @@ -151,12 +143,20 @@ func (s *StaticACL) OperatorWrite() bool { return s.defaultAllow } -func (s *StaticACL) ACLList() bool { - return s.allowManage +func (s *StaticACL) PreparedQueryRead(string) bool { + return s.defaultAllow } -func (s *StaticACL) ACLModify() bool { - return s.allowManage +func (s *StaticACL) PreparedQueryWrite(string) bool { + return s.defaultAllow +} + +func (s *StaticACL) ServiceRead(string) bool { + return s.defaultAllow +} + +func (s *StaticACL) ServiceWrite(string) bool { + return s.defaultAllow } func (s *StaticACL) Snapshot() bool { @@ -260,6 +260,50 @@ func New(parent ACL, policy *Policy) (*PolicyACL, error) { return p, nil } +// ACLList checks if listing of ACLs is allowed +func (p *PolicyACL) ACLList() bool { + return p.parent.ACLList() +} + +// ACLModify checks if modification of ACLs is allowed +func (p *PolicyACL) ACLModify() bool { + return p.parent.ACLModify() +} + +// Snapshot checks if taking and restoring snapshots is allowed. +func (p *PolicyACL) Snapshot() bool { + return p.parent.Snapshot() +} + +// EventRead is used to determine if the policy allows for a +// specific user event to be read. +func (p *PolicyACL) EventRead(name string) bool { + // Longest-prefix match on event names + if _, rule, ok := p.eventRules.LongestPrefix(name); ok { + switch rule { + case PolicyRead, PolicyWrite: + return true + default: + return false + } + } + + // Nothing matched, use parent + return p.parent.EventRead(name) +} + +// EventWrite is used to determine if new events can be created +// (fired) by the policy. +func (p *PolicyACL) EventWrite(name string) bool { + // Longest-prefix match event names + if _, rule, ok := p.eventRules.LongestPrefix(name); ok { + return rule == PolicyWrite + } + + // No match, use parent + return p.parent.EventWrite(name) +} + // KeyRead returns if a key is allowed to be read func (p *PolicyACL) KeyRead(key string) bool { // Look for a matching rule @@ -327,109 +371,6 @@ func (p *PolicyACL) KeyWritePrefix(prefix string) bool { return p.parent.KeyWritePrefix(prefix) } -// ServiceRead checks if reading (discovery) of a service is allowed -func (p *PolicyACL) ServiceRead(name string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.serviceRules.LongestPrefix(name) - - if ok { - switch rule { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.ServiceRead(name) -} - -// ServiceWrite checks if writing (registering) a service is allowed -func (p *PolicyACL) ServiceWrite(name string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.serviceRules.LongestPrefix(name) - - if ok { - switch rule { - case PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.ServiceWrite(name) -} - -// EventRead is used to determine if the policy allows for a -// specific user event to be read. -func (p *PolicyACL) EventRead(name string) bool { - // Longest-prefix match on event names - if _, rule, ok := p.eventRules.LongestPrefix(name); ok { - switch rule { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // Nothing matched, use parent - return p.parent.EventRead(name) -} - -// EventWrite is used to determine if new events can be created -// (fired) by the policy. -func (p *PolicyACL) EventWrite(name string) bool { - // Longest-prefix match event names - if _, rule, ok := p.eventRules.LongestPrefix(name); ok { - return rule == PolicyWrite - } - - // No match, use parent - return p.parent.EventWrite(name) -} - -// PreparedQueryRead checks if reading (listing) of a prepared query is -// allowed - this isn't execution, just listing its contents. -func (p *PolicyACL) PreparedQueryRead(prefix string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.preparedQueryRules.LongestPrefix(prefix) - - if ok { - switch rule { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.PreparedQueryRead(prefix) -} - -// PreparedQueryWrite checks if writing (creating, updating, or deleting) of a -// prepared query is allowed. -func (p *PolicyACL) PreparedQueryWrite(prefix string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.preparedQueryRules.LongestPrefix(prefix) - - if ok { - switch rule { - case PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.PreparedQueryWrite(prefix) -} - // KeyringRead is used to determine if the keyring can be // read by the current ACL token. func (p *PolicyACL) KeyringRead() bool { @@ -472,17 +413,76 @@ func (p *PolicyACL) OperatorWrite() bool { return p.parent.OperatorWrite() } -// ACLList checks if listing of ACLs is allowed -func (p *PolicyACL) ACLList() bool { - return p.parent.ACLList() +// PreparedQueryRead checks if reading (listing) of a prepared query is +// allowed - this isn't execution, just listing its contents. +func (p *PolicyACL) PreparedQueryRead(prefix string) bool { + // Check for an exact rule or catch-all + _, rule, ok := p.preparedQueryRules.LongestPrefix(prefix) + + if ok { + switch rule { + case PolicyRead, PolicyWrite: + return true + default: + return false + } + } + + // No matching rule, use the parent. + return p.parent.PreparedQueryRead(prefix) } -// ACLModify checks if modification of ACLs is allowed -func (p *PolicyACL) ACLModify() bool { - return p.parent.ACLModify() +// PreparedQueryWrite checks if writing (creating, updating, or deleting) of a +// prepared query is allowed. +func (p *PolicyACL) PreparedQueryWrite(prefix string) bool { + // Check for an exact rule or catch-all + _, rule, ok := p.preparedQueryRules.LongestPrefix(prefix) + + if ok { + switch rule { + case PolicyWrite: + return true + default: + return false + } + } + + // No matching rule, use the parent. + return p.parent.PreparedQueryWrite(prefix) } -// Snapshot checks if taking and restoring snapshots is allowed. -func (p *PolicyACL) Snapshot() bool { - return p.parent.Snapshot() +// ServiceRead checks if reading (discovery) of a service is allowed +func (p *PolicyACL) ServiceRead(name string) bool { + // Check for an exact rule or catch-all + _, rule, ok := p.serviceRules.LongestPrefix(name) + + if ok { + switch rule { + case PolicyRead, PolicyWrite: + return true + default: + return false + } + } + + // No matching rule, use the parent. + return p.parent.ServiceRead(name) +} + +// ServiceWrite checks if writing (registering) a service is allowed +func (p *PolicyACL) ServiceWrite(name string) bool { + // Check for an exact rule or catch-all + _, rule, ok := p.serviceRules.LongestPrefix(name) + + if ok { + switch rule { + case PolicyWrite: + return true + default: + return false + } + } + + // No matching rule, use the parent. + return p.parent.ServiceWrite(name) } diff --git a/acl/acl_test.go b/acl/acl_test.go index c6ce5789ab..9a6e710f41 100644 --- a/acl/acl_test.go +++ b/acl/acl_test.go @@ -35,17 +35,11 @@ func TestStaticACL(t *testing.T) { t.Fatalf("expected static") } - if !all.KeyRead("foobar") { - t.Fatalf("should allow") + if all.ACLList() { + t.Fatalf("should not allow") } - if !all.KeyWrite("foobar") { - t.Fatalf("should allow") - } - if !all.ServiceRead("foobar") { - t.Fatalf("should allow") - } - if !all.ServiceWrite("foobar") { - t.Fatalf("should allow") + if all.ACLModify() { + t.Fatalf("should not allow") } if !all.EventRead("foobar") { t.Fatalf("should allow") @@ -53,10 +47,10 @@ func TestStaticACL(t *testing.T) { if !all.EventWrite("foobar") { t.Fatalf("should allow") } - if !all.PreparedQueryRead("foobar") { + if !all.KeyRead("foobar") { t.Fatalf("should allow") } - if !all.PreparedQueryWrite("foobar") { + if !all.KeyWrite("foobar") { t.Fatalf("should allow") } if !all.KeyringRead() { @@ -71,26 +65,26 @@ func TestStaticACL(t *testing.T) { if !all.OperatorWrite() { t.Fatalf("should allow") } - if all.ACLList() { - t.Fatalf("should not allow") + if !all.PreparedQueryRead("foobar") { + t.Fatalf("should allow") } - if all.ACLModify() { - t.Fatalf("should not allow") + if !all.PreparedQueryWrite("foobar") { + t.Fatalf("should allow") + } + if !all.ServiceRead("foobar") { + t.Fatalf("should allow") + } + if !all.ServiceWrite("foobar") { + t.Fatalf("should allow") } if all.Snapshot() { t.Fatalf("should not allow") } - if none.KeyRead("foobar") { + if none.ACLList() { t.Fatalf("should not allow") } - if none.KeyWrite("foobar") { - t.Fatalf("should not allow") - } - if none.ServiceRead("foobar") { - t.Fatalf("should not allow") - } - if none.ServiceWrite("foobar") { + if none.ACLModify() { t.Fatalf("should not allow") } if none.EventRead("foobar") { @@ -105,10 +99,10 @@ func TestStaticACL(t *testing.T) { if none.EventWrite("") { t.Fatalf("should not allow") } - if none.PreparedQueryRead("foobar") { + if none.KeyRead("foobar") { t.Fatalf("should not allow") } - if none.PreparedQueryWrite("foobar") { + if none.KeyWrite("foobar") { t.Fatalf("should not allow") } if none.KeyringRead() { @@ -123,26 +117,26 @@ func TestStaticACL(t *testing.T) { if none.OperatorWrite() { t.Fatalf("should not allow") } - if none.ACLList() { + if none.PreparedQueryRead("foobar") { t.Fatalf("should not allow") } - if none.ACLModify() { + if none.PreparedQueryWrite("foobar") { + t.Fatalf("should not allow") + } + if none.ServiceRead("foobar") { + t.Fatalf("should not allow") + } + if none.ServiceWrite("foobar") { t.Fatalf("should not allow") } if none.Snapshot() { t.Fatalf("should not allow") } - if !manage.KeyRead("foobar") { + if !manage.ACLList() { t.Fatalf("should allow") } - if !manage.KeyWrite("foobar") { - t.Fatalf("should allow") - } - if !manage.ServiceRead("foobar") { - t.Fatalf("should allow") - } - if !manage.ServiceWrite("foobar") { + if !manage.ACLModify() { t.Fatalf("should allow") } if !manage.EventRead("foobar") { @@ -151,10 +145,10 @@ func TestStaticACL(t *testing.T) { if !manage.EventWrite("foobar") { t.Fatalf("should allow") } - if !manage.PreparedQueryRead("foobar") { + if !manage.KeyRead("foobar") { t.Fatalf("should allow") } - if !manage.PreparedQueryWrite("foobar") { + if !manage.KeyWrite("foobar") { t.Fatalf("should allow") } if !manage.KeyringRead() { @@ -169,10 +163,16 @@ func TestStaticACL(t *testing.T) { if !manage.OperatorWrite() { t.Fatalf("should allow") } - if !manage.ACLList() { + if !manage.PreparedQueryRead("foobar") { t.Fatalf("should allow") } - if !manage.ACLModify() { + if !manage.PreparedQueryWrite("foobar") { + t.Fatalf("should allow") + } + if !manage.ServiceRead("foobar") { + t.Fatalf("should allow") + } + if !manage.ServiceWrite("foobar") { t.Fatalf("should allow") } if !manage.Snapshot() { @@ -183,6 +183,20 @@ func TestStaticACL(t *testing.T) { func TestPolicyACL(t *testing.T) { all := AllowAll() policy := &Policy{ + Events: []*EventPolicy{ + &EventPolicy{ + Event: "", + Policy: PolicyRead, + }, + &EventPolicy{ + Event: "foo", + Policy: PolicyWrite, + }, + &EventPolicy{ + Event: "bar", + Policy: PolicyDeny, + }, + }, Keys: []*KeyPolicy{ &KeyPolicy{ Prefix: "foo/", @@ -201,38 +215,6 @@ func TestPolicyACL(t *testing.T) { Policy: PolicyRead, }, }, - Services: []*ServicePolicy{ - &ServicePolicy{ - Name: "", - Policy: PolicyWrite, - }, - &ServicePolicy{ - Name: "foo", - Policy: PolicyRead, - }, - &ServicePolicy{ - Name: "bar", - Policy: PolicyDeny, - }, - &ServicePolicy{ - Name: "barfoo", - Policy: PolicyWrite, - }, - }, - Events: []*EventPolicy{ - &EventPolicy{ - Event: "", - Policy: PolicyRead, - }, - &EventPolicy{ - Event: "foo", - Policy: PolicyWrite, - }, - &EventPolicy{ - Event: "bar", - Policy: PolicyDeny, - }, - }, PreparedQueries: []*PreparedQueryPolicy{ &PreparedQueryPolicy{ Prefix: "", @@ -251,6 +233,24 @@ func TestPolicyACL(t *testing.T) { Policy: PolicyWrite, }, }, + Services: []*ServicePolicy{ + &ServicePolicy{ + Name: "", + Policy: PolicyWrite, + }, + &ServicePolicy{ + Name: "foo", + Policy: PolicyRead, + }, + &ServicePolicy{ + Name: "bar", + Policy: PolicyDeny, + }, + &ServicePolicy{ + Name: "barfoo", + Policy: PolicyWrite, + }, + }, } acl, err := New(all, policy) if err != nil { @@ -369,16 +369,6 @@ func TestPolicyACL_Parent(t *testing.T) { Policy: PolicyRead, }, }, - Services: []*ServicePolicy{ - &ServicePolicy{ - Name: "other", - Policy: PolicyWrite, - }, - &ServicePolicy{ - Name: "foo", - Policy: PolicyRead, - }, - }, PreparedQueries: []*PreparedQueryPolicy{ &PreparedQueryPolicy{ Prefix: "other", @@ -389,6 +379,16 @@ func TestPolicyACL_Parent(t *testing.T) { Policy: PolicyRead, }, }, + Services: []*ServicePolicy{ + &ServicePolicy{ + Name: "other", + Policy: PolicyWrite, + }, + &ServicePolicy{ + Name: "foo", + Policy: PolicyRead, + }, + }, } root, err := New(deny, policyRoot) if err != nil { @@ -410,18 +410,18 @@ func TestPolicyACL_Parent(t *testing.T) { Policy: PolicyRead, }, }, - Services: []*ServicePolicy{ - &ServicePolicy{ - Name: "bar", - Policy: PolicyDeny, - }, - }, PreparedQueries: []*PreparedQueryPolicy{ &PreparedQueryPolicy{ Prefix: "bar", Policy: PolicyDeny, }, }, + Services: []*ServicePolicy{ + &ServicePolicy{ + Name: "bar", + Policy: PolicyDeny, + }, + }, } acl, err := New(root, policy) if err != nil { diff --git a/acl/policy_test.go b/acl/policy_test.go index 7f31bf8608..f086c4d13f 100644 --- a/acl/policy_test.go +++ b/acl/policy_test.go @@ -8,6 +8,15 @@ import ( func TestACLPolicy_Parse_HCL(t *testing.T) { inp := ` +event "" { + policy = "read" +} +event "foo" { + policy = "write" +} +event "bar" { + policy = "deny" +} key "" { policy = "read" } @@ -20,21 +29,14 @@ key "foo/bar/" { key "foo/bar/baz" { policy = "deny" } +keyring = "deny" +operator = "deny" service "" { policy = "write" } service "foo" { policy = "read" } -event "" { - policy = "read" -} -event "foo" { - policy = "write" -} -event "bar" { - policy = "deny" -} query "" { policy = "read" } @@ -44,10 +46,23 @@ query "foo" { query "bar" { policy = "deny" } -keyring = "deny" -operator = "deny" ` exp := &Policy{ + Events: []*EventPolicy{ + &EventPolicy{ + Event: "", + Policy: PolicyRead, + }, + &EventPolicy{ + Event: "foo", + Policy: PolicyWrite, + }, + &EventPolicy{ + Event: "bar", + Policy: PolicyDeny, + }, + }, + Keyring: PolicyDeny, Keys: []*KeyPolicy{ &KeyPolicy{ Prefix: "", @@ -66,30 +81,7 @@ operator = "deny" Policy: PolicyDeny, }, }, - Services: []*ServicePolicy{ - &ServicePolicy{ - Name: "", - Policy: PolicyWrite, - }, - &ServicePolicy{ - Name: "foo", - Policy: PolicyRead, - }, - }, - Events: []*EventPolicy{ - &EventPolicy{ - Event: "", - Policy: PolicyRead, - }, - &EventPolicy{ - Event: "foo", - Policy: PolicyWrite, - }, - &EventPolicy{ - Event: "bar", - Policy: PolicyDeny, - }, - }, + Operator: PolicyDeny, PreparedQueries: []*PreparedQueryPolicy{ &PreparedQueryPolicy{ Prefix: "", @@ -104,8 +96,16 @@ operator = "deny" Policy: PolicyDeny, }, }, - Keyring: PolicyDeny, - Operator: PolicyDeny, + Services: []*ServicePolicy{ + &ServicePolicy{ + Name: "", + Policy: PolicyWrite, + }, + &ServicePolicy{ + Name: "foo", + Policy: PolicyRead, + }, + }, } out, err := Parse(inp) @@ -120,6 +120,17 @@ operator = "deny" func TestACLPolicy_Parse_JSON(t *testing.T) { inp := `{ + "event": { + "": { + "policy": "read" + }, + "foo": { + "policy": "write" + }, + "bar": { + "policy": "deny" + } + }, "key": { "": { "policy": "read" @@ -134,25 +145,8 @@ func TestACLPolicy_Parse_JSON(t *testing.T) { "policy": "deny" } }, - "service": { - "": { - "policy": "write" - }, - "foo": { - "policy": "read" - } - }, - "event": { - "": { - "policy": "read" - }, - "foo": { - "policy": "write" - }, - "bar": { - "policy": "deny" - } - }, + "keyring": "deny", + "operator": "deny", "query": { "": { "policy": "read" @@ -164,10 +158,31 @@ func TestACLPolicy_Parse_JSON(t *testing.T) { "policy": "deny" } }, - "keyring": "deny", - "operator": "deny" + "service": { + "": { + "policy": "write" + }, + "foo": { + "policy": "read" + } + } }` exp := &Policy{ + Events: []*EventPolicy{ + &EventPolicy{ + Event: "", + Policy: PolicyRead, + }, + &EventPolicy{ + Event: "foo", + Policy: PolicyWrite, + }, + &EventPolicy{ + Event: "bar", + Policy: PolicyDeny, + }, + }, + Keyring: PolicyDeny, Keys: []*KeyPolicy{ &KeyPolicy{ Prefix: "", @@ -186,30 +201,7 @@ func TestACLPolicy_Parse_JSON(t *testing.T) { Policy: PolicyDeny, }, }, - Services: []*ServicePolicy{ - &ServicePolicy{ - Name: "", - Policy: PolicyWrite, - }, - &ServicePolicy{ - Name: "foo", - Policy: PolicyRead, - }, - }, - Events: []*EventPolicy{ - &EventPolicy{ - Event: "", - Policy: PolicyRead, - }, - &EventPolicy{ - Event: "foo", - Policy: PolicyWrite, - }, - &EventPolicy{ - Event: "bar", - Policy: PolicyDeny, - }, - }, + Operator: PolicyDeny, PreparedQueries: []*PreparedQueryPolicy{ &PreparedQueryPolicy{ Prefix: "", @@ -224,8 +216,16 @@ func TestACLPolicy_Parse_JSON(t *testing.T) { Policy: PolicyDeny, }, }, - Keyring: PolicyDeny, - Operator: PolicyDeny, + Services: []*ServicePolicy{ + &ServicePolicy{ + Name: "", + Policy: PolicyWrite, + }, + &ServicePolicy{ + Name: "foo", + Policy: PolicyRead, + }, + }, } out, err := Parse(inp) @@ -276,12 +276,12 @@ operator = "" func TestACLPolicy_Bad_Policy(t *testing.T) { cases := []string{ - `key "" { policy = "nope" }`, - `service "" { policy = "nope" }`, `event "" { policy = "nope" }`, - `query "" { policy = "nope" }`, + `key "" { policy = "nope" }`, `keyring = "nope"`, `operator = "nope"`, + `query "" { policy = "nope" }`, + `service "" { policy = "nope" }`, } for _, c := range cases { _, err := Parse(c)