forked from TrueCloudLab/policy-engine
Evgenii Stratonikov
a11e80e2c7
So, it's sunday evening and I am sitting on-call trying to debug strange node behaviour. It took me 3 whole minutes to understand the code being changed: it accumulates bools in slices, even though no slice is needed; it uses subtle condition from the first loop to make decision in the second one, and finally it uses named return values. In this commit we remove the slice and the second loop, because why not. Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
111 lines
3 KiB
Go
111 lines
3 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 hasAllow bool
|
|
for _, target := range rt.Targets() {
|
|
status, ruleFound, err = dr.matchLocalOverrides(name, target, r)
|
|
if err != nil || ruleFound && status != chain.Allow {
|
|
return
|
|
}
|
|
hasAllow = hasAllow || ruleFound
|
|
}
|
|
|
|
status = chain.NoRuleFound
|
|
if hasAllow {
|
|
status = chain.Allow
|
|
}
|
|
return
|
|
}
|
|
|
|
func (dr *defaultChainRouter) checkMorph(name chain.Name, rt RequestTarget, r resource.Request) (status chain.Status, ruleFound bool, err error) {
|
|
var hasAllow bool
|
|
for _, target := range rt.Targets() {
|
|
status, ruleFound, err = dr.matchMorphRuleChains(name, target, r)
|
|
if err != nil || ruleFound && status != chain.Allow {
|
|
return
|
|
}
|
|
hasAllow = hasAllow || ruleFound
|
|
}
|
|
|
|
status = chain.NoRuleFound
|
|
if hasAllow {
|
|
status = chain.Allow
|
|
}
|
|
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
|
|
}
|