[#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 <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2022-05-24 21:47:21 +03:00 committed by LeL
parent d69eb2aaf3
commit 57c5fccc8c
6 changed files with 79 additions and 77 deletions

View file

@ -15,7 +15,6 @@ import (
v2 "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/v2" v2 "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/v2"
bearerSDK "github.com/nspcc-dev/neofs-sdk-go/bearer" bearerSDK "github.com/nspcc-dev/neofs-sdk-go/bearer"
eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl" 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" "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) hdrSrcOpts := make([]eaclV2.Option, 0, 3)
addr := addressSDK.NewAddress()
addr.SetContainerID(cid)
addr.SetObjectID(*reqInfo.ObjectID())
hdrSrcOpts = append(hdrSrcOpts, hdrSrcOpts = append(hdrSrcOpts,
eaclV2.WithLocalObjectStorage(c.localStorage), eaclV2.WithLocalObjectStorage(c.localStorage),
eaclV2.WithAddress(addr), eaclV2.WithCID(cid),
eaclV2.WithOID(reqInfo.ObjectID()),
) )
if req, ok := msg.(eaclV2.Request); ok { if req, ok := msg.(eaclV2.Request); ok {

View file

@ -103,11 +103,15 @@ func TestHeadRequest(t *testing.T) {
obj: obj, obj: obj,
} }
cid, _ := addr.ContainerID()
oid, _ := addr.ObjectID()
newSource := func(t *testing.T) eaclSDK.TypedHeaderSource { newSource := func(t *testing.T) eaclSDK.TypedHeaderSource {
hdrSrc, err := NewMessageHeaderSource( hdrSrc, err := NewMessageHeaderSource(
WithObjectStorage(lStorage), WithObjectStorage(lStorage),
WithServiceRequest(req), WithServiceRequest(req),
WithAddress(addr)) WithCID(cid),
WithOID(&oid))
require.NoError(t, err) require.NoError(t, err)
return hdrSrc return hdrSrc
} }

View file

@ -8,11 +8,12 @@ import (
objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object" objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
refsV2 "github.com/nspcc-dev/neofs-api-go/v2/refs" refsV2 "github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-api-go/v2/session" "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" eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/object"
objectSDKAddress "github.com/nspcc-dev/neofs-sdk-go/object/address" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
objectSDKID "github.com/nspcc-dev/neofs-sdk-go/object/id" 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" "github.com/nspcc-dev/neofs-sdk-go/user"
) )
@ -23,11 +24,12 @@ type cfg struct {
msg xHeaderSource msg xHeaderSource
addr *objectSDKAddress.Address cid cidSDK.ID
oid *oidSDK.ID
} }
type ObjectStorage interface { type ObjectStorage interface {
Head(*objectSDKAddress.Address) (*object.Object, error) Head(*addressSDK.Address) (*object.Object, error)
} }
type Request interface { type Request interface {
@ -86,58 +88,42 @@ func requestHeaders(msg xHeaderSource) []eaclSDK.Header {
return msg.GetXHeaders() return msg.GetXHeaders()
} }
var errMissingOID = errors.New("object ID is missing")
func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) { func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) {
switch m := h.msg.(type) { switch m := h.msg.(type) {
default: default:
panic(fmt.Sprintf("unexpected message type %T", h.msg)) panic(fmt.Sprintf("unexpected message type %T", h.msg))
case requestXHeaderSource: case requestXHeaderSource:
switch req := m.req.(type) { switch req := m.req.(type) {
case *objectV2.GetRequest: case
return h.localObjectHeaders(h.addr) *objectV2.GetRequest,
case *objectV2.HeadRequest: *objectV2.HeadRequest:
return h.localObjectHeaders(h.addr) if h.oid == nil {
return nil, errMissingOID
}
return h.localObjectHeaders(h.cid, h.oid)
case case
*objectV2.GetRangeRequest, *objectV2.GetRangeRequest,
*objectV2.GetRangeHashRequest, *objectV2.GetRangeHashRequest,
*objectV2.DeleteRequest: *objectV2.DeleteRequest:
return addressHeaders(h.addr), nil if h.oid == nil {
return nil, errMissingOID
}
return addressHeaders(h.cid, h.oid), nil
case *objectV2.PutRequest: case *objectV2.PutRequest:
if v, ok := req.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok { if v, ok := req.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok {
oV2 := new(objectV2.Object) oV2 := new(objectV2.Object)
oV2.SetObjectID(v.GetObjectID()) oV2.SetObjectID(v.GetObjectID())
oV2.SetHeader(v.GetHeader()) oV2.SetHeader(v.GetHeader())
if h.addr == nil { return headersFromObject(object.NewFromV2(oV2), h.cid, h.oid), 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
} }
case *objectV2.SearchRequest: case *objectV2.SearchRequest:
cnrV2 := req.GetBody().GetContainerID() cnrV2 := req.GetBody().GetContainerID()
var cnr cid.ID var cnr cidSDK.ID
if cnrV2 != nil { if cnrV2 != nil {
if err := cnr.ReadFromV2(*cnrV2); err != nil { if err := cnr.ReadFromV2(*cnrV2); err != nil {
@ -150,7 +136,7 @@ func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) {
case responseXHeaderSource: case responseXHeaderSource:
switch resp := m.resp.(type) { switch resp := m.resp.(type) {
default: default:
hs, _ := h.localObjectHeaders(h.addr) hs, _ := h.localObjectHeaders(h.cid, h.oid)
return hs, nil return hs, nil
case *objectV2.GetResponse: case *objectV2.GetResponse:
if v, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok { 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.SetObjectID(v.GetObjectID())
oV2.SetHeader(v.GetHeader()) 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: case *objectV2.HeadResponse:
oV2 := new(objectV2.Object) oV2 := new(objectV2.Object)
@ -169,10 +155,8 @@ func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) {
case *objectV2.ShortHeader: case *objectV2.ShortHeader:
hdr = new(objectV2.Header) hdr = new(objectV2.Header)
id, _ := h.addr.ContainerID()
var idV2 refsV2.ContainerID var idV2 refsV2.ContainerID
id.WriteToV2(&idV2) h.cid.WriteToV2(&idV2)
hdr.SetContainerID(&idV2) hdr.SetContainerID(&idV2)
hdr.SetVersion(v.GetVersion()) hdr.SetVersion(v.GetVersion())
@ -186,30 +170,40 @@ func (h *cfg) objectHeaders() ([]eaclSDK.Header, error) {
oV2.SetHeader(hdr) oV2.SetHeader(hdr)
return headersFromObject(object.NewFromV2(oV2), h.addr), nil return headersFromObject(object.NewFromV2(oV2), h.cid, h.oid), nil
} }
} }
return nil, nil return nil, nil
} }
func (h *cfg) localObjectHeaders(addr *objectSDKAddress.Address) ([]eaclSDK.Header, error) { func (h *cfg) localObjectHeaders(cid cidSDK.ID, oid *oidSDK.ID) ([]eaclSDK.Header, error) {
obj, err := h.storage.Head(addr) var obj *objectSDK.Object
if err != nil { var err error
// Still parse addressHeaders, because the errors is ignored in some places.
return addressHeaders(addr), err 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{ return sysObjHdr{
k: acl.FilterObjectContainerID, k: acl.FilterObjectContainerID,
v: idCnr.EncodeToString(), v: idCnr.EncodeToString(),
} }
} }
func oidHeader(oid objectSDKID.ID) sysObjHdr { func oidHeader(oid oidSDK.ID) sysObjHdr {
return sysObjHdr{ return sysObjHdr{
k: acl.FilterObjectID, k: acl.FilterObjectID,
v: oid.EncodeToString(), v: oid.EncodeToString(),
@ -223,15 +217,13 @@ func ownerIDHeader(ownerID user.ID) sysObjHdr {
} }
} }
func addressHeaders(addr *objectSDKAddress.Address) []eaclSDK.Header { func addressHeaders(cid cidSDK.ID, oid *oidSDK.ID) []eaclSDK.Header {
cnr, _ := addr.ContainerID() hh := make([]eaclSDK.Header, 0, 2)
hh = append(hh, cidHeader(cid))
res := make([]eaclSDK.Header, 1, 2) if oid != nil {
res[0] = cidHeader(cnr) hh = append(hh, oidHeader(*oid))
if oid, ok := addr.ObjectID(); ok {
res = append(res, oidHeader(oid))
} }
return res return hh
} }

View file

@ -4,9 +4,10 @@ import (
"strconv" "strconv"
"github.com/nspcc-dev/neofs-api-go/v2/acl" "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" eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/object" "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 { type sysObjHdr struct {
@ -25,7 +26,7 @@ func u64Value(v uint64) string {
return strconv.FormatUint(v, 10) 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 var count int
for obj := obj; obj != nil; obj = obj.Parent() { for obj := obj; obj != nil; obj = obj.Parent() {
count += 9 + len(obj.Attributes()) count += 9 + len(obj.Attributes())
@ -33,11 +34,8 @@ func headersFromObject(obj *object.Object, addr *objectSDKAddress.Address) []eac
res := make([]eaclSDK.Header, 0, count) res := make([]eaclSDK.Header, 0, count)
for ; obj != nil; obj = obj.Parent() { for ; obj != nil; obj = obj.Parent() {
cnr, _ := addr.ContainerID()
id, _ := addr.ObjectID()
res = append(res, res = append(res,
cidHeader(cnr), cidHeader(cid),
// creation epoch // creation epoch
sysObjHdr{ sysObjHdr{
k: acl.FilterObjectCreationEpoch, k: acl.FilterObjectCreationEpoch,
@ -48,7 +46,6 @@ func headersFromObject(obj *object.Object, addr *objectSDKAddress.Address) []eac
k: acl.FilterObjectPayloadLength, k: acl.FilterObjectPayloadLength,
v: u64Value(obj.PayloadSize()), v: u64Value(obj.PayloadSize()),
}, },
oidHeader(id),
// object version // object version
sysObjHdr{ sysObjHdr{
k: acl.FilterObjectVersion, 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 { if idOwner := obj.OwnerID(); idOwner != nil {
res = append(res, ownerIDHeader(*idOwner)) res = append(res, ownerIDHeader(*idOwner))
} }

View file

@ -2,7 +2,8 @@ package v2
import ( import (
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine" "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 { 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) { return func(c *cfg) {
c.addr = v c.cid = v
}
}
func WithOID(v *oidSDK.ID) Option {
return func(c *cfg) {
c.oid = v
} }
} }

View file

@ -25,6 +25,8 @@ type RequestInfo struct {
idCnr containerIDSDK.ID idCnr containerIDSDK.ID
// optional for some request
// e.g. Put, Search
oid *oidSDK.ID oid *oidSDK.ID
senderKey []byte senderKey []byte