From 9a006ac14f600cd0ba5eab3fc6c4aa3c109b6769 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Mon, 10 Oct 2022 22:31:19 +0400 Subject: [PATCH] [#1865] cli/object: Do not open remote sessions in reading ops It does not make sense to open remote sessions with the storage node in `get`, `head`, `search`, `range` and `hash` sub-commands of `neofs-cli object` command. Do not use NeoFS API `SessionService` in mentioned commands. Decode object session from JSON file specified `--session` flag. Perform some sanity checks instantly on CLI side. Signed-off-by: Leonard Lyubich --- CHANGELOG.md | 1 + cmd/neofs-cli/modules/object/get.go | 6 +- cmd/neofs-cli/modules/object/hash.go | 5 +- cmd/neofs-cli/modules/object/head.go | 6 +- cmd/neofs-cli/modules/object/range.go | 6 +- cmd/neofs-cli/modules/object/search.go | 6 +- cmd/neofs-cli/modules/object/util.go | 91 ++++++++++++++++++++++++++ 7 files changed, 112 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30ecfa767..6932f6709 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Changelog for NeoFS Node - Policer marks nodes under maintenance as OK without requests (#1680) - Unify help messages in CLI (#1854) - `evacuate`, `set-mode` and `flush-cache` control subcommands now accept a list of shard ids (#1867) +- Reading `object` commands of NeoFS CLI don't open remote sessions (#1865) ### Fixed - Description of command `netmap nodeinfo` (#1821) diff --git a/cmd/neofs-cli/modules/object/get.go b/cmd/neofs-cli/modules/object/get.go index 4612de895..d163716e9 100644 --- a/cmd/neofs-cli/modules/object/get.go +++ b/cmd/neofs-cli/modules/object/get.go @@ -10,7 +10,6 @@ import ( "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" - sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" @@ -65,9 +64,12 @@ func getObject(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) + cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + var prm internalclient.GetObjectPrm - sessionCli.Prepare(cmd, cnr, &obj, pk, &prm) + prm.SetClient(cli) Prepare(cmd, &prm) + readSession(cmd, &prm, pk, cnr, obj) raw, _ := cmd.Flags().GetBool(rawFlag) prm.SetRawFlag(raw) diff --git a/cmd/neofs-cli/modules/object/hash.go b/cmd/neofs-cli/modules/object/hash.go index 8a1f19edd..7538dcfe9 100644 --- a/cmd/neofs-cli/modules/object/hash.go +++ b/cmd/neofs-cli/modules/object/hash.go @@ -95,9 +95,12 @@ func getObjectHash(cmd *cobra.Command, _ []string) { return } + cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + var hashPrm internalclient.HashPayloadRangesPrm - sessionCli.Prepare(cmd, cnr, &obj, pk, &hashPrm) + hashPrm.SetClient(cli) Prepare(cmd, &hashPrm) + readSession(cmd, &hashPrm, pk, cnr, obj) hashPrm.SetAddress(objAddr) hashPrm.SetSalt(salt) hashPrm.SetRanges(ranges) diff --git a/cmd/neofs-cli/modules/object/head.go b/cmd/neofs-cli/modules/object/head.go index 1f4642418..da94bc523 100644 --- a/cmd/neofs-cli/modules/object/head.go +++ b/cmd/neofs-cli/modules/object/head.go @@ -11,7 +11,6 @@ import ( "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" - sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" @@ -53,9 +52,12 @@ func getObjectHeader(cmd *cobra.Command, _ []string) { mainOnly, _ := cmd.Flags().GetBool("main-only") pk := key.GetOrGenerate(cmd) + cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + var prm internalclient.HeadObjectPrm - sessionCli.Prepare(cmd, cnr, &obj, pk, &prm) + prm.SetClient(cli) Prepare(cmd, &prm) + readSession(cmd, &prm, pk, cnr, obj) raw, _ := cmd.Flags().GetBool(rawFlag) prm.SetRawFlag(raw) diff --git a/cmd/neofs-cli/modules/object/range.go b/cmd/neofs-cli/modules/object/range.go index a1fc2a3bb..62fb2d852 100644 --- a/cmd/neofs-cli/modules/object/range.go +++ b/cmd/neofs-cli/modules/object/range.go @@ -13,7 +13,6 @@ import ( "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" - sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" @@ -75,9 +74,12 @@ func getObjectRange(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) + cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + var prm internalclient.PayloadRangePrm - sessionCli.Prepare(cmd, cnr, &obj, pk, &prm) + prm.SetClient(cli) Prepare(cmd, &prm) + readSession(cmd, &prm, pk, cnr, obj) raw, _ := cmd.Flags().GetBool(rawFlag) prm.SetRawFlag(raw) diff --git a/cmd/neofs-cli/modules/object/search.go b/cmd/neofs-cli/modules/object/search.go index 8136f897f..28dcbb76b 100644 --- a/cmd/neofs-cli/modules/object/search.go +++ b/cmd/neofs-cli/modules/object/search.go @@ -9,7 +9,6 @@ import ( "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" - sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/object" oidSDK "github.com/nspcc-dev/neofs-sdk-go/object/id" @@ -55,9 +54,12 @@ func searchObject(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) + cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + var prm internalclient.SearchObjectsPrm - sessionCli.Prepare(cmd, cnr, nil, pk, &prm) + prm.SetClient(cli) Prepare(cmd, &prm) + readSessionGlobal(cmd, &prm, pk, cnr) prm.SetContainerID(cnr) prm.SetFilters(sf) diff --git a/cmd/neofs-cli/modules/object/util.go b/cmd/neofs-cli/modules/object/util.go index 1e20614fa..73c77c16a 100644 --- a/cmd/neofs-cli/modules/object/util.go +++ b/cmd/neofs-cli/modules/object/util.go @@ -1,14 +1,19 @@ package object import ( + "crypto/ecdsa" + "errors" "fmt" "strings" + internal "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-sdk-go/bearer" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" + "github.com/nspcc-dev/neofs-sdk-go/session" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -81,3 +86,89 @@ func readOID(cmd *cobra.Command, id *oid.ID) { err := id.DecodeString(cmd.Flag("oid").Value.String()) common.ExitOnErr(cmd, "decode object ID string: %w", err) } + +// common interface of object operation's input which supports sessions. +// Implemented on types like internal.PutObjectPrm. +type sessionPrm interface { + SetSessionToken(*session.Object) +} + +// forwards all parameters to _readSession and object as nil. +func readSessionGlobal(cmd *cobra.Command, dst sessionPrm, key *ecdsa.PrivateKey, cnr cid.ID) { + _readSession(cmd, dst, key, cnr, nil) +} + +// forwards all parameters to _readSession. +func readSession(cmd *cobra.Command, dst sessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj oid.ID) { + _readSession(cmd, dst, key, cnr, &obj) +} + +// decodes object session from JSON file from "session" command flag if it is provided, +// and writes resulting session into the provided sessionPrm. Checks: +// +// - if session verb corresponds to given sessionPrm according to its type +// - relation to the given container +// - relation to the given object if non-nil +// - relation to the given private key used withing the command +// - session signature +// +// sessionPrm MUST be one of: +// +// *internal.PutObjectPrm +// *internal.DeleteObjectPrm +// *internal.GetObjectPrm +// *internal.HeadObjectPrm +// *internal.SearchObjectsPrm +// *internal.PayloadRangePrm +// *internal.HashPayloadRangesPrm +func _readSession(cmd *cobra.Command, dst sessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { + var cmdVerb session.ObjectVerb + + switch dst.(type) { + default: + panic(fmt.Sprintf("unsupported op parameters %T", dst)) + case *internal.PutObjectPrm: + cmdVerb = session.VerbObjectPut + case *internal.DeleteObjectPrm: + cmdVerb = session.VerbObjectDelete + case *internal.GetObjectPrm: + cmdVerb = session.VerbObjectGet + case *internal.HeadObjectPrm: + cmdVerb = session.VerbObjectHead + case *internal.SearchObjectsPrm: + cmdVerb = session.VerbObjectSearch + case *internal.PayloadRangePrm: + cmdVerb = session.VerbObjectRange + case *internal.HashPayloadRangesPrm: + cmdVerb = session.VerbObjectRangeHash + } + + sessionTokenPath, _ := cmd.Flags().GetString(commonflags.SessionToken) + if sessionTokenPath != "" { + common.PrintVerbose("Reading object session from the JSON file [%s]...", sessionTokenPath) + + var tok session.Object + common.ReadSessionToken(cmd, &tok, sessionTokenPath) + + common.PrintVerbose("Checking session correctness...") + + switch false { + case tok.AssertContainer(cnr): + common.ExitOnErr(cmd, "", errors.New("unrelated container in the session")) + case obj == nil || tok.AssertObject(*obj): + common.ExitOnErr(cmd, "", errors.New("unrelated object in the session")) + case tok.AssertVerb(cmdVerb): + common.ExitOnErr(cmd, "", errors.New("wrong verb of the session")) + case tok.AssertAuthKey((*neofsecdsa.PublicKey)(&key.PublicKey)): + common.ExitOnErr(cmd, "", errors.New("unrelated key in the session")) + case tok.VerifySignature(): + common.ExitOnErr(cmd, "", errors.New("invalid signature of the session data")) + } + + common.PrintVerbose("Session is correct.") + + dst.SetSessionToken(&tok) + } else { + common.PrintVerbose("Session is not provided.") + } +}