policy-engine/pkg/engine/chain_router.go
aarifullin 4154899cff [#54] morph: Introduce ContractStorageReader
* Implement MorphRuleChainStorageReader interface to make
  possible to read from Policy contract without wallets.

Signed-off-by: Airat Arifullin <aarifullin@yadro.com>
2024-02-29 13:57:15 +03:00

116 lines
3.1 KiB
Go

package engine
import (
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource"
)
type defaultChainRouter struct {
morph MorphRuleChainStorageReader
local LocalOverrideStorage
}
func NewDefaultChainRouter(morph MorphRuleChainStorageReader) ChainRouter {
return &defaultChainRouter{
morph: morph,
}
}
func NewDefaultChainRouterWithLocalOverrides(morph MorphRuleChainStorageReader, local LocalOverrideStorage) ChainRouter {
return &defaultChainRouter{
morph: morph,
local: local,
}
}
func (dr *defaultChainRouter) IsAllowed(name chain.Name, rt RequestTarget, r resource.Request) (status chain.Status, ruleFound bool, err error) {
status, ruleFound, err = dr.checkLocal(name, rt, r)
if err != nil {
return chain.NoRuleFound, false, err
} else if ruleFound {
// The local overrides have the highest priority and thus
// morph rules are not considered if a local one is found.
return
}
status, ruleFound, err = dr.checkMorph(name, rt, r)
return
}
func (dr *defaultChainRouter) checkLocal(name chain.Name, rt RequestTarget, r resource.Request) (status chain.Status, ruleFound bool, err error) {
if dr.local == nil {
return
}
var ruleFounds []bool
for _, target := range rt.Targets() {
status, ruleFound, err = dr.matchLocalOverrides(name, target, r)
if err != nil || ruleFound && status != chain.Allow {
return
}
ruleFounds = append(ruleFounds, ruleFound)
}
status = chain.NoRuleFound
for _, ruleFound = range ruleFounds {
if ruleFound {
status = chain.Allow
break
}
}
return
}
func (dr *defaultChainRouter) checkMorph(name chain.Name, rt RequestTarget, r resource.Request) (status chain.Status, ruleFound bool, err error) {
var ruleFounds []bool
for _, target := range rt.Targets() {
status, ruleFound, err = dr.matchMorphRuleChains(name, target, r)
if err != nil || ruleFound && status != chain.Allow {
return
}
ruleFounds = append(ruleFounds, ruleFound)
}
status = chain.NoRuleFound
for _, ruleFound = range ruleFounds {
if ruleFound {
status = chain.Allow
break
}
}
return
}
func (dr *defaultChainRouter) matchLocalOverrides(name chain.Name, target Target, r resource.Request) (status chain.Status, ruleFound bool, err error) {
localOverrides, err := dr.local.ListOverrides(name, target)
if err != nil {
return
}
status, ruleFound = dr.getStatusFromChains(localOverrides, r)
return
}
func (dr *defaultChainRouter) matchMorphRuleChains(name chain.Name, target Target, r resource.Request) (status chain.Status, ruleFound bool, err error) {
namespaceChains, err := dr.morph.ListMorphRuleChains(name, target)
if err != nil {
return chain.NoRuleFound, false, err
}
status, ruleFound = dr.getStatusFromChains(namespaceChains, r)
return
}
func (dr *defaultChainRouter) getStatusFromChains(chains []*chain.Chain, r resource.Request) (chain.Status, bool) {
var allow bool
for _, c := range chains {
if status, found := c.Match(r); found {
if status != chain.Allow {
return status, true
}
allow = true
}
}
if allow {
return chain.Allow, true
}
return chain.NoRuleFound, false
}