From 57c5fccc8cc11c2cfd5b63ddaab565b5a4267fb2 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Tue, 24 May 2022 21:47:21 +0300 Subject: [PATCH] [#1428] node/acl: Make OID optional Not all the NeoFS requests must contain OID in their bodies (or must NOT contain them at all). Do not pass object address in helper functions, pass CID and OID separately instead. Also, fixed NPE in the ACL service: updated SDK library brought errors when working with `Put` and `Search` requests without OID fields. Signed-off-by: Pavel Karpy --- pkg/services/object/acl/acl.go | 8 +- pkg/services/object/acl/eacl/v2/eacl_test.go | 6 +- pkg/services/object/acl/eacl/v2/headers.go | 112 +++++++++---------- pkg/services/object/acl/eacl/v2/object.go | 15 +-- pkg/services/object/acl/eacl/v2/opts.go | 13 ++- pkg/services/object/acl/v2/request.go | 2 + 6 files changed, 79 insertions(+), 77 deletions(-) diff --git a/pkg/services/object/acl/acl.go b/pkg/services/object/acl/acl.go index c731d3854..90863d810 100644 --- a/pkg/services/object/acl/acl.go +++ b/pkg/services/object/acl/acl.go @@ -15,7 +15,6 @@ import ( v2 "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/v2" bearerSDK "github.com/nspcc-dev/neofs-sdk-go/bearer" eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl" - addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" "github.com/nspcc-dev/neofs-sdk-go/user" ) @@ -168,13 +167,10 @@ func (c *Checker) CheckEACL(msg interface{}, reqInfo v2.RequestInfo) error { hdrSrcOpts := make([]eaclV2.Option, 0, 3) - addr := addressSDK.NewAddress() - addr.SetContainerID(cid) - addr.SetObjectID(*reqInfo.ObjectID()) - hdrSrcOpts = append(hdrSrcOpts, eaclV2.WithLocalObjectStorage(c.localStorage), - eaclV2.WithAddress(addr), + eaclV2.WithCID(cid), + eaclV2.WithOID(reqInfo.ObjectID()), ) if req, ok := msg.(eaclV2.Request); ok { diff --git a/pkg/services/object/acl/eacl/v2/eacl_test.go b/pkg/services/object/acl/eacl/v2/eacl_test.go index 195753eea..b9c2406a4 100644 --- a/pkg/services/object/acl/eacl/v2/eacl_test.go +++ b/pkg/services/object/acl/eacl/v2/eacl_test.go @@ -103,11 +103,15 @@ func TestHeadRequest(t *testing.T) { obj: obj, } + cid, _ := addr.ContainerID() + oid, _ := addr.ObjectID() + newSource := func(t *testing.T) eaclSDK.TypedHeaderSource { hdrSrc, err := NewMessageHeaderSource( WithObjectStorage(lStorage), WithServiceRequest(req), - WithAddress(addr)) + WithCID(cid), + WithOID(&oid)) require.NoError(t, err) return hdrSrc } diff --git a/pkg/services/object/acl/eacl/v2/headers.go b/pkg/services/object/acl/eacl/v2/headers.go index 3caf99843..8d0d71e1b 100644 --- a/pkg/services/object/acl/eacl/v2/headers.go +++ b/pkg/services/object/acl/eacl/v2/headers.go @@ -8,11 +8,12 @@ import ( objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object" refsV2 "github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-api-go/v2/session" - cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + cidSDK "github.com/nspcc-dev/neofs-sdk-go/container/id" eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/object" - objectSDKAddress "github.com/nspcc-dev/neofs-sdk-go/object/address" - objectSDKID "github.com/nspcc-dev/neofs-sdk-go/object/id" + objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" + addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" + oidSDK "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/nspcc-dev/neofs-sdk-go/user" ) @@ -23,11 +24,12 @@ type cfg struct { msg xHeaderSource - addr *objectSDKAddress.Address + cid cidSDK.ID + oid *oidSDK.ID } type ObjectStorage interface { - Head(*objectSDKAddress.Address) (*object.Object, error) + Head(*addressSDK.Address) (*object.Object, error) } type Request interface { @@ -86,58 +88,42 @@ func requestHeaders(msg xHeaderSource) []eaclSDK.Header { return msg.GetXHeaders() } +var errMissingOID = errors.New("object ID is missing") + func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) { switch m := h.msg.(type) { default: panic(fmt.Sprintf("unexpected message type %T", h.msg)) case requestXHeaderSource: switch req := m.req.(type) { - case *objectV2.GetRequest: - return h.localObjectHeaders(h.addr) - case *objectV2.HeadRequest: - return h.localObjectHeaders(h.addr) + case + *objectV2.GetRequest, + *objectV2.HeadRequest: + if h.oid == nil { + return nil, errMissingOID + } + + return h.localObjectHeaders(h.cid, h.oid) case *objectV2.GetRangeRequest, *objectV2.GetRangeHashRequest, *objectV2.DeleteRequest: - return addressHeaders(h.addr), nil + if h.oid == nil { + return nil, errMissingOID + } + + return addressHeaders(h.cid, h.oid), nil case *objectV2.PutRequest: if v, ok := req.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok { oV2 := new(objectV2.Object) oV2.SetObjectID(v.GetObjectID()) oV2.SetHeader(v.GetHeader()) - if h.addr == nil { - idV2 := v.GetObjectID() - var id objectSDKID.ID - - if idV2 != nil { - if err := id.ReadFromV2(*idV2); err != nil { - return nil, fmt.Errorf("can't parse object ID: %w", err) - } - } - - cnrV2 := v.GetHeader().GetContainerID() - var cnr cid.ID - - if cnrV2 != nil { - if err := cnr.ReadFromV2(*cnrV2); err != nil { - return nil, fmt.Errorf("can't parse container ID: %w", err) - } - } - - h.addr = new(objectSDKAddress.Address) - h.addr.SetContainerID(cnr) - h.addr.SetObjectID(id) - } - - hs := headersFromObject(object.NewFromV2(oV2), h.addr) - - return hs, nil + return headersFromObject(object.NewFromV2(oV2), h.cid, h.oid), nil } case *objectV2.SearchRequest: cnrV2 := req.GetBody().GetContainerID() - var cnr cid.ID + var cnr cidSDK.ID if cnrV2 != nil { if err := cnr.ReadFromV2(*cnrV2); err != nil { @@ -150,7 +136,7 @@ func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) { case responseXHeaderSource: switch resp := m.resp.(type) { default: - hs, _ := h.localObjectHeaders(h.addr) + hs, _ := h.localObjectHeaders(h.cid, h.oid) return hs, nil case *objectV2.GetResponse: if v, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok { @@ -158,7 +144,7 @@ func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) { oV2.SetObjectID(v.GetObjectID()) oV2.SetHeader(v.GetHeader()) - return headersFromObject(object.NewFromV2(oV2), h.addr), nil + return headersFromObject(object.NewFromV2(oV2), h.cid, h.oid), nil } case *objectV2.HeadResponse: oV2 := new(objectV2.Object) @@ -169,10 +155,8 @@ func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) { case *objectV2.ShortHeader: hdr = new(objectV2.Header) - id, _ := h.addr.ContainerID() - var idV2 refsV2.ContainerID - id.WriteToV2(&idV2) + h.cid.WriteToV2(&idV2) hdr.SetContainerID(&idV2) hdr.SetVersion(v.GetVersion()) @@ -186,30 +170,40 @@ func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) { oV2.SetHeader(hdr) - return headersFromObject(object.NewFromV2(oV2), h.addr), nil + return headersFromObject(object.NewFromV2(oV2), h.cid, h.oid), nil } } return nil, nil } -func (h *cfg) localObjectHeaders(addr *objectSDKAddress.Address) ([]eaclSDK.Header, error) { - obj, err := h.storage.Head(addr) - if err != nil { - // Still parse addressHeaders, because the errors is ignored in some places. - return addressHeaders(addr), err +func (h *cfg) localObjectHeaders(cid cidSDK.ID, oid *oidSDK.ID) ([]eaclSDK.Header, error) { + var obj *objectSDK.Object + var err error + + if oid != nil { + var addr addressSDK.Address + addr.SetContainerID(cid) + addr.SetObjectID(*oid) + + obj, err = h.storage.Head(&addr) + if err == nil { + return headersFromObject(obj, cid, oid), nil + } } - return headersFromObject(obj, addr), nil + + // Still parse addressHeaders, because the errors is ignored in some places. + return addressHeaders(cid, oid), err } -func cidHeader(idCnr cid.ID) sysObjHdr { +func cidHeader(idCnr cidSDK.ID) sysObjHdr { return sysObjHdr{ k: acl.FilterObjectContainerID, v: idCnr.EncodeToString(), } } -func oidHeader(oid objectSDKID.ID) sysObjHdr { +func oidHeader(oid oidSDK.ID) sysObjHdr { return sysObjHdr{ k: acl.FilterObjectID, v: oid.EncodeToString(), @@ -223,15 +217,13 @@ func ownerIDHeader(ownerID user.ID) sysObjHdr { } } -func addressHeaders(addr *objectSDKAddress.Address) []eaclSDK.Header { - cnr, _ := addr.ContainerID() +func addressHeaders(cid cidSDK.ID, oid *oidSDK.ID) []eaclSDK.Header { + hh := make([]eaclSDK.Header, 0, 2) + hh = append(hh, cidHeader(cid)) - res := make([]eaclSDK.Header, 1, 2) - res[0] = cidHeader(cnr) - - if oid, ok := addr.ObjectID(); ok { - res = append(res, oidHeader(oid)) + if oid != nil { + hh = append(hh, oidHeader(*oid)) } - return res + return hh } diff --git a/pkg/services/object/acl/eacl/v2/object.go b/pkg/services/object/acl/eacl/v2/object.go index 8f4ee3fb5..1c3e4ee23 100644 --- a/pkg/services/object/acl/eacl/v2/object.go +++ b/pkg/services/object/acl/eacl/v2/object.go @@ -4,9 +4,10 @@ import ( "strconv" "github.com/nspcc-dev/neofs-api-go/v2/acl" + cidSDK "github.com/nspcc-dev/neofs-sdk-go/container/id" eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/object" - objectSDKAddress "github.com/nspcc-dev/neofs-sdk-go/object/address" + oidSDK "github.com/nspcc-dev/neofs-sdk-go/object/id" ) type sysObjHdr struct { @@ -25,7 +26,7 @@ func u64Value(v uint64) string { return strconv.FormatUint(v, 10) } -func headersFromObject(obj *object.Object, addr *objectSDKAddress.Address) []eaclSDK.Header { +func headersFromObject(obj *object.Object, cid cidSDK.ID, oid *oidSDK.ID) []eaclSDK.Header { var count int for obj := obj; obj != nil; obj = obj.Parent() { count += 9 + len(obj.Attributes()) @@ -33,11 +34,8 @@ func headersFromObject(obj *object.Object, addr *objectSDKAddress.Address) []eac res := make([]eaclSDK.Header, 0, count) for ; obj != nil; obj = obj.Parent() { - cnr, _ := addr.ContainerID() - id, _ := addr.ObjectID() - res = append(res, - cidHeader(cnr), + cidHeader(cid), // creation epoch sysObjHdr{ k: acl.FilterObjectCreationEpoch, @@ -48,7 +46,6 @@ func headersFromObject(obj *object.Object, addr *objectSDKAddress.Address) []eac k: acl.FilterObjectPayloadLength, v: u64Value(obj.PayloadSize()), }, - oidHeader(id), // object version sysObjHdr{ k: acl.FilterObjectVersion, @@ -61,6 +58,10 @@ func headersFromObject(obj *object.Object, addr *objectSDKAddress.Address) []eac }, ) + if oid != nil { + res = append(res, oidHeader(*oid)) + } + if idOwner := obj.OwnerID(); idOwner != nil { res = append(res, ownerIDHeader(*idOwner)) } diff --git a/pkg/services/object/acl/eacl/v2/opts.go b/pkg/services/object/acl/eacl/v2/opts.go index 3d07a41e2..6eaf84b0d 100644 --- a/pkg/services/object/acl/eacl/v2/opts.go +++ b/pkg/services/object/acl/eacl/v2/opts.go @@ -2,7 +2,8 @@ package v2 import ( "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine" - addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" + cidSDK "github.com/nspcc-dev/neofs-sdk-go/container/id" + oidSDK "github.com/nspcc-dev/neofs-sdk-go/object/id" ) func WithObjectStorage(v ObjectStorage) Option { @@ -36,8 +37,14 @@ func WithServiceResponse(resp Response, req Request) Option { } } -func WithAddress(v *addressSDK.Address) Option { +func WithCID(v cidSDK.ID) Option { return func(c *cfg) { - c.addr = v + c.cid = v + } +} + +func WithOID(v *oidSDK.ID) Option { + return func(c *cfg) { + c.oid = v } } diff --git a/pkg/services/object/acl/v2/request.go b/pkg/services/object/acl/v2/request.go index 6c0d578f8..47ba38c94 100644 --- a/pkg/services/object/acl/v2/request.go +++ b/pkg/services/object/acl/v2/request.go @@ -25,6 +25,8 @@ type RequestInfo struct { idCnr containerIDSDK.ID + // optional for some request + // e.g. Put, Search oid *oidSDK.ID senderKey []byte