From 491a908af1364d9d990caf0fc4ac0d65074bfb50 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Wed, 17 Aug 2022 14:22:05 +0400 Subject: [PATCH] [#1652] cli/container: Pre-check ACL extensibility in `set-eacl` Container ACL in NeoFS can be extended only for container in which the corresponding option is enabled. In previous implementation command `set-eacl` could hang up on modifying eACL of the non-existent or non-extendable container. To improve UX, there is a need to pre-check the availability of `SETEACL` operation. Add boolean `precheck` flag to `set-eacl` cmd which reads the container before the actual transaction formation. If flag is set, command fails on non-extendable container ACL. Signed-off-by: Leonard Lyubich --- cmd/neofs-cli/internal/client/client.go | 15 +++++++++++++++ cmd/neofs-cli/modules/container/set_eacl.go | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/cmd/neofs-cli/internal/client/client.go b/cmd/neofs-cli/internal/client/client.go index 5178d968..c9485637 100644 --- a/cmd/neofs-cli/internal/client/client.go +++ b/cmd/neofs-cli/internal/client/client.go @@ -131,6 +131,21 @@ func GetContainer(prm GetContainerPrm) (res GetContainerRes, err error) { return } +// IsACLExtendable checks if ACL of the container referenced by the given identifier +// can be extended. Client connection MUST BE correctly established in advance. +func IsACLExtendable(c *client.Client, cnr cid.ID) (bool, error) { + var prm GetContainerPrm + prm.SetClient(c) + prm.SetContainer(cnr) + + res, err := GetContainer(prm) + if err != nil { + return false, fmt.Errorf("get container from the NeoFS: %w", err) + } + + return res.Container().BasicACL().Extendable(), nil +} + // DeleteContainerPrm groups parameters of DeleteContainerPrm operation. type DeleteContainerPrm struct { commonPrm diff --git a/cmd/neofs-cli/modules/container/set_eacl.go b/cmd/neofs-cli/modules/container/set_eacl.go index 4bb82b9c..22fc7ec5 100644 --- a/cmd/neofs-cli/modules/container/set_eacl.go +++ b/cmd/neofs-cli/modules/container/set_eacl.go @@ -2,6 +2,7 @@ package container import ( "bytes" + "errors" "time" internalclient "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client" @@ -14,6 +15,10 @@ import ( var eaclPathFrom string +var flagVarsSetEACL struct { + preCheck bool +} + var setExtendedACLCmd = &cobra.Command{ Use: "set-eacl", Short: "Set new extended ACL table for container", @@ -36,6 +41,19 @@ Container ID in EACL table will be substituted with ID from the CLI.`, pk := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + if flagVarsSetEACL.preCheck { + cmd.Println("Checking the ability to modify access rights in the container...") + + extendable, err := internalclient.IsACLExtendable(cli, id) + common.ExitOnErr(cmd, "Extensibility check failure: %w", err) + + if !extendable { + common.ExitOnErr(cmd, "", errors.New("container ACL is immutable")) + } + + cmd.Println("ACL extension is enabled in the container, continue processing.") + } + var setEACLPrm internalclient.SetEACLPrm setEACLPrm.SetClient(cli) setEACLPrm.SetTable(*eaclTable) @@ -88,4 +106,5 @@ func initContainerSetEACLCmd() { flags.StringVar(&containerID, "cid", "", "container ID") flags.StringVar(&eaclPathFrom, "table", "", "path to file with JSON or binary encoded EACL table") flags.BoolVar(&containerAwait, "await", false, "block execution until EACL is persisted") + flags.BoolVar(&flagVarsSetEACL.preCheck, "precheck", false, "pre-check the extensibility of the container ACL") }