forked from TrueCloudLab/frostfs-node
[#1437] neofs-cli: Move util
command to a separate package
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
786c920fb2
commit
dda56f1319
16 changed files with 645 additions and 566 deletions
49
cmd/neofs-cli/internal/common/eacl.go
Normal file
49
cmd/neofs-cli/internal/common/eacl.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/nspcc-dev/neofs-node/pkg/core/version"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||
versionSDK "github.com/nspcc-dev/neofs-sdk-go/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var errUnsupportedEACLFormat = errors.New("unsupported eACL format")
|
||||
|
||||
// ReadEACL reads extended ACL table from eaclPath.
|
||||
func ReadEACL(cmd *cobra.Command, eaclPath string) *eacl.Table {
|
||||
_, err := os.Stat(eaclPath) // check if `eaclPath` is an existing file
|
||||
if err != nil {
|
||||
ExitOnErr(cmd, "", errors.New("incorrect path to file with EACL"))
|
||||
}
|
||||
|
||||
PrintVerbose("Reading EACL from file: %s", eaclPath)
|
||||
|
||||
data, err := os.ReadFile(eaclPath)
|
||||
ExitOnErr(cmd, "can't read file with EACL: %w", err)
|
||||
|
||||
table := eacl.NewTable()
|
||||
|
||||
if err = table.UnmarshalJSON(data); err == nil {
|
||||
validateAndFixEACLVersion(table)
|
||||
PrintVerbose("Parsed JSON encoded EACL table")
|
||||
return table
|
||||
}
|
||||
|
||||
if err = table.Unmarshal(data); err == nil {
|
||||
validateAndFixEACLVersion(table)
|
||||
PrintVerbose("Parsed binary encoded EACL table")
|
||||
return table
|
||||
}
|
||||
|
||||
ExitOnErr(cmd, "", errUnsupportedEACLFormat)
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAndFixEACLVersion(table *eacl.Table) {
|
||||
if !version.IsValid(table.Version()) {
|
||||
table.SetVersion(versionSDK.Current())
|
||||
}
|
||||
}
|
57
cmd/neofs-cli/internal/common/token.go
Normal file
57
cmd/neofs-cli/internal/common/token.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// ReadBearerToken reads bearer token from the path provided in a specified flag.
|
||||
func ReadBearerToken(cmd *cobra.Command, flagname string) *bearer.Token {
|
||||
path, err := cmd.Flags().GetString(flagname)
|
||||
ExitOnErr(cmd, "", err)
|
||||
|
||||
if len(path) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(path)
|
||||
ExitOnErr(cmd, "can't read bearer token file: %w", err)
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
return &tok
|
||||
}
|
||||
|
||||
// ReadSessionToken reads session token as JSON file with session token
|
||||
// from path provided in a specified flag.
|
||||
func ReadSessionToken(cmd *cobra.Command, flag string) *session.Token {
|
||||
// try to read session token from file
|
||||
var tok *session.Token
|
||||
|
||||
path, err := cmd.Flags().GetString(flag)
|
||||
ExitOnErr(cmd, "", err)
|
||||
|
||||
if path == "" {
|
||||
return tok
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(path)
|
||||
ExitOnErr(cmd, "could not open file with session token: %w", err)
|
||||
|
||||
tok = session.NewToken()
|
||||
err = tok.UnmarshalJSON(data)
|
||||
ExitOnErr(cmd, "could not ummarshal session token from file: %w", err)
|
||||
|
||||
return tok
|
||||
}
|
|
@ -16,7 +16,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-node/pkg/core/version"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/acl"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
|
@ -25,7 +24,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/policy"
|
||||
"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"
|
||||
versionSDK "github.com/nspcc-dev/neofs-sdk-go/version"
|
||||
|
@ -91,10 +89,9 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
errDeleteTimeout = errors.New("timeout: container has not been removed from sidechain")
|
||||
errCreateTimeout = errors.New("timeout: container has not been persisted on sidechain")
|
||||
errSetEACLTimeout = errors.New("timeout: EACL has not been persisted on sidechain")
|
||||
errUnsupportedEACLFormat = errors.New("unsupported eACL format")
|
||||
errDeleteTimeout = errors.New("timeout: container has not been removed from sidechain")
|
||||
errCreateTimeout = errors.New("timeout: container has not been persisted on sidechain")
|
||||
errSetEACLTimeout = errors.New("timeout: EACL has not been persisted on sidechain")
|
||||
)
|
||||
|
||||
// containerCmd represents the container command
|
||||
|
@ -161,9 +158,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
|
|||
nonce, err := parseNonce(containerNonce)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
tok, err := getSessionToken(sessionTokenPath)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
tok := common.ReadSessionToken(cmd, sessionTokenFlag)
|
||||
key := key.GetOrGenerate(cmd)
|
||||
|
||||
var idOwner *user.ID
|
||||
|
@ -228,8 +223,7 @@ Only owner of the container has a permission to remove container.`,
|
|||
id, err := parseContainerID(containerID)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
tok, err := getSessionToken(sessionTokenPath)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
tok := common.ReadSessionToken(cmd, sessionTokenFlag)
|
||||
|
||||
var (
|
||||
delPrm internalclient.DeleteContainerPrm
|
||||
|
@ -416,11 +410,9 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
|
|||
id, err := parseContainerID(containerID)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
eaclTable, err := parseEACL(eaclPathFrom)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
eaclTable := common.ReadEACL(cmd, eaclPathFrom)
|
||||
|
||||
tok, err := getSessionToken(sessionTokenPath)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
tok := common.ReadSessionToken(cmd, sessionTokenFlag)
|
||||
|
||||
eaclTable.SetCID(*id)
|
||||
eaclTable.SetSessionToken(tok)
|
||||
|
@ -591,26 +583,6 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
// getSessionToken reads `<path>` as JSON file with session token and parses it.
|
||||
func getSessionToken(path string) (*session.Token, error) {
|
||||
// try to read session token from file
|
||||
var tok *session.Token
|
||||
|
||||
if path != "" {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not open file with session token: %w", err)
|
||||
}
|
||||
|
||||
tok = session.NewToken()
|
||||
if err = tok.UnmarshalJSON(data); err != nil {
|
||||
return nil, fmt.Errorf("could not ummarshal session token from file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tok, nil
|
||||
}
|
||||
|
||||
func prettyPrintContainerList(cmd *cobra.Command, list []cid.ID) {
|
||||
for i := range list {
|
||||
cmd.Println(list[i].String())
|
||||
|
@ -787,42 +759,6 @@ func prettyPrintContainer(cmd *cobra.Command, cnr *container.Container, jsonEnco
|
|||
cmd.Println(strings.Join(policy.Encode(cnr.PlacementPolicy()), "\n"))
|
||||
}
|
||||
|
||||
func parseEACL(eaclPath string) (*eacl.Table, error) {
|
||||
_, err := os.Stat(eaclPath) // check if `eaclPath` is an existing file
|
||||
if err != nil {
|
||||
return nil, errors.New("incorrect path to file with EACL")
|
||||
}
|
||||
|
||||
common.PrintVerbose("Reading EACL from file: %s", eaclPath)
|
||||
|
||||
data, err := os.ReadFile(eaclPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't read file with EACL: %w", err)
|
||||
}
|
||||
|
||||
table := eacl.NewTable()
|
||||
|
||||
if err = table.UnmarshalJSON(data); err == nil {
|
||||
validateAndFixEACLVersion(table)
|
||||
common.PrintVerbose("Parsed JSON encoded EACL table")
|
||||
return table, nil
|
||||
}
|
||||
|
||||
if err = table.Unmarshal(data); err == nil {
|
||||
validateAndFixEACLVersion(table)
|
||||
common.PrintVerbose("Parsed binary encoded EACL table")
|
||||
return table, nil
|
||||
}
|
||||
|
||||
return nil, errUnsupportedEACLFormat
|
||||
}
|
||||
|
||||
func validateAndFixEACLVersion(table *eacl.Table) {
|
||||
if !version.IsValid(table.Version()) {
|
||||
table.SetVersion(versionSDK.Current())
|
||||
}
|
||||
}
|
||||
|
||||
func prettyPrintEACL(cmd *cobra.Command, table *eacl.Table) {
|
||||
common.PrettyPrintJSON(cmd, table, "eACL")
|
||||
}
|
||||
|
@ -837,3 +773,14 @@ func prettyPrintBasicACL(cmd *cobra.Command, basicACL acl.BasicACL) {
|
|||
}
|
||||
cmd.Println()
|
||||
}
|
||||
|
||||
func prettyPrintUnixTime(s string) string {
|
||||
unixTime, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return "malformed"
|
||||
}
|
||||
|
||||
timestamp := time.Unix(unixTime, 0)
|
||||
|
||||
return timestamp.String()
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
"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/bearer"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/checksum"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
|
@ -1110,31 +1109,6 @@ func marshalHeader(cmd *cobra.Command, hdr *object.Object) ([]byte, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func getBearerToken(cmd *cobra.Command, flagname string) (*bearer.Token, error) {
|
||||
path, err := cmd.Flags().GetString(flagname)
|
||||
if err != nil || len(path) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't read bearer token file: %w", err)
|
||||
}
|
||||
|
||||
var tok bearer.Token
|
||||
if err := tok.UnmarshalJSON(data); err != nil {
|
||||
if err = tok.Unmarshal(data); err != nil {
|
||||
return nil, fmt.Errorf("can't decode bearer token: %w", err)
|
||||
}
|
||||
|
||||
common.PrintVerbose("Using binary encoded bearer token")
|
||||
} else {
|
||||
common.PrintVerbose("Using JSON encoded bearer token")
|
||||
}
|
||||
|
||||
return &tok, nil
|
||||
}
|
||||
|
||||
func getObjectRange(cmd *cobra.Command, _ []string) {
|
||||
objAddr, err := getObjectAddress(cmd)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
bearerCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/bearer"
|
||||
controlCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/control"
|
||||
sessionCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/session"
|
||||
utilCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/util"
|
||||
"github.com/nspcc-dev/neofs-node/misc"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/util/gendoc"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||
|
@ -95,6 +96,7 @@ func init() {
|
|||
rootCmd.AddCommand(sessionCli.Cmd)
|
||||
rootCmd.AddCommand(accountingCli.Cmd)
|
||||
rootCmd.AddCommand(controlCli.Cmd)
|
||||
rootCmd.AddCommand(utilCli.Cmd)
|
||||
rootCmd.AddCommand(gendoc.Command(rootCmd))
|
||||
}
|
||||
|
||||
|
@ -164,8 +166,7 @@ type bearerPrm interface {
|
|||
}
|
||||
|
||||
func prepareBearerPrm(cmd *cobra.Command, prm bearerPrm) {
|
||||
btok, err := getBearerToken(cmd, bearerTokenFlag)
|
||||
common.ExitOnErr(cmd, "bearer token: %w", err)
|
||||
btok := common.ReadBearerToken(cmd, bearerTokenFlag)
|
||||
|
||||
prm.SetBearerToken(btok)
|
||||
}
|
||||
|
|
|
@ -1,467 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"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-node/pkg/util/keyer"
|
||||
locodedb "github.com/nspcc-dev/neofs-node/pkg/util/locode/db"
|
||||
airportsdb "github.com/nspcc-dev/neofs-node/pkg/util/locode/db/airports"
|
||||
locodebolt "github.com/nspcc-dev/neofs-node/pkg/util/locode/db/boltdb"
|
||||
continentsdb "github.com/nspcc-dev/neofs-node/pkg/util/locode/db/continents/geojson"
|
||||
csvlocode "github.com/nspcc-dev/neofs-node/pkg/util/locode/table/csv"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var errKeyerSingleArgument = errors.New("pass only one argument at a time")
|
||||
|
||||
var (
|
||||
utilCmd = &cobra.Command{
|
||||
Use: "util",
|
||||
Short: "Utility operations",
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
flags := cmd.Flags()
|
||||
|
||||
_ = viper.BindPFlag(commonflags.GenerateKey, flags.Lookup(commonflags.GenerateKey))
|
||||
_ = viper.BindPFlag(commonflags.WalletPath, flags.Lookup(commonflags.WalletPath))
|
||||
_ = viper.BindPFlag(commonflags.Account, flags.Lookup(commonflags.Account))
|
||||
},
|
||||
}
|
||||
|
||||
signCmd = &cobra.Command{
|
||||
Use: "sign",
|
||||
Short: "Sign NeoFS structure",
|
||||
}
|
||||
|
||||
signBearerCmd = &cobra.Command{
|
||||
Use: "bearer-token",
|
||||
Short: "Sign bearer token to use it in requests",
|
||||
Run: signBearerToken,
|
||||
}
|
||||
|
||||
signSessionCmd = &cobra.Command{
|
||||
Use: "session-token",
|
||||
Short: "Sign session token to use it in requests",
|
||||
Run: signSessionToken,
|
||||
}
|
||||
|
||||
convertCmd = &cobra.Command{
|
||||
Use: "convert",
|
||||
Short: "Convert representation of NeoFS structures",
|
||||
}
|
||||
|
||||
convertEACLCmd = &cobra.Command{
|
||||
Use: "eacl",
|
||||
Short: "Convert representation of extended ACL table",
|
||||
Run: convertEACLTable,
|
||||
}
|
||||
|
||||
keyerCmd = &cobra.Command{
|
||||
Use: "keyer",
|
||||
Short: "Generate or print information about keys",
|
||||
Run: processKeyer,
|
||||
}
|
||||
)
|
||||
|
||||
// locode section
|
||||
var locodeCmd = &cobra.Command{
|
||||
Use: "locode",
|
||||
Short: "Working with NeoFS UN/LOCODE database",
|
||||
}
|
||||
|
||||
const (
|
||||
locodeGenerateInputFlag = "in"
|
||||
locodeGenerateSubDivFlag = "subdiv"
|
||||
locodeGenerateAirportsFlag = "airports"
|
||||
locodeGenerateCountriesFlag = "countries"
|
||||
locodeGenerateContinentsFlag = "continents"
|
||||
locodeGenerateOutputFlag = "out"
|
||||
)
|
||||
|
||||
type namesDB struct {
|
||||
*airportsdb.DB
|
||||
*csvlocode.Table
|
||||
}
|
||||
|
||||
var (
|
||||
locodeGenerateInPaths []string
|
||||
locodeGenerateSubDivPath string
|
||||
locodeGenerateAirportsPath string
|
||||
locodeGenerateCountriesPath string
|
||||
locodeGenerateContinentsPath string
|
||||
locodeGenerateOutPath string
|
||||
|
||||
locodeGenerateCmd = &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "generate UN/LOCODE database for NeoFS",
|
||||
Run: func(cmd *cobra.Command, _ []string) {
|
||||
locodeDB := csvlocode.New(
|
||||
csvlocode.Prm{
|
||||
Path: locodeGenerateInPaths[0],
|
||||
SubDivPath: locodeGenerateSubDivPath,
|
||||
},
|
||||
csvlocode.WithExtraPaths(locodeGenerateInPaths[1:]...),
|
||||
)
|
||||
|
||||
airportDB := airportsdb.New(airportsdb.Prm{
|
||||
AirportsPath: locodeGenerateAirportsPath,
|
||||
CountriesPath: locodeGenerateCountriesPath,
|
||||
})
|
||||
|
||||
continentsDB := continentsdb.New(continentsdb.Prm{
|
||||
Path: locodeGenerateContinentsPath,
|
||||
})
|
||||
|
||||
targetDB := locodebolt.New(locodebolt.Prm{
|
||||
Path: locodeGenerateOutPath,
|
||||
})
|
||||
|
||||
err := targetDB.Open()
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
defer targetDB.Close()
|
||||
|
||||
names := &namesDB{
|
||||
DB: airportDB,
|
||||
Table: locodeDB,
|
||||
}
|
||||
|
||||
err = locodedb.FillDatabase(locodeDB, airportDB, continentsDB, names, targetDB)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
locodeInfoDBFlag = "db"
|
||||
locodeInfoCodeFlag = "locode"
|
||||
)
|
||||
|
||||
var (
|
||||
locodeInfoDBPath string
|
||||
locodeInfoCode string
|
||||
|
||||
locodeInfoCmd = &cobra.Command{
|
||||
Use: "info",
|
||||
Short: "print information about UN/LOCODE from NeoFS database",
|
||||
Run: func(cmd *cobra.Command, _ []string) {
|
||||
targetDB := locodebolt.New(locodebolt.Prm{
|
||||
Path: locodeInfoDBPath,
|
||||
}, locodebolt.ReadOnly())
|
||||
|
||||
err := targetDB.Open()
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
defer targetDB.Close()
|
||||
|
||||
record, err := locodedb.LocodeRecord(targetDB, locodeInfoCode)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
cmd.Printf("Country: %s\n", record.CountryName())
|
||||
cmd.Printf("Location: %s\n", record.LocationName())
|
||||
cmd.Printf("Continent: %s\n", record.Continent())
|
||||
if subDivCode := record.SubDivCode(); subDivCode != "" {
|
||||
cmd.Printf("Subdivision: [%s] %s\n", subDivCode, record.SubDivName())
|
||||
}
|
||||
|
||||
geoPoint := record.GeoPoint()
|
||||
cmd.Printf("Coordinates: %0.2f, %0.2f\n", geoPoint.Latitude(), geoPoint.Longitude())
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func initUtilKeyerCmd() {
|
||||
keyerCmd.Flags().BoolP("generate", "g", false, "generate new private key")
|
||||
keyerCmd.Flags().Bool("hex", false, "print all values in hex encoding")
|
||||
keyerCmd.Flags().BoolP("uncompressed", "u", false, "use uncompressed public key format")
|
||||
keyerCmd.Flags().BoolP("multisig", "m", false, "calculate multisig address from public keys")
|
||||
}
|
||||
|
||||
func initUtilSignBearerCmd() {
|
||||
commonflags.InitWithoutRPC(signBearerCmd)
|
||||
|
||||
flags := signBearerCmd.Flags()
|
||||
|
||||
flags.String("from", "", "File with JSON or binary encoded bearer token to sign")
|
||||
_ = signBearerCmd.MarkFlagFilename("from")
|
||||
_ = signBearerCmd.MarkFlagRequired("from")
|
||||
|
||||
flags.String("to", "", "File to dump signed bearer token (default: binary encoded)")
|
||||
flags.Bool("json", false, "Dump bearer token in JSON encoding")
|
||||
}
|
||||
|
||||
func initUtilSignSessionCmd() {
|
||||
commonflags.InitWithoutRPC(signSessionCmd)
|
||||
|
||||
flags := signSessionCmd.Flags()
|
||||
|
||||
flags.String("from", "", "File with JSON encoded session token to sign")
|
||||
_ = signSessionCmd.MarkFlagFilename("from")
|
||||
_ = signSessionCmd.MarkFlagRequired("from")
|
||||
|
||||
flags.String("to", "", "File to save signed session token (optional)")
|
||||
}
|
||||
|
||||
func initUtilConvertEACLCmd() {
|
||||
flags := convertEACLCmd.Flags()
|
||||
|
||||
flags.String("from", "", "File with JSON or binary encoded extended ACL table")
|
||||
_ = convertEACLCmd.MarkFlagFilename("from")
|
||||
_ = convertEACLCmd.MarkFlagRequired("from")
|
||||
|
||||
flags.String("to", "", "File to dump extended ACL table (default: binary encoded)")
|
||||
flags.Bool("json", false, "Dump extended ACL table in JSON encoding")
|
||||
}
|
||||
|
||||
func initUtilLocodeGenerateCmd() {
|
||||
flags := locodeGenerateCmd.Flags()
|
||||
|
||||
flags.StringSliceVar(&locodeGenerateInPaths, locodeGenerateInputFlag, nil, "List of paths to UN/LOCODE tables (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateInputFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateSubDivPath, locodeGenerateSubDivFlag, "", "Path to UN/LOCODE subdivision database (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateSubDivFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateAirportsPath, locodeGenerateAirportsFlag, "", "Path to OpenFlights airport database (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateAirportsFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateCountriesPath, locodeGenerateCountriesFlag, "", "Path to OpenFlights country database (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateCountriesFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateContinentsPath, locodeGenerateContinentsFlag, "", "Path to continent polygons (GeoJSON)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateContinentsFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateOutPath, locodeGenerateOutputFlag, "", "Target path for generated database")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateOutputFlag)
|
||||
}
|
||||
|
||||
func initUtilLocodeInfoCmd() {
|
||||
flags := locodeInfoCmd.Flags()
|
||||
|
||||
flags.StringVar(&locodeInfoDBPath, locodeInfoDBFlag, "", "Path to NeoFS UN/LOCODE database")
|
||||
_ = locodeInfoCmd.MarkFlagRequired(locodeInfoDBFlag)
|
||||
|
||||
flags.StringVar(&locodeInfoCode, locodeInfoCodeFlag, "", "UN/LOCODE")
|
||||
_ = locodeInfoCmd.MarkFlagRequired(locodeInfoCodeFlag)
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(utilCmd)
|
||||
|
||||
utilCmd.AddCommand(
|
||||
signCmd,
|
||||
convertCmd,
|
||||
keyerCmd,
|
||||
locodeCmd,
|
||||
)
|
||||
|
||||
signCmd.AddCommand(signBearerCmd, signSessionCmd)
|
||||
convertCmd.AddCommand(convertEACLCmd)
|
||||
locodeCmd.AddCommand(locodeGenerateCmd, locodeInfoCmd)
|
||||
|
||||
initUtilKeyerCmd()
|
||||
|
||||
initUtilSignBearerCmd()
|
||||
initUtilSignSessionCmd()
|
||||
|
||||
initUtilConvertEACLCmd()
|
||||
|
||||
initUtilLocodeInfoCmd()
|
||||
initUtilLocodeGenerateCmd()
|
||||
}
|
||||
|
||||
func signBearerToken(cmd *cobra.Command, _ []string) {
|
||||
btok, err := getBearerToken(cmd, "from")
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
pk := key.GetOrGenerate(cmd)
|
||||
|
||||
err = btok.Sign(*pk)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
to := cmd.Flag("to").Value.String()
|
||||
jsonFlag, _ := cmd.Flags().GetBool("json")
|
||||
|
||||
var data []byte
|
||||
if jsonFlag || len(to) == 0 {
|
||||
data, err = btok.MarshalJSON()
|
||||
common.ExitOnErr(cmd, "can't JSON encode bearer token: %w", err)
|
||||
} else {
|
||||
data = btok.Marshal()
|
||||
}
|
||||
|
||||
if len(to) == 0 {
|
||||
prettyPrintJSON(cmd, data)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = os.WriteFile(to, data, 0644)
|
||||
common.ExitOnErr(cmd, "can't write signed bearer token to file: %w", err)
|
||||
|
||||
cmd.Printf("signed bearer token was successfully dumped to %s\n", to)
|
||||
}
|
||||
|
||||
func signSessionToken(cmd *cobra.Command, _ []string) {
|
||||
path, err := cmd.Flags().GetString("from")
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
stok, err := getSessionToken(path)
|
||||
if err != nil {
|
||||
common.ExitOnErr(cmd, "", fmt.Errorf("can't read session token from %s: %w", path, err))
|
||||
}
|
||||
|
||||
pk := key.GetOrGenerate(cmd)
|
||||
|
||||
err = stok.Sign(pk)
|
||||
common.ExitOnErr(cmd, "can't sign token: %w", err)
|
||||
|
||||
data, err := stok.MarshalJSON()
|
||||
common.ExitOnErr(cmd, "can't encode session token: %w", err)
|
||||
|
||||
to := cmd.Flag("to").Value.String()
|
||||
if len(to) == 0 {
|
||||
prettyPrintJSON(cmd, data)
|
||||
return
|
||||
}
|
||||
|
||||
err = os.WriteFile(to, data, 0644)
|
||||
if err != nil {
|
||||
common.ExitOnErr(cmd, "", fmt.Errorf("can't write signed session token to %s: %w", to, err))
|
||||
}
|
||||
|
||||
cmd.Printf("signed session token saved in %s\n", to)
|
||||
}
|
||||
|
||||
func convertEACLTable(cmd *cobra.Command, _ []string) {
|
||||
pathFrom := cmd.Flag("from").Value.String()
|
||||
to := cmd.Flag("to").Value.String()
|
||||
jsonFlag, _ := cmd.Flags().GetBool("json")
|
||||
|
||||
table, err := parseEACL(pathFrom)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
var data []byte
|
||||
if jsonFlag || len(to) == 0 {
|
||||
data, err = table.MarshalJSON()
|
||||
common.ExitOnErr(cmd, "can't JSON encode extended ACL table: %w", err)
|
||||
} else {
|
||||
data, err = table.Marshal()
|
||||
common.ExitOnErr(cmd, "can't binary encode extended ACL table: %w", err)
|
||||
}
|
||||
|
||||
if len(to) == 0 {
|
||||
prettyPrintJSON(cmd, data)
|
||||
return
|
||||
}
|
||||
err = os.WriteFile(to, data, 0644)
|
||||
common.ExitOnErr(cmd, "can't write exteded ACL table to file: %w", err)
|
||||
|
||||
cmd.Printf("extended ACL table was successfully dumped to %s\n", to)
|
||||
}
|
||||
|
||||
func processKeyer(cmd *cobra.Command, args []string) {
|
||||
var (
|
||||
err error
|
||||
|
||||
result = new(keyer.Dashboard)
|
||||
generate, _ = cmd.Flags().GetBool("generate")
|
||||
useHex, _ = cmd.Flags().GetBool("hex")
|
||||
uncompressed, _ = cmd.Flags().GetBool("uncompressed")
|
||||
multisig, _ = cmd.Flags().GetBool("multisig")
|
||||
)
|
||||
|
||||
if multisig {
|
||||
err = result.ParseMultiSig(args)
|
||||
} else {
|
||||
if len(args) > 1 {
|
||||
common.ExitOnErr(cmd, "", errKeyerSingleArgument)
|
||||
}
|
||||
|
||||
var argument string
|
||||
if len(args) > 0 {
|
||||
argument = args[0]
|
||||
}
|
||||
|
||||
switch {
|
||||
case generate:
|
||||
err = keyerGenerate(argument, result)
|
||||
case fileExists(argument):
|
||||
err = keyerParseFile(argument, result)
|
||||
default:
|
||||
err = result.ParseString(argument)
|
||||
}
|
||||
}
|
||||
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
result.PrettyPrint(uncompressed, useHex)
|
||||
}
|
||||
|
||||
func prettyPrintJSON(cmd *cobra.Command, data []byte) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := json.Indent(buf, data, "", " "); err != nil {
|
||||
common.PrintVerbose("Can't pretty print json: %w", err)
|
||||
}
|
||||
|
||||
cmd.Println(buf)
|
||||
}
|
||||
|
||||
func prettyPrintUnixTime(s string) string {
|
||||
unixTime, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return "malformed"
|
||||
}
|
||||
|
||||
timestamp := time.Unix(unixTime, 0)
|
||||
|
||||
return timestamp.String()
|
||||
}
|
||||
|
||||
func keyerGenerate(filename string, d *keyer.Dashboard) error {
|
||||
key := make([]byte, keyer.NeoPrivateKeySize)
|
||||
|
||||
_, err := rand.Read(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't get random source: %w", err)
|
||||
}
|
||||
|
||||
err = d.ParseBinary(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't parse key: %w", err)
|
||||
}
|
||||
|
||||
if filename != "" {
|
||||
return os.WriteFile(filename, key, 0600)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fileExists(filename string) bool {
|
||||
info, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
|
||||
return !info.IsDir()
|
||||
}
|
||||
|
||||
func keyerParseFile(filename string, d *keyer.Dashboard) error {
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't open %v file: %w", filename, err)
|
||||
}
|
||||
|
||||
return d.ParseBinary(data)
|
||||
}
|
14
cmd/neofs-cli/modules/util/convert.go
Normal file
14
cmd/neofs-cli/modules/util/convert.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package util
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
var convertCmd = &cobra.Command{
|
||||
Use: "convert",
|
||||
Short: "Convert representation of NeoFS structures",
|
||||
}
|
||||
|
||||
func initConvertCmd() {
|
||||
convertCmd.AddCommand(convertEACLCmd)
|
||||
|
||||
initConvertEACLCmd()
|
||||
}
|
64
cmd/neofs-cli/modules/util/convert_eacl.go
Normal file
64
cmd/neofs-cli/modules/util/convert_eacl.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var convertEACLCmd = &cobra.Command{
|
||||
Use: "eacl",
|
||||
Short: "Convert representation of extended ACL table",
|
||||
Run: convertEACLTable,
|
||||
}
|
||||
|
||||
func initConvertEACLCmd() {
|
||||
flags := convertEACLCmd.Flags()
|
||||
|
||||
flags.String("from", "", "File with JSON or binary encoded extended ACL table")
|
||||
_ = convertEACLCmd.MarkFlagFilename("from")
|
||||
_ = convertEACLCmd.MarkFlagRequired("from")
|
||||
|
||||
flags.String("to", "", "File to dump extended ACL table (default: binary encoded)")
|
||||
flags.Bool("json", false, "Dump extended ACL table in JSON encoding")
|
||||
}
|
||||
|
||||
func convertEACLTable(cmd *cobra.Command, _ []string) {
|
||||
pathFrom := cmd.Flag("from").Value.String()
|
||||
to := cmd.Flag("to").Value.String()
|
||||
jsonFlag, _ := cmd.Flags().GetBool("json")
|
||||
|
||||
table := common.ReadEACL(cmd, pathFrom)
|
||||
|
||||
var data []byte
|
||||
var err error
|
||||
if jsonFlag || len(to) == 0 {
|
||||
data, err = table.MarshalJSON()
|
||||
common.ExitOnErr(cmd, "can't JSON encode extended ACL table: %w", err)
|
||||
} else {
|
||||
data, err = table.Marshal()
|
||||
common.ExitOnErr(cmd, "can't binary encode extended ACL table: %w", err)
|
||||
}
|
||||
|
||||
if len(to) == 0 {
|
||||
prettyPrintJSON(cmd, data)
|
||||
return
|
||||
}
|
||||
|
||||
err = os.WriteFile(to, data, 0644)
|
||||
common.ExitOnErr(cmd, "can't write exteded ACL table to file: %w", err)
|
||||
|
||||
cmd.Printf("extended ACL table was successfully dumped to %s\n", to)
|
||||
}
|
||||
|
||||
func prettyPrintJSON(cmd *cobra.Command, data []byte) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := json.Indent(buf, data, "", " "); err != nil {
|
||||
common.PrintVerbose("Can't pretty print json: %w", err)
|
||||
}
|
||||
|
||||
cmd.Println(buf)
|
||||
}
|
99
cmd/neofs-cli/modules/util/keyer.go
Normal file
99
cmd/neofs-cli/modules/util/keyer.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/util/keyer"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var keyerCmd = &cobra.Command{
|
||||
Use: "keyer",
|
||||
Short: "Generate or print information about keys",
|
||||
Run: processKeyer,
|
||||
}
|
||||
|
||||
var errKeyerSingleArgument = errors.New("pass only one argument at a time")
|
||||
|
||||
func initKeyerCmd() {
|
||||
keyerCmd.Flags().BoolP("generate", "g", false, "generate new private key")
|
||||
keyerCmd.Flags().Bool("hex", false, "print all values in hex encoding")
|
||||
keyerCmd.Flags().BoolP("uncompressed", "u", false, "use uncompressed public key format")
|
||||
keyerCmd.Flags().BoolP("multisig", "m", false, "calculate multisig address from public keys")
|
||||
}
|
||||
|
||||
func processKeyer(cmd *cobra.Command, args []string) {
|
||||
var (
|
||||
err error
|
||||
|
||||
result = new(keyer.Dashboard)
|
||||
generate, _ = cmd.Flags().GetBool("generate")
|
||||
useHex, _ = cmd.Flags().GetBool("hex")
|
||||
uncompressed, _ = cmd.Flags().GetBool("uncompressed")
|
||||
multisig, _ = cmd.Flags().GetBool("multisig")
|
||||
)
|
||||
|
||||
if multisig {
|
||||
err = result.ParseMultiSig(args)
|
||||
} else {
|
||||
if len(args) > 1 {
|
||||
common.ExitOnErr(cmd, "", errKeyerSingleArgument)
|
||||
}
|
||||
|
||||
var argument string
|
||||
if len(args) > 0 {
|
||||
argument = args[0]
|
||||
}
|
||||
|
||||
switch {
|
||||
case generate:
|
||||
err = keyerGenerate(argument, result)
|
||||
case fileExists(argument):
|
||||
err = keyerParseFile(argument, result)
|
||||
default:
|
||||
err = result.ParseString(argument)
|
||||
}
|
||||
}
|
||||
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
result.PrettyPrint(uncompressed, useHex)
|
||||
}
|
||||
|
||||
func keyerGenerate(filename string, d *keyer.Dashboard) error {
|
||||
key := make([]byte, keyer.NeoPrivateKeySize)
|
||||
|
||||
_, err := rand.Read(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't get random source: %w", err)
|
||||
}
|
||||
|
||||
err = d.ParseBinary(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't parse key: %w", err)
|
||||
}
|
||||
|
||||
if filename != "" {
|
||||
return os.WriteFile(filename, key, 0600)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fileExists(filename string) bool {
|
||||
info, err := os.Stat(filename)
|
||||
return !os.IsNotExist(err) && !info.IsDir()
|
||||
}
|
||||
|
||||
func keyerParseFile(filename string, d *keyer.Dashboard) error {
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't open %v file: %w", filename, err)
|
||||
}
|
||||
|
||||
return d.ParseBinary(data)
|
||||
}
|
18
cmd/neofs-cli/modules/util/locode.go
Normal file
18
cmd/neofs-cli/modules/util/locode.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// locode section
|
||||
var locodeCmd = &cobra.Command{
|
||||
Use: "locode",
|
||||
Short: "Working with NeoFS UN/LOCODE database",
|
||||
}
|
||||
|
||||
func initLocodeCmd() {
|
||||
locodeCmd.AddCommand(locodeGenerateCmd, locodeInfoCmd)
|
||||
|
||||
initUtilLocodeInfoCmd()
|
||||
initUtilLocodeGenerateCmd()
|
||||
}
|
96
cmd/neofs-cli/modules/util/locode_generate.go
Normal file
96
cmd/neofs-cli/modules/util/locode_generate.go
Normal file
|
@ -0,0 +1,96 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
|
||||
locodedb "github.com/nspcc-dev/neofs-node/pkg/util/locode/db"
|
||||
airportsdb "github.com/nspcc-dev/neofs-node/pkg/util/locode/db/airports"
|
||||
locodebolt "github.com/nspcc-dev/neofs-node/pkg/util/locode/db/boltdb"
|
||||
continentsdb "github.com/nspcc-dev/neofs-node/pkg/util/locode/db/continents/geojson"
|
||||
csvlocode "github.com/nspcc-dev/neofs-node/pkg/util/locode/table/csv"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type namesDB struct {
|
||||
*airportsdb.DB
|
||||
*csvlocode.Table
|
||||
}
|
||||
|
||||
const (
|
||||
locodeGenerateInputFlag = "in"
|
||||
locodeGenerateSubDivFlag = "subdiv"
|
||||
locodeGenerateAirportsFlag = "airports"
|
||||
locodeGenerateCountriesFlag = "countries"
|
||||
locodeGenerateContinentsFlag = "continents"
|
||||
locodeGenerateOutputFlag = "out"
|
||||
)
|
||||
|
||||
var (
|
||||
locodeGenerateInPaths []string
|
||||
locodeGenerateSubDivPath string
|
||||
locodeGenerateAirportsPath string
|
||||
locodeGenerateCountriesPath string
|
||||
locodeGenerateContinentsPath string
|
||||
locodeGenerateOutPath string
|
||||
|
||||
locodeGenerateCmd = &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "generate UN/LOCODE database for NeoFS",
|
||||
Run: func(cmd *cobra.Command, _ []string) {
|
||||
locodeDB := csvlocode.New(
|
||||
csvlocode.Prm{
|
||||
Path: locodeGenerateInPaths[0],
|
||||
SubDivPath: locodeGenerateSubDivPath,
|
||||
},
|
||||
csvlocode.WithExtraPaths(locodeGenerateInPaths[1:]...),
|
||||
)
|
||||
|
||||
airportDB := airportsdb.New(airportsdb.Prm{
|
||||
AirportsPath: locodeGenerateAirportsPath,
|
||||
CountriesPath: locodeGenerateCountriesPath,
|
||||
})
|
||||
|
||||
continentsDB := continentsdb.New(continentsdb.Prm{
|
||||
Path: locodeGenerateContinentsPath,
|
||||
})
|
||||
|
||||
targetDB := locodebolt.New(locodebolt.Prm{
|
||||
Path: locodeGenerateOutPath,
|
||||
})
|
||||
|
||||
err := targetDB.Open()
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
defer targetDB.Close()
|
||||
|
||||
names := &namesDB{
|
||||
DB: airportDB,
|
||||
Table: locodeDB,
|
||||
}
|
||||
|
||||
err = locodedb.FillDatabase(locodeDB, airportDB, continentsDB, names, targetDB)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func initUtilLocodeGenerateCmd() {
|
||||
flags := locodeGenerateCmd.Flags()
|
||||
|
||||
flags.StringSliceVar(&locodeGenerateInPaths, locodeGenerateInputFlag, nil, "List of paths to UN/LOCODE tables (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateInputFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateSubDivPath, locodeGenerateSubDivFlag, "", "Path to UN/LOCODE subdivision database (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateSubDivFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateAirportsPath, locodeGenerateAirportsFlag, "", "Path to OpenFlights airport database (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateAirportsFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateCountriesPath, locodeGenerateCountriesFlag, "", "Path to OpenFlights country database (csv)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateCountriesFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateContinentsPath, locodeGenerateContinentsFlag, "", "Path to continent polygons (GeoJSON)")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateContinentsFlag)
|
||||
|
||||
flags.StringVar(&locodeGenerateOutPath, locodeGenerateOutputFlag, "", "Target path for generated database")
|
||||
_ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateOutputFlag)
|
||||
}
|
56
cmd/neofs-cli/modules/util/locode_info.go
Normal file
56
cmd/neofs-cli/modules/util/locode_info.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
|
||||
locodedb "github.com/nspcc-dev/neofs-node/pkg/util/locode/db"
|
||||
locodebolt "github.com/nspcc-dev/neofs-node/pkg/util/locode/db/boltdb"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
locodeInfoDBFlag = "db"
|
||||
locodeInfoCodeFlag = "locode"
|
||||
)
|
||||
|
||||
var (
|
||||
locodeInfoDBPath string
|
||||
locodeInfoCode string
|
||||
|
||||
locodeInfoCmd = &cobra.Command{
|
||||
Use: "info",
|
||||
Short: "print information about UN/LOCODE from NeoFS database",
|
||||
Run: func(cmd *cobra.Command, _ []string) {
|
||||
targetDB := locodebolt.New(locodebolt.Prm{
|
||||
Path: locodeInfoDBPath,
|
||||
}, locodebolt.ReadOnly())
|
||||
|
||||
err := targetDB.Open()
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
defer targetDB.Close()
|
||||
|
||||
record, err := locodedb.LocodeRecord(targetDB, locodeInfoCode)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
cmd.Printf("Country: %s\n", record.CountryName())
|
||||
cmd.Printf("Location: %s\n", record.LocationName())
|
||||
cmd.Printf("Continent: %s\n", record.Continent())
|
||||
if subDivCode := record.SubDivCode(); subDivCode != "" {
|
||||
cmd.Printf("Subdivision: [%s] %s\n", subDivCode, record.SubDivName())
|
||||
}
|
||||
|
||||
geoPoint := record.GeoPoint()
|
||||
cmd.Printf("Coordinates: %0.2f, %0.2f\n", geoPoint.Latitude(), geoPoint.Longitude())
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func initUtilLocodeInfoCmd() {
|
||||
flags := locodeInfoCmd.Flags()
|
||||
|
||||
flags.StringVar(&locodeInfoDBPath, locodeInfoDBFlag, "", "Path to NeoFS UN/LOCODE database")
|
||||
_ = locodeInfoCmd.MarkFlagRequired(locodeInfoDBFlag)
|
||||
|
||||
flags.StringVar(&locodeInfoCode, locodeInfoCodeFlag, "", "UN/LOCODE")
|
||||
_ = locodeInfoCmd.MarkFlagRequired(locodeInfoCodeFlag)
|
||||
}
|
33
cmd/neofs-cli/modules/util/root.go
Normal file
33
cmd/neofs-cli/modules/util/root.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var Cmd = &cobra.Command{
|
||||
Use: "util",
|
||||
Short: "Utility operations",
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
flags := cmd.Flags()
|
||||
|
||||
_ = viper.BindPFlag(commonflags.GenerateKey, flags.Lookup(commonflags.GenerateKey))
|
||||
_ = viper.BindPFlag(commonflags.WalletPath, flags.Lookup(commonflags.WalletPath))
|
||||
_ = viper.BindPFlag(commonflags.Account, flags.Lookup(commonflags.Account))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
Cmd.AddCommand(
|
||||
signCmd,
|
||||
convertCmd,
|
||||
keyerCmd,
|
||||
locodeCmd,
|
||||
)
|
||||
|
||||
initSignCmd()
|
||||
initConvertCmd()
|
||||
initKeyerCmd()
|
||||
initLocodeCmd()
|
||||
}
|
22
cmd/neofs-cli/modules/util/sign.go
Normal file
22
cmd/neofs-cli/modules/util/sign.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
signFromFlag = "from"
|
||||
signToFlag = "to"
|
||||
)
|
||||
|
||||
var signCmd = &cobra.Command{
|
||||
Use: "sign",
|
||||
Short: "Sign NeoFS structure",
|
||||
}
|
||||
|
||||
func initSignCmd() {
|
||||
signCmd.AddCommand(signBearerCmd, signSessionCmd)
|
||||
|
||||
initSignBearerCmd()
|
||||
initSignSessionCmd()
|
||||
}
|
63
cmd/neofs-cli/modules/util/sign_bearer.go
Normal file
63
cmd/neofs-cli/modules/util/sign_bearer.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"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/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
signBearerJSONFlag = "json"
|
||||
)
|
||||
|
||||
var signBearerCmd = &cobra.Command{
|
||||
Use: "bearer-token",
|
||||
Short: "Sign bearer token to use it in requests",
|
||||
Run: signBearerToken,
|
||||
}
|
||||
|
||||
func initSignBearerCmd() {
|
||||
commonflags.InitWithoutRPC(signBearerCmd)
|
||||
|
||||
flags := signBearerCmd.Flags()
|
||||
|
||||
flags.String(signFromFlag, "", "File with JSON or binary encoded bearer token to sign")
|
||||
_ = signBearerCmd.MarkFlagFilename(signFromFlag)
|
||||
_ = signBearerCmd.MarkFlagRequired(signFromFlag)
|
||||
|
||||
flags.String(signToFlag, "", "File to dump signed bearer token (default: binary encoded)")
|
||||
flags.Bool(signBearerJSONFlag, false, "Dump bearer token in JSON encoding")
|
||||
}
|
||||
|
||||
func signBearerToken(cmd *cobra.Command, _ []string) {
|
||||
btok := common.ReadBearerToken(cmd, signFromFlag)
|
||||
pk := key.GetOrGenerate(cmd)
|
||||
|
||||
err := btok.Sign(*pk)
|
||||
common.ExitOnErr(cmd, "", err)
|
||||
|
||||
to := cmd.Flag(signToFlag).Value.String()
|
||||
jsonFlag, _ := cmd.Flags().GetBool(signBearerJSONFlag)
|
||||
|
||||
var data []byte
|
||||
if jsonFlag || len(to) == 0 {
|
||||
data, err = btok.MarshalJSON()
|
||||
common.ExitOnErr(cmd, "can't JSON encode bearer token: %w", err)
|
||||
} else {
|
||||
data = btok.Marshal()
|
||||
}
|
||||
|
||||
if len(to) == 0 {
|
||||
prettyPrintJSON(cmd, data)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = os.WriteFile(to, data, 0644)
|
||||
common.ExitOnErr(cmd, "can't write signed bearer token to file: %w", err)
|
||||
|
||||
cmd.Printf("signed bearer token was successfully dumped to %s\n", to)
|
||||
}
|
53
cmd/neofs-cli/modules/util/sign_session.go
Normal file
53
cmd/neofs-cli/modules/util/sign_session.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"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/spf13/cobra"
|
||||
)
|
||||
|
||||
var signSessionCmd = &cobra.Command{
|
||||
Use: "session-token",
|
||||
Short: "Sign session token to use it in requests",
|
||||
Run: signSessionToken,
|
||||
}
|
||||
|
||||
func initSignSessionCmd() {
|
||||
commonflags.InitWithoutRPC(signSessionCmd)
|
||||
|
||||
flags := signSessionCmd.Flags()
|
||||
|
||||
flags.String(signFromFlag, "", "File with JSON encoded session token to sign")
|
||||
_ = signSessionCmd.MarkFlagFilename(signFromFlag)
|
||||
_ = signSessionCmd.MarkFlagRequired(signFromFlag)
|
||||
|
||||
flags.String(signToFlag, "", "File to save signed session token (optional)")
|
||||
}
|
||||
|
||||
func signSessionToken(cmd *cobra.Command, _ []string) {
|
||||
stok := common.ReadSessionToken(cmd, signFromFlag)
|
||||
pk := key.GetOrGenerate(cmd)
|
||||
|
||||
err := stok.Sign(pk)
|
||||
common.ExitOnErr(cmd, "can't sign token: %w", err)
|
||||
|
||||
data, err := stok.MarshalJSON()
|
||||
common.ExitOnErr(cmd, "can't encode session token: %w", err)
|
||||
|
||||
to := cmd.Flag(signToFlag).Value.String()
|
||||
if len(to) == 0 {
|
||||
prettyPrintJSON(cmd, data)
|
||||
return
|
||||
}
|
||||
|
||||
err = os.WriteFile(to, data, 0644)
|
||||
if err != nil {
|
||||
common.ExitOnErr(cmd, "", fmt.Errorf("can't write signed session token to %s: %w", to, err))
|
||||
}
|
||||
|
||||
cmd.Printf("signed session token saved in %s\n", to)
|
||||
}
|
Loading…
Reference in a new issue