diff --git a/CHANGELOG.md b/CHANGELOG.md index a8737dd4..b7c97ea3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Changelog for NeoFS Node - Use `sync.Pool` in Object.PUT service (#2139) - Shard uses metabase for `HEAD` requests by default, not write-cache (#2167) - Clarify help for `--expire-at` parameter for commands `object lock/put` and `bearer create` (#2097) +- Node spawns `GETRANGE` requests signed with the node's key if session key was not found for `RANGEHASH` (#2144) ### Fixed - Open FSTree in sync mode by default (#1992) diff --git a/pkg/services/object/get/exec.go b/pkg/services/object/get/exec.go index f1d1098b..89b3f8aa 100644 --- a/pkg/services/object/get/exec.go +++ b/pkg/services/object/get/exec.go @@ -109,6 +109,12 @@ func (exec execCtx) isChild(obj *objectSDK.Object) bool { } func (exec execCtx) key() (*ecdsa.PrivateKey, error) { + if exec.prm.signerKey != nil { + // the key has already been requested and + // cached in the previous operations + return exec.prm.signerKey, nil + } + var sessionInfo *util.SessionInfo if tok := exec.prm.common.SessionToken(); tok != nil { diff --git a/pkg/services/object/get/prm.go b/pkg/services/object/get/prm.go index 6f737c71..1050a895 100644 --- a/pkg/services/object/get/prm.go +++ b/pkg/services/object/get/prm.go @@ -1,6 +1,7 @@ package getsvc import ( + "crypto/ecdsa" "errors" "hash" @@ -74,6 +75,11 @@ type commonPrm struct { raw bool forwarder RequestForwarder + + // signerKey is a cached key that should be used for spawned + // requests (if any), could be nil if incoming request handling + // routine does not include any key fetching operations + signerKey *ecdsa.PrivateKey } // ChunkWriter is an interface of target component @@ -145,6 +151,11 @@ func (p *commonPrm) WithRawFlag(raw bool) { p.raw = raw } +// WithCachedSignerKey sets optional key for all further requests. +func (p *commonPrm) WithCachedSignerKey(signerKey *ecdsa.PrivateKey) { + p.signerKey = signerKey +} + // SetHeaderWriter sets target component to write the object header. func (p *HeadPrm) SetHeaderWriter(w HeaderWriter) { p.objWriter = &partWriter{ diff --git a/pkg/services/object/get/v2/util.go b/pkg/services/object/get/v2/util.go index b2513cfe..f887b3da 100644 --- a/pkg/services/object/get/v2/util.go +++ b/pkg/services/object/get/v2/util.go @@ -362,6 +362,23 @@ func (s *Service) toHashRangePrm(req *objectV2.GetRangeHashRequest) (*getsvc.Ran p.WithAddress(addr) + if tok := commonPrm.SessionToken(); tok != nil { + signerKey, err := s.keyStorage.GetKey(&util.SessionInfo{ + ID: tok.ID(), + Owner: tok.Issuer(), + }) + if err != nil && errors.As(err, new(apistatus.SessionTokenNotFound)) { + commonPrm.ForgetTokens() + signerKey, err = s.keyStorage.GetKey(nil) + } + + if err != nil { + return nil, fmt.Errorf("fetching session key: %w", err) + } + + p.WithCachedSignerKey(signerKey) + } + rngsV2 := body.GetRanges() rngs := make([]object.Range, len(rngsV2))