package engine import ( "git.frostfs.info/TrueCloudLab/policy-engine/util" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" ) type inmemory struct { namespace map[chain.Name][]chainWrapper resource map[chain.Name][]chainWrapper local map[chain.Name][]*chain.Chain } type chainWrapper struct { object string chain *chain.Chain } // NewInMemory returns new inmemory instance of chain storage. func NewInMemory() CachedChainStorage { return &inmemory{ namespace: make(map[chain.Name][]chainWrapper), resource: make(map[chain.Name][]chainWrapper), local: make(map[chain.Name][]*chain.Chain), } } // IsAllowed implements the Engine interface. func (s *inmemory) IsAllowed(name chain.Name, namespace string, r resource.Request) (chain.Status, bool) { var ruleFound bool if local, ok := s.local[name]; ok { for _, c := range local { if status, matched := c.Match(r); matched && status != chain.Allow { return status, true } } } if cs, ok := s.namespace[name]; ok { status, ok := matchArray(cs, namespace, r) if ok && status != chain.Allow { return status, true } ruleFound = ruleFound || ok } if cs, ok := s.resource[name]; ok { status, ok := matchArray(cs, r.Resource().Name(), r) if ok { return status, true } ruleFound = ruleFound || ok } if ruleFound { return chain.Allow, true } return chain.NoRuleFound, false } func matchArray(cs []chainWrapper, object string, r resource.Request) (chain.Status, bool) { for _, c := range cs { if !util.GlobMatch(object, c.object) { continue } if status, matched := c.chain.Match(r); matched { return status, true } } return chain.NoRuleFound, false } func (s *inmemory) AddResourceChain(name chain.Name, resource string, c *chain.Chain) { s.resource[name] = append(s.resource[name], chainWrapper{resource, c}) } func (s *inmemory) AddNameSpaceChain(name chain.Name, namespace string, c *chain.Chain) { s.namespace[name] = append(s.namespace[name], chainWrapper{namespace, c}) } func (s *inmemory) AddOverride(name chain.Name, c *chain.Chain) { s.local[name] = append(s.local[name], c) } func (s *inmemory) GetOverride(name chain.Name, chainID chain.ID) (chain *chain.Chain, found bool) { chains := s.local[name] for _, chain = range chains { if chain.ID == chainID { found = true return } } return } func (s *inmemory) RemoveOverride(name chain.Name, chainID chain.ID) (found bool) { chains := s.local[name] for i, chain := range chains { if chain.ID == chainID { s.local[name] = append(chains[:i], chains[i+1:]...) found = true return } } return } func (s *inmemory) ListOverrides(name chain.Name) []*chain.Chain { return s.local[name] }