Documentation
¶
Overview ¶
Example (Functions) ¶
ExampleFunctions shows how to use a custom util.MatchingFunc
package main
import (
"github.com/abichinger/fastac"
"github.com/abichinger/fastac/model"
"github.com/abichinger/fastac/model/fm"
)
// the model uses a custom MatchingFunc named customPathMatch
var example_functions_model = `
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && customPathMatch(r.obj, p.obj) && r.act == p.act`
var example_functions_policy = [][]string{
{"p", "alice", "*", "GET"},
{"p", "alice", "/user/alice", "PATCH"},
}
// ExampleFunctions shows how to use a custom util.MatchingFunc
func main() {
//customPathMatch needs to be registered before loading the model
fm.SetFunction("customPathMatch", func(arguments ...interface{}) (interface{}, error) {
rObj := arguments[0].(string)
rSub := arguments[1].(string)
if rSub == "*" {
return true, nil
}
return rObj == rSub, nil
})
//create enforcer and add rules
m := model.NewModel()
_ = m.LoadModelFromText(example_functions_model)
e, _ := fastac.NewEnforcer(m, nil)
_ = e.AddRules(example_functions_policy)
//perform some requests
printReq(e, "alice", "/user/alice/entry/1", "GET")
printReq(e, "bob", "/user/alice/entry/1", "GET")
printReq(e, "alice", "/user/alice", "PATCH")
printReq(e, "bob", "/user/alice", "PATCH")
}
Output: alice, /user/alice/entry/1, GET => allow bob, /user/alice/entry/1, GET => deny alice, /user/alice, PATCH => allow bob, /user/alice, PATCH => deny
Example (ManagePolicy) ¶
ExampleManagePolicy demonstrates the usage of functions to modify the policy
package main
import (
"fmt"
"sort"
"github.com/abichinger/fastac"
"github.com/abichinger/fastac/util"
)
var example_rules_policy = [][]string{
{"p", "alice", "data1", "read"},
{"p", "alice", "data1", "write"},
{"p", "bob", "data2", "read"},
{"p", "bob", "data2", "write"},
{"p", "alice", "data3", "read"},
{"p", "bob", "data3", "read"},
{"p", "manager", "data3", "write"},
{"g", "bob", "manager"},
}
// ExampleManagePolicy demonstrates the usage of functions to modify the policy
func main() {
//create enforcer with rbac model and empty policy
e, _ := fastac.NewEnforcer("examples/rbac_model.conf", nil)
//add multiple rules at once
_ = e.AddRules(example_rules_policy)
//remove all rules of user bob
bobRules, _ := e.Filter(fastac.SetMatcher(`p.sub == "bob"`))
bobGroupingRules, _ := e.Filter(fastac.SetMatcher(`g.user == "bob"`))
_ = e.RemoveRules(append(bobRules, bobGroupingRules...))
//make alice a manager
alice_manager := []string{"g", "alice", "manager"}
added, _ := e.AddRule(alice_manager)
if added {
fmt.Println("rule added successfully")
}
//get a list of all rules
var allRules [][]string
e.GetModel().RangeRules(func(rule []string) bool {
allRules = append(allRules, rule)
return true
})
//sort and print rules
allRulesStr := util.Join2D(allRules, ", ")
sort.Strings(allRulesStr)
for _, rule := range allRulesStr {
fmt.Println(rule)
}
}
Output: rule added successfully g, alice, manager p, alice, data1, read p, alice, data1, write p, alice, data3, read p, manager, data3, write
Example (Matchers) ¶
ExampleMatchers shows the usage of util.MatchingFunc and util.IMatcher
package main
import (
"fmt"
"strings"
"github.com/abichinger/fastac"
"github.com/abichinger/fastac/model"
"github.com/abichinger/fastac/rbac"
"github.com/abichinger/fastac/util"
)
// the model uses the built-in MatchingFunc pathMatch
var example_matcher_model = `
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && pathMatch(r.obj, p.obj) && r.act == p.act`
var example_matcher_policy = [][]string{
{"p", "role:user", "/user/:uid/entry/:eid", "GET"},
{"p", "user:alice", "/user/alice/*", "POST"},
{"p", "role:admin", "/user/:uid/entry/:eid", "DELETE"},
{"g", "reg:user:.*", "role:user"},
{"g", "user:alice", "role:admin"},
}
func printReq(e *fastac.Enforcer, params ...interface{}) {
b, _ := e.Enforce(params...)
var rule []string
for _, param := range params {
rule = append(rule, param.(string))
}
if b {
fmt.Printf("%s => allow\n", strings.Join(rule, ", "))
} else {
fmt.Printf("%s => deny\n", strings.Join(rule, ", "))
}
}
// ExampleMatchers shows the usage of util.MatchingFunc and util.IMatcher
func main() {
//create enforcer and add rules
m := model.NewModel()
_ = m.LoadModelFromText(example_matcher_model)
e, _ := fastac.NewEnforcer(m, nil)
_ = e.AddRules(example_matcher_policy)
//get the default rolemanager
rm, _ := e.GetModel().GetRoleManager("g")
// set a role matcher.
// create a PrefixMatcher. PrefixMatcher implements the interface util.IMatcher
// each regex pattern needs to be marked with the prefix "reg:"
roleMatcher := util.NewPrefixMatcher("reg:", util.RegexMatch)
rm.(rbac.IDefaultRoleManager).SetMatcher(roleMatcher)
printReq(e, "user:alice", "/user/joe/entry/1", "GET") //allow, because user:alice has role:user
printReq(e, "user:alice", "/user/alice/entry/2", "POST")
printReq(e, "user:alice", "/user/bob/entry/3", "POST")
printReq(e, "user:alice", "/user/bob/entry/3", "DELETE")
printReq(e, "user:bob", "/user/alice/entry/2", "DELETE")
}
Output: user:alice, /user/joe/entry/1, GET => allow user:alice, /user/alice/entry/2, POST => allow user:alice, /user/bob/entry/3, POST => deny user:alice, /user/bob/entry/3, DELETE => allow user:bob, /user/alice/entry/2, DELETE => deny
Example (StorageAdapter) ¶
ExampleStorageAdapter shows how to store/load policy rules to/from a storage adapter
package main
import (
"fmt"
"os"
"sort"
"strings"
"github.com/abichinger/fastac"
gormadapter "github.com/abichinger/gorm-adapter"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var example_rules_1 = [][]string{
{"p", "alice", "data1", "read"},
{"p", "alice", "data1", "write"},
{"p", "bob", "data1", "read"},
}
func createDB(name string) *gorm.DB {
_ = os.Mkdir(".tmp", 0755)
db, _ := gorm.Open(sqlite.Open(".tmp/"+name+".db"), &gorm.Config{})
return db
}
func removeDB(name string) {
os.Remove(".tmp/" + name + ".db")
}
// ExampleStorageAdapter shows how to store/load policy rules to/from a storage adapter
func main() {
//init adapter
db := createDB("example")
defer removeDB("example")
a, err := gormadapter.NewAdapter(db)
if err != nil {
panic(err)
}
//create enforcer and store rules using the autosave feature
e, _ := fastac.NewEnforcer("examples/basic_model.conf", a, fastac.OptionAutosave(true))
err = e.AddRules(example_rules_1)
if err != nil {
panic(err)
}
//second enforcer to demonstrate LoadPolicy
e2, _ := fastac.NewEnforcer("examples/basic_model.conf", a)
err = e2.LoadPolicy()
if err != nil {
panic(err)
}
loadedRules := []string{}
e2.GetModel().RangeRules(func(rule []string) bool {
loadedRules = append(loadedRules, strings.Join(rule, ", "))
return true
})
sort.Strings(loadedRules)
for _, rule := range loadedRules {
fmt.Println(rule)
}
}
Output: p, alice, data1, read p, alice, data1, write p, bob, data1, read
Index ¶
- type Context
- type ContextOption
- type Enforcer
- func (e *Enforcer) AddRule(rule []string) (bool, error)
- func (e *Enforcer) AddRules(rules [][]string) error
- func (e *Enforcer) Enforce(params ...interface{}) (bool, error)
- func (e *Enforcer) EnforceWithContext(ctx *Context, rvals ...interface{}) (bool, error)
- func (e *Enforcer) Filter(params ...interface{}) ([][]string, error)
- func (e *Enforcer) FilterWithContext(ctx *Context, rvals ...interface{}) ([][]string, error)
- func (e *Enforcer) Flush() error
- func (e *Enforcer) GetAdapter() storage.Adapter
- func (e *Enforcer) GetModel() m.IModel
- func (e *Enforcer) GetStorageController() *storage.StorageController
- func (e *Enforcer) LoadPolicy() error
- func (e *Enforcer) RangeMatches(params []interface{}, fn func(rule []string) bool) error
- func (e *Enforcer) RangeMatchesWithContext(ctx *Context, rvals []interface{}, fn func(rule []string) bool) error
- func (e *Enforcer) RemoveRule(rule []string) (bool, error)
- func (e *Enforcer) RemoveRules(rules [][]string) error
- func (e *Enforcer) SavePolicy() error
- func (e *Enforcer) SetAdapter(adapter storage.Adapter)
- func (e *Enforcer) SetModel(model m.IModel)
- func (e *Enforcer) SetOption(option Option) error
- type IEnforcer
- type Option
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
func NewContext ¶
func NewContext(model model.IModel, options ...ContextOption) (*Context, error)
type ContextOption ¶
func SetEffector ¶
func SetEffector(effector interface{}) ContextOption
func SetMatcher ¶
func SetMatcher(matcher interface{}) ContextOption
func SetRequestDef ¶
func SetRequestDef(definition interface{}) ContextOption
type Enforcer ¶
type Enforcer struct {
// contains filtered or unexported fields
}
func NewEnforcer ¶
NewEnforcer creates a new Enforcer instance. An Enforcer is the main item of FastAC
Without adapter and default options:
NewEnforcer("model.conf", nil)
With adapter and autosave enabled
adapter := gormadapter.NewAdapter(db, tableName)
NewEnforcer("model.conf", adapter, OptionAutosave(true))
func (*Enforcer) AddRule ¶
AddRule adds a rule to the model Returns false, if the rule was already present
Add policy rule:
e.AddRule([]string{"p", "alice", "data1", "read"})
Add grouping rule:
e.AddRule([]string{"g", "alice", "group1"})
func (*Enforcer) Enforce ¶
Enforce decides whether to allow or deny a request It is possible to pass ContextOptions, everything else will be treated as a request value
func (*Enforcer) EnforceWithContext ¶
func (*Enforcer) Filter ¶
Filter will fetch all rules which match the given request It is possible to pass ContextOptions, everything else will be treated as a request value The effect of rules is not considered.
Get all permissons from alice:
e.Filter(SetMatcher("p.user == \"alice\""))
Get all grouping rules in domain1:
e.Filter(SetMatcher("g.domain == \"domain1\""))
func (*Enforcer) FilterWithContext ¶
func (*Enforcer) Flush ¶
Flush sends all the modifications of the rule set to the storage adapter.
store rule, when autosave is disabled:
e.AddRule("g", "alice", "group1")
e.Flush()
func (*Enforcer) GetAdapter ¶ added in v1.1.0
func (*Enforcer) GetStorageController ¶
func (e *Enforcer) GetStorageController() *storage.StorageController
func (*Enforcer) LoadPolicy ¶
LoadPolicy loads all rules from the storage adapter into the model. The model is not cleared before the loading process
func (*Enforcer) RangeMatches ¶
func (*Enforcer) RangeMatchesWithContext ¶
func (*Enforcer) RemoveRule ¶
RemoveRule removes a rule from the model Returns false, if the rule was not present
Add policy rule:
e.RemoveRule([]string{"p", "alice", "data1", "read"})
Add grouping rule:
e.RemoveRule([]string{"g", "alice", "group1"})
func (*Enforcer) RemoveRules ¶
RemoveRules removes multiple rules from the model
func (*Enforcer) SavePolicy ¶
SavePolicy stores all rules from the model into the storage adapter.
func (*Enforcer) SetAdapter ¶
SetAdapter sets the storage adapter
type IEnforcer ¶
type IEnforcer interface {
SetOption(option Option) error
GetStorageController() *storage.StorageController
GetModel() model.IModel
SetModel(m model.IModel)
GetAdapter() storage.Adapter
SetAdapter(storage.Adapter)
AddRule(rule []string) (bool, error)
AddRules(rules [][]string) error
RemoveRule(rule []string) (bool, error)
RemoveRules(rules [][]string) error
LoadPolicy() error
SavePolicy() error
Enforce(params ...interface{}) (bool, error)
EnforceWithContext(ctx *Context, rvals ...interface{}) (bool, error)
Filter(params ...interface{}) ([][]string, error)
FilterWithContext(ctx *Context, rvals ...interface{}) ([][]string, error)
RangeMatches(params []interface{}, fn func(rule []string) bool) error
RangeMatchesWithContext(ctx *Context, rvals []interface{}, fn func(rule []string) bool) error
Flush() error
}
type Option ¶
func OptionAutosave ¶
Option to disable/enable the autosave feature (default: disabled) If autosave is disabled, Flush needs to be called to save modified rules Enable autosave:
NewEnforcer(model, adapter, OptionAutosave(true))
Or:
e.SetOption(OptionAutosave(true))
func OptionStorage ¶
Option to disable/enable the storage feature (default: enabled, if an adapter is supplied) If storage is disabled, the StorageController will not listen for rule updates