Redis【有与无】【Admin-7】Redis访问控制列表(ACL)...

本文基于Redis 6.0.9版本,前提至少 Redis 3.0或更高版本。

目录

1.ACL(Redis Access Control Lists)

1.1.什么时候ACL有用

1.2.使用ACL命令配置ACL

1.3.ACL规则

1.4.使用ACL SETUSER命令创建和编辑用户ACL

1.5.多次调用ACL SETUSER会发生什么

1.6.Playings命令类别

1.7.添加子命令

1.8.+@all VS -@all

1.9.内部如何存储密码

1.10.使用外部ACL文件

1.11.前哨(Sentinel)和复制节点(Replicas)的ACL规则

1.12.本文档的待办事项清单


1.ACL(Redis Access Control Lists)

Redis ACL是Access Control List(访问控制列表)的缩写,该功能允许根据可以执行的命令和可以访问的键来限制某些连接。 在连接之后,它的工作方式是需要客户端进行身份验证,以提供用户名和有效密码:如果身份验证阶段成功,则连接与给定用户关联,并且该用户具有限制。可以对Redis进行配置,以便新连接已经通过“default”用户进行身份验证(这是默认配置),因此,配置默认用户具有的能力是,仅向未明确认证的连接提供特定功能子集的功能。

在默认配置中,Redis 6(第一个具有ACL的版本)的工作方式与Redis的旧版本完全相同,也就是说,每个新连接都能够调用每个可能的命令并访问每个键,因此ACL功能与旧版本向后兼容。 客户和应用程序。 同样,使用requirepass配置指令配置密码的旧方法仍然可以按预期方式工作,但是现在它所要做的只是为默认用户设置密码。

Redis AUTH 命令在Redis 6中进行了扩展,因此现在可以在两个参数的形式中使用它:

AUTH <username> <password>

按照旧形式使用时,即:

AUTH <password>

发生的是用于认证的用户名是“default”,因此仅指定密码就意味着我们要针对默认用户进行认证。 这提供了与过去的完美向后兼容性。

1.1.什么时候ACL有用

在使用ACL之前,你可能会问自己,要实现此保护层要实现的目标是什么。 通常,ACL可以很好地实现两个主要目标:

  • 你希望通过限制对命令和键的访问来提高安全性,以便不受信任的客户端无法访问,而受信任的客户端仅具有对数据库的最低访问级别才能执行所需的工作。 例如,某些客户端可能仅能够执行只读命令。
  • 你想提高操作安全性,以便由于软件错误或人为错误,不允许进程或人员访问Redis,以免损坏数据或配置。 例如,没有必要让工作人员从Redis获取延迟的作业来调用FLUSHALL命令。

ACL的另一种典型用法与托管Redis实例有关。 Redis通常由管理内部Redis基础结构的内部公司团队为其所拥有的其他内部客户提供的一项托管服务,或者由云提供商在软件即服务设置中提供。 在这两种设置中,我们都希望确保为客户排除配置命令。 过去通过命令重命名来完成此操作的方式是一种技巧,它使我们能够长时间不用ACL生存下来,但并不理想。

1.2.使用ACL命令配置ACL

ACL是使用DSL(域特定语言domain specific language)定义的,该DSL描述了给定用户能够执行的操作。 此类规则始终从左到右从第一个到最后一个实施,因为有时规则的顺序对于理解用户的实际能力很重要。

默认情况下,只有一个用户定义,称为default。 我们可以使用 ACL LIST命令来检查当前活动的ACL并验证新启动的,默认配置的Redis实例的配置是:

> ACL LIST
1) "user default on nopass ~* &* +@all"

上面的命令通过将为用户设置的当前ACL转换回其描述中,以与Redis配置文件中使用的格式相同的格式报告用户列表。

每行的前两个单词是“user”,后跟用户名。 接下来的单词是描述不同事物的ACL规则。 我们将详细显示规则的工作方式,但现在足以说明默认用户已配置为活动状态(on),不需要密码(nopass),访问所有可能的键(~*)和 发布/订阅(Pub/Sub)频道(&*),并能够调用所有可能的命令(+@all)。

同样,在默认用户的特殊情况下,具有nopass规则意味着新连接将自动与默认用户进行身份验证,而无需任何显式的AUTH调用。

1.3.ACL规则

以下是有效的ACL规则的列表。 某些规则只是一个单词,用于激活或删除标志或对用户ACL执行给定的更改。 其他规则是与命令或类别名称、键模式等、关联的字符前缀。

启用和禁用用户:

  • on: 启用用户:可以验证为该用户。
  • off: 禁用该用户:无法再与此用户进行身份验证,但是已经身份验证的连接仍然可以使用。 请注意,如果默认用户被标记为关闭,则新连接将不会通过身份验证开始,并且将要求用户发送带有AUTH选项的AUTHHELLO,以便以某种方式进行身份验证,而与默认用户配置无关。

允许和禁止命令:

  • +<command>: 将命令添加到用户可以调用的命令列表中。
  • -<command>: 将命令删除到用户可以调用的命令列表中。
  • +@<category>: 添加该类别中要由用户调用的所有命令,有效类别为@admin, @set, @sortedset等,请通过调用ACL CAT命令查看完整列表。 特殊类别@all表示所有命令,包括当前在服务器中存在的命令,以及将来将通过模块加载的命令。
  • -@<category>: 类似于+@<category>,但是从客户端可以调用的命令列表中删除命令。
  • +<command>|subcommand: 允许使用本来禁用的命令的特定子命令。 请注意,此格式不允许像-DEBUG|SEGFAULT那样为负数,而只能以“+”开头。 如果命令在整体上已经处于活动状态,则此ACL将导致错误。
  • allcommands: +@all的别名。 请注意,这意味着可以执行将来通过模块系统加载的所有命令。
  • nocommands: -@all的别名。

允许和禁止某些键:

  • ~<pattern>: 添加可以在命令中提及的键模式。 例如 ~* 允许所有键。 该模式是一种球形样式的模式,类似于KEYS之一。 可以指定多个模式。
  • allkeys: ~*的别名.
  • resetkeys: 刷新允许的键模式列表。 例如ACL~foo:* ~bar:* resetkeys ~objects:*,将导致客户端只能访问与模式objects:*匹配的键。

允许和禁止发布/订阅(Pub/Sub)频道:

  • &<pattern>: 添加用户可以访问的Pub/Sub通道的全局样式模式。 可以指定多个通道模式。 请注意,仅对PUBLISH 和SUBSCRIBE提及的通道进行模式匹配,而PSUBSCRIBE 需要在其通道模式与用户允许的通道模式之间进行文字匹配。
  • allchannels: &*的别名,允许用户访问所有Pub/Sub通道。
  • resetchannels: 刷新允许的频道模式列表,如果用户的Pub/Sub客户端不再能够访问其各自的频道and/or频道模式,则断开其连接。

为用户配置有效密码:

  • ><password>: 将此密码添加到用户的有效密码列表中。 例如,>mypass会将“mypass”添加到有效密码列表中。 该指令清除nopass标志(请参阅下文)。 每个用户可以具有任意数量的密码。
  • <<password>: 从有效密码列表中删除此密码。 万一实际上你未设置要删除的密码,则会发出错误消息。
  • #<hash>: 将此SHA-256哈希值添加到用户的有效密码列表中。 该哈希值将与为ACL用户输入的密码的哈希值进行比较。 这允许用户将哈希存储在acl.conf文件中,而不是存储明文密码。 仅接受SHA-256哈希值,因为密码哈希必须为64个字符,并且只能为容器的小写十六进制字符。
  • !<hash>: 从有效密码列表中删除该哈希值。 当你不知道哈希值指定的密码但想从用户中删除密码时,这很有用。
  • nopass: 用户的所有设置密码都将被删除,并且该用户被标记为不需要密码:这意味着每个密码都将对该用户起作用。 如果此指令用于默认用户,则每个新连接都将立即通过默认用户进行身份验证,而无需任何显式的AUTH命令。 请注意,resetpass指令将清除此情况。
  • resetpass: 刷新允许的密码列表。 此外删除Nopass状态。 重置密码后,用户没有关联的密码,并且没有添加一些密码(或将密码设置为更高密码)就无法进行身份验证。

注意:未使用nopass进行标记且没有有效密码列表的使用实际上是无法使用的,因为将无法以该用户身份登录。

重置用户:

  • reset 执行以下操作:resetpass, resetkeys, resetchannels, off, -@all。 用户返回到创建后立即具有的相同状态。

1.4.使用ACL SETUSER命令创建和编辑用户ACL

可以通过两种主要方式来创建和修改用户:

  • 使用ACL命令及其ACL SETUSER子命令。
  • 修改服务器配置(可以在其中定义用户)并重新启动服务器,或者如果我们使用的是外部ACL文件,则只需发出ACL LOAD

在本节中,我们将学习如何使用ACL命令定义用户。 有了这样的知识,通过配置文件执行相同的操作将变得很简单。 在配置中定义用户值得一小节,稍后将单独讨论。

首先,让我们尝试最简单的ACL SETUSER命令调用:

> ACL SETUSER alice
OK

SETUSER命令采用用户名和要应用于用户的ACL规则列表。 但是在上面的示例中,我根本没有指定任何规则。 如果不存在该用户,它将使用新用户的默认值来创建该用户。 如果用户已经存在,则上面的命令将不执行任何操作。

让我们检查一下默认的用户状态:

> ACL LIST
1) "user alice off &* -@all"
2) "user default on nopass ~* ~& +@all"

刚创建的用户“alice”是:

  • 处于关闭状态,即已禁用。 AUTH将不起作用。
  • 用户也没有设置密码。
  • 无法访问任何命令。 请注意,默认情况下,该用户是默认创建的,无法访问任何命令,因此可以忽略上面输出中的-@all,但是ACL LIST尝试是显式的而不是隐式的。
  • 没有用户可以访问的键模式。
  • 用户可以访问所有发布/订阅(Pub/Sub)频道。

默认情况下,使用限制性权限创建新用户。 从Redis 6.2开始,ACL还提供发布/订阅(Pub/Sub)通道访问管理。 为了确保在升级到Redis 6.2时与版本6.0向后兼容,默认情况下,新用户被授予“allchannels”权限。 可以通过acl-pubsub-default配置指令将默认值设置为resetchannels 。

这样的用户是完全无用的。 让我们尝试定义用户,使其处于活动状态,具有密码并只能使用GET 命令访问以字符串“cached:”开头的键名称。

> ACL SETUSER alice on >p1pp0 ~cached:* +get
OK

现在,用户可以执行某些操作,但是会拒绝执行其他操作:

> AUTH alice p1pp0
OK
> GET foo
(error) NOPERM this user has no permissions to access one of the keys used as arguments
> GET cached:1234
(nil)
> SET cached:1234 zap
(error) NOPERM this user has no permissions to run the 'set' command or its subcommand

事情按预期进行。 为了检查用户alice的配置(请记住用户名区分大小写),可以使用ACL LIST的替代方法,该替代方法被设计为更适合计算机读取,而ACL LIST则更偏向于人的使用方式。

> ACL GETUSER alice
1) "flags"
2) 1) "on"
   2) "allchannels"
3) "passwords"
4) 1) "2d9c75..."
5) "commands"
6) "-@all +get"
7) "keys"
8) 1) "cached:*"
9) "channels"
10) 1) "*"

ACL GETUSER返回一个字段值数组,该字段值数组以更可解析的术语描述用户。 输出包括标志集,键模式列表,密码等。 如果使用RESP3,则输出的可读性可能更高,因此,将其作为map回复返回:

> ACL GETUSER alice
1# "flags" => 1~ "on"
   2~ "allchannels"
2# "passwords" => 1) "2d9c75273d72b32df726fb545c8a4edc719f0a95a6fd993950b10c474ad9c927"
3# "commands" => "-@all +get"
4# "keys" => 1) "cached:*"
5# "channels" => 1) "*"

注意:从现在开始,我们将继续使用Redis默认协议版本2,因为社区切换到新协议会花费一些时间。

使用另一个ACL SETUSER命令(来自其他用户,因为alice无法运行ACL命令),我们可以向用户添加多个模式:

> ACL SETUSER alice ~objects:* ~items:* ~public:*
OK
> ACL LIST
1) "user alice on >2d9c75... ~cached:* ~objects:* ~items:* ~public:* &* -@all +get"
2) "user default on nopass ~* &* +@all"

内存中的用户表示现在已达到我们的预期。

1.5.多次调用ACL SETUSER会发生什么

了解多次调用ACL SETUSER会发生什么非常重要。 重要的是要知道,每个SETUSER调用都不会重置用户,而只会将ACL规则应用于现有用户。 仅在以前不知道的情况下才重置用户:在这种情况下,将使用zeroed-ACLs创建一个全新的用户,即该用户无法执行任何操作,被禁用,没有密码等等:为了安全起见,这是最佳的默认设置。

但是,以后的调用只会逐步修改用户,因此例如以下顺序:

> ACL SETUSER myuser +set
OK
> ACL SETUSER myuser +get
OK

将导致myuser能够调用GET 和SET

> ACL LIST
1) "user default on nopass ~* &* +@all"
2) "user myuser off &* -@all +set +get"

1.6.Playings命令类别

通过一个接一个地指定所有命令来设置用户ACL确实很烦人,所以我们这样做:

> ACL SETUSER antirez on +@all -@dangerous >42a979... ~*

通过+@all 和-@dangerous,我们包含了所有命令,然后在Redis命令表中删除了所有标记为危险的命令。 请注意,除了+@all外,命令类别从不包含模块命令。 如果+@all,则所有命令都可以由用户执行,甚至将来的命令也可以通过模块系统加载。 但是,如果使用ACL规则+@read或其他任何规则,则始终会排除modules命令。 这非常重要,因为你应该信任Redis内部命令表以保持理智。 模块可能会暴露出危险的东西,并且在ACL只是附加的情况下,即以+@all -...的形式存在。你应该绝对确保你永远不会包含你不想要的内容。

但是要记住要定义类别,并且每个类别确切包含的命令是不可能的,并且会很无聊,因此Redis ACL命令导出CAT子命令,该命令可以两种形式使用:

ACL CAT -- Will just list all the categories available
ACL CAT <category-name> -- Will list all the commands inside the category

例如:

 > ACL CAT
 1) "keyspace"
 2) "read"
 3) "write"
 4) "set"
 5) "sortedset"
 6) "list"
 7) "hash"
 8) "string"
 9) "bitmap"
10) "hyperloglog"
11) "geo"
12) "stream"
13) "pubsub"
14) "admin"
15) "fast"
16) "slow"
17) "blocking"
18) "dangerous"
19) "connection"
20) "transaction"
21) "scripting"

到目前为止,你可以看到21个不同的类别。 现在,让我们检查什么命令属于geo类别:

> ACL CAT geo
1) "geohash"
2) "georadius_ro"
3) "georadiusbymember"
4) "geopos"
5) "geoadd"
6) "georadiusbymember_ro"
7) "geodist"
8) "georadius"

请注意,命令可能是多个类别的一部分,例如,像+@geo -@read这样的ACL规则将导致某些geo命令被排除在外,因为它们是只读命令。

1.7.添加子命令

通常,仅仅排除或包含命令的能力是不够的。 许多Redis命令基于作为参数传递的子命令执行多项操作。 例如,可以使用CLIENT命令来执行危险和非危险操作。 许多部署可能不愿意向非管理员级别的用户提供执行CLIENT KILL的能力,但仍可能希望他们能够运行 CLIENT SETNAME

注意:新的RESP3 HELLO命令可能很快会提供SETNAME选项,但这仍然是一个很好的示例。

在这种情况下,我可以通过以下方式更改用户的ACL:

ACL SETUSER myuser -client +client|setname +client|getname

我开始删除CLIENT命令,后来又添加了两个允许的子命令。 请注意,不可能相反,只能添加而不是排除子命令,因为将来可能会添加新的子命令:指定对以下所有有效的子命令更安全 一些用户。此外,如果添加有关尚未禁用的命令的子命令,则会生成错误,因为这只能是ACL规则中的错误:

> ACL SETUSER default +debug|segfault
(error) ERR Error in ACL SETUSER modifier '+debug|segfault': Adding a
subcommand of a command already fully added is not allowed. Remove the
command to start. Example: -DEBUG +DEBUG|DIGEST

请注意,子命令匹配可能会增加一些性能损失,但是即使使用合成基准测试也很难衡量这种损失,并且仅在调用该命令时才花费额外的CPU开销,而在调用其他命令时则不会。

1.8.+@all VS -@all

在上一节中,我们观察了如何基于adding/removing单个命令来定义命令ACL。

1.9.内部如何存储密码

Redis在内部存储用SHA256散列的密码,如果你设置密码并检查ACL LIST或GETUSER的输出,你会看到一个长的十六进制字符串,看起来是伪随机的。 这是一个示例,因为在前面的示例中,为了简洁起见,对长的十六进制字符串进行了修剪(trimmed):

> ACL GETUSER default
1) "flags"
2) 1) "on"
   2) "allkeys"
   3) "allcommands"
   4) "allchannels"
3) "passwords"
4) 1) "2d9c75273d72b32df726fb545c8a4edc719f0a95a6fd993950b10c474ad9c927"
5) "commands"
6) "+@all"
7) "keys"
8) 1) "*"
9) "channels"
10) 1) "*"

同样,从Redis 6开始,旧命令CONFIG GET requirepass将不再返回明文密码,而是散列密码。

使用SHA256可以避免以明文形式存储密码,同时仍然允许非常快速的AUTH 命令,这是Redis的一个非常重要的功能,并且与客户端对Redis的期望保持一致。

但是,ACL密码并不是真正的密码:它们是服务器和客户端之间的共享机密,因为在这种情况下,该密码不是作为使用的身份验证令牌。 例如:

* There are no length limits, the password will just be memorized in some client software, there is no human that need to recall a password in this context.
* The ACL password does not protect any other thing: it will never be, for instance, the password for some email account.
* Often when you are able to access the hashed password itself, by having full access to the Redis commands of a given server, or corrupting the system itself, you have already access to what such password is protecting: the Redis instance stability and the data it contains.

因此,为了使用一个使用时间和空间的算法来减慢密码认证的速度,从而使密码难以破解,是一个非常糟糕的选择。 相反,我们建议你生成非常强的密码,这样,即使拥有哈希,任何人都无法使用字典或蛮力攻击来破解它。 因此,有一个特殊的ACL命令可使用系统密码伪随机生成器生成密码:

> ACL GENPASS
"dd721260bfe1b3d9601e7fbab36de6d04e2e67b0ef1c53de59d45950db0dd3cc"

该命令输出一个32字节(256位)的伪随机字符串,将其转换为64字节的字母数字字符串。 这足够长,可以避免受到攻击,而足够短,可以轻松地进行管理,剪切和粘贴,存储等。 这是你用来生成Redis密码的方式。

1.10.使用外部ACL文件

有两种方法可以将用户存储在Redis配置中。

  1. 用户可以直接在`redis.conf`文件中指定。
  2. 可以指定一个外部ACL文件。

两种方法互不兼容,Redis会要求你使用其中一种。 在redis.conf中指定用户是一种非常简单的方法,适用于简单的用例。 当有多个用户要定义时,在复杂的环境中,强烈建议你​​​​​​​使用ACL文件。

在redis.conf内部和外部ACL文件中使用的格式是完全相同的,因此从一个切换到另一个很简单,如下所示:

user <username> ... acl rules ...

例如:

user worker +@list +@connection ~jobs:* on >ffa9203c493aa99

当你要使用外部ACL文件时,需要指定称为aclfile的配置指令,如下所示:

aclfile /etc/redis/users.acl

当仅在redis.conf文件中直接指定几个用户时,可以使用CONFIG REWRITE以便通过重写将新的用户配置存储在文件中。

但是,外部ACL文件功能更强大。你可以执行以下操作:

* Use [ACL LOAD](/commands/acl-load) if you modified the ACL file manually and you want Redis to reload the new configuration. Note that this command is able to load the file *only if all the users are correctly specified*, otherwise an error is reported to the user, and the old configuration will remain valid.
* USE [ACL SAVE](/commands/acl-save) in order to save the current ACL configuration to the ACL file.

请注意,CONFIG REWRITE也不会触发ACL SAVE:当你使用ACL文件时,配置和ACL会分别处理。

1.11.前哨(Sentinel)和复制节点(Replicas)的ACL规则

如果你不想为Redis复制节点和Redis Sentinel实例提供对Redis实例的完全访问权限,则以下是必须允许使用的命令集,以确保一切正常工作。

对于Sentinel,允许用户在主节点实例和复制节点实例中都访问以下命令:

  • AUTH, CLIENT, SUBSCRIBE, SCRIPT, PUBLISH, PING, INFO, MULTI, SLAVEOF, CONFIG, CLIENT, EXEC.

Sentinel不需要访问数据库中的任何键,但使用Pub/Sub,因此ACL规则如下(注意:不需要AUTH,因为始终允许使用AUTH):

ACL SETUSER sentinel-user on >somepassword allchannels +multi +slaveof +ping +exec +subscribe +config|rewrite +role +publish +info +client|setname +client|kill +script|kill

Redis复制节点需要在主节点实例上将以下命令列入白名单:

  • PSYNC, REPLCONF, PING

不需要访问任何键,因此这转化为以下规则:

ACL setuser replica-user on >somepassword +psync +replconf +ping

请注意,你不需要配置复制节点就可以使主节点能够执行任何命令集:从复制节点的角度来看,主节点始终被认证为root用户。

1.12.本文档的待办事项清单

  • 添加/删除类别时,请确保指定忽略模块命令。
  • 与某些基准匹配的密钥的文档成本。
  • 记录+@all如何还包括模块命令和每个以后的命令。
  • 使用requirepass和单个参数AUTH向后兼容文档。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琴 韵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值