diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 0c6732108..d7177dd96 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -12,7 +12,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - ape "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) @@ -50,7 +50,7 @@ func addRule(cmd *cobra.Command, _ []string) { rule, _ := cmd.Flags().GetString(ruleFlag) - chain := new(ape.Chain) + chain := new(apechain.Chain) commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, []string{rule})) serializedChain := chain.Bytes() diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index df2bf94fe..0c34a696e 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -9,7 +9,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) @@ -53,7 +53,7 @@ func getRule(cmd *cobra.Command, _ []string) { verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) - var chain policyengine.Chain + var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain())) // TODO (aarifullin): make pretty-formatted output for chains. diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index b3d7a5b9c..6a0879d0e 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -9,7 +9,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) @@ -58,7 +58,7 @@ func listRules(cmd *cobra.Command, _ []string) { for _, c := range chains { // TODO (aarifullin): make pretty-formatted output for chains. - var chain policyengine.Chain + var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c)) cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, chain.Bytes())) } diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 47ce37bb7..c5f8526e2 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/flynn-archive/go-shlex" ) @@ -21,13 +21,13 @@ var ( ) // ParseAPEChain parses APE chain rules. -func ParseAPEChain(chain *policyengine.Chain, rules []string) error { +func ParseAPEChain(chain *apechain.Chain, rules []string) error { if len(rules) == 0 { return errors.New("no APE rules provided") } for _, rule := range rules { - r := new(policyengine.Rule) + r := new(apechain.Rule) if err := ParseAPERule(r, rule); err != nil { return err } @@ -47,7 +47,7 @@ func ParseAPEChain(chain *policyengine.Chain, rules []string) error { // allow Object.Get Object.Resource:Department=HR Object.Request:Actor=ownerA * // //nolint:godot -func ParseAPERule(r *policyengine.Rule, rule string) error { +func ParseAPERule(r *apechain.Rule, rule string) error { lexemes, err := shlex.Split(rule) if err != nil { return fmt.Errorf("can't parse rule '%s': %v", rule, err) @@ -55,7 +55,7 @@ func ParseAPERule(r *policyengine.Rule, rule string) error { return parseRuleLexemes(r, lexemes) } -func parseRuleLexemes(r *policyengine.Rule, lexemes []string) error { +func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { if len(lexemes) < 2 { return errInvalidStatementFormat } @@ -80,14 +80,14 @@ func parseRuleLexemes(r *policyengine.Rule, lexemes []string) error { return err } -func parseStatus(lexeme string) (policyengine.Status, error) { +func parseStatus(lexeme string) (apechain.Status, error) { action, expression, found := strings.Cut(lexeme, ":") switch action = strings.ToLower(action); action { case "deny": if !found { - return policyengine.AccessDenied, nil + return apechain.AccessDenied, nil } else if strings.EqualFold(expression, "QuotaLimitReached") { - return policyengine.QuotaLimitReached, nil + return apechain.QuotaLimitReached, nil } else { return 0, fmt.Errorf("%w: %s", errUnknownActionDetail, expression) } @@ -95,38 +95,38 @@ func parseStatus(lexeme string) (policyengine.Status, error) { if found { return 0, errUnknownActionDetail } - return policyengine.Allow, nil + return apechain.Allow, nil default: return 0, errUnknownAction } } -func parseAction(lexeme string) (policyengine.Actions, error) { +func parseAction(lexeme string) (apechain.Actions, error) { switch strings.ToLower(lexeme) { case "object.put": - return policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodPutObject}}, nil case "object.get": - return policyengine.Actions{Names: []string{nativeschema.MethodGetObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodGetObject}}, nil case "object.head": - return policyengine.Actions{Names: []string{nativeschema.MethodHeadObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodHeadObject}}, nil case "object.delete": - return policyengine.Actions{Names: []string{nativeschema.MethodDeleteObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodDeleteObject}}, nil case "object.search": - return policyengine.Actions{Names: []string{nativeschema.MethodSearchObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodSearchObject}}, nil case "object.range": - return policyengine.Actions{Names: []string{nativeschema.MethodRangeObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodRangeObject}}, nil case "object.hash": - return policyengine.Actions{Names: []string{nativeschema.MethodHashObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodHashObject}}, nil default: } - return policyengine.Actions{}, fmt.Errorf("%w: %s", errUnknownOperation, lexeme) + return apechain.Actions{}, fmt.Errorf("%w: %s", errUnknownOperation, lexeme) } -func parseResource(lexeme string) (policyengine.Resources, error) { +func parseResource(lexeme string) (apechain.Resources, error) { if lexeme == "*" { - return policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, nil + return apechain.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, nil } - return policyengine.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, lexeme)}}, nil + return apechain.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, lexeme)}}, nil } const ( @@ -134,13 +134,13 @@ const ( ObjectRequest = "object.request" ) -var typeToCondObject = map[string]policyengine.ObjectType{ - ObjectResource: policyengine.ObjectResource, - ObjectRequest: policyengine.ObjectRequest, +var typeToCondObject = map[string]apechain.ObjectType{ + ObjectResource: apechain.ObjectResource, + ObjectRequest: apechain.ObjectRequest, } -func parseConditions(lexemes []string) ([]policyengine.Condition, error) { - conds := make([]policyengine.Condition, 0) +func parseConditions(lexemes []string) ([]apechain.Condition, error) { + conds := make([]apechain.Condition, 0) for _, lexeme := range lexemes { typ, expression, found := strings.Cut(lexeme, ":") @@ -155,7 +155,7 @@ func parseConditions(lexemes []string) ([]policyengine.Condition, error) { var lhs, rhs string var binExpFound bool - var cond policyengine.Condition + var cond apechain.Condition cond.Object = objType lhs, rhs, binExpFound = strings.Cut(expression, "!=") @@ -164,9 +164,9 @@ func parseConditions(lexemes []string) ([]policyengine.Condition, error) { if !binExpFound { return nil, fmt.Errorf("%w: %s", errUnknownBinaryOperator, expression) } - cond.Op = policyengine.CondStringEquals + cond.Op = apechain.CondStringEquals } else { - cond.Op = policyengine.CondStringNotEquals + cond.Op = apechain.CondStringNotEquals } cond.Key, cond.Value = lhs, rhs diff --git a/cmd/frostfs-cli/modules/util/ape_test.go b/cmd/frostfs-cli/modules/util/ape_test.go index b2e9d1d87..1cab8e6ae 100644 --- a/cmd/frostfs-cli/modules/util/ape_test.go +++ b/cmd/frostfs-cli/modules/util/ape_test.go @@ -3,7 +3,7 @@ package util import ( "testing" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/stretchr/testify/require" ) diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go index f0bd78629..248cddb11 100644 --- a/cmd/frostfs-node/policy_engine.go +++ b/cmd/frostfs-node/policy_engine.go @@ -5,23 +5,24 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" ) type apeChainSourceImpl struct { mtx sync.Mutex - localChainStorage map[cid.ID]policyengine.CachedChainStorage + localChainStorage map[cid.ID]engine.LocalOverrideEngine } func NewAPESource() container.AccessPolicyEngineChainSource { return &apeChainSourceImpl{ - localChainStorage: make(map[cid.ID]policyengine.CachedChainStorage), + localChainStorage: make(map[cid.ID]engine.LocalOverrideEngine), } } var _ container.AccessPolicyEngineChainSource = (*apeChainSourceImpl)(nil) -func (c *apeChainSourceImpl) GetChainSource(cid cid.ID) (policyengine.CachedChainStorage, error) { +func (c *apeChainSourceImpl) GetChainSource(cid cid.ID) (engine.LocalOverrideEngine, error) { c.mtx.Lock() defer c.mtx.Unlock() @@ -29,6 +30,6 @@ func (c *apeChainSourceImpl) GetChainSource(cid cid.ID) (policyengine.CachedChai if ok { return s, nil } - c.localChainStorage[cid] = policyengine.NewInMemory() + c.localChainStorage[cid] = inmemory.NewInMemoryLocalOverrides() return c.localChainStorage[cid], nil } diff --git a/go.mod b/go.mod index 5def2fade..120c05ff4 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231114100951-38985e4ec86b + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index 5c30a75e4..642280d95 100644 Binary files a/go.sum and b/go.sum differ diff --git a/internal/ape/converter.go b/internal/ape/converter.go index e268626e6..dec6f80d8 100644 --- a/internal/ape/converter.go +++ b/internal/ape/converter.go @@ -6,7 +6,7 @@ import ( v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) @@ -28,12 +28,12 @@ func (e *ConvertEACLError) Unwrap() error { return e.nested } -// ConvertEACLToAPE converts eacl.Table to policyengine.Chain. -func ConvertEACLToAPE(eaclTable *eacl.Table) (*policyengine.Chain, error) { +// ConvertEACLToAPE converts eacl.Table to apechain.Chain. +func ConvertEACLToAPE(eaclTable *eacl.Table) (*apechain.Chain, error) { if eaclTable == nil { return nil, nil } - res := &policyengine.Chain{} + res := &apechain.Chain{} resource := getResource(eaclTable) @@ -67,53 +67,53 @@ func ConvertEACLToAPE(eaclTable *eacl.Table) (*policyengine.Chain, error) { return res, nil } -func appendTargetsOnly(source []policyengine.Rule, st policyengine.Status, act policyengine.Actions, res policyengine.Resources, targets []eacl.Target) []policyengine.Rule { +func appendTargetsOnly(source []apechain.Rule, st apechain.Status, act apechain.Actions, res apechain.Resources, targets []eacl.Target) []apechain.Rule { // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 // role OR public key must be equal - rule := policyengine.Rule{ + rule := apechain.Rule{ Status: st, Actions: act, Resources: res, Any: true, } for _, target := range targets { - var roleCondition policyengine.Condition - roleCondition.Object = policyengine.ObjectRequest + var roleCondition apechain.Condition + roleCondition.Object = apechain.ObjectRequest roleCondition.Key = nativeschema.PropertyKeyActorRole roleCondition.Value = target.Role().String() - roleCondition.Op = policyengine.CondStringEquals + roleCondition.Op = apechain.CondStringEquals rule.Condition = append(rule.Condition, roleCondition) for _, binKey := range target.BinaryKeys() { - var pubKeyCondition policyengine.Condition - pubKeyCondition.Object = policyengine.ObjectRequest + var pubKeyCondition apechain.Condition + pubKeyCondition.Object = apechain.ObjectRequest pubKeyCondition.Key = nativeschema.PropertyKeyActorPublicKey pubKeyCondition.Value = hex.EncodeToString(binKey) - pubKeyCondition.Op = policyengine.CondStringEquals + pubKeyCondition.Op = apechain.CondStringEquals rule.Condition = append(rule.Condition, pubKeyCondition) } } return append(source, rule) } -func appendTargetsAndFilters(source []policyengine.Rule, st policyengine.Status, act policyengine.Actions, res policyengine.Resources, +func appendTargetsAndFilters(source []apechain.Rule, st apechain.Status, act apechain.Actions, res apechain.Resources, targets []eacl.Target, filters []eacl.Filter, -) ([]policyengine.Rule, error) { +) ([]apechain.Rule, error) { // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 // role OR public key must be equal // so filters are repeated for each role and public key var err error for _, target := range targets { - rule := policyengine.Rule{ + rule := apechain.Rule{ Status: st, Actions: act, Resources: res, } - var roleCondition policyengine.Condition - roleCondition.Object = policyengine.ObjectRequest + var roleCondition apechain.Condition + roleCondition.Object = apechain.ObjectRequest roleCondition.Key = nativeschema.PropertyKeyActorRole roleCondition.Value = target.Role().String() - roleCondition.Op = policyengine.CondStringEquals + roleCondition.Op = apechain.CondStringEquals rule.Condition = append(rule.Condition, roleCondition) rule.Condition, err = appendFilters(rule.Condition, filters) @@ -124,16 +124,16 @@ func appendTargetsAndFilters(source []policyengine.Rule, st policyengine.Status, source = append(source, rule) for _, binKey := range target.BinaryKeys() { - rule := policyengine.Rule{ + rule := apechain.Rule{ Status: st, Actions: act, Resources: res, } - var pubKeyCondition policyengine.Condition - pubKeyCondition.Object = policyengine.ObjectRequest + var pubKeyCondition apechain.Condition + pubKeyCondition.Object = apechain.ObjectRequest pubKeyCondition.Key = nativeschema.PropertyKeyActorPublicKey pubKeyCondition.Value = hex.EncodeToString(binKey) - pubKeyCondition.Op = policyengine.CondStringEquals + pubKeyCondition.Op = apechain.CondStringEquals rule.Condition = append(rule.Condition, pubKeyCondition) rule.Condition, err = appendFilters(rule.Condition, filters) @@ -148,23 +148,23 @@ func appendTargetsAndFilters(source []policyengine.Rule, st policyengine.Status, return source, nil } -func appendFilters(source []policyengine.Condition, filters []eacl.Filter) ([]policyengine.Condition, error) { +func appendFilters(source []apechain.Condition, filters []eacl.Filter) ([]apechain.Condition, error) { for _, filter := range filters { - var cond policyengine.Condition + var cond apechain.Condition var isObject bool if filter.From() == eacl.HeaderFromObject { - cond.Object = policyengine.ObjectResource + cond.Object = apechain.ObjectResource isObject = true } else if filter.From() == eacl.HeaderFromRequest { - cond.Object = policyengine.ObjectRequest + cond.Object = apechain.ObjectRequest } else { return nil, &ConvertEACLError{nested: fmt.Errorf("unknown filter from: %d", filter.From())} } if filter.Matcher() == eacl.MatchStringEqual { - cond.Op = policyengine.CondStringEquals + cond.Op = apechain.CondStringEquals } else if filter.Matcher() == eacl.MatchStringNotEqual { - cond.Op = policyengine.CondStringNotEquals + cond.Op = apechain.CondStringNotEquals } else { return nil, &ConvertEACLError{nested: fmt.Errorf("unknown filter matcher: %d", filter.Matcher())} } @@ -205,30 +205,30 @@ func eaclKeyToAPEKey(key string, isObject bool) string { } } -func getResource(eaclTable *eacl.Table) policyengine.Resources { +func getResource(eaclTable *eacl.Table) apechain.Resources { cnrID, isSet := eaclTable.CID() if isSet { - return policyengine.Resources{ + return apechain.Resources{ Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, } } - return policyengine.Resources{ + return apechain.Resources{ Names: []string{nativeschema.ResourceFormatRootObjects}, } } -func actionToStatus(a eacl.Action) (policyengine.Status, error) { +func actionToStatus(a eacl.Action) (apechain.Status, error) { switch a { case eacl.ActionAllow: - return policyengine.Allow, nil + return apechain.Allow, nil case eacl.ActionDeny: - return policyengine.AccessDenied, nil + return apechain.AccessDenied, nil default: - return policyengine.NoRuleFound, &ConvertEACLError{nested: fmt.Errorf("unknown action: %d", a)} + return apechain.NoRuleFound, &ConvertEACLError{nested: fmt.Errorf("unknown action: %d", a)} } } -var eaclOperationToEngineAction = map[eacl.Operation]policyengine.Actions{ +var eaclOperationToEngineAction = map[eacl.Operation]apechain.Actions{ eacl.OperationGet: {Names: []string{nativeschema.MethodGetObject}}, eacl.OperationHead: {Names: []string{nativeschema.MethodHeadObject}}, eacl.OperationPut: {Names: []string{nativeschema.MethodPutObject}}, @@ -238,9 +238,9 @@ var eaclOperationToEngineAction = map[eacl.Operation]policyengine.Actions{ eacl.OperationRangeHash: {Names: []string{nativeschema.MethodHashObject}}, } -func operationToAction(op eacl.Operation) (policyengine.Actions, error) { +func operationToAction(op eacl.Operation) (apechain.Actions, error) { if v, ok := eaclOperationToEngineAction[op]; ok { return v, nil } - return policyengine.Actions{}, &ConvertEACLError{nested: fmt.Errorf("unknown operation: %d", op)} + return apechain.Actions{}, &ConvertEACLError{nested: fmt.Errorf("unknown operation: %d", op)} } diff --git a/internal/ape/converter_test.go b/internal/ape/converter_test.go index bf6205ec9..de72408b1 100644 --- a/internal/ape/converter_test.go +++ b/internal/ape/converter_test.go @@ -7,7 +7,8 @@ import ( cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" @@ -393,7 +394,7 @@ func TestNoHeader(t *testing.T) { compare(t, tb, vu, ch, req) } -func compare(t *testing.T, eaclTable *eacl.Table, vu *eacl.ValidationUnit, ch *policyengine.Chain, req *testRequest) { +func compare(t *testing.T, eaclTable *eacl.Table, vu *eacl.ValidationUnit, ch *apechain.Chain, req *testRequest) { validator := eacl.NewValidator() for eaclOp, apeOp := range eaclOperationToEngineAction { vu.WithOperation(eaclOp) @@ -406,12 +407,12 @@ func compare(t *testing.T, eaclTable *eacl.Table, vu *eacl.ValidationUnit, ch *p require.NotEqual(t, eacl.ActionUnknown, eaclAct) if eaclAct == eacl.ActionAllow { if recordFound { - require.Equal(t, policyengine.Allow, apeSt) + require.Equal(t, apechain.Allow, apeSt) } else { - require.Equal(t, policyengine.NoRuleFound, apeSt) + require.Equal(t, apechain.NoRuleFound, apeSt) } } else { - require.Equal(t, policyengine.AccessDenied, apeSt) + require.Equal(t, apechain.AccessDenied, apeSt) } } } @@ -433,7 +434,7 @@ func (r *testRequest) Property(key string) string { return "" } -func (r *testRequest) Resource() policyengine.Resource { +func (r *testRequest) Resource() resource.Resource { return r.res } diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index ebafd22db..cc358b436 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -7,7 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" ) // Container groups information about the FrostFS container stored in the FrostFS network. @@ -77,5 +77,5 @@ type EACLSource interface { // policy engine chain storage. type AccessPolicyEngineChainSource interface { // TODO (aarifullin): Better to use simpler interface instead CachedChainStorage. - GetChainSource(cid cid.ID) (policyengine.CachedChainStorage, error) + GetChainSource(cid cid.ID) (engine.LocalOverrideEngine, error) } diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 19d1b7148..8565cd9c1 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -2,11 +2,14 @@ package control import ( "context" + "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + engine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -22,7 +25,7 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL return nil, status.Error(codes.InvalidArgument, err.Error()) } - var chain policyengine.Chain + var chain apechain.Chain if err = chain.DecodeBytes(req.GetBody().GetChain()); err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -34,9 +37,12 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL s.apeChainCounter.Add(1) // TODO (aarifullin): the such chain id is not well-designed yet. - chain.ID = policyengine.ChainID(fmt.Sprintf("%s:%d", policyengine.Ingress, s.apeChainCounter.Load())) + chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load())) - src.AddOverride(policyengine.Ingress, &chain) + resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + if _, err = src.LocalStorage().AddOverride(apechain.Ingress, resource, &chain); err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) + } resp := &control.AddChainLocalOverrideResponse{ Body: &control.AddChainLocalOverrideResponse_Body{ @@ -66,10 +72,10 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL return nil, status.Error(codes.Internal, err.Error()) } - chain, found := src.GetOverride(policyengine.Ingress, policyengine.ChainID(req.GetBody().GetChainId())) - if !found { - err = fmt.Errorf("local override has not been found") - return nil, status.Error(codes.NotFound, err.Error()) + resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + chain, err := src.LocalStorage().GetOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())) + if err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } resp := &control.GetChainLocalOverrideResponse{ @@ -100,7 +106,11 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha return nil, status.Error(codes.Internal, err.Error()) } - chains := src.ListOverrides(policyengine.Ingress) + resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + chains, err := src.LocalStorage().ListOverrides(apechain.Ingress, resource) + if err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) + } serializedChains := make([][]byte, 0, len(chains)) for _, chain := range chains { serializedChains = append(serializedChains, chain.Bytes()) @@ -134,10 +144,13 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return nil, status.Error(codes.Internal, err.Error()) } - removed := src.RemoveOverride(policyengine.Ingress, policyengine.ChainID(req.GetBody().GetChainId())) + resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + if err = src.LocalStorage().RemoveOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())); err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) + } resp := &control.RemoveChainLocalOverrideResponse{ Body: &control.RemoveChainLocalOverrideResponse_Body{ - Removed: removed, + Removed: true, }, } err = SignMessage(s.key, resp) @@ -146,3 +159,10 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove } return resp, nil } + +func getCodeByLocalStorageErr(err error) codes.Code { + if errors.Is(err, engine.ErrChainNotFound) { + return codes.NotFound + } + return codes.Internal +} diff --git a/pkg/services/object/acl/ape.go b/pkg/services/object/acl/ape.go index 86af440fe..525ed5930 100644 --- a/pkg/services/object/acl/ape.go +++ b/pkg/services/object/acl/ape.go @@ -8,7 +8,7 @@ import ( v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" ) var errAPEChainNoSource = errors.New("could not get ape chain source for the container") @@ -36,9 +36,12 @@ func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { request := new(Request) request.FromRequestInfo(reqInfo) - status, ruleFound := chainCache.IsAllowed(policyengine.Ingress, "", request) + status, ruleFound, err := chainCache.IsAllowed(apechain.Ingress, "", request) + if err != nil { + return err + } - if !ruleFound || status == policyengine.Allow { + if !ruleFound || status == apechain.Allow { return nil } @@ -47,7 +50,7 @@ func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { const accessDeniedAPEReasonFmt = "access to operation %s is denied by access policy engine: %s" -func apeErr(req v2.RequestInfo, status policyengine.Status) error { +func apeErr(req v2.RequestInfo, status apechain.Status) error { errAccessDenied := &apistatus.ObjectAccessDenied{} errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedAPEReasonFmt, req.Operation(), status.String())) return errAccessDenied diff --git a/pkg/services/object/acl/ape_request.go b/pkg/services/object/acl/ape_request.go index 3e8bb173d..accbdce5f 100644 --- a/pkg/services/object/acl/ape_request.go +++ b/pkg/services/object/acl/ape_request.go @@ -5,7 +5,8 @@ import ( v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" aclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) type Request struct { @@ -14,14 +15,14 @@ type Request struct { properties map[string]string } -var _ policyengine.Request = (*Request)(nil) +var _ aperesource.Request = (*Request)(nil) type resource struct { name string properties map[string]string } -var _ policyengine.Resource = (*resource)(nil) +var _ aperesource.Resource = (*resource)(nil) func (r *resource) Name() string { return r.name @@ -31,18 +32,14 @@ func (r *resource) Property(key string) string { return r.properties[key] } -// TODO (aarifullin): these stringified verbs, properties and namespaces -// should be non-implementation-specific. func getResource(reqInfo v2.RequestInfo) *resource { + var name string cid := reqInfo.ContainerID() - oid := "*" - if reqOID := reqInfo.ObjectID(); reqOID != nil { - oid = reqOID.EncodeToString() + if oid := reqInfo.ObjectID(); oid != nil { + name = fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, cid.EncodeToString(), oid.EncodeToString()) + } else { + name = fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) } - name := fmt.Sprintf("native:::object/%s/%s", - cid, - oid) - return &resource{ name: name, properties: make(map[string]string), @@ -51,32 +48,30 @@ func getResource(reqInfo v2.RequestInfo) *resource { func getProperties(_ v2.RequestInfo) map[string]string { return map[string]string{ - "Actor": "", + nativeschema.PropertyKeyActorPublicKey: "", + nativeschema.PropertyKeyActorRole: "", } } -// TODO (aarifullin): these stringified verbs, properties and namespaces -// should be non-implementation-specific. func getOperation(reqInfo v2.RequestInfo) string { - var verb string switch op := reqInfo.Operation(); op { case aclSDK.OpObjectGet: - verb = "GetObject" + return nativeschema.MethodGetObject case aclSDK.OpObjectHead: - verb = "HeadObject" + return nativeschema.MethodHeadObject case aclSDK.OpObjectPut: - verb = "PutObject" + return nativeschema.MethodPutObject case aclSDK.OpObjectDelete: - verb = "DeleteObject" + return nativeschema.MethodDeleteObject case aclSDK.OpObjectSearch: - verb = "SearchObject" + return nativeschema.MethodSearchObject case aclSDK.OpObjectRange: - verb = "RangeObject" + return nativeschema.MethodRangeObject case aclSDK.OpObjectHash: - verb = "HashObject" + return nativeschema.MethodHashObject + default: + return "" } - - return "native:" + verb } func NewRequest() *Request { @@ -100,6 +95,6 @@ func (r *Request) Property(key string) string { return r.properties[key] } -func (r *Request) Resource() policyengine.Resource { +func (r *Request) Resource() aperesource.Resource { return r.resource }