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