[#1190] object: GroupIDs must also be target of APE checks

* Also add new test case for ape middleware in container service.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
Airat Arifullin 2024-06-20 15:39:39 +03:00 committed by Evgenii Stratonikov
parent 621dbf58ab
commit 0b87388c18
2 changed files with 58 additions and 6 deletions

View file

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid"
@ -159,11 +160,19 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to create ape request: %w", err) return fmt.Errorf("failed to create ape request: %w", err)
} }
pub, err := keys.NewPublicKeyFromString(prm.SenderKey) pub, err := keys.NewPublicKeyFromString(prm.SenderKey)
if err != nil { if err != nil {
return err return err
} }
groups, err := aperequest.Groups(c.frostFSIDClient, pub)
if err != nil {
return fmt.Errorf("failed to get group ids: %w", err)
}
// Policy contract keeps group related chains as namespace-group pair.
for i := range groups {
groups[i] = fmt.Sprintf("%s:%s", prm.Namespace, groups[i])
}
if prm.BearerToken != nil && !prm.BearerToken.Impersonate() { if prm.BearerToken != nil && !prm.BearerToken.Impersonate() {
if err := isValidBearer(prm.BearerToken, prm.ContainerOwner, prm.Container, pub, c.st); err != nil { if err := isValidBearer(prm.BearerToken, prm.ContainerOwner, prm.Container, pub, c.st); err != nil {
@ -185,7 +194,7 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error {
} }
} }
rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, pub.Address()), nil) rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, pub.Address()), groups)
status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, rt, r) status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, rt, r)
if err != nil { if err != nil {
return err return err

View file

@ -27,6 +27,7 @@ import (
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory"
commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
@ -159,6 +160,8 @@ var (
objectID = "BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R" objectID = "BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R"
groupID = "1"
role = "Container" role = "Container"
senderPrivateKey, _ = keys.NewPrivateKey() senderPrivateKey, _ = keys.NewPrivateKey()
@ -238,6 +241,7 @@ var apeCheckTestCases = []struct {
methods []string methods []string
header testHeader header testHeader
containerRules []chain.Rule containerRules []chain.Rule
groupidRules []chain.Rule
expectAPEErr bool expectAPEErr bool
}{ }{
{ {
@ -393,6 +397,36 @@ var apeCheckTestCases = []struct {
}, },
expectAPEErr: true, expectAPEErr: true,
}, },
{
name: "optional oid requests reached quota limit by group-id",
container: containerID,
methods: methodsOptionalOID,
header: testHeader{
headerObjSDK: &headerObjectSDKParams{
payloadSize: 1000,
},
fromRequestResponseHeader: true,
},
groupidRules: []chain.Rule{
{
Status: chain.QuotaLimitReached,
Actions: chain.Actions{Names: methodsOptionalOID},
Resources: chain.Resources{
Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)},
},
Any: true,
Condition: []chain.Condition{
{
Op: chain.CondStringEquals,
Kind: chain.KindRequest,
Key: commonschema.PropertyKeyFrostFSIDGroupID,
Value: groupID,
},
},
},
},
expectAPEErr: true,
},
} }
type stMock struct{} type stMock struct{}
@ -486,10 +520,19 @@ func TestAPECheck(t *testing.T) {
ls := inmemory.NewInmemoryLocalStorage() ls := inmemory.NewInmemoryLocalStorage()
ms := inmemory.NewInmemoryMorphRuleChainStorage() ms := inmemory.NewInmemoryMorphRuleChainStorage()
ls.AddOverride(chain.Ingress, policyengine.ContainerTarget(test.container), &chain.Chain{ if len(test.containerRules) > 0 {
Rules: test.containerRules, ls.AddOverride(chain.Ingress, policyengine.ContainerTarget(test.container), &chain.Chain{
MatchType: chain.MatchTypeFirstMatch, Rules: test.containerRules,
}) MatchType: chain.MatchTypeFirstMatch,
})
}
if len(test.groupidRules) > 0 {
ls.AddOverride(chain.Ingress, policyengine.GroupTarget(":"+groupID), &chain.Chain{
Rules: test.groupidRules,
MatchType: chain.MatchTypeFirstMatch,
})
}
router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls)