[#69] object/acl: Check eACL rules in ACL service

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2020-10-03 10:50:41 +03:00 committed by Alex Vanin
parent 1d676fcfb2
commit 9cdf7d3896

View file

@ -13,6 +13,7 @@ import (
core "github.com/nspcc-dev/neofs-node/pkg/core/container" core "github.com/nspcc-dev/neofs-node/pkg/core/container"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/localstore" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/localstore"
"github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl" "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl"
eaclV2 "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl/v2"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -25,11 +26,15 @@ type (
putStreamBasicChecker struct { putStreamBasicChecker struct {
source *Service source *Service
next object.PutObjectStreamer next object.PutObjectStreamer
*eACLCfg
} }
getStreamBasicChecker struct { getStreamBasicChecker struct {
next object.GetObjectStreamer next object.GetObjectStreamer
info requestInfo info requestInfo
*eACLCfg
} }
searchStreamBasicChecker struct { searchStreamBasicChecker struct {
@ -126,13 +131,16 @@ func (b Service) Get(
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return nil, basicACLErr(reqInfo) return nil, basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
return nil, eACLErr(reqInfo)
} }
stream, err := b.next.Get(ctx, request) stream, err := b.next.Get(ctx, request)
return getStreamBasicChecker{ return getStreamBasicChecker{
next: stream, next: stream,
info: reqInfo, info: reqInfo,
eACLCfg: b.eACLCfg,
}, err }, err
} }
@ -140,8 +148,9 @@ func (b Service) Put(ctx context.Context) (object.PutObjectStreamer, error) {
streamer, err := b.next.Put(ctx) streamer, err := b.next.Put(ctx)
return putStreamBasicChecker{ return putStreamBasicChecker{
source: &b, source: &b,
next: streamer, next: streamer,
eACLCfg: b.eACLCfg,
}, err }, err
} }
@ -166,9 +175,18 @@ func (b Service) Head(
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return nil, basicACLErr(reqInfo) return nil, basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
return nil, eACLErr(reqInfo)
} }
return b.next.Head(ctx, request) resp, err := b.next.Head(ctx, request)
if err == nil {
if !eACLCheck(resp, reqInfo, b.eACLCfg) {
err = eACLErr(reqInfo)
}
}
return resp, err
} }
func (b Service) Search( func (b Service) Search(
@ -194,6 +212,8 @@ func (b Service) Search(
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return nil, basicACLErr(reqInfo) return nil, basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
return nil, eACLErr(reqInfo)
} }
stream, err := b.next.Search(ctx, request) stream, err := b.next.Search(ctx, request)
@ -221,6 +241,8 @@ func (b Service) Delete(
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return nil, basicACLErr(reqInfo) return nil, basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
return nil, eACLErr(reqInfo)
} }
return b.next.Delete(ctx, request) return b.next.Delete(ctx, request)
@ -247,6 +269,8 @@ func (b Service) GetRange(
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return nil, basicACLErr(reqInfo) return nil, basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
return nil, eACLErr(reqInfo)
} }
stream, err := b.next.GetRange(ctx, request) stream, err := b.next.GetRange(ctx, request)
@ -274,6 +298,8 @@ func (b Service) GetRangeHash(
if !basicACLCheck(reqInfo) { if !basicACLCheck(reqInfo) {
return nil, basicACLErr(reqInfo) return nil, basicACLErr(reqInfo)
} else if !eACLCheck(request, reqInfo, b.eACLCfg) {
return nil, eACLErr(reqInfo)
} }
return b.next.GetRangeHash(ctx, request) return b.next.GetRangeHash(ctx, request)
@ -309,6 +335,8 @@ func (p putStreamBasicChecker) Send(request *object.PutRequest) error {
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) {
return eACLErr(reqInfo)
} }
} }
@ -339,6 +367,8 @@ func (g getStreamBasicChecker) Recv() (*object.GetResponse, error) {
if !stickyBitCheck(g.info, ownerID) { if !stickyBitCheck(g.info, ownerID) {
return nil, basicACLErr(g.info) return nil, basicACLErr(g.info)
} else if !eACLCheck(resp, g.info, g.eACLCfg) {
return nil, eACLErr(g.info)
} }
} }
@ -460,6 +490,34 @@ func stickyBitCheck(info requestInfo, owner *owner.ID) bool {
return bytes.Equal(owner.ToV2().GetValue(), info.owner.ToV2().GetValue()) return bytes.Equal(owner.ToV2().GetValue(), info.owner.ToV2().GetValue())
} }
func eACLCheck(msg interface{}, reqInfo requestInfo, cfg *eACLCfg) bool {
if reqInfo.basicACL.Final() {
return true
}
hdrSrcOpts := make([]eaclV2.Option, 0, 2)
hdrSrcOpts = append(hdrSrcOpts, eaclV2.WithLocalObjectStorage(cfg.localStorage))
if req, ok := msg.(eaclV2.Request); ok {
hdrSrcOpts = append(hdrSrcOpts, eaclV2.WithServiceRequest(req))
} else {
hdrSrcOpts = append(hdrSrcOpts, eaclV2.WithServiceResponse(msg.(eaclV2.Response)))
}
action := cfg.eACL.CalculateAction(new(eacl.ValidationUnit).
WithRole(reqInfo.requestRole).
WithOperation(reqInfo.operation).
WithContainerID(reqInfo.cid).
WithSenderKey(reqInfo.senderKey).
WithHeaderSource(
eaclV2.NewMessageHeaderSource(hdrSrcOpts...),
),
)
return action == acl.ActionAllow
}
// sourceVerbOfRequest looks for verb in session token and if it is not found, // sourceVerbOfRequest looks for verb in session token and if it is not found,
// returns reqVerb. // returns reqVerb.
func sourceVerbOfRequest(req metaWithToken, reqVerb acl.Operation) acl.Operation { func sourceVerbOfRequest(req metaWithToken, reqVerb acl.Operation) acl.Operation {
@ -506,3 +564,10 @@ func basicACLErr(info requestInfo) error {
failedCheckTyp: "basic ACL", failedCheckTyp: "basic ACL",
} }
} }
func eACLErr(info requestInfo) error {
return &accessErr{
requestInfo: info,
failedCheckTyp: "extended ACL",
}
}