[#1933] cli: Support binary sessions
There is a need to support NeoFS-binary sessions along with JSON ones in NeoFS CLI. Provide generic `common.ReadBinaryOrJSON` functions which tries to decode NeoFS-binary structure and falls back to JSON format. Use this function in all places with token reading. Signed-off-by: Leonard Lyubich <ctulhurider@gmail.com>
This commit is contained in:
parent
04b67f3ba5
commit
8bba490c30
24 changed files with 259 additions and 206 deletions
|
@ -21,6 +21,7 @@ Changelog for NeoFS Node
|
|||
- Setting node's network state to `MAINTENANCE` while network settings forbid it (#1916)
|
||||
- Do not panic during API client creation (#1936)
|
||||
- Correctly sign new epoch transaction in neofs-adm for a committee of more than 4 nodes (#1949)
|
||||
- Inability to provide session to NeoFS CLI in a NeoFS-binary format (#1933)
|
||||
|
||||
### Removed
|
||||
### Updated
|
||||
|
|
|
@ -2,6 +2,7 @@ package common
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
|
@ -18,39 +19,47 @@ func ReadBearerToken(cmd *cobra.Command, flagname string) *bearer.Token {
|
|||
return nil
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(path)
|
||||
ExitOnErr(cmd, "can't read bearer token file: %w", err)
|
||||
PrintVerbose("Reading bearer token from file [%s]...", path)
|
||||
|
||||
var tok bearer.Token
|
||||
if err := tok.UnmarshalJSON(data); err != nil {
|
||||
err = tok.Unmarshal(data)
|
||||
ExitOnErr(cmd, "can't decode bearer token: %w", err)
|
||||
|
||||
PrintVerbose("Using binary encoded bearer token")
|
||||
} else {
|
||||
PrintVerbose("Using JSON encoded bearer token")
|
||||
}
|
||||
err = ReadBinaryOrJSON(&tok, path)
|
||||
ExitOnErr(cmd, "invalid bearer token: %v", err)
|
||||
|
||||
return &tok
|
||||
}
|
||||
|
||||
// ReadSessionToken calls ReadSessionTokenErr and exists on error.
|
||||
func ReadSessionToken(cmd *cobra.Command, dst json.Unmarshaler, fPath string) {
|
||||
ExitOnErr(cmd, "", ReadSessionTokenErr(dst, fPath))
|
||||
// BinaryOrJSON is an interface of entities which provide json.Unmarshaler
|
||||
// and NeoFS binary decoder.
|
||||
type BinaryOrJSON interface {
|
||||
Unmarshal([]byte) error
|
||||
json.Unmarshaler
|
||||
}
|
||||
|
||||
// ReadSessionTokenErr reads session token as JSON file with session token
|
||||
// from path provided in a specified flag.
|
||||
func ReadSessionTokenErr(dst json.Unmarshaler, fPath string) error {
|
||||
// ReadBinaryOrJSON reads file data using provided path and decodes
|
||||
// BinaryOrJSON from the data.
|
||||
func ReadBinaryOrJSON(dst BinaryOrJSON, fPath string) error {
|
||||
PrintVerbose("Reading file [%s]...", fPath)
|
||||
|
||||
// try to read session token from file
|
||||
data, err := os.ReadFile(fPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not open file with session token <%s>: %w", fPath, err)
|
||||
return fmt.Errorf("read file <%s>: %w", fPath, err)
|
||||
}
|
||||
|
||||
err = dst.UnmarshalJSON(data)
|
||||
PrintVerbose("Trying to decode binary...")
|
||||
|
||||
err = dst.Unmarshal(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not unmarshal session token from file: %w", err)
|
||||
PrintVerbose("Failed to decode binary: %v", err)
|
||||
|
||||
PrintVerbose("Trying to decode JSON...")
|
||||
|
||||
err = dst.UnmarshalJSON(data)
|
||||
if err != nil {
|
||||
PrintVerbose("Failed to decode JSON: %v", err)
|
||||
return errors.New("invalid format")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
package commonflags
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const SessionToken = "session"
|
||||
|
||||
// InitSession initializes session parameter for cmd.
|
||||
func InitSession(cmd *cobra.Command) {
|
||||
// InitSession registers SessionToken flag representing filepath to the token
|
||||
// of the session with the given name. Supports NeoFS-binary and JSON files.
|
||||
func InitSession(cmd *cobra.Command, name string) {
|
||||
cmd.Flags().String(
|
||||
SessionToken,
|
||||
"",
|
||||
"Path to a JSON-encoded container session token",
|
||||
fmt.Sprintf("Filepath to a JSON- or binary-encoded token of the %s session", name),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/container/acl"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/user"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -74,13 +73,9 @@ It will be stored in sidechain when inner ring will accepts it.`,
|
|||
var basicACL acl.Basic
|
||||
common.ExitOnErr(cmd, "decode basic ACL string: %w", basicACL.DecodeString(containerACL))
|
||||
|
||||
var tok *session.Container
|
||||
|
||||
sessionTokenPath, _ := cmd.Flags().GetString(commonflags.SessionToken)
|
||||
if sessionTokenPath != "" {
|
||||
tok = new(session.Container)
|
||||
common.ReadSessionToken(cmd, tok, sessionTokenPath)
|
||||
tok := getSession(cmd)
|
||||
|
||||
if tok != nil {
|
||||
issuer := tok.Issuer()
|
||||
cnr.SetOwner(issuer)
|
||||
} else {
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key"
|
||||
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -21,13 +20,7 @@ Only owner of the container has a permission to remove container.`,
|
|||
Run: func(cmd *cobra.Command, args []string) {
|
||||
id := parseContainerID(cmd)
|
||||
|
||||
var tok *session.Container
|
||||
|
||||
sessionTokenPath, _ := cmd.Flags().GetString(commonflags.SessionToken)
|
||||
if sessionTokenPath != "" {
|
||||
tok = new(session.Container)
|
||||
common.ReadSessionToken(cmd, tok, sessionTokenPath)
|
||||
}
|
||||
tok := getSession(cmd)
|
||||
|
||||
pk := key.Get(cmd)
|
||||
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key"
|
||||
objectCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/object"
|
||||
sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -35,16 +34,17 @@ var listContainerObjectsCmd = &cobra.Command{
|
|||
filters := new(object.SearchFilters)
|
||||
filters.AddRootFilter() // search only user created objects
|
||||
|
||||
pk := key.GetOrGenerate(cmd)
|
||||
cli := internalclient.GetSDKClientByFlag(cmd, key.GetOrGenerate(cmd), commonflags.RPC)
|
||||
|
||||
var prmSearch internalclient.SearchObjectsPrm
|
||||
var prmHead internalclient.HeadObjectPrm
|
||||
|
||||
prmSearch.SetClient(cli)
|
||||
|
||||
if flagVarListObjectsPrintAttr {
|
||||
sessionCli.Prepare(cmd, id, nil, pk, &prmSearch, &prmHead)
|
||||
prmHead.SetClient(cli)
|
||||
objectCli.Prepare(cmd, &prmSearch, &prmHead)
|
||||
} else {
|
||||
sessionCli.Prepare(cmd, id, nil, pk, &prmSearch)
|
||||
objectCli.Prepare(cmd, &prmSearch)
|
||||
}
|
||||
|
||||
|
|
|
@ -45,11 +45,14 @@ func init() {
|
|||
commonflags.InitAPI(containerCommand)
|
||||
}
|
||||
|
||||
for _, cmd := range []*cobra.Command{
|
||||
createContainerCmd,
|
||||
deleteContainerCmd,
|
||||
setExtendedACLCmd,
|
||||
for _, el := range []struct {
|
||||
cmd *cobra.Command
|
||||
verb string
|
||||
}{
|
||||
{createContainerCmd, "PUT"},
|
||||
{deleteContainerCmd, "DELETE"},
|
||||
{setExtendedACLCmd, "SETEACL"},
|
||||
} {
|
||||
commonflags.InitSession(cmd)
|
||||
commonflags.InitSession(el.cmd, "container "+el.verb)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -28,13 +27,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
|
|||
id := parseContainerID(cmd)
|
||||
eaclTable := common.ReadEACL(cmd, flagVarsSetEACL.srcPath)
|
||||
|
||||
var tok *session.Container
|
||||
|
||||
sessionTokenPath, _ := cmd.Flags().GetString(commonflags.SessionToken)
|
||||
if sessionTokenPath != "" {
|
||||
tok = new(session.Container)
|
||||
common.ReadSessionToken(cmd, tok, sessionTokenPath)
|
||||
}
|
||||
tok := getSession(cmd)
|
||||
|
||||
eaclTable.SetCID(id)
|
||||
|
||||
|
|
|
@ -4,7 +4,9 @@ import (
|
|||
"errors"
|
||||
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -30,3 +32,26 @@ func parseContainerID(cmd *cobra.Command) cid.ID {
|
|||
common.ExitOnErr(cmd, "can't decode container ID value: %w", err)
|
||||
return id
|
||||
}
|
||||
|
||||
// decodes session.Container from the file by path provided in
|
||||
// commonflags.SessionToken flag. Returns nil if the path is not specified.
|
||||
func getSession(cmd *cobra.Command) *session.Container {
|
||||
common.PrintVerbose("Reading container session...")
|
||||
|
||||
path, _ := cmd.Flags().GetString(commonflags.SessionToken)
|
||||
if path == "" {
|
||||
common.PrintVerbose("Session not provided.")
|
||||
return nil
|
||||
}
|
||||
|
||||
common.PrintVerbose("Reading container session from the file [%s]...", path)
|
||||
|
||||
var res session.Container
|
||||
|
||||
err := common.ReadBinaryOrJSON(&res, path)
|
||||
common.ExitOnErr(cmd, "read container session: %v", err)
|
||||
|
||||
common.PrintVerbose("Session successfully read.")
|
||||
|
||||
return &res
|
||||
}
|
||||
|
|
|
@ -5,7 +5,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"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -21,7 +20,7 @@ var objectDelCmd = &cobra.Command{
|
|||
|
||||
func initObjectDeleteCmd() {
|
||||
commonflags.Init(objectDelCmd)
|
||||
commonflags.InitSession(objectDelCmd)
|
||||
initFlagSession(objectDelCmd, "DELETE")
|
||||
|
||||
flags := objectDelCmd.Flags()
|
||||
|
||||
|
@ -40,7 +39,7 @@ func deleteObject(cmd *cobra.Command, _ []string) {
|
|||
pk := key.GetOrGenerate(cmd)
|
||||
|
||||
var prm internalclient.DeleteObjectPrm
|
||||
sessionCli.Prepare(cmd, cnr, &obj, pk, &prm)
|
||||
ReadOrOpenSession(cmd, &prm, pk, cnr, &obj)
|
||||
Prepare(cmd, &prm)
|
||||
prm.SetAddress(objAddr)
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ var objectGetCmd = &cobra.Command{
|
|||
|
||||
func initObjectGetCmd() {
|
||||
commonflags.Init(objectGetCmd)
|
||||
commonflags.InitSession(objectGetCmd)
|
||||
initFlagSession(objectGetCmd, "GET")
|
||||
|
||||
flags := objectGetCmd.Flags()
|
||||
|
||||
|
|
|
@ -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"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/checksum"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
|
@ -69,7 +68,6 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
|
|||
fullHash := len(ranges) == 0
|
||||
if fullHash {
|
||||
var headPrm internalclient.HeadObjectPrm
|
||||
sessionCli.Prepare(cmd, cnr, &obj, pk, &headPrm)
|
||||
Prepare(cmd, &headPrm)
|
||||
headPrm.SetAddress(objAddr)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ var objectHeadCmd = &cobra.Command{
|
|||
|
||||
func initObjectHeadCmd() {
|
||||
commonflags.Init(objectHeadCmd)
|
||||
commonflags.InitSession(objectHeadCmd)
|
||||
initFlagSession(objectHeadCmd, "HEAD")
|
||||
|
||||
flags := objectHeadCmd.Flags()
|
||||
|
||||
|
|
|
@ -12,7 +12,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"
|
||||
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
|
@ -79,8 +78,7 @@ var objectLockCmd = &cobra.Command{
|
|||
obj.SetPayload(lock.Marshal())
|
||||
|
||||
var prm internalclient.PutObjectPrm
|
||||
|
||||
sessionCli.Prepare(cmd, cnr, nil, key, &prm)
|
||||
ReadOrOpenSession(cmd, &prm, key, cnr, nil)
|
||||
Prepare(cmd, &prm)
|
||||
prm.SetHeader(obj)
|
||||
|
||||
|
@ -94,7 +92,7 @@ var objectLockCmd = &cobra.Command{
|
|||
|
||||
func initCommandObjectLock() {
|
||||
commonflags.Init(objectLockCmd)
|
||||
commonflags.InitSession(objectLockCmd)
|
||||
initFlagSession(objectLockCmd, "PUT")
|
||||
|
||||
objectLockCmd.Flags().Uint64P(commonflags.ExpireAt, "e", 0, "Lock expiration epoch")
|
||||
objectLockCmd.Flags().Uint64(commonflags.Lifetime, 0, "Lock lifetime")
|
||||
|
|
|
@ -14,7 +14,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"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/user"
|
||||
|
@ -37,7 +36,7 @@ var objectPutCmd = &cobra.Command{
|
|||
|
||||
func initObjectPutCmd() {
|
||||
commonflags.Init(objectPutCmd)
|
||||
commonflags.InitSession(objectPutCmd)
|
||||
initFlagSession(objectPutCmd, "PUT")
|
||||
|
||||
flags := objectPutCmd.Flags()
|
||||
|
||||
|
@ -109,7 +108,7 @@ func putObject(cmd *cobra.Command, _ []string) {
|
|||
}
|
||||
|
||||
var prm internalclient.PutObjectPrm
|
||||
sessionCli.Prepare(cmd, cnr, nil, pk, &prm)
|
||||
ReadOrOpenSession(cmd, &prm, pk, cnr, nil)
|
||||
Prepare(cmd, &prm)
|
||||
prm.SetHeader(obj)
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ var objectRangeCmd = &cobra.Command{
|
|||
|
||||
func initObjectRangeCmd() {
|
||||
commonflags.Init(objectRangeCmd)
|
||||
commonflags.InitSession(objectRangeCmd)
|
||||
initFlagSession(objectRangeCmd, "RANGE")
|
||||
|
||||
flags := objectRangeCmd.Flags()
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ var (
|
|||
|
||||
func initObjectSearchCmd() {
|
||||
commonflags.Init(objectSearchCmd)
|
||||
commonflags.InitSession(objectSearchCmd)
|
||||
initFlagSession(objectSearchCmd, "SEARCH")
|
||||
|
||||
flags := objectSearchCmd.Flags()
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@ import (
|
|||
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"
|
||||
sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||
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"
|
||||
|
@ -87,50 +89,67 @@ func readOID(cmd *cobra.Command, id *oid.ID) {
|
|||
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 {
|
||||
// SessionPrm is a common interface of object operation's input which supports
|
||||
// sessions.
|
||||
type SessionPrm interface {
|
||||
SetSessionToken(*session.Object)
|
||||
SetClient(*client.Client)
|
||||
}
|
||||
|
||||
// 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 _readVerifiedSession and object as nil.
|
||||
func readSessionGlobal(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID) {
|
||||
_readVerifiedSession(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)
|
||||
// forwards all parameters to _readVerifiedSession.
|
||||
func readSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj oid.ID) {
|
||||
_readVerifiedSession(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:
|
||||
// decodes session.Object from the file by path specified in the
|
||||
// commonflags.SessionToken flag. Returns nil if flag is not set.
|
||||
func getSession(cmd *cobra.Command) *session.Object {
|
||||
common.PrintVerbose("Trying to read session from the file...")
|
||||
|
||||
path, _ := cmd.Flags().GetString(commonflags.SessionToken)
|
||||
if path == "" {
|
||||
common.PrintVerbose("File with session token is not provided.")
|
||||
return nil
|
||||
}
|
||||
|
||||
common.PrintVerbose("Reading session from the file [%s]...", path)
|
||||
|
||||
var tok session.Object
|
||||
|
||||
err := common.ReadBinaryOrJSON(&tok, path)
|
||||
common.ExitOnErr(cmd, "read session: %v", err)
|
||||
|
||||
return &tok
|
||||
}
|
||||
|
||||
// decodes object session from JSON file from commonflags.SessionToken command
|
||||
// flag if it is provided, and writes resulting session into the provided SessionPrm.
|
||||
// Returns flag presence. Checks:
|
||||
//
|
||||
// - if session verb corresponds to given sessionPrm according to its type
|
||||
// - 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 within the command
|
||||
// - session signature
|
||||
//
|
||||
// sessionPrm MUST be one of:
|
||||
// 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) {
|
||||
func _readVerifiedSession(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:
|
||||
|
@ -143,32 +162,125 @@ func _readSession(cmd *cobra.Command, dst sessionPrm, key *ecdsa.PrivateKey, cnr
|
|||
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.")
|
||||
tok := getSession(cmd)
|
||||
if tok == nil {
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// ReadOrOpenSession opens client connection and calls ReadOrOpenSessionViaClient with it.
|
||||
func ReadOrOpenSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) {
|
||||
cli := internal.GetSDKClientByFlag(cmd, key, commonflags.RPC)
|
||||
ReadOrOpenSessionViaClient(cmd, dst, cli, key, cnr, obj)
|
||||
}
|
||||
|
||||
// ReadOrOpenSessionViaClient tries to read session from the file specified in
|
||||
// commonflags.SessionToken flag, finalizes structures of the decoded token
|
||||
// and write the result into provided SessionPrm. If file is missing,
|
||||
// ReadOrOpenSessionViaClient calls OpenSessionViaClient.
|
||||
func ReadOrOpenSessionViaClient(cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) {
|
||||
tok := getSession(cmd)
|
||||
if tok == nil {
|
||||
OpenSessionViaClient(cmd, dst, cli, key, cnr, obj)
|
||||
return
|
||||
}
|
||||
|
||||
finalizeSession(cmd, dst, tok, key, cnr, obj)
|
||||
dst.SetClient(cli)
|
||||
}
|
||||
|
||||
// OpenSession opens client connection and calls OpenSessionViaClient with it.
|
||||
func OpenSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) {
|
||||
cli := internal.GetSDKClientByFlag(cmd, key, commonflags.RPC)
|
||||
OpenSessionViaClient(cmd, dst, cli, key, cnr, obj)
|
||||
}
|
||||
|
||||
// OpenSessionViaClient opens object session with the remote node, finalizes
|
||||
// structure of the session token and writes the result into the provided
|
||||
// SessionPrm. Also writes provided client connection to the SessionPrm.
|
||||
//
|
||||
// SessionPrm MUST be one of:
|
||||
//
|
||||
// *internal.PutObjectPrm
|
||||
// *internal.DeleteObjectPrm
|
||||
func OpenSessionViaClient(cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) {
|
||||
var tok session.Object
|
||||
|
||||
const sessionLifetime = 10 // in NeoFS epochs
|
||||
|
||||
common.PrintVerbose("Opening remote session with the node...")
|
||||
|
||||
err := sessionCli.CreateSession(&tok, cli, sessionLifetime)
|
||||
common.ExitOnErr(cmd, "open remote session: %w", err)
|
||||
|
||||
common.PrintVerbose("Session successfully opened.")
|
||||
|
||||
finalizeSession(cmd, dst, &tok, key, cnr, obj)
|
||||
|
||||
dst.SetClient(cli)
|
||||
}
|
||||
|
||||
// specifies session verb, binds the session to the given container and limits
|
||||
// the session by the given object (if specified). After all data is written,
|
||||
// signs session using provided private key and writes the session into the
|
||||
// given SessionPrm.
|
||||
//
|
||||
// SessionPrm MUST be one of:
|
||||
//
|
||||
// *internal.PutObjectPrm
|
||||
// *internal.DeleteObjectPrm
|
||||
func finalizeSession(cmd *cobra.Command, dst SessionPrm, tok *session.Object, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) {
|
||||
common.PrintVerbose("Finalizing session token...")
|
||||
|
||||
switch dst.(type) {
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported op parameters %T", dst))
|
||||
case *internal.PutObjectPrm:
|
||||
common.PrintVerbose("Binding session to object PUT...")
|
||||
tok.ForVerb(session.VerbObjectPut)
|
||||
case *internal.DeleteObjectPrm:
|
||||
common.PrintVerbose("Binding session to object DELETE...")
|
||||
tok.ForVerb(session.VerbObjectDelete)
|
||||
}
|
||||
|
||||
common.PrintVerbose("Binding session to container %s...", cnr)
|
||||
|
||||
tok.BindContainer(cnr)
|
||||
if obj != nil {
|
||||
common.PrintVerbose("Limiting session by object %s...", obj)
|
||||
tok.LimitByObjects(*obj)
|
||||
}
|
||||
|
||||
common.PrintVerbose("Signing session...")
|
||||
|
||||
err := tok.Sign(*key)
|
||||
common.ExitOnErr(cmd, "sign session: %w", err)
|
||||
|
||||
common.PrintVerbose("Session token successfully formed and attached to the request.")
|
||||
|
||||
dst.SetSessionToken(tok)
|
||||
}
|
||||
|
||||
// calls commonflags.InitSession with "object <verb>" name.
|
||||
func initFlagSession(cmd *cobra.Command, verb string) {
|
||||
commonflags.InitSession(cmd, "object "+verb)
|
||||
}
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"os"
|
||||
|
||||
internalclient "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/client"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// RPCParameters represents parameters for operations with session token.
|
||||
type RPCParameters interface {
|
||||
SetClient(*client.Client)
|
||||
SetSessionToken(*session.Object)
|
||||
}
|
||||
|
||||
const sessionTokenLifetime = 10 // in epochs
|
||||
|
||||
// Prepare prepares session for a command.
|
||||
func Prepare(cmd *cobra.Command, cnr cid.ID, obj *oid.ID, key *ecdsa.PrivateKey, prms ...RPCParameters) {
|
||||
cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC)
|
||||
|
||||
var tok session.Object
|
||||
if tokenPath, _ := cmd.Flags().GetString(commonflags.SessionToken); len(tokenPath) != 0 {
|
||||
data, err := os.ReadFile(tokenPath)
|
||||
common.ExitOnErr(cmd, "can't read session token: %w", err)
|
||||
|
||||
if err := tok.Unmarshal(data); err != nil {
|
||||
err = tok.UnmarshalJSON(data)
|
||||
common.ExitOnErr(cmd, "can't unmarshal session token: %w", err)
|
||||
}
|
||||
} else {
|
||||
err := CreateSession(&tok, cli, sessionTokenLifetime)
|
||||
common.ExitOnErr(cmd, "create session: %w", err)
|
||||
}
|
||||
|
||||
for i := range prms {
|
||||
tok := tok
|
||||
switch prms[i].(type) {
|
||||
case *internalclient.GetObjectPrm:
|
||||
tok.ForVerb(session.VerbObjectGet)
|
||||
case *internalclient.HeadObjectPrm:
|
||||
tok.ForVerb(session.VerbObjectHead)
|
||||
case *internalclient.PutObjectPrm:
|
||||
tok.ForVerb(session.VerbObjectPut)
|
||||
case *internalclient.DeleteObjectPrm:
|
||||
tok.ForVerb(session.VerbObjectDelete)
|
||||
case *internalclient.SearchObjectsPrm:
|
||||
tok.ForVerb(session.VerbObjectSearch)
|
||||
case *internalclient.PayloadRangePrm:
|
||||
tok.ForVerb(session.VerbObjectRange)
|
||||
case *internalclient.HashPayloadRangesPrm:
|
||||
tok.ForVerb(session.VerbObjectRangeHash)
|
||||
default:
|
||||
panic("invalid client parameter type")
|
||||
}
|
||||
|
||||
tok.BindContainer(cnr)
|
||||
if obj != nil {
|
||||
tok.LimitByObjects(*obj)
|
||||
}
|
||||
|
||||
err := tok.Sign(*key)
|
||||
common.ExitOnErr(cmd, "session token signing: %w", err)
|
||||
|
||||
prms[i].SetClient(cli)
|
||||
prms[i].SetSessionToken(&tok)
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key"
|
||||
objectCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/object"
|
||||
sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -40,7 +39,7 @@ func delSG(cmd *cobra.Command, _ []string) {
|
|||
addr := readObjectAddress(cmd, &cnr, &obj)
|
||||
|
||||
var prm internalclient.DeleteObjectPrm
|
||||
sessionCli.Prepare(cmd, cnr, &obj, pk, &prm)
|
||||
objectCli.OpenSession(cmd, &prm, pk, cnr, &obj)
|
||||
objectCli.Prepare(cmd, &prm)
|
||||
prm.SetAddress(addr)
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key"
|
||||
objectCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/object"
|
||||
sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
storagegroupSDK "github.com/nspcc-dev/neofs-sdk-go/storagegroup"
|
||||
|
@ -46,9 +45,11 @@ func getSG(cmd *cobra.Command, _ []string) {
|
|||
pk := key.GetOrGenerate(cmd)
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
||||
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
|
||||
|
||||
var prm internalclient.GetObjectPrm
|
||||
sessionCli.Prepare(cmd, cnr, &obj, pk, &prm)
|
||||
objectCli.Prepare(cmd, &prm)
|
||||
prm.SetClient(cli)
|
||||
|
||||
raw, _ := cmd.Flags().GetBool(sgRawFlag)
|
||||
prm.SetRawFlag(raw)
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key"
|
||||
objectCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/object"
|
||||
sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/storagegroup"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -32,9 +31,11 @@ func listSG(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)
|
||||
objectCli.Prepare(cmd, &prm)
|
||||
prm.SetClient(cli)
|
||||
prm.SetContainerID(cnr)
|
||||
prm.SetFilters(storagegroup.SearchQuery())
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key"
|
||||
objectCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/object"
|
||||
sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/storagegroup"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
|
@ -83,10 +82,11 @@ func putSG(cmd *cobra.Command, _ []string) {
|
|||
resGetCnr, err := internalclient.GetContainer(getCnrPrm)
|
||||
common.ExitOnErr(cmd, "get container RPC call: %w", err)
|
||||
|
||||
sessionCli.Prepare(cmd, cnr, nil, pk, &putPrm)
|
||||
objectCli.OpenSessionViaClient(cmd, &putPrm, cli, pk, cnr, nil)
|
||||
objectCli.Prepare(cmd, &headPrm, &putPrm)
|
||||
|
||||
headPrm.SetRawFlag(true)
|
||||
headPrm.SetClient(cli)
|
||||
|
||||
sg, err := storagegroup.CollectMembers(sgHeadReceiver{
|
||||
cmd: cmd,
|
||||
|
@ -128,9 +128,6 @@ type sgHeadReceiver struct {
|
|||
}
|
||||
|
||||
func (c sgHeadReceiver) Head(addr oid.Address) (interface{}, error) {
|
||||
obj := addr.Object()
|
||||
|
||||
sessionCli.Prepare(c.cmd, addr.Container(), &obj, c.key, &c.prm)
|
||||
c.prm.SetAddress(addr)
|
||||
|
||||
res, err := internalclient.HeadObject(c.prm)
|
||||
|
|
|
@ -42,7 +42,7 @@ func signSessionToken(cmd *cobra.Command, _ []string) {
|
|||
|
||||
type iTokenSession interface {
|
||||
json.Marshaler
|
||||
json.Unmarshaler
|
||||
common.BinaryOrJSON
|
||||
Sign(ecdsa.PrivateKey) error
|
||||
}
|
||||
var errLast error
|
||||
|
@ -52,14 +52,14 @@ func signSessionToken(cmd *cobra.Command, _ []string) {
|
|||
new(session.Object),
|
||||
new(session.Container),
|
||||
} {
|
||||
errLast = common.ReadSessionTokenErr(el, fPath)
|
||||
errLast = common.ReadBinaryOrJSON(el, fPath)
|
||||
if errLast == nil {
|
||||
stok = el
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
common.ExitOnErr(cmd, "", errLast)
|
||||
common.ExitOnErr(cmd, "decode session: %v", errLast)
|
||||
|
||||
pk := key.GetOrGenerate(cmd)
|
||||
|
||||
|
|
Loading…
Reference in a new issue