2023-11-07 18:29:51 +00:00
|
|
|
package engine
|
|
|
|
|
|
|
|
import (
|
|
|
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
|
|
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource"
|
|
|
|
)
|
|
|
|
|
|
|
|
type defaultChainRouter struct {
|
|
|
|
morph MorphRuleChainStorage
|
|
|
|
|
|
|
|
local LocalOverrideStorage
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDefaultChainRouter(morph MorphRuleChainStorage) ChainRouter {
|
|
|
|
return &defaultChainRouter{
|
|
|
|
morph: morph,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDefaultChainRouterWithLocalOverrides(morph MorphRuleChainStorage, local LocalOverrideStorage) ChainRouter {
|
|
|
|
return &defaultChainRouter{
|
|
|
|
morph: morph,
|
|
|
|
local: local,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-01 15:12:57 +00:00
|
|
|
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)
|
2023-12-01 13:08:52 +00:00
|
|
|
if err != nil {
|
|
|
|
return chain.NoRuleFound, false, err
|
|
|
|
} else if ruleFound {
|
2023-12-01 15:12:57 +00:00
|
|
|
// The local overrides have the highest priority and thus
|
|
|
|
// morph rules are not considered if a local one is found.
|
2023-12-01 13:08:52 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-12-01 15:12:57 +00:00
|
|
|
status, ruleFound, err = dr.checkMorph(name, rt, r)
|
2023-12-01 13:08:52 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-12-01 15:12:57 +00:00
|
|
|
func (dr *defaultChainRouter) checkLocal(name chain.Name, rt RequestTarget, r resource.Request) (status chain.Status, ruleFound bool, err error) {
|
2023-12-01 13:08:52 +00:00
|
|
|
if dr.local == nil {
|
|
|
|
return
|
|
|
|
}
|
2023-12-01 15:12:57 +00:00
|
|
|
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)
|
2023-11-07 18:29:51 +00:00
|
|
|
}
|
|
|
|
|
2023-12-01 15:12:57 +00:00
|
|
|
status = chain.NoRuleFound
|
|
|
|
for _, ruleFound = range ruleFounds {
|
|
|
|
if ruleFound {
|
|
|
|
status = chain.Allow
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2023-12-01 13:08:52 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-12-01 15:12:57 +00:00
|
|
|
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)
|
2023-11-07 18:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
status = chain.NoRuleFound
|
2023-12-01 15:12:57 +00:00
|
|
|
for _, ruleFound = range ruleFounds {
|
|
|
|
if ruleFound {
|
|
|
|
status = chain.Allow
|
|
|
|
break
|
|
|
|
}
|
2023-11-07 18:29:51 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-12-01 13:08:52 +00:00
|
|
|
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)
|
2023-11-07 18:29:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2023-12-08 09:37:29 +00:00
|
|
|
status, ruleFound = dr.getStatusFromChains(localOverrides, r)
|
2023-11-07 18:29:51 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-12-01 13:08:52 +00:00
|
|
|
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)
|
2023-11-07 18:29:51 +00:00
|
|
|
if err != nil {
|
2023-12-08 09:37:29 +00:00
|
|
|
return chain.NoRuleFound, false, err
|
2023-11-07 18:29:51 +00:00
|
|
|
}
|
2023-12-08 09:37:29 +00:00
|
|
|
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
|
2023-11-07 18:29:51 +00:00
|
|
|
}
|
|
|
|
}
|
2023-12-08 09:37:29 +00:00
|
|
|
if allow {
|
|
|
|
return chain.Allow, true
|
|
|
|
}
|
|
|
|
return chain.NoRuleFound, false
|
2023-11-07 18:29:51 +00:00
|
|
|
}
|