Skip to content

Commit

Permalink
cmd: Add support for glob matching
Browse files Browse the repository at this point in the history
Signed-off-by: Rob Liebowitz <[email protected]>
  • Loading branch information
rliebz committed Jan 24, 2019
1 parent 6811607 commit e4e3ed7
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ install-stable:
git checkout master

install:
GO111MODULE=on go install .
GO111MODULE=on go install .
8 changes: 6 additions & 2 deletions engine/ladon/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Engine struct {
h herodot.Writer
}

var EnabledFlavors = []string{"exact", "regex"}
var EnabledFlavors = []string{"exact", "glob", "regex"}

const (
BasePath = "/engines/acp/ory/:flavor"
Expand All @@ -37,6 +37,10 @@ const (
"policies": [],
"roles": []
},
"glob": {
"policies": [],
"roles": []
},
"exact": {
"policies": [],
"roles": []
Expand All @@ -49,7 +53,7 @@ const (
func RoutesToObserve() []string {
var r []string

for _, f := range []string{"exact", "regex"} {
for _, f := range EnabledFlavors {
for _, p := range []string{"policies", "roles", "allowed"} {
r = append(r,
fmt.Sprintf(strings.Replace(BasePath, ":flavor", "%s", 1)+"/%s", f, p),
Expand Down
6 changes: 3 additions & 3 deletions engine/ladon/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestAllowed(t *testing.T) {

cl := swagger.NewEnginesApiWithBasePath(ts.URL)

for _, f := range []string{"regex", "exact"} {
for _, f := range EnabledFlavors {
t.Run(fmt.Sprintf("flavor=%s", f), func(t *testing.T) {
t.Run(fmt.Sprint("action=create"), func(t *testing.T) {
for _, p := range policies[f] {
Expand Down Expand Up @@ -139,7 +139,7 @@ func TestPolicyCRUD(t *testing.T) {
defer ts.Close()

c := swagger.NewEnginesApiWithBasePath(ts.URL)
for _, f := range []string{"exact", "regex"} {
for _, f := range EnabledFlavors {
for l, p := range policies[f] {
_, resp, err := c.GetOryAccessControlPolicy(f, p.ID)
x.CheckResponseTest(t, err, http.StatusNotFound, resp)
Expand Down Expand Up @@ -177,7 +177,7 @@ func TestRoleCRUD(t *testing.T) {
defer ts.Close()

c := swagger.NewEnginesApiWithBasePath(ts.URL)
for _, f := range []string{"exact", "regex"} {
for _, f := range EnabledFlavors {
for l, r := range roles[f] {
_, resp, err := c.GetOryAccessControlPolicyRole(f, r.ID)
x.CheckResponseTest(t, err, http.StatusNotFound, resp)
Expand Down
40 changes: 40 additions & 0 deletions engine/ladon/rego/glob/main.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package ory.glob

import data.store.ory.glob as store
import data.ory.core as core
import data.ory.condition as condition
import input as request

default allow = false

allow {
decide_allow(store.policies, store.roles)
}

decide_allow(policies, roles) {
effects := [effect | effect := policies[i].effect
matcher(policies[i].resources, request.resource)
match_subjects(policies[i].subjects, roles, request.subject)
matcher(policies[i].actions, request.action)
condition.all_conditions_true(policies[i])
]

count(effects, c)
c > 0

core.effect_allow(effects)
}

matcher(patterns, compare) {
pattern := patterns[_]
glob.match(pattern, [":"], compare, output)
output == true
}

match_subjects(matches, roles, subject) {
matcher(matches, subject)
} {
r := core.role_ids(roles, subject)
rr := r[_]
matcher(matches, rr)
}
171 changes: 171 additions & 0 deletions engine/ladon/rego/glob/main_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package ory.glob

policies = [
{
"id": "1",
"resources": [`articles:1`],
"subjects": [`subjects:1`],
"actions": [`actions:1`],
"effect": "allow",
"conditions": {
"foobar": {
"type": "StringEqualCondition",
"options": {
"equals": "the-value-should-be-this"
}
}
}
},
{
"id": "2",
"resources": [`articles:2`],
"subjects": [`subjects:2`],
"actions": [`actions:2`],
"effect": "deny",
},
{
"id": "3-1",
"resources": [`articles:3`],
"subjects": [`subjects:3`],
"actions": [`actions:3`],
"effect": "allow",
},
{
"id": "3-2",
"resources": [`articles:3`],
"subjects": [`subjects:3`],
"actions": [`actions:3`],
"effect": "deny",
},
{
"id": "3-3",
"resources": [`articles:3`],
"subjects": [`subjects:3`],
"actions": [`actions:3`],
"effect": "allow",
},
{
"id": "4",
"resources": [`articles:?4`],
"subjects": [`subjects:?4`],
"actions": [`actions:?4`],
"effect": "allow",
},
{
"id": "5",
"resources": [`articles:5`],
"subjects": [`subjects:5`],
"actions": [`actions:5`],
"effect": "allow",
"conditions": {
"foobar": {
"type": "InvalidCondition"
}
}
},
{
"id": "6",
"resources": [`articles:6`],
"subjects": [`{subjects,groups}:6`],
"actions": [`actions:6`],
"effect": "allow"
},
{
"id": "7",
"resources": [`articles:?:7`],
"subjects": [`subjects:*:7`],
"actions": [`actions:**:7`],
"effect": "allow"
},
{
"id": "8",
"resources": [`articles:[cb]at:8`],
"subjects": [`subjects:[a-c]at:8`],
"actions": [`actions:[!cb]a[!x-z]:8`],
"effect": "allow"
},
{
"id": "9",
"resources": [`articles:foo**{bar,baz}:9`],
"subjects": [`subjects:{?at,d*g}:9`],
"actions": [`actions:{[cbm]at,d[!j-n]g}:9`],
"effect": "allow"
},
]

test_allow_policy {
decide_allow(policies, []) with input as {"resource": "articles:44", "subject": "subjects:44", "action": "actions:44"}
decide_allow(policies, []) with input as {"resource": "articles:54", "subject": "subjects:54", "action": "actions:54"}
not decide_allow(policies, []) with input as {"resource": "articles:45", "subject": "subjects:45", "action": "actions:45"}
not decide_allow(policies, []) with input as {"resource": "articles:4", "subject": "subjects:4", "action": "actions:4"}
not decide_allow(policies, []) with input as {"resource": "articles:454", "subject": "subjects:454", "action": "actions:454"}
}

test_allow_group_policy {
decide_allow(policies, []) with input as {"resource": "articles:6", "subject": "subjects:6", "action": "actions:6"}
decide_allow(policies, []) with input as {"resource": "articles:6", "subject": "groups:6", "action": "actions:6"}

decide_allow(policies, [{"id": "groups:6", "members": ["group-subject"]}]) with input as {"resource": "articles:6", "subject": "group-subject", "action": "actions:6"}

not decide_allow(policies, [{"id": "groups:6", "members": ["group-subject"]}]) with input as {"resource": "articles:6", "subject": "not-group-subject", "action": "actions:6"}
not decide_allow(policies, [{"id": "not-groups", "members": ["group-subject"]}]) with input as {"resource": "articles:6", "subject": "group-subject", "action": "actions:6"}
}

test_deny_policy {
not decide_allow(policies, []) with input as {"resource": "articles:2", "subject": "subjects:2", "action": "actions:2"}
}

test_deny_overrides {
not decide_allow(policies, []) with input as {"resource": "articles:3", "subject": "subjects:3", "action": "actions:3"}
}

test_deny_without_match {
not decide_allow(policies, []) with input as {"resource": "unknown", "subject": "unknown", "action": "unknown", "context": {"unknown": "unknown"}}
}

test_with_condition {
decide_allow(policies, []) with input as {"resource": "articles:1", "subject": "subjects:1", "action": "actions:1", "context": {"foobar": "the-value-should-be-this"}}
not decide_allow(policies, []) with input as {"resource": "articles:1", "subject": "subjects:1", "action": "actions:1", "context": {"foobar": "not-the-value-should-be-this"}}
not decide_allow(policies, []) with input as {"resource": "articles:1", "subject": "subjects:1", "action": "actions:1", "context": {"not-foobar": "the-value-should-be-this"}}
not decide_allow(policies, []) with input as {"resource": "articles:1", "subject": "subjects:1", "action": "actions:1", "context": {"foobar": 1234}}
not decide_allow(policies, []) with input as {"resource": "articles:1", "subject": "subjects:1", "action": "actions:1", "context": {}}
not decide_allow(policies, []) with input as {"resource": "articles:1", "subject": "subjects:1", "action": "actions:1"}
}

test_with_unknown_condition {
not decide_allow(policies, []) with input as {"resource": "articles:5", "subject": "subjects:5", "action": "actions:5", "context": {"foobar": {}}}
}

test_allow_wildcards {
decide_allow(policies, []) with input as {"resource": "articles:a:7", "subject": "subjects:a:7", "action": "actions:a:7"}
decide_allow(policies, []) with input as {"resource": "articles:a:7", "subject": "subjects:ab:7", "action": "actions:a:7"}
decide_allow(policies, []) with input as {"resource": "articles:a:7", "subject": "subjects:a:7", "action": "actions:ab:7"}
decide_allow(policies, []) with input as {"resource": "articles:a:7", "subject": "subjects:a:7", "action": "actions:a:b:7"}
decide_allow(policies, []) with input as {"resource": "articles:a:7", "subject": "subjects:a:7", "action": "actions:7"}

not decide_allow(policies, []) with input as {"resource": "articles:ab:7", "subject": "subjects:a:7", "action": "actions:a:7"}
not decide_allow(policies, []) with input as {"resource": "articles:a:7", "subject": "subjects:a:b:7", "action": "actions:a:7"}
}

test_allow_lists {
decide_allow(policies, []) with input as {"resource": "articles:cat:8", "subject": "subjects:cat:8", "action": "actions:tat:8"}
decide_allow(policies, []) with input as {"resource": "articles:bat:8", "subject": "subjects:bat:8", "action": "actions:dad:8"}
not decide_allow(policies, []) with input as {"resource": "articles:dat:8", "subject": "subjects:cat:8", "action": "actions:tat:8"}
not decide_allow(policies, []) with input as {"resource": "articles:cat:8", "subject": "subjects:dat:8", "action": "actions:tat:8"}
not decide_allow(policies, []) with input as {"resource": "articles:cat:8", "subject": "subjects:cat:8", "action": "actions:cat:8"}
not decide_allow(policies, []) with input as {"resource": "articles:cat:8", "subject": "subjects:cat:8", "action": "actions:tay:8"}
not decide_allow(policies, []) with input as {"resource": "articles:cay:8", "subject": "subjects:cat:8", "action": "actions:tat:8"}
}

test_allow_combinations {
decide_allow(policies, []) with input as {"resource": "articles:foobar:9", "subject": "subjects:cat:9", "action": "actions:cat:9"}
decide_allow(policies, []) with input as {"resource": "articles:foobarbaz:9", "subject": "subjects:doooog:9", "action": "actions:dig:9"}
decide_allow(policies, []) with input as {"resource": "articles:foo:bar::quux:baz:9", "subject": "subjects:dg:9", "action": "actions:dig:9"}

not decide_allow(policies, []) with input as {"resource": "articles:foo:9", "subject": "subjects:cat:9", "action": "actions:cat:9"}
not decide_allow(policies, []) with input as {"resource": "articles:foobard:9", "subject": "subjects:cat:9", "action": "actions:cat:9"}
not decide_allow(policies, []) with input as {"resource": "articles:foobar:9", "subject": "subjects:at:9", "action": "actions:cat:9"}
not decide_allow(policies, []) with input as {"resource": "articles:foobar:9", "subject": "subjects:catdog:9", "action": "actions:cat:9"}
not decide_allow(policies, []) with input as {"resource": "articles:foobar:9", "subject": "subjects:cat:9", "action": "actions:catdog:9"}
not decide_allow(policies, []) with input as {"resource": "articles:foobar:9", "subject": "subjects:cat:9", "action": "actions:doog:9"}
}
12 changes: 12 additions & 0 deletions scripts/test-e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ keto engines acp ory policies import regex ./tests/stubs/policies.json
export KETO_URL=http://127.0.0.1:4466
keto engines acp ory policies import exact ./tests/stubs/policies.json

# One more for the glob endpoint
keto engines acp ory policies import glob ./tests/stubs/policies.json

# Now explicitly check if that works with the --endpoint flag
keto engines --endpoint http://localhost:4466 acp ory roles import regex ./tests/stubs/roles.json
# And with slash
keto engines --endpoint http://localhost:4466/ acp ory roles import exact ./tests/stubs/roles.json
# And with globs
keto engines --endpoint http://localhost:4466/ acp ory roles import exact ./tests/stubs/roles.json

# Importing data is done, let's perform some checks

Expand All @@ -36,5 +41,12 @@ exit $(keto engines --endpoint http://localhost:4466 acp ory allowed exact group

exit $(keto engines --endpoint http://localhost:4466 acp ory allowed exact not-exist resources-11 actions-11 | grep -c '"allowed": true')

exit $(keto engines --endpoint http://localhost:4466 acp ory allowed glob peter-1 resources-11 actions-11 | grep -c '"allowed": false')
exit $(keto engines --endpoint http://localhost:4466 acp ory allowed glob maria-1 resources-11 actions-11 | grep -c '"allowed": false')
exit $(keto engines --endpoint http://localhost:4466 acp ory allowed glob group-1 resources-11 actions-11 | grep -c '"allowed": false')

exit $(keto engines --endpoint http://localhost:4466 acp ory allowed glob not-exist resources-11 actions-11 | grep -c '"allowed": true')


kill %1
exit 0

0 comments on commit e4e3ed7

Please sign in to comment.