diff --git a/cmd/neofs-cli/modules/root.go b/cmd/neofs-cli/modules/root.go index 0978ccf2..555a9327 100644 --- a/cmd/neofs-cli/modules/root.go +++ b/cmd/neofs-cli/modules/root.go @@ -16,6 +16,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/acl" + tokenCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/token" "github.com/nspcc-dev/neofs-node/misc" "github.com/nspcc-dev/neofs-node/pkg/network" "github.com/nspcc-dev/neofs-sdk-go/client" @@ -126,6 +127,7 @@ func init() { rootCmd.Flags().Bool("version", false, "Application version and NeoFS API compatibility") rootCmd.AddCommand(acl.Cmd) + rootCmd.AddCommand(tokenCli.Cmd) } func entryPoint(cmd *cobra.Command, _ []string) { diff --git a/cmd/neofs-cli/modules/token/create.go b/cmd/neofs-cli/modules/token/create.go new file mode 100644 index 00000000..1f9489d8 --- /dev/null +++ b/cmd/neofs-cli/modules/token/create.go @@ -0,0 +1,98 @@ +package token + +import ( + "encoding/json" + "fmt" + "io/ioutil" + + eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl" + "github.com/nspcc-dev/neofs-sdk-go/owner" + "github.com/nspcc-dev/neofs-sdk-go/token" + "github.com/spf13/cobra" +) + +const ( + eaclFlag = "eacl" + issuedAtFlag = "issued-at" + notValidBeforeFlag = "not-valid-before" + expireAtFlag = "expire-at" + ownerFlag = "owner" + outFlag = "out" + jsonFlag = "json" +) + +var createCmd = &cobra.Command{ + Use: "create", + Short: "Create bearer token", + RunE: createToken, +} + +func init() { + createCmd.Flags().StringP(eaclFlag, "e", "", "path to the extended ACL table") + createCmd.Flags().Uint64P(issuedAtFlag, "i", 0, "epoch to issue token at") + createCmd.Flags().Uint64P(notValidBeforeFlag, "n", 0, "not valid before epoch") + createCmd.Flags().Uint64P(expireAtFlag, "x", 0, "expiration epoch") + createCmd.Flags().StringP(ownerFlag, "o", "", "token owner") + createCmd.Flags().String(outFlag, "", "file to write token to") + createCmd.Flags().Bool(jsonFlag, false, "output token in JSON") + + _ = cobra.MarkFlagFilename(createCmd.Flags(), eaclFlag) + + _ = cobra.MarkFlagRequired(createCmd.Flags(), issuedAtFlag) + _ = cobra.MarkFlagRequired(createCmd.Flags(), notValidBeforeFlag) + _ = cobra.MarkFlagRequired(createCmd.Flags(), expireAtFlag) + _ = cobra.MarkFlagRequired(createCmd.Flags(), ownerFlag) + _ = cobra.MarkFlagRequired(createCmd.Flags(), outFlag) +} + +func createToken(cmd *cobra.Command, _ []string) error { + iat, _ := cmd.Flags().GetUint64(issuedAtFlag) + exp, _ := cmd.Flags().GetUint64(expireAtFlag) + nvb, _ := cmd.Flags().GetUint64(notValidBeforeFlag) + if exp < nvb { + return fmt.Errorf("expiration epoch is less than not-valid-before epoch: %d < %d", exp, nvb) + } + + ownerStr, _ := cmd.Flags().GetString(ownerFlag) + ownerID := owner.NewID() + if err := ownerID.Parse(ownerStr); err != nil { + return fmt.Errorf("can't parse recipient: %w", err) + } + + b := token.NewBearerToken() + b.SetLifetime(exp, nvb, iat) + b.SetOwner(ownerID) + + eaclPath, _ := cmd.Flags().GetString(eaclFlag) + if eaclPath != "" { + table := eaclSDK.NewTable() + raw, err := ioutil.ReadFile(eaclPath) + if err != nil { + return fmt.Errorf("can't read extended ACL file: %w", err) + } + if err := json.Unmarshal(raw, table); err != nil { + return fmt.Errorf("can't parse extended ACL: %w", err) + } + b.SetEACLTable(table) + } + + var data []byte + var err error + + toJSON, _ := cmd.Flags().GetBool(jsonFlag) + if toJSON { + data, err = json.Marshal(b) + } else { + data, err = b.Marshal(nil) + } + if err != nil { + return fmt.Errorf("can't mashal token: %w", err) + } + + out, _ := cmd.Flags().GetString(outFlag) + if err := ioutil.WriteFile(out, data, 0644); err != nil { + return fmt.Errorf("can't write token to file: %w", err) + } + + return nil +} diff --git a/cmd/neofs-cli/modules/token/root.go b/cmd/neofs-cli/modules/token/root.go new file mode 100644 index 00000000..fb25534a --- /dev/null +++ b/cmd/neofs-cli/modules/token/root.go @@ -0,0 +1,14 @@ +package token + +import ( + "github.com/spf13/cobra" +) + +var Cmd = &cobra.Command{ + Use: "token", + Short: "Operations with bearer token", +} + +func init() { + Cmd.AddCommand(createCmd) +}