diff --git a/go.mod b/go.mod index d4eb52f4d..ee8b1bb16 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 84fdbd47a..c7c3b87eb 100644 Binary files a/go.sum and b/go.sum differ diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index c6f9b711d..a1972292e 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -7,6 +7,7 @@ import ( "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" 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/core/container" @@ -79,6 +80,9 @@ type Prm struct { // The request's bearer token. It is used in order to check APE overrides with the token. BearerToken *bearer.Token + + // XHeaders from the request. + XHeaders []session.XHeader } var ( diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 27c314dfb..090f6a83c 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" @@ -240,6 +241,7 @@ var apeCheckTestCases = []struct { object *string methods []string header testHeader + xHeaders []session.XHeader containerRules []chain.Rule groupidRules []chain.Rule expectAPEErr bool @@ -367,6 +369,52 @@ var apeCheckTestCases = []struct { }, expectAPEErr: true, }, + { + name: "oid required requests are denied by xheader", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + attributes: []struct { + key string + val string + }{ + { + key: "attr1", + val: "attribute_value", + }, + }, + }, + fromHeaderProvider: true, + }, + xHeaders: []session.XHeader{ + func() (xhead session.XHeader) { + xhead.SetKey("X-Test-ID") + xhead.SetValue("aezakmi") + return + }(), + }, + containerRules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringLike, + Kind: chain.KindRequest, + Key: fmt.Sprintf(commonschema.PropertyKeyFrostFSXHeader, "X-Test-ID"), + Value: "aezakmi", + }, + }, + }, + }, + expectAPEErr: true, + }, { name: "optional oid requests reached quota limit by an attribute", container: containerID, diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 02ead8c60..1c129f65f 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -126,6 +126,12 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, nativeschema.PropertyKeyActorRole: prm.Role, } + + for _, xhead := range prm.XHeaders { + xheadKey := fmt.Sprintf(commonschema.PropertyKeyFrostFSXHeader, xhead.GetKey()) + reqProps[xheadKey] = xhead.GetValue() + } + var err error reqProps, err = c.fillWithUserClaimTags(reqProps, prm) if err != nil { diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 853c3b80d..56c66002d 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -111,6 +111,7 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { Role: g.role, SoftAPECheck: g.softAPECheck, BearerToken: g.bearerToken, + XHeaders: resp.GetMetaHeader().GetXHeaders(), } if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil { @@ -154,6 +155,7 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt SoftAPECheck: reqCtx.SoftAPECheck, WithoutHeaderRequest: true, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -200,6 +202,7 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR Role: nativeSchemaRole(reqCtx.Role), SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -245,6 +248,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj SoftAPECheck: reqCtx.SoftAPECheck, WithoutHeaderRequest: true, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -285,6 +289,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -314,6 +319,7 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -343,6 +349,7 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -377,6 +384,7 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -406,6 +414,7 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -445,6 +454,7 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil {