From 4baf00aa214e168f26f9b41217b5e25882ad0186 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 12 Oct 2022 16:41:23 +0300 Subject: [PATCH] [#1884] services/object: Fallback to GET in GET_RANGE Current spec allows denying GET_RANGE requests from other storage nodes. However, GET should always be allowed and it is enough to perform GET_RANGE locally Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 1 + pkg/services/object/get/util.go | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f35f41d2..51e42a08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Changelog for NeoFS Node - `container nodes` command to output list of nodes for container, grouped by replica (#1704) - Configuration flag to ignore shard in `neofs-node` (#1840) - Add new RPC `TreeService.Healthcheck` +- Fallback to `GET` if `GET_RANGE` from one storage nodes to another is denied by basic ACL (#1884) ### Changed - Allow to evacuate shard data with `EvacuateShard` control RPC (#1800) diff --git a/pkg/services/object/get/util.go b/pkg/services/object/get/util.go index be8c22d2..5fa364ab 100644 --- a/pkg/services/object/get/util.go +++ b/pkg/services/object/get/util.go @@ -1,6 +1,8 @@ package getsvc import ( + "crypto/ecdsa" + "errors" "io" coreclient "github.com/nspcc-dev/neofs-node/pkg/core/client" @@ -143,12 +145,35 @@ func (c *clientWrapper) getObject(exec *execCtx, info coreclient.NodeInfo) (*obj res, err := internalclient.PayloadRange(prm) if err != nil { + var errAccessDenied *apistatus.ObjectAccessDenied + if errors.As(err, &errAccessDenied) { + // Current spec allows other storage node to deny access, + // fallback to GET_RANGE here. + obj, err := c.get(exec, key) + if err != nil { + return nil, err + } + + payload := obj.Payload() + from := rng.GetOffset() + to := from + rng.GetLength() + + if pLen := uint64(len(payload)); to < from || pLen < from || pLen < to { + return nil, apistatus.ObjectOutOfRange{} + } + + return payloadOnlyObject(payload[from:to]), nil + } return nil, err } return payloadOnlyObject(res.PayloadRange()), nil } + return c.get(exec, key) +} + +func (c *clientWrapper) get(exec *execCtx, key *ecdsa.PrivateKey) (*object.Object, error) { var prm internalclient.GetObjectPrm prm.SetContext(exec.context())