diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index b51386e0..1f1c275c 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -113,10 +113,11 @@ type wrappedGetObjectStream struct { func (w *wrappedGetObjectStream) Context() context.Context { return context.WithValue(w.GetObjectStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), - SoftAPECheck: w.requestInfo.IsSoftAPECheck(), + Namespace: w.requestInfo.ContainerNamespace(), + ContainerOwner: w.requestInfo.ContainerOwner(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + SoftAPECheck: w.requestInfo.IsSoftAPECheck(), }) } @@ -137,10 +138,11 @@ type wrappedRangeStream struct { func (w *wrappedRangeStream) Context() context.Context { return context.WithValue(w.GetObjectRangeStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), - SoftAPECheck: w.requestInfo.IsSoftAPECheck(), + Namespace: w.requestInfo.ContainerNamespace(), + ContainerOwner: w.requestInfo.ContainerOwner(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + SoftAPECheck: w.requestInfo.IsSoftAPECheck(), }) } @@ -161,10 +163,11 @@ type wrappedSearchStream struct { func (w *wrappedSearchStream) Context() context.Context { return context.WithValue(w.SearchStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), - SoftAPECheck: w.requestInfo.IsSoftAPECheck(), + Namespace: w.requestInfo.ContainerNamespace(), + ContainerOwner: w.requestInfo.ContainerOwner(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + SoftAPECheck: w.requestInfo.IsSoftAPECheck(), }) } @@ -471,10 +474,11 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context { return context.WithValue(ctx, object.RequestContextKey, &object.RequestContext{ - Namespace: reqInfo.ContainerNamespace(), - SenderKey: reqInfo.SenderKey(), - Role: reqInfo.RequestRole(), - SoftAPECheck: reqInfo.IsSoftAPECheck(), + Namespace: reqInfo.ContainerNamespace(), + ContainerOwner: reqInfo.ContainerOwner(), + SenderKey: reqInfo.SenderKey(), + Role: reqInfo.RequestRole(), + SoftAPECheck: reqInfo.IsSoftAPECheck(), }) } diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 1d42d21d..45efce5a 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -8,6 +8,7 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" @@ -48,6 +49,9 @@ type Prm struct { // An encoded sender's public key string. SenderKey string + // An encoded container's owner user ID. + ContainerOwner user.ID + // If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow. SoftAPECheck bool } diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index caf52645..3689bd17 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -10,6 +10,7 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) @@ -78,11 +79,13 @@ func resourceName(cid cid.ID, oid *oid.ID, namespace string) string { } // objectProperties collects object properties from address parameters and a header if it is passed. -func objectProperties(cnr cid.ID, oid *oid.ID, header *objectV2.Header) map[string]string { +func objectProperties(cnr cid.ID, oid *oid.ID, cnrOwner user.ID, header *objectV2.Header) map[string]string { objectProps := map[string]string{ nativeschema.PropertyKeyObjectContainerID: cnr.EncodeToString(), } + objectProps[nativeschema.PropertyKeyContainerOwnerID] = cnrOwner.EncodeToString() + if oid != nil { objectProps[nativeschema.PropertyKeyObjectID] = oid.String() } @@ -149,7 +152,7 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (*request, err operation: prm.Method, resource: &resource{ name: resourceName(prm.Container, prm.Object, prm.Namespace), - properties: objectProperties(prm.Container, prm.Object, header), + properties: objectProperties(prm.Container, prm.Object, prm.ContainerOwner, header), }, properties: map[string]string{ nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index 0dcc0b84..c5b43fa8 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -8,11 +8,16 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/stretchr/testify/require" ) +const ( + testOwnerID = "FPPtmAi9TCX329" +) + func TestObjectProperties(t *testing.T) { for _, test := range []struct { name string @@ -82,8 +87,12 @@ func TestObjectProperties(t *testing.T) { obj := newObjectIDSDK(t, test.object) header := newHeaderObjectSDK(cnr, obj, test.header) - props := objectProperties(cnr, obj, header.ToV2().GetHeader()) + var testCnrOwner user.ID + require.NoError(t, testCnrOwner.DecodeString(testOwnerID)) + + props := objectProperties(cnr, obj, testCnrOwner, header.ToV2().GetHeader()) require.Equal(t, test.container, props[nativeschema.PropertyKeyObjectContainerID]) + require.Equal(t, testOwnerID, props[nativeschema.PropertyKeyContainerOwnerID]) if obj != nil { require.Equal(t, *test.object, props[nativeschema.PropertyKeyObjectID]) @@ -210,13 +219,17 @@ func TestNewAPERequest(t *testing.T) { cnr := newContainerIDSDK(t, test.container) obj := newObjectIDSDK(t, test.object) + var testCnrOwner user.ID + require.NoError(t, testCnrOwner.DecodeString(testOwnerID)) + prm := Prm{ - Namespace: test.namespace, - Method: method, - Container: cnr, - Object: obj, - Role: role, - SenderKey: senderKey, + Namespace: test.namespace, + Method: method, + Container: cnr, + Object: obj, + Role: role, + SenderKey: senderKey, + ContainerOwner: testCnrOwner, } headerSource := newHeaderProviderMock() @@ -247,7 +260,7 @@ func TestNewAPERequest(t *testing.T) { operation: method, resource: &resource{ name: resourceName(cnr, obj, prm.Namespace), - properties: objectProperties(cnr, obj, func() *objectV2.Header { + properties: objectProperties(cnr, obj, testCnrOwner, func() *objectV2.Header { if headerObjSDK != nil { return headerObjSDK.ToV2().GetHeader() } diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 8f45a8ff..0c203209 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -14,6 +14,7 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) @@ -67,6 +68,8 @@ type getStreamBasicChecker struct { senderKey []byte + containerOwner user.ID + role string softAPECheck bool @@ -80,14 +83,15 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { } prm := Prm{ - Namespace: g.namespace, - Container: cnrID, - Object: objID, - Header: partInit.GetHeader(), - Method: nativeschema.MethodGetObject, - SenderKey: hex.EncodeToString(g.senderKey), - Role: g.role, - SoftAPECheck: g.softAPECheck, + Namespace: g.namespace, + Container: cnrID, + Object: objID, + Header: partInit.GetHeader(), + Method: nativeschema.MethodGetObject, + SenderKey: hex.EncodeToString(g.senderKey), + ContainerOwner: g.containerOwner, + Role: g.role, + SoftAPECheck: g.softAPECheck, } if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil { @@ -121,13 +125,14 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodGetObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodGetObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return toStatusErr(err) @@ -162,14 +167,15 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Header: partInit.GetHeader(), - Method: nativeschema.MethodPutObject, - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - Role: nativeSchemaRole(reqCtx.Role), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: partInit.GetHeader(), + Method: nativeschema.MethodPutObject, + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + Role: nativeSchemaRole(reqCtx.Role), + SoftAPECheck: reqCtx.SoftAPECheck, } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -205,13 +211,14 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodHeadObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodHeadObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return nil, toStatusErr(err) @@ -242,14 +249,15 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Header: header, - Method: nativeschema.MethodHeadObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: header, + Method: nativeschema.MethodHeadObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return nil, toStatusErr(err) @@ -271,12 +279,13 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Method: nativeschema.MethodSearchObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Method: nativeschema.MethodSearchObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return toStatusErr(err) @@ -297,13 +306,14 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodDeleteObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodDeleteObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return nil, toStatusErr(err) @@ -329,13 +339,14 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodRangeObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodRangeObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return toStatusErr(err) @@ -356,13 +367,14 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodHashObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodHashObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -392,14 +404,15 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Header: request.GetBody().GetObject().GetHeader(), - Method: nativeschema.MethodPutObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: request.GetBody().GetObject().GetHeader(), + Method: nativeschema.MethodPutObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { diff --git a/pkg/services/object/request_context.go b/pkg/services/object/request_context.go index e0e6c9ed..6a0965b4 100644 --- a/pkg/services/object/request_context.go +++ b/pkg/services/object/request_context.go @@ -1,6 +1,9 @@ package object -import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" +) type RequestContextKeyT struct{} @@ -12,6 +15,8 @@ type RequestContext struct { SenderKey []byte + ContainerOwner user.ID + Role acl.Role SoftAPECheck bool