frostfs-node/pkg/services/object/util/prm.go
Alex Vanin c30aa20b04 [#943] service/object: Refactor private key fetching during execution
`CommonPrm` structure has private key for remote operations.
It obtained in the beginning of request processing. However,
not every operation triggers remote calls. Therefore, key
might not be used. It is important to avoid early key fetching
because `TokenStore` now returns error if session token does not
exist. This is valid case when container nodes receive request with
session token (for ACL pass) and they should process request locally.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2021-10-27 20:25:25 +03:00

219 lines
4.1 KiB
Go

package util
import (
"crypto/ecdsa"
"strconv"
"github.com/nspcc-dev/neofs-api-go/pkg"
"github.com/nspcc-dev/neofs-api-go/pkg/client"
sessionsdk "github.com/nspcc-dev/neofs-api-go/pkg/session"
"github.com/nspcc-dev/neofs-api-go/pkg/token"
"github.com/nspcc-dev/neofs-api-go/v2/session"
)
type CommonPrm struct {
local bool
netmapEpoch, netmapLookupDepth uint64
token *sessionsdk.Token
bearer *token.BearerToken
keyStor *KeyStorage
callOpts []client.CallOption
}
type remoteCallOpts struct {
opts []client.CallOption
}
type DynamicCallOption func(*remoteCallOpts)
func (p *CommonPrm) WithLocalOnly(v bool) *CommonPrm {
if p != nil {
p.local = v
}
return p
}
func (p *CommonPrm) LocalOnly() bool {
if p != nil {
return p.local
}
return false
}
func (p *CommonPrm) WithSessionToken(token *sessionsdk.Token) *CommonPrm {
if p != nil {
p.token = token
}
return p
}
func (p *CommonPrm) WithBearerToken(token *token.BearerToken) *CommonPrm {
if p != nil {
p.bearer = token
}
return p
}
// WithKeyStorage sets private key storage to use during execution.
func (p *CommonPrm) WithKeyStorage(stor *KeyStorage) *CommonPrm {
if p != nil {
p.keyStor = stor
}
return p
}
// KeyStorage returns private key storage to use during execution.
func (p *CommonPrm) KeyStorage() *KeyStorage {
if p != nil {
return p.keyStor
}
return nil
}
// WithRemoteCallOptions sets call options remote remote client calls.
func (p *CommonPrm) WithRemoteCallOptions(opts ...client.CallOption) *CommonPrm {
if p != nil {
p.callOpts = opts
}
return p
}
// RemoteCallOptions return call options for remote client calls.
func (p *CommonPrm) RemoteCallOptions(dynamic ...DynamicCallOption) []client.CallOption {
if p != nil {
o := &remoteCallOpts{
opts: p.callOpts,
}
for _, applier := range dynamic {
applier(o)
}
return o.opts
}
return nil
}
func WithNetmapEpoch(v uint64) DynamicCallOption {
return func(o *remoteCallOpts) {
xHdr := pkg.NewXHeader()
xHdr.SetKey(session.XHeaderNetmapEpoch)
xHdr.SetValue(strconv.FormatUint(v, 10))
o.opts = append(o.opts, client.WithXHeader(xHdr))
}
}
// WithKey sets key to use for the request.
func WithKey(key *ecdsa.PrivateKey) DynamicCallOption {
return func(o *remoteCallOpts) {
o.opts = append(o.opts, client.WithKey(key))
}
}
func (p *CommonPrm) SessionToken() *sessionsdk.Token {
if p != nil {
return p.token
}
return nil
}
func (p *CommonPrm) BearerToken() *token.BearerToken {
if p != nil {
return p.bearer
}
return nil
}
func (p *CommonPrm) NetmapEpoch() uint64 {
if p != nil {
return p.netmapEpoch
}
return 0
}
func (p *CommonPrm) NetmapLookupDepth() uint64 {
if p != nil {
return p.netmapLookupDepth
}
return 0
}
func (p *CommonPrm) SetNetmapLookupDepth(v uint64) {
if p != nil {
p.netmapLookupDepth = v
}
}
func CommonPrmFromV2(req interface {
GetMetaHeader() *session.RequestMetaHeader
}) (*CommonPrm, error) {
meta := req.GetMetaHeader()
xHdrs := meta.GetXHeaders()
const staticOptNum = 3
prm := &CommonPrm{
local: meta.GetTTL() <= 1, // FIXME: use constant
token: nil,
bearer: nil,
callOpts: make([]client.CallOption, 0, staticOptNum+len(xHdrs)),
}
prm.callOpts = append(prm.callOpts, client.WithTTL(meta.GetTTL()-1))
if tok := meta.GetSessionToken(); tok != nil {
prm.token = sessionsdk.NewTokenFromV2(tok)
prm.callOpts = append(prm.callOpts, client.WithSession(prm.token))
}
if tok := meta.GetBearerToken(); tok != nil {
prm.bearer = token.NewBearerTokenFromV2(tok)
prm.callOpts = append(prm.callOpts, client.WithBearer(prm.bearer))
}
for i := range xHdrs {
switch xHdrs[i].GetKey() {
case session.XHeaderNetmapEpoch:
var err error
prm.netmapEpoch, err = strconv.ParseUint(xHdrs[i].GetValue(), 10, 64)
if err != nil {
return nil, err
}
case session.XHeaderNetmapLookupDepth:
var err error
prm.netmapLookupDepth, err = strconv.ParseUint(xHdrs[i].GetValue(), 10, 64)
if err != nil {
return nil, err
}
default:
prm.callOpts = append(prm.callOpts,
client.WithXHeader(
pkg.NewXHeaderFromV2(xHdrs[i]),
),
)
}
}
return prm, nil
}