diff --git a/CHANGELOG.md b/CHANGELOG.md index 0641cc509e..b730b3bd11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Changelog for NeoFS Node - Support for 0.20.0+ neofs-contract archive format (#2872) - `neofs-cli control object status` command (#2886) - Check the account alongside the public key in ACL (#2883) +- Allow addresses to be used in EACLs created from CLI (#2914) ### Fixed - Control service's Drop call does not clean metabase (#2822) diff --git a/cmd/neofs-cli/modules/acl/extended/create.go b/cmd/neofs-cli/modules/acl/extended/create.go index b46c43cfba..92d4fc2dbd 100644 --- a/cmd/neofs-cli/modules/acl/extended/create.go +++ b/cmd/neofs-cli/modules/acl/extended/create.go @@ -41,7 +41,8 @@ Target is 'user' for container owner, 'system' for Storage nodes in container and Inner Ring nodes, 'others' for all other request senders, - 'pubkey:,,...' for exact request sender, where is a hex-encoded 33-byte public key. + 'pubkey:,,...' for exact request sender, where is a hex-encoded 33-byte public key, + 'address:,,...' for exact request sender, where is a base58 25-byte address. Example: NSiVJYZej4XsxG5CUpdwn7VRQk8iiiDMPM. When both '--rule' and '--file' arguments are used, '--rule' records will be placed higher in resulting extended ACL table. `, diff --git a/cmd/neofs-cli/modules/acl/extended/create_test.go b/cmd/neofs-cli/modules/acl/extended/create_test.go index 4af985c5c2..d09d976a22 100644 --- a/cmd/neofs-cli/modules/acl/extended/create_test.go +++ b/cmd/neofs-cli/modules/acl/extended/create_test.go @@ -29,6 +29,11 @@ func TestParseTable(t *testing.T) { rule: "deny getrange pubkey:036410abb260bbbda89f61c0cad65a4fa15ac5cb83b3c3abf8aee403856fcf65ed", jsonRecord: `{"operation":"GETRANGE","action":"DENY","filters":[],"targets":[{"role":"ROLE_UNSPECIFIED","keys":["A2QQq7Jgu72on2HAytZaT6FaxcuDs8Or+K7kA4Vvz2Xt"]}]}`, }, + { + name: "valid rule with account", + rule: "deny getrange address:NWcSSzMkw5Vuq3gFmcih5yfCNxfXjWdKz8", + jsonRecord: `{"operation":"GETRANGE","action":"DENY","filters":[],"targets":[{"role":"ROLE_UNSPECIFIED","keys":["NXVYp24sheVFxW8PazdLtZEvUM/gLAhtqQ=="]}]}`, + }, { name: "missing action", rule: "get obj:a=b others", @@ -57,6 +62,10 @@ func TestParseTable(t *testing.T) { name: "invalid public key", rule: "deny get obj:a=b pubkey:0123", }, + { + name: "invalid account", + rule: "deny get obj:a=b account:1234", + }, } eaclTable := eacl.NewTable() diff --git a/cmd/neofs-cli/modules/util/acl.go b/cmd/neofs-cli/modules/util/acl.go index 360a1a0043..7c7bd8eb6b 100644 --- a/cmd/neofs-cli/modules/util/acl.go +++ b/cmd/neofs-cli/modules/util/acl.go @@ -14,6 +14,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neofs-sdk-go/container/acl" "github.com/nspcc-dev/neofs-sdk-go/eacl" + "github.com/nspcc-dev/neofs-sdk-go/user" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" ) @@ -276,7 +277,24 @@ func parseEACLRecord(args []string) (*eacl.Record, error) { } eacl.AddFormedTarget(r, role, pubs...) + case "address": // targets + var ( + err error + accounts []user.ID + ) + if len(ss) != 2 { + return nil, fmt.Errorf("invalid address: %s", args[i]) + } + + accounts, err = parseAccountList(ss[1]) + if err != nil { + return nil, err + } + + t := eacl.NewTarget() + t.SetAccounts(accounts) + eacl.AddRecordTarget(r, t) default: return nil, fmt.Errorf("invalid prefix: %s", ss[0]) } @@ -363,6 +381,23 @@ func parseKeyList(s string) ([]ecdsa.PublicKey, error) { return pubs, nil } +func parseAccountList(s string) ([]user.ID, error) { + parts := strings.Split(s, ",") + accounts := make([]user.ID, len(parts)) + + for i := range parts { + st := strings.TrimSpace(parts[i]) + acc, err := user.DecodeString(st) + if err != nil { + return nil, fmt.Errorf("invalid account %q: %w", parts[i], err) + } + + accounts[i] = acc + } + + return accounts, nil +} + // eaclOperationsFromString parses list of eacl.Operation separated by comma. func eaclOperationsFromString(s string) ([]eacl.Operation, error) { ss := strings.Split(s, ",")