forked from TrueCloudLab/frostfs-node
[#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:
parent
bbe700fa37
commit
168dcbdccd
5 changed files with 98 additions and 20 deletions
|
@ -8,10 +8,12 @@ import (
|
|||
|
||||
acl "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"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||
"github.com/nspcc-dev/neofs-api-go/util/signature"
|
||||
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/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
|
@ -70,6 +72,8 @@ type (
|
|||
|
||||
cid *container.ID
|
||||
|
||||
oid *objectSDK.ID
|
||||
|
||||
senderKey []byte
|
||||
|
||||
bearer *bearer.BearerToken // bearer token of request
|
||||
|
@ -150,6 +154,8 @@ func (b Service) Get(request *object.GetRequest, stream objectSvc.GetObjectStrea
|
|||
return err
|
||||
}
|
||||
|
||||
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
|
||||
|
||||
if !basicACLCheck(reqInfo) {
|
||||
return basicACLErr(reqInfo)
|
||||
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
|
||||
|
@ -193,6 +199,8 @@ func (b Service) Head(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
|
||||
|
||||
if !basicACLCheck(reqInfo) {
|
||||
return nil, basicACLErr(reqInfo)
|
||||
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
|
||||
|
@ -228,6 +236,8 @@ func (b Service) Search(request *object.SearchRequest, stream objectSvc.SearchSt
|
|||
return err
|
||||
}
|
||||
|
||||
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
|
||||
|
||||
if !basicACLCheck(reqInfo) {
|
||||
return basicACLErr(reqInfo)
|
||||
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
|
||||
|
@ -261,6 +271,8 @@ func (b Service) Delete(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
|
||||
|
||||
if !basicACLCheck(reqInfo) {
|
||||
return nil, basicACLErr(reqInfo)
|
||||
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
|
||||
|
@ -287,6 +299,8 @@ func (b Service) GetRange(request *object.GetRangeRequest, stream objectSvc.GetO
|
|||
return err
|
||||
}
|
||||
|
||||
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
|
||||
|
||||
if !basicACLCheck(reqInfo) {
|
||||
return basicACLErr(reqInfo)
|
||||
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
|
||||
|
@ -320,6 +334,8 @@ func (b Service) GetRangeHash(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
reqInfo.oid = getObjectIDFromRequestBody(request.GetBody())
|
||||
|
||||
if !basicACLCheck(reqInfo) {
|
||||
return nil, basicACLErr(reqInfo)
|
||||
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
|
||||
|
@ -358,6 +374,8 @@ func (p putStreamBasicChecker) Send(request *object.PutRequest) error {
|
|||
return err
|
||||
}
|
||||
|
||||
reqInfo.oid = getObjectIDFromRequestBody(part)
|
||||
|
||||
if !basicACLCheck(reqInfo) || !stickyBitCheck(reqInfo, ownerID) {
|
||||
return basicACLErr(reqInfo)
|
||||
} 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) {
|
||||
switch v := req.(type) {
|
||||
case *object.PutRequest:
|
||||
|
@ -547,7 +580,12 @@ func eACLCheck(msg interface{}, reqInfo requestInfo, cfg *eACLCfg) bool {
|
|||
if req, ok := msg.(eaclV2.Request); ok {
|
||||
hdrSrcOpts = append(hdrSrcOpts, eaclV2.WithServiceRequest(req))
|
||||
} 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).
|
||||
|
|
|
@ -5,7 +5,9 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg"
|
||||
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"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||
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/session"
|
||||
|
@ -62,7 +64,7 @@ func (h *headerSource) HeadersOfType(typ eaclSDK.FilterHeaderType) ([]eacl.Heade
|
|||
case eaclSDK.HeaderFromRequest:
|
||||
return requestHeaders(h.msg), true
|
||||
case eaclSDK.HeaderFromObject:
|
||||
return h.objectHeaders()
|
||||
return h.objectHeaders(), true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +80,7 @@ func requestHeaders(msg xHeaderSource) []eacl.Header {
|
|||
return res
|
||||
}
|
||||
|
||||
func (h *headerSource) objectHeaders() ([]eacl.Header, bool) {
|
||||
func (h *headerSource) objectHeaders() []eacl.Header {
|
||||
switch m := h.msg.(type) {
|
||||
default:
|
||||
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.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:
|
||||
switch resp := m.resp.(type) {
|
||||
default:
|
||||
return h.localObjectHeaders(m.addr)
|
||||
case *objectV2.GetResponse:
|
||||
if v, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok {
|
||||
oV2 := new(objectV2.Object)
|
||||
oV2.SetObjectID(v.GetObjectID())
|
||||
oV2.SetHeader(v.GetHeader())
|
||||
|
||||
return headersFromObject(object.NewFromV2(oV2)), true
|
||||
return headersFromObject(object.NewFromV2(oV2))
|
||||
}
|
||||
case *objectV2.HeadResponse:
|
||||
oV2 := new(objectV2.Object)
|
||||
|
@ -122,6 +132,7 @@ func (h *headerSource) objectHeaders() ([]eacl.Header, bool) {
|
|||
case *objectV2.ShortHeader:
|
||||
hdr = new(objectV2.Header)
|
||||
|
||||
hdr.SetContainerID(m.addr.GetContainerID())
|
||||
hdr.SetVersion(v.GetVersion())
|
||||
hdr.SetCreationEpoch(v.GetCreationEpoch())
|
||||
hdr.SetOwnerID(v.GetOwnerID())
|
||||
|
@ -133,18 +144,48 @@ func (h *headerSource) objectHeaders() ([]eacl.Header, bool) {
|
|||
|
||||
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) {
|
||||
obj, err := h.storage.Head(objectSDK.NewAddressFromV2(addr))
|
||||
func (h *headerSource) localObjectHeaders(addrV2 *refs.Address) []eacl.Header {
|
||||
addr := objectSDK.NewAddressFromV2(addrV2)
|
||||
|
||||
obj, err := h.storage.Head(addr)
|
||||
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
|
||||
}
|
||||
|
|
|
@ -46,10 +46,7 @@ func headersFromObject(obj *object.Object) []eacl.Header {
|
|||
for ; obj != nil; obj = obj.GetParent() {
|
||||
res = append(res,
|
||||
// container ID
|
||||
&sysObjHdr{
|
||||
k: acl.FilterObjectContainerID,
|
||||
v: cidValue(obj.ContainerID()),
|
||||
},
|
||||
cidHeader(obj.ContainerID()),
|
||||
// owner ID
|
||||
&sysObjHdr{
|
||||
k: acl.FilterObjectOwnerID,
|
||||
|
@ -65,10 +62,7 @@ func headersFromObject(obj *object.Object) []eacl.Header {
|
|||
k: acl.FilterObjectPayloadLength,
|
||||
v: u64Value(obj.PayloadSize()),
|
||||
},
|
||||
&sysObjHdr{
|
||||
k: acl.FilterObjectID,
|
||||
v: idValue(obj.ID()),
|
||||
},
|
||||
oidHeader(obj.ID()),
|
||||
// TODO: add others fields after neofs-api#84
|
||||
)
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package v2
|
|||
|
||||
import (
|
||||
"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 {
|
||||
|
@ -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) {
|
||||
c.msg = &responseXHeaderSource{
|
||||
resp: v,
|
||||
addr: addr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package v2
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
)
|
||||
|
||||
|
@ -14,6 +15,8 @@ type requestXHeaderSource struct {
|
|||
|
||||
type responseXHeaderSource struct {
|
||||
resp Response
|
||||
|
||||
addr *refs.Address
|
||||
}
|
||||
|
||||
func (s *requestXHeaderSource) GetXHeaders() []*session.XHeader {
|
||||
|
|
Loading…
Reference in a new issue