diff --git a/CHANGELOG.md b/CHANGELOG.md index 3903785055..e4df9286ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ Changelog for NeoFS Node - `LOCK` object are stored on every container node (#1502) - `neofs-cli container get-eacl` print ACL table in json format only with arg `--json' (#2012) - Side chain notary deposits use max uint32 as till parameter (#1486) +- Allow object removal without linking object (#2100) +- `neofs-cli container delete` command pre-checks container ownership (#2106) ### Fixed - Open FSTree in sync mode by default (#1992) @@ -68,6 +70,9 @@ The default value is taken from `object.put.pool_size_remote` as in earlier vers Added `neofs_node_object_*_req_count_success` metrics for tracking successfully executed requests. +`neofs-cli container delete` command now requires given account or session issuer +to match the container owner. Use `--force` (`-f`) flag to bypass this requirement. + ## [0.34.0] - 2022-10-31 - Marado (마라도, 馬羅島) ### Added diff --git a/cmd/frostfs-cli/modules/container/delete.go b/cmd/frostfs-cli/modules/container/delete.go index 049d8fb19e..b9c9590711 100644 --- a/cmd/frostfs-cli/modules/container/delete.go +++ b/cmd/frostfs-cli/modules/container/delete.go @@ -9,6 +9,7 @@ import ( "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" objectSDK "github.com/TrueCloudLab/frostfs-sdk-go/object" + "github.com/TrueCloudLab/frostfs-sdk-go/user" "github.com/spf13/cobra" ) @@ -26,6 +27,36 @@ Only owner of the container has a permission to remove container.`, cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) if force, _ := cmd.Flags().GetBool(commonflags.ForceFlag); !force { + common.PrintVerbose("Reading the container to check ownership...") + + var getPrm internalclient.GetContainerPrm + getPrm.SetClient(cli) + getPrm.SetContainer(id) + + resGet, err := internalclient.GetContainer(getPrm) + common.ExitOnErr(cmd, "can't get the container: %w", err) + + owner := resGet.Container().Owner() + + if tok != nil { + common.PrintVerbose("Checking session issuer...") + + if !tok.Issuer().Equals(owner) { + common.ExitOnErr(cmd, "", fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer())) + } + } else { + common.PrintVerbose("Checking provided account...") + + var acc user.ID + user.IDFromKey(&acc, pk.PublicKey) + + if !acc.Equals(owner) { + common.ExitOnErr(cmd, "", fmt.Errorf("provided account differs with the container owner: expected %s, has %s", owner, acc)) + } + } + + common.PrintVerbose("Account matches the container owner.") + fs := objectSDK.NewSearchFilters() fs.AddTypeFilter(objectSDK.MatchStringEqual, objectSDK.TypeLock) @@ -91,5 +122,5 @@ func initContainerDeleteCmd() { flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage) flags.BoolVar(&containerAwait, "await", false, "Block execution until container is removed") - flags.BoolP(commonflags.ForceFlag, commonflags.ForceFlagShorthand, false, "Do not check whether container contains locks and remove immediately") + flags.BoolP(commonflags.ForceFlag, commonflags.ForceFlagShorthand, false, "Skip validation checks (ownership, presence of LOCK objects)") }