[#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"
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 {

View file

@ -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
}

View file

@ -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
}

View file

@ -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))
}

View file

@ -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
}
}

View file

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