[#247] object/eacl: Process object address from request

In previous implementation eACL validator didn't take into account container
and object ID fields of request bodies.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2020-12-14 15:07:20 +03:00 committed by Leonard Lyubich
parent bbe700fa37
commit 168dcbdccd
5 changed files with 98 additions and 20 deletions

View file

@ -8,10 +8,12 @@ import (
acl "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl" acl "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
"github.com/nspcc-dev/neofs-api-go/pkg/container" "github.com/nspcc-dev/neofs-api-go/pkg/container"
objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-api-go/pkg/owner" "github.com/nspcc-dev/neofs-api-go/pkg/owner"
"github.com/nspcc-dev/neofs-api-go/util/signature" "github.com/nspcc-dev/neofs-api-go/util/signature"
bearer "github.com/nspcc-dev/neofs-api-go/v2/acl" bearer "github.com/nspcc-dev/neofs-api-go/v2/acl"
"github.com/nspcc-dev/neofs-api-go/v2/object" "github.com/nspcc-dev/neofs-api-go/v2/object"
"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"
v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature" v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature"
crypto "github.com/nspcc-dev/neofs-crypto" crypto "github.com/nspcc-dev/neofs-crypto"
@ -70,6 +72,8 @@ type (
cid *container.ID cid *container.ID
oid *objectSDK.ID
senderKey []byte senderKey []byte
bearer *bearer.BearerToken // bearer token of request bearer *bearer.BearerToken // bearer token of request
@ -150,6 +154,8 @@ func (b Service) Get(request *object.GetRequest, stream objectSvc.GetObjectStrea
return err return err
} }
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return basicACLErr(reqInfo) return basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) { } else if !eACLCheck(request, reqInfo, b.eACLCfg) {
@ -193,6 +199,8 @@ func (b Service) Head(
return nil, err return nil, err
} }
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return nil, basicACLErr(reqInfo) return nil, basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) { } else if !eACLCheck(request, reqInfo, b.eACLCfg) {
@ -228,6 +236,8 @@ func (b Service) Search(request *object.SearchRequest, stream objectSvc.SearchSt
return err return err
} }
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return basicACLErr(reqInfo) return basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) { } else if !eACLCheck(request, reqInfo, b.eACLCfg) {
@ -261,6 +271,8 @@ func (b Service) Delete(
return nil, err return nil, err
} }
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return nil, basicACLErr(reqInfo) return nil, basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) { } else if !eACLCheck(request, reqInfo, b.eACLCfg) {
@ -287,6 +299,8 @@ func (b Service) GetRange(request *object.GetRangeRequest, stream objectSvc.GetO
return err return err
} }
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return basicACLErr(reqInfo) return basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) { } else if !eACLCheck(request, reqInfo, b.eACLCfg) {
@ -320,6 +334,8 @@ func (b Service) GetRangeHash(
return nil, err return nil, err
} }
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return nil, basicACLErr(reqInfo) return nil, basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) { } else if !eACLCheck(request, reqInfo, b.eACLCfg) {
@ -358,6 +374,8 @@ func (p putStreamBasicChecker) Send(request *object.PutRequest) error {
return err return err
} }
reqInfo.oid = getObjectIDFromRequestBody(part)
if !basicACLCheck(reqInfo) || !stickyBitCheck(reqInfo, ownerID) { if !basicACLCheck(reqInfo) || !stickyBitCheck(reqInfo, ownerID) {
return basicACLErr(reqInfo) return basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, p.eACLCfg) { } else if !eACLCheck(request, reqInfo, p.eACLCfg) {
@ -466,6 +484,21 @@ func getContainerIDFromRequest(req interface{}) (id *container.ID, err error) {
} }
} }
func getObjectIDFromRequestBody(body interface{}) *objectSDK.ID {
switch v := body.(type) {
default:
return nil
case interface {
GetObjectID() *refs.ObjectID
}:
return objectSDK.NewIDFromV2(v.GetObjectID())
case interface {
GetAddress() *refs.Address
}:
return objectSDK.NewIDFromV2(v.GetAddress().GetObjectID())
}
}
func getObjectOwnerFromMessage(req interface{}) (id *owner.ID, err error) { func getObjectOwnerFromMessage(req interface{}) (id *owner.ID, err error) {
switch v := req.(type) { switch v := req.(type) {
case *object.PutRequest: case *object.PutRequest:
@ -547,7 +580,12 @@ func eACLCheck(msg interface{}, reqInfo requestInfo, cfg *eACLCfg) bool {
if req, ok := msg.(eaclV2.Request); ok { if req, ok := msg.(eaclV2.Request); ok {
hdrSrcOpts = append(hdrSrcOpts, eaclV2.WithServiceRequest(req)) hdrSrcOpts = append(hdrSrcOpts, eaclV2.WithServiceRequest(req))
} else { } else {
hdrSrcOpts = append(hdrSrcOpts, eaclV2.WithServiceResponse(msg.(eaclV2.Response))) addr := objectSDK.NewAddress()
addr.SetContainerID(reqInfo.cid)
addr.SetObjectID(reqInfo.oid)
// TODO: Add 'WithAddress' option to config and use address from reqInfo
hdrSrcOpts = append(hdrSrcOpts, eaclV2.WithServiceResponse(msg.(eaclV2.Response), addr.ToV2()))
} }
action := cfg.eACL.CalculateAction(new(eacl.ValidationUnit). action := cfg.eACL.CalculateAction(new(eacl.ValidationUnit).

View file

@ -5,7 +5,9 @@ import (
"github.com/nspcc-dev/neofs-api-go/pkg" "github.com/nspcc-dev/neofs-api-go/pkg"
eaclSDK "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl" eaclSDK "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
"github.com/nspcc-dev/neofs-api-go/pkg/container"
objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object" objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-api-go/v2/acl"
objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object" objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
"github.com/nspcc-dev/neofs-api-go/v2/refs" "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"
@ -62,7 +64,7 @@ func (h *headerSource) HeadersOfType(typ eaclSDK.FilterHeaderType) ([]eacl.Heade
case eaclSDK.HeaderFromRequest: case eaclSDK.HeaderFromRequest:
return requestHeaders(h.msg), true return requestHeaders(h.msg), true
case eaclSDK.HeaderFromObject: case eaclSDK.HeaderFromObject:
return h.objectHeaders() return h.objectHeaders(), true
} }
} }
@ -78,7 +80,7 @@ func requestHeaders(msg xHeaderSource) []eacl.Header {
return res return res
} }
func (h *headerSource) objectHeaders() ([]eacl.Header, bool) { func (h *headerSource) objectHeaders() []eacl.Header {
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))
@ -100,18 +102,26 @@ func (h *headerSource) objectHeaders() ([]eacl.Header, bool) {
oV2.SetObjectID(v.GetObjectID()) oV2.SetObjectID(v.GetObjectID())
oV2.SetHeader(v.GetHeader()) oV2.SetHeader(v.GetHeader())
return headersFromObject(object.NewFromV2(oV2)), true return headersFromObject(object.NewFromV2(oV2))
}
case *objectV2.SearchRequest:
return []eacl.Header{cidHeader(
container.NewIDFromV2(
req.GetBody().GetContainerID()),
),
} }
} }
case *responseXHeaderSource: case *responseXHeaderSource:
switch resp := m.resp.(type) { switch resp := m.resp.(type) {
default:
return h.localObjectHeaders(m.addr)
case *objectV2.GetResponse: case *objectV2.GetResponse:
if v, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok { if v, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); 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())
return headersFromObject(object.NewFromV2(oV2)), true return headersFromObject(object.NewFromV2(oV2))
} }
case *objectV2.HeadResponse: case *objectV2.HeadResponse:
oV2 := new(objectV2.Object) oV2 := new(objectV2.Object)
@ -122,6 +132,7 @@ func (h *headerSource) objectHeaders() ([]eacl.Header, bool) {
case *objectV2.ShortHeader: case *objectV2.ShortHeader:
hdr = new(objectV2.Header) hdr = new(objectV2.Header)
hdr.SetContainerID(m.addr.GetContainerID())
hdr.SetVersion(v.GetVersion()) hdr.SetVersion(v.GetVersion())
hdr.SetCreationEpoch(v.GetCreationEpoch()) hdr.SetCreationEpoch(v.GetCreationEpoch())
hdr.SetOwnerID(v.GetOwnerID()) hdr.SetOwnerID(v.GetOwnerID())
@ -133,18 +144,48 @@ func (h *headerSource) objectHeaders() ([]eacl.Header, bool) {
oV2.SetHeader(hdr) oV2.SetHeader(hdr)
return headersFromObject(object.NewFromV2(oV2)), true return append(
headersFromObject(object.NewFromV2(oV2)),
oidHeader(objectSDK.NewIDFromV2(m.addr.GetObjectID())),
)
} }
} }
return nil, true return nil
} }
func (h *headerSource) localObjectHeaders(addr *refs.Address) ([]eacl.Header, bool) { func (h *headerSource) localObjectHeaders(addrV2 *refs.Address) []eacl.Header {
obj, err := h.storage.Head(objectSDK.NewAddressFromV2(addr)) addr := objectSDK.NewAddressFromV2(addrV2)
obj, err := h.storage.Head(addr)
if err == nil { if err == nil {
return headersFromObject(obj), true return headersFromObject(obj)
} }
return nil, false return addressHeaders(addr)
}
func cidHeader(cid *container.ID) eacl.Header {
return &sysObjHdr{
k: acl.FilterObjectContainerID,
v: cidValue(cid),
}
}
func oidHeader(oid *objectSDK.ID) eacl.Header {
return &sysObjHdr{
k: acl.FilterObjectID,
v: idValue(oid),
}
}
func addressHeaders(addr *objectSDK.Address) []eacl.Header {
res := make([]eacl.Header, 1, 2)
res[0] = cidHeader(addr.ContainerID())
if oid := addr.ObjectID(); oid != nil {
res = append(res, oidHeader(oid))
}
return res
} }

