Skip to content

Instantly share code, notes, and snippets.

@Dowwie
Created January 21, 2017 18:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dowwie/4ee4e2b059769bc03c7ce14bc7ca4905 to your computer and use it in GitHub Desktop.
Save Dowwie/4ee4e2b059769bc03c7ce14bc7ca4905 to your computer and use it in GitHub Desktop.
experimenting with refactoring yosai permission authorization checks using Go
package main
import (
"C"
"fmt"
"strings"
"gopkg.in/fatih/set.v0"
)
type Permission struct {
domain string
actions *set.Set
targets *set.Set
}
func perm_parts(wildcard_perm string) func() (string, bool) {
perms := strings.Split(wildcard_perm, ":")
i := -1
return func() (string, bool) {
i++
if i >= len(perms) {
return "", false
}
return perms[i], true
}
}
func (p *Permission) init_parts(wildcard_perm string) {
next_part := perm_parts(wildcard_perm)
d_part, _ := next_part()
p.domain = strings.TrimSpace(d_part)
action_part := ""
a_part, a_check := next_part()
if !a_check {
action_part = "*"
} else {
action_part = a_part
}
p.actions = set.New()
for _, sub_part := range strings.Split(action_part, ",") {
p.actions.Add(strings.TrimSpace(sub_part))
}
target_part := ""
t_part, t_check := next_part()
if !t_check {
target_part = "*"
} else {
target_part = t_part
}
p.targets = set.New()
for _, t_sub_part := range strings.Split(target_part, ",") {
p.targets.Add(strings.TrimSpace(t_sub_part))
}
}
func new_permission(wildcard_perm string) *Permission {
p := new(Permission)
p.init_parts(wildcard_perm)
return p
}
func (self *Permission) implies_from_perm(permission *Permission) bool {
if self.domain != "*" {
if self.domain != permission.domain { return false }
}
if !self.actions.Has("*"){
if !self.actions.IsSubset(permission.actions) { return false }
}
if !self.targets.Has("*"){
if !self.targets.IsSubset(permission.targets) { return false }
}
return true
}
//export is_permitted_from_str
func is_permitted_from_str(required_perm string, assigned_perms []string) bool {
required_permission := new_permission(required_perm)
for _, assigned := range assigned_perms {
assigned_permission := new_permission(assigned)
if assigned_permission.implies_from_perm(required_permission){
return true
}
}
return false
}
func main() {
p1 := new_permission("domain:action1, action2, action3:*")
p2 := new_permission("domain:action1")
p3 := new_permission("domain:action4")
p4 := new_permission("domain")
fmt.Println("p1 implies p2: ", p1.implies_from_perm(p2))
fmt.Println("p1 implies p3: ", p1.implies_from_perm(p3))
fmt.Println("p4 implies p3: ", p4.implies_from_perm(p3))
fmt.Println("p4 implies p2: ", p4.implies_from_perm(p2))
fmt.Println("p4 implies p1: ", p4.implies_from_perm(p1))
fmt.Println("p1 implies p4: ", p1.implies_from_perm(p4))
result := is_permitted_from_str("domain:action1:target1", []string{"domain:action2:target2", "domain:action1"})
fmt.Println("result is: ", result)
result2 := is_permitted_from_str("domain:action3:target4", []string{"domain:action2:target2", "domain:action1"})
fmt.Println("result is: ", result2)
}
package authz
import "testing"
var authzTests = []struct {
required_perm string
assigned_perms []string
expected_result bool
}{
{"domain1:action4:target4",
[]string {"domain1:action1","domain1:action2","domain1:action4"},
true},
{"domain1:action5:target4",
[]string {"domain1:action1","domain1:action2","domain1:action4"},
false},
}
func TestImplies(t *testing.T) {
for _, tt := range authzTests {
result := is_permitted_from_str(tt.required_perm, tt.assigned_perms)
if result != tt.expected_result {
t.Errorf("is_permitted_from_str failed")
}
}
}
func benchmarkAuthz(required string, assigned []string, b *testing.B) {
for n := 0; n < b.N; n++ {
is_permitted_from_str(required, assigned)
}
}
func BenchmarkAuthz1(b *testing.B) {
benchmarkAuthz("domain1:action4:target4",
[]string {"domain1:action1","domain1:action2","domain1:action4"},
b)
}
var result bool
func BenchmarkAuthzComplete(b *testing.B) {
var r bool
for n := 0; n < b.N; n++ {
// always record the result of Authz to prevent
// the compiler eliminating the function call.
r = is_permitted_from_str("domain1:action4:target4",
[]string {"domain1:action1","domain1:action2","domain1:action4"})
}
// always store the result to a package level variable
// so the compiler cannot eliminate the Benchmark itself.
result = r
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment