[#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 <evgeniy@morphbits.ru>
This commit is contained in:
Evgenii Stratonikov 2022-10-12 16:41:23 +03:00 committed by fyrchik
parent dde4d4df2a
commit 4baf00aa21
2 changed files with 26 additions and 0 deletions

View file

@ -18,6 +18,7 @@ Changelog for NeoFS Node
- `container nodes` command to output list of nodes for container, grouped by replica (#1704) - `container nodes` command to output list of nodes for container, grouped by replica (#1704)
- Configuration flag to ignore shard in `neofs-node` (#1840) - Configuration flag to ignore shard in `neofs-node` (#1840)
- Add new RPC `TreeService.Healthcheck` - Add new RPC `TreeService.Healthcheck`
- Fallback to `GET` if `GET_RANGE` from one storage nodes to another is denied by basic ACL (#1884)
### Changed ### Changed
- Allow to evacuate shard data with `EvacuateShard` control RPC (#1800) - Allow to evacuate shard data with `EvacuateShard` control RPC (#1800)

View file

@ -1,6 +1,8 @@
package getsvc package getsvc
import ( import (
"crypto/ecdsa"
"errors"
"io" "io"
coreclient "github.com/nspcc-dev/neofs-node/pkg/core/client" 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) res, err := internalclient.PayloadRange(prm)
if err != nil { 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 nil, err
} }
return payloadOnlyObject(res.PayloadRange()), nil 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 var prm internalclient.GetObjectPrm
prm.SetContext(exec.context()) prm.SetContext(exec.context())