From 2e814941c098269f3d8f19858019faee30e0bba5 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 28 May 2021 16:28:50 +0300 Subject: [PATCH] [#560] cli/container: Support session tokens Container sessions allow to perform some operations on behalf of another user. There is a need to to attach session tokens to commands. Add `session` flag to `put`, `delete` and `set-eacl` commands from `container` section. It should be a path to the JSON-encoded session token. Signed-off-by: Leonard Lyubich --- cmd/neofs-cli/modules/container.go | 64 +++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/cmd/neofs-cli/modules/container.go b/cmd/neofs-cli/modules/container.go index 6a7b9c89..6413e0b8 100644 --- a/cmd/neofs-cli/modules/container.go +++ b/cmd/neofs-cli/modules/container.go @@ -22,6 +22,7 @@ import ( "github.com/nspcc-dev/neofs-api-go/pkg/netmap" "github.com/nspcc-dev/neofs-api-go/pkg/object" "github.com/nspcc-dev/neofs-api-go/pkg/owner" + "github.com/nspcc-dev/neofs-api-go/pkg/session" "github.com/nspcc-dev/neofs-sdk-go/pkg/policy" "github.com/spf13/cobra" ) @@ -39,6 +40,11 @@ const ( basicACLPublic = "public-read-write" ) +const sessionTokenFlag = "session" + +// path to a file with encoded session token +var sessionTokenPath string + var ( containerOwner string @@ -154,11 +160,18 @@ It will be stored in sidechain when inner ring will accepts it.`, return err } + tok, err := containerSessionToken() + if err != nil { + return err + } + cnr := container.New() cnr.SetPlacementPolicy(placementPolicy) cnr.SetBasicACL(basicACL) cnr.SetAttributes(attributes) cnr.SetNonceUUID(nonce) + cnr.SetSessionToken(tok) + cnr.SetOwnerID(tok.OwnerID()) id, err := cli.PutContainer(ctx, cnr, globalCallOptions()...) if err != nil { @@ -210,7 +223,18 @@ Only owner of the container has a permission to remove container.`, return err } - err = cli.DeleteContainer(ctx, id, globalCallOptions()...) + tok, err := containerSessionToken() + if err != nil { + return err + } + + callOpts := globalCallOptions() + + if tok != nil { + callOpts = append(callOpts, client.WithSession(tok)) + } + + err = cli.DeleteContainer(ctx, id, callOpts...) if err != nil { return fmt.Errorf("rpc error: %w", err) } @@ -452,7 +476,13 @@ Container ID in EACL table will be substituted with ID from the CLI.`, return err } + tok, err := containerSessionToken() + if err != nil { + return err + } + eaclTable.SetCID(id) + eaclTable.SetSessionToken(tok) err = cli.SetEACL(ctx, eaclTable, globalCallOptions()...) if err != nil { @@ -549,6 +579,38 @@ func init() { setExtendedACLCmd.Flags().StringVar(&containerID, "cid", "", "container ID") setExtendedACLCmd.Flags().StringVar(&eaclPathFrom, "table", "", "path to file with JSON or binary encoded EACL table") setExtendedACLCmd.Flags().BoolVar(&containerAwait, "await", false, "block execution until EACL is persisted") + + for _, cmd := range []*cobra.Command{ + createContainerCmd, + deleteContainerCmd, + setExtendedACLCmd, + } { + cmd.Flags().StringVar( + &sessionTokenPath, + sessionTokenFlag, + "", + "path to a JSON-encoded container session token", + ) + } +} + +func containerSessionToken() (*session.Token, error) { + // try to read session token from file + var tok *session.Token + + if sessionTokenPath != "" { + data, err := ioutil.ReadFile(sessionTokenPath) + if err != nil { + return nil, err + } + + tok = session.NewToken() + if err = tok.UnmarshalJSON(data); err != nil { + return nil, err + } + } + + return tok, nil } func prettyPrintContainerList(list []*container.ID) {