[#1689] object: Make APE middleware form container system attributes
* Extract container system attributes into request info; * Form APE-resource proprties from the extracted attributes; * Fix unit-test. Change-Id: I8fbd9a167ad05af0e75df350ac882b866da7bdcb Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
parent
a5f76a609d
commit
c2a495814f
5 changed files with 128 additions and 88 deletions
|
@ -64,6 +64,9 @@ type Prm struct {
|
|||
// An encoded container's owner user ID.
|
||||
ContainerOwner user.ID
|
||||
|
||||
// Attributes defined for the container.
|
||||
ContainerAttributes map[string]string
|
||||
|
||||
// The request's bearer token. It is used in order to check APE overrides with the token.
|
||||
BearerToken *bearer.Token
|
||||
|
||||
|
|
|
@ -63,6 +63,8 @@ type RequestInfo struct {
|
|||
|
||||
ContainerOwner user.ID
|
||||
|
||||
ContainerAttributes map[string]string
|
||||
|
||||
// Namespace defines to which namespace a container is belonged.
|
||||
Namespace string
|
||||
|
||||
|
@ -131,6 +133,11 @@ func (e *extractor) GetRequestInfo(ctx context.Context, m Metadata, method strin
|
|||
ri.Role = nativeSchemaRole(res.Role)
|
||||
ri.ContainerOwner = cnr.Value.Owner()
|
||||
|
||||
ri.ContainerAttributes = map[string]string{}
|
||||
for key, val := range cnr.Value.Attributes() {
|
||||
ri.ContainerAttributes[key] = val
|
||||
}
|
||||
|
||||
cnrNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(cnr.Value).Zone(), ".ns")
|
||||
if hasNamespace {
|
||||
ri.Namespace = cnrNamespace
|
||||
|
|
|
@ -57,11 +57,16 @@ 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, cnrOwner user.ID, header *objectV2.Header) map[string]string {
|
||||
func objectProperties(cnr cid.ID, oid *oid.ID, cnrOwner user.ID, cnrAttrs map[string]string, header *objectV2.Header) map[string]string {
|
||||
objectProps := map[string]string{
|
||||
nativeschema.PropertyKeyObjectContainerID: cnr.EncodeToString(),
|
||||
}
|
||||
|
||||
for attrName, attrValue := range cnrAttrs {
|
||||
prop := fmt.Sprintf(nativeschema.PropertyKeyFormatObjectContainerAttribute, attrName)
|
||||
objectProps[prop] = attrValue
|
||||
}
|
||||
|
||||
objectProps[nativeschema.PropertyKeyContainerOwnerID] = cnrOwner.EncodeToString()
|
||||
|
||||
if oid != nil {
|
||||
|
@ -155,7 +160,7 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re
|
|||
prm.Method,
|
||||
aperequest.NewResource(
|
||||
resourceName(prm.Container, prm.Object, prm.Namespace),
|
||||
objectProperties(prm.Container, prm.Object, prm.ContainerOwner, header),
|
||||
objectProperties(prm.Container, prm.Object, prm.ContainerOwner, prm.ContainerAttributes, header),
|
||||
),
|
||||
reqProps,
|
||||
), nil
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"testing"
|
||||
|
||||
aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request"
|
||||
cnrV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container"
|
||||
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
|
||||
checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
|
@ -22,8 +23,17 @@ const (
|
|||
testOwnerID = "NURFM8PWbLA2aLt2vrD8q4FyfAdgESwM8y"
|
||||
|
||||
incomingIP = "192.92.33.1"
|
||||
|
||||
testSysAttrName = "unittest"
|
||||
|
||||
testSysAttrZone = "eggplant"
|
||||
)
|
||||
|
||||
var containerAttrs = map[string]string{
|
||||
cnrV2.SysAttributeName: testSysAttrName,
|
||||
cnrV2.SysAttributeZone: testSysAttrZone,
|
||||
}
|
||||
|
||||
func ctxWithPeerInfo() context.Context {
|
||||
return peer.NewContext(context.Background(), &peer.Peer{
|
||||
Addr: &net.TCPAddr{
|
||||
|
@ -105,7 +115,7 @@ func TestObjectProperties(t *testing.T) {
|
|||
var testCnrOwner user.ID
|
||||
require.NoError(t, testCnrOwner.DecodeString(testOwnerID))
|
||||
|
||||
props := objectProperties(cnr, obj, testCnrOwner, header.ToV2().GetHeader())
|
||||
props := objectProperties(cnr, obj, testCnrOwner, containerAttrs, header.ToV2().GetHeader())
|
||||
require.Equal(t, test.container, props[nativeschema.PropertyKeyObjectContainerID])
|
||||
require.Equal(t, testOwnerID, props[nativeschema.PropertyKeyContainerOwnerID])
|
||||
|
||||
|
@ -124,6 +134,8 @@ func TestObjectProperties(t *testing.T) {
|
|||
require.Equal(t, test.header.typ.String(), props[nativeschema.PropertyKeyObjectType])
|
||||
require.Equal(t, test.header.payloadChecksum.String(), props[nativeschema.PropertyKeyObjectPayloadHash])
|
||||
require.Equal(t, test.header.payloadHomomorphicHash.String(), props[nativeschema.PropertyKeyObjectHomomorphicHash])
|
||||
require.Equal(t, containerAttrs[cnrV2.SysAttributeName], props[fmt.Sprintf(nativeschema.PropertyKeyFormatObjectContainerAttribute, cnrV2.SysAttributeName)])
|
||||
require.Equal(t, containerAttrs[cnrV2.SysAttributeZone], props[fmt.Sprintf(nativeschema.PropertyKeyFormatObjectContainerAttribute, cnrV2.SysAttributeZone)])
|
||||
|
||||
for _, attr := range test.header.attributes {
|
||||
require.Equal(t, attr.val, props[attr.key])
|
||||
|
@ -245,6 +257,10 @@ func TestNewAPERequest(t *testing.T) {
|
|||
Role: role,
|
||||
SenderKey: senderKey,
|
||||
ContainerOwner: testCnrOwner,
|
||||
ContainerAttributes: map[string]string{
|
||||
cnrV2.SysAttributeZone: testSysAttrZone,
|
||||
cnrV2.SysAttributeName: testSysAttrName,
|
||||
},
|
||||
}
|
||||
|
||||
headerSource := newHeaderProviderMock()
|
||||
|
@ -277,7 +293,7 @@ func TestNewAPERequest(t *testing.T) {
|
|||
method,
|
||||
aperequest.NewResource(
|
||||
resourceName(cnr, obj, prm.Namespace),
|
||||
objectProperties(cnr, obj, testCnrOwner, func() *objectV2.Header {
|
||||
objectProperties(cnr, obj, testCnrOwner, containerAttrs, func() *objectV2.Header {
|
||||
if headerObjSDK != nil {
|
||||
return headerObjSDK.ToV2().GetHeader()
|
||||
}
|
||||
|
|
|
@ -86,16 +86,17 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error {
|
|||
}
|
||||
|
||||
prm := Prm{
|
||||
Namespace: g.reqInfo.Namespace,
|
||||
Container: cnrID,
|
||||
Object: objID,
|
||||
Header: partInit.GetHeader(),
|
||||
Method: nativeschema.MethodGetObject,
|
||||
SenderKey: g.reqInfo.SenderKey,
|
||||
ContainerOwner: g.reqInfo.ContainerOwner,
|
||||
Role: g.reqInfo.Role,
|
||||
BearerToken: g.metadata.BearerToken,
|
||||
XHeaders: resp.GetMetaHeader().GetXHeaders(),
|
||||
Namespace: g.reqInfo.Namespace,
|
||||
Container: cnrID,
|
||||
Object: objID,
|
||||
Header: partInit.GetHeader(),
|
||||
Method: nativeschema.MethodGetObject,
|
||||
SenderKey: g.reqInfo.SenderKey,
|
||||
ContainerOwner: g.reqInfo.ContainerOwner,
|
||||
ContainerAttributes: g.reqInfo.ContainerAttributes,
|
||||
Role: g.reqInfo.Role,
|
||||
BearerToken: g.metadata.BearerToken,
|
||||
XHeaders: resp.GetMetaHeader().GetXHeaders(),
|
||||
}
|
||||
|
||||
if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil {
|
||||
|
@ -142,16 +143,17 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR
|
|||
}
|
||||
|
||||
prm := Prm{
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Header: partInit.GetHeader(),
|
||||
Method: nativeschema.MethodPutObject,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
Role: reqInfo.Role,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Header: partInit.GetHeader(),
|
||||
Method: nativeschema.MethodPutObject,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
ContainerAttributes: reqInfo.ContainerAttributes,
|
||||
Role: reqInfo.Role,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
}
|
||||
|
||||
if err := p.apeChecker.CheckAPE(ctx, prm); err != nil {
|
||||
|
@ -200,15 +202,16 @@ func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.Pa
|
|||
}
|
||||
|
||||
prm := Prm{
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Method: nativeschema.MethodPatchObject,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
Role: reqInfo.Role,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Method: nativeschema.MethodPatchObject,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
ContainerAttributes: reqInfo.ContainerAttributes,
|
||||
Role: reqInfo.Role,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
}
|
||||
|
||||
if err := p.apeChecker.CheckAPE(ctx, prm); err != nil {
|
||||
|
@ -268,16 +271,17 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj
|
|||
}
|
||||
|
||||
err = c.apeChecker.CheckAPE(ctx, Prm{
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Header: header,
|
||||
Method: nativeschema.MethodHeadObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Header: header,
|
||||
Method: nativeschema.MethodHeadObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
ContainerAttributes: reqInfo.ContainerAttributes,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, toStatusErr(err)
|
||||
|
@ -296,14 +300,15 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc
|
|||
}
|
||||
|
||||
err = c.apeChecker.CheckAPE(stream.Context(), Prm{
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Method: nativeschema.MethodSearchObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Method: nativeschema.MethodSearchObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
ContainerAttributes: reqInfo.ContainerAttributes,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
})
|
||||
if err != nil {
|
||||
return toStatusErr(err)
|
||||
|
@ -323,15 +328,16 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) (
|
|||
}
|
||||
|
||||
err = c.apeChecker.CheckAPE(ctx, Prm{
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Method: nativeschema.MethodDeleteObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Method: nativeschema.MethodDeleteObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
ContainerAttributes: reqInfo.ContainerAttributes,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, toStatusErr(err)
|
||||
|
@ -356,15 +362,16 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G
|
|||
}
|
||||
|
||||
err = c.apeChecker.CheckAPE(stream.Context(), Prm{
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Method: nativeschema.MethodRangeObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Method: nativeschema.MethodRangeObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
ContainerAttributes: reqInfo.ContainerAttributes,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
})
|
||||
if err != nil {
|
||||
return toStatusErr(err)
|
||||
|
@ -384,15 +391,16 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa
|
|||
}
|
||||
|
||||
prm := Prm{
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Method: nativeschema.MethodHashObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Method: nativeschema.MethodHashObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
ContainerAttributes: reqInfo.ContainerAttributes,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
}
|
||||
|
||||
resp, err := c.next.GetRangeHash(ctx, request)
|
||||
|
@ -417,16 +425,17 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ
|
|||
}
|
||||
|
||||
prm := Prm{
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Header: request.GetBody().GetObject().GetHeader(),
|
||||
Method: nativeschema.MethodPutObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
Namespace: reqInfo.Namespace,
|
||||
Container: md.Container,
|
||||
Object: md.Object,
|
||||
Header: request.GetBody().GetObject().GetHeader(),
|
||||
Method: nativeschema.MethodPutObject,
|
||||
Role: reqInfo.Role,
|
||||
SenderKey: reqInfo.SenderKey,
|
||||
ContainerOwner: reqInfo.ContainerOwner,
|
||||
ContainerAttributes: reqInfo.ContainerAttributes,
|
||||
BearerToken: md.BearerToken,
|
||||
XHeaders: md.MetaHeader.GetXHeaders(),
|
||||
}
|
||||
|
||||
if err = c.apeChecker.CheckAPE(ctx, prm); err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue