forked from TrueCloudLab/frostfs-node
[#69] object/acl: Check eACL rules in ACL service
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
1d676fcfb2
commit
9cdf7d3896
1 changed files with 70 additions and 5 deletions
|
@ -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",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue