diff --git a/etcdctl/ctlv3/command/role_command.go b/etcdctl/ctlv3/command/role_command.go index b467a56322b2..469fffb24830 100644 --- a/etcdctl/ctlv3/command/role_command.go +++ b/etcdctl/ctlv3/command/role_command.go @@ -170,11 +170,30 @@ func roleGrantPermissionCommandFunc(cmd *cobra.Command, args []string) { ExitWithError(ExitBadArgs, err) } - rangeEnd, rerr := rangeEndFromPermFlags(args[2:]) - if rerr != nil { - ExitWithError(ExitBadArgs, rerr) + key := args[2] + var rangeEnd string + if len(key) == 0 { + // Range permission is expressed as adt.BytesAffineInterval, + // so the empty prefix which should be matched with every key must be like this ["\x00", ). + key = "\x00" + if rolePermPrefix || rolePermFromKey { + if rolePermPrefix && rolePermFromKey { + ExitWithError(ExitBadArgs, fmt.Errorf("--from-key and --prefix flags are mutually exclusive")) + } + + // For the both cases of prefix and from-key, a permission with an empty key + // should allow access to the entire key space. + // 0x00 will be treated as open ended in server side. + rangeEnd = "\x00" + } + } else { + rangeEnd, err = rangeEndFromPermFlags(args[2:]) + if err != nil { + ExitWithError(ExitBadArgs, err) + } } - resp, err := mustClientFromCmd(cmd).Auth.RoleGrantPermission(context.TODO(), args[0], args[2], rangeEnd, perm) + + resp, err := mustClientFromCmd(cmd).Auth.RoleGrantPermission(context.TODO(), args[0], key, rangeEnd, perm) if err != nil { ExitWithError(ExitError, err) } @@ -188,11 +207,25 @@ func roleRevokePermissionCommandFunc(cmd *cobra.Command, args []string) { ExitWithError(ExitBadArgs, fmt.Errorf("role revoke-permission command requires role name and key [endkey] as its argument.")) } - rangeEnd, rerr := rangeEndFromPermFlags(args[1:]) - if rerr != nil { - ExitWithError(ExitBadArgs, rerr) + key := args[1] + var rangeEnd string + if len(key) == 0 { + // the rule is shared with roleGrantPermissionCommandFunc() + key = "\x00" + if rolePermPrefix || rolePermFromKey { + if rolePermPrefix && rolePermFromKey { + ExitWithError(ExitBadArgs, fmt.Errorf("--from-key and --prefix flags are mutually exclusive")) + } + rangeEnd = "\x00" + } + } else { + var rerr error + rangeEnd, rerr = rangeEndFromPermFlags(args[1:]) + if rerr != nil { + ExitWithError(ExitBadArgs, rerr) + } } - resp, err := mustClientFromCmd(cmd).Auth.RoleRevokePermission(context.TODO(), args[0], args[1], rangeEnd) + resp, err := mustClientFromCmd(cmd).Auth.RoleRevokePermission(context.TODO(), args[0], key, rangeEnd) if err != nil { ExitWithError(ExitError, err) }