View file

@ -46,10 +46,7 @@ func headersFromObject(obj *object.Object) []eacl.Header {
for ; obj != nil; obj = obj.GetParent() { for ; obj != nil; obj = obj.GetParent() {
res = append(res, res = append(res,
// container ID // container ID
&sysObjHdr{ cidHeader(obj.ContainerID()),
k: acl.FilterObjectContainerID,
v: cidValue(obj.ContainerID()),
},
// owner ID // owner ID
&sysObjHdr{ &sysObjHdr{
k: acl.FilterObjectOwnerID, k: acl.FilterObjectOwnerID,
@ -65,10 +62,7 @@ func headersFromObject(obj *object.Object) []eacl.Header {
k: acl.FilterObjectPayloadLength, k: acl.FilterObjectPayloadLength,
v: u64Value(obj.PayloadSize()), v: u64Value(obj.PayloadSize()),
}, },
&sysObjHdr{ oidHeader(obj.ID()),
k: acl.FilterObjectID,
v: idValue(obj.ID()),
},
// TODO: add others fields after neofs-api#84 // TODO: add others fields after neofs-api#84
) )

View file

@ -2,6 +2,7 @@ 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"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
) )
func WithObjectStorage(v ObjectStorage) Option { func WithObjectStorage(v ObjectStorage) Option {
@ -26,10 +27,11 @@ func WithServiceRequest(v Request) Option {
} }
} }
func WithServiceResponse(v Response) Option { func WithServiceResponse(v Response, addr *refs.Address) Option {
return func(c *cfg) { return func(c *cfg) {
c.msg = &responseXHeaderSource{ c.msg = &responseXHeaderSource{
resp: v, resp: v,
addr: addr,
} }
} }
} }

View file

@ -1,6 +1,7 @@
package v2 package v2
import ( import (
"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"
) )
@ -14,6 +15,8 @@ type requestXHeaderSource struct {
type responseXHeaderSource struct { type responseXHeaderSource struct {
resp Response resp Response
addr *refs.Address
} }
func (s *requestXHeaderSource) GetXHeaders() []*session.XHeader { func (s *requestXHeaderSource) GetXHeaders() []*session.XHeader {