2023-11-07 17:20:54 +00:00
|
|
|
package engine
|
|
|
|
|
|
|
|
import (
|
|
|
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
|
|
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource"
|
2024-02-22 09:09:22 +00:00
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
2023-11-29 13:36:54 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
2023-11-07 17:20:54 +00:00
|
|
|
)
|
|
|
|
|
2023-11-07 18:29:51 +00:00
|
|
|
type ChainRouter interface {
|
2023-11-07 17:20:54 +00:00
|
|
|
// IsAllowed returns status for the operation after all checks.
|
|
|
|
// The second return value signifies whether a matching rule was found.
|
2023-12-01 15:12:57 +00:00
|
|
|
IsAllowed(name chain.Name, reqTarget RequestTarget, r resource.Request) (status chain.Status, found bool, err error)
|
2023-11-07 18:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// LocalOverrideStorage is the interface to manage local overrides defined
|
|
|
|
// for a node. Local overrides have a higher priority than chains got from morph storage.
|
|
|
|
type LocalOverrideStorage interface {
|
2023-12-01 13:08:52 +00:00
|
|
|
AddOverride(name chain.Name, target Target, c *chain.Chain) (chain.ID, error)
|
2023-11-07 18:29:51 +00:00
|
|
|
|
2023-12-01 13:08:52 +00:00
|
|
|
GetOverride(name chain.Name, target Target, chainID chain.ID) (*chain.Chain, error)
|
2023-11-07 18:29:51 +00:00
|
|
|
|
2023-12-01 13:08:52 +00:00
|
|
|
RemoveOverride(name chain.Name, target Target, chainID chain.ID) error
|
2023-11-07 18:29:51 +00:00
|
|
|
|
2024-03-07 10:55:41 +00:00
|
|
|
RemoveOverridesByTarget(name chain.Name, target Target) error
|
|
|
|
|
2023-12-01 13:08:52 +00:00
|
|
|
ListOverrides(name chain.Name, target Target) ([]*chain.Chain, error)
|
2023-11-07 18:29:51 +00:00
|
|
|
|
|
|
|
DropAllOverrides(name chain.Name) error
|
2024-01-26 14:25:59 +00:00
|
|
|
|
|
|
|
ListOverrideDefinedTargets(name chain.Name) ([]Target, error)
|
2023-11-07 17:20:54 +00:00
|
|
|
}
|
|
|
|
|
2023-11-07 18:29:51 +00:00
|
|
|
type TargetType rune
|
|
|
|
|
|
|
|
const (
|
|
|
|
Namespace TargetType = 'n'
|
|
|
|
Container TargetType = 'c'
|
2024-04-09 15:10:56 +00:00
|
|
|
User TargetType = 'u'
|
|
|
|
Group TargetType = 'g'
|
2023-11-07 18:29:51 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Target struct {
|
|
|
|
Type TargetType
|
|
|
|
Name string
|
|
|
|
}
|
|
|
|
|
2023-12-01 15:12:57 +00:00
|
|
|
// RequestTarget combines several targets on which the request is performed.
|
|
|
|
type RequestTarget struct {
|
|
|
|
Namespace *Target
|
|
|
|
Container *Target
|
2024-04-09 15:10:56 +00:00
|
|
|
User *Target
|
|
|
|
Groups []Target
|
2023-12-01 15:12:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewRequestTargetWithNamespace(namespace string) RequestTarget {
|
|
|
|
nt := NamespaceTarget(namespace)
|
|
|
|
return RequestTarget{
|
|
|
|
Namespace: &nt,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRequestTargetWithContainer(container string) RequestTarget {
|
|
|
|
ct := ContainerTarget(container)
|
|
|
|
return RequestTarget{
|
|
|
|
Container: &ct,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRequestTarget(namespace, container string) RequestTarget {
|
|
|
|
nt := NamespaceTarget(namespace)
|
|
|
|
ct := ContainerTarget(container)
|
|
|
|
return RequestTarget{
|
|
|
|
Namespace: &nt,
|
|
|
|
Container: &ct,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-09 15:10:56 +00:00
|
|
|
func NewRequestTargetExtended(namespace, container, user string, groups []string) RequestTarget {
|
|
|
|
nt := NamespaceTarget(namespace)
|
|
|
|
ct := ContainerTarget(container)
|
|
|
|
u := UserTarget(user)
|
|
|
|
rt := RequestTarget{
|
|
|
|
Namespace: &nt,
|
|
|
|
Container: &ct,
|
|
|
|
User: &u,
|
|
|
|
}
|
|
|
|
if len(groups) != 0 {
|
|
|
|
rt.Groups = make([]Target, len(groups))
|
|
|
|
for i := range groups {
|
|
|
|
rt.Groups[i] = GroupTarget(groups[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rt
|
|
|
|
}
|
|
|
|
|
2023-12-01 15:12:57 +00:00
|
|
|
func (rt *RequestTarget) Targets() (targets []Target) {
|
|
|
|
if rt.Namespace != nil {
|
|
|
|
targets = append(targets, *rt.Namespace)
|
|
|
|
}
|
2024-02-06 08:44:11 +00:00
|
|
|
if rt.Container != nil {
|
|
|
|
targets = append(targets, *rt.Container)
|
|
|
|
}
|
2024-04-09 15:10:56 +00:00
|
|
|
if rt.User != nil {
|
|
|
|
targets = append(targets, *rt.User)
|
|
|
|
}
|
|
|
|
if len(rt.Groups) != 0 {
|
|
|
|
targets = append(targets, rt.Groups...)
|
|
|
|
}
|
2023-12-01 15:12:57 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-11-07 18:29:51 +00:00
|
|
|
func NamespaceTarget(namespace string) Target {
|
|
|
|
return Target{
|
|
|
|
Type: Namespace,
|
|
|
|
Name: namespace,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func ContainerTarget(container string) Target {
|
|
|
|
return Target{
|
|
|
|
Type: Container,
|
|
|
|
Name: container,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-09 15:10:56 +00:00
|
|
|
func UserTarget(user string) Target {
|
|
|
|
return Target{
|
|
|
|
Type: User,
|
|
|
|
Name: user,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func GroupTarget(group string) Target {
|
|
|
|
return Target{
|
|
|
|
Type: Group,
|
|
|
|
Name: group,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-26 15:19:37 +00:00
|
|
|
// MorphRuleChainStorageReader is the interface that provides read-only methods to receive
|
|
|
|
// data like chains, target or admin from a chain storage.
|
|
|
|
type MorphRuleChainStorageReader interface {
|
|
|
|
// ListMorphRuleChains just lists deserialized chains.
|
|
|
|
ListMorphRuleChains(name chain.Name, target Target) ([]*chain.Chain, error)
|
|
|
|
|
|
|
|
GetAdmin() (util.Uint160, error)
|
2024-02-22 09:09:22 +00:00
|
|
|
|
|
|
|
// ListTargetsIterator provides an iterator to list targets for which rules are defined.
|
|
|
|
ListTargetsIterator(targetType TargetType) (uuid.UUID, result.Iterator, error)
|
2024-02-26 15:19:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MorphRuleChainStorage is the interface to read and manage data within a chain storage.
|
2023-11-07 18:29:51 +00:00
|
|
|
// Basically, this implies that the storage manages rules stored in policy contract.
|
|
|
|
type MorphRuleChainStorage interface {
|
2024-02-26 15:19:37 +00:00
|
|
|
MorphRuleChainStorageReader
|
|
|
|
|
2023-11-29 13:36:54 +00:00
|
|
|
// AddMorphRuleChain adds a chain rule to the policy contract and returns transaction hash, VUB and error.
|
|
|
|
AddMorphRuleChain(name chain.Name, target Target, c *chain.Chain) (util.Uint256, uint32, error)
|
2023-11-07 18:29:51 +00:00
|
|
|
|
2023-11-29 13:36:54 +00:00
|
|
|
// RemoveMorphRuleChain removes a chain rule to the policy contract and returns transaction hash, VUB and error.
|
|
|
|
RemoveMorphRuleChain(name chain.Name, target Target, chainID chain.ID) (util.Uint256, uint32, error)
|
2023-11-07 18:29:51 +00:00
|
|
|
|
2024-03-07 10:55:41 +00:00
|
|
|
// RemoveMorphRuleChainsByTarget removes all chains by target and returns transaction hash, VUB and error.
|
|
|
|
RemoveMorphRuleChainsByTarget(name chain.Name, target Target) (util.Uint256, uint32, error)
|
|
|
|
|
2024-02-26 15:19:37 +00:00
|
|
|
SetAdmin(addr util.Uint160) (util.Uint256, uint32, error)
|
2023-11-07 18:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Engine is the interface that provides methods to check request permissions checking
|
|
|
|
// chain rules from morph client - this implies using the policy contract.
|
|
|
|
type Engine interface {
|
|
|
|
ChainRouter
|
|
|
|
|
|
|
|
MorphRuleChainStorage() MorphRuleChainStorage
|
|
|
|
}
|
|
|
|
|
|
|
|
// LocalOverrideEngine is extended Engine that also provides methods to manage a local
|
|
|
|
// chain rule storage. Local overrides must have the highest priority during request checking.
|
|
|
|
type LocalOverrideEngine interface {
|
2023-11-07 17:20:54 +00:00
|
|
|
Engine
|
2023-11-07 18:29:51 +00:00
|
|
|
|
|
|
|
LocalStorage() LocalOverrideStorage
|
2023-11-07 17:20:54 +00:00
|
|
|
}
|