0%

redis ACL使用手册

redis在 6.0 版本加入了ACL支持,虽然已经发布很久了,但是这个命令属于不太常用的命令,导致很多人对ACL还不太了解。比较好的文档就是redis ACL的官方文档 ,其他网上搜索到的相关知识大多数不全面,尤其中文文档缺失比较多。

我之前写过一篇 redis ACL源码分析的文章。但是这篇文章偏向源码学习,对ACL的使用基本没有介绍。所以这次就来写一下 ACL 的使用。我作为 pika ACL 功能的贡献者,pika ACL PR,自认为对ACL有一些了解,如果文中有错误,还请不吝赐教。

我会从 ### ACL功能的介绍ACL命令的使用 两方面来写

ACL功能

ACL简单来说,就是给redis加了用户的概念。以前的redis中,没有用户这个概念,只有一个密码。当一个连接完成认证后,可以执行所有命令。这样是有风险的,如果一个普通的用户,执行了 flushall 这样的命令,整个redis的数据都会被删除。当加入了用户这个概念以后,redis可以通过给不同的用户划分不同的权限,比如普通用户只给数据的读写权限,不能对redis服务做任何管理。这样就能保证redis服务的安全和稳定。

就像MySQL一样,有一个默认的 root 用户,这个用户拥有最高的权限。但是在实际使用中,不会在业务处理的连接中使用root用户,而是创建一个普通的用户。限制这个用户的权限,只能操作自己业务的库。当redis有了ACL功能后,也可以实现类似的功能了

使用ACL

在redis使用ACL不需要特殊的配置,只要redis版本支持这个功能即可。redis在启动的时候,会初始化一个默认用户 default 这个用户就相当于MySQL中的 root 用户。默认拥有所有权限。

操作和修改redis的ACL,可以使用redis中ACL的相关命令(后面会逐个介绍),可以在配置文件中预先设定,启动redis的时候会自动加载预设的ACL规则。

可以在redis的配置文件(默认是redis.conf)中进行配置。

例:

1
user default on nopass ~* &* +@ALL

这就是一条ACL的配置。

除了在 redis.conf这配置以外,还可以在 redis.conf 中指定一个文件,然后在指定的文件中配置ACL规则。
ACL文件在redis.conf配置如下

1
aclfile /etc/redis/users.acl

除了这两个外,ACL几个个配置

ACL log记录的条数,log的作用就是记录用户越权行为。

配置:

1
acllog-max-len 128

ACL 中channel 的默认状态。可以配置 allchannelsresetchannels

  • allchannels: 可以访问所有Pub/Sub频道的权限
  • resetchannels: 撤销对所有Pub/Sub频道的访问

配置:

1
acl-pubsub-default resetchannels

ACL配置语法

首先,ACL可以对 命令key的名字channel 做限制,多个规则之间用空格分割。

user1 on >123 ~* &* +@ALL 这条配置中。

  • user1:用户名
  • on:用户启用,如果设置为 off 那么用户不能使用
  • >123: 用户密码
  • ~*:不做任何 key名字的限制
  • &*:不做 pub/sub 的限制
  • +@ALL:允许执行所有命令
密码

redis ACL中,一个用户可以有多个密码,只要有一个密码认证成功就可以。也可以使用 nopass 这个关键词来表示该用户没有密码。

在设置密码的时候,使用 >password 来设置密码,使用<password 来删除对应的密码。

还可以使用 #5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 来设置密码,5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8passwordsha1 值。为了密码安全,redis内部存储密码使用的是密码的 sha1,这样在配置文件和转储ACL规则的时候,可以保证密码的安全。

同样的,可以使用 !5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 来删除对应的密码。

key名限制

redis中每个key都有一个名字,使用 ~ 来做key名字限制,支持 * 通配符,而且支持key的只读 R 和 写 W 区分。

比如 对 app1 这个key只读 %R~app1。对所有 app2 开头的key都有权限 ~app2*

pub/sub限制

pub/sub限制和key名限制类似,要使用pub/sub的前提是可以使用 pub/sub相关的命令,这部分在命令限制中配置,这里是限制 channel 的名字。

和key限制不同的是,channel 使用 & 符号

这里有两个关键词

  • allchannels: 可以访问所有Pub/Sub频道的权限
  • resetchannels: 撤销对所有Pub/Sub频道的访问
命令限制

命令最好理解了,就是限制当前用户可以执行哪些命令,不能执行哪些命令。
在ACL中使用 + 来赋予命令的权限,用 - 来撤销命令的权限。比如 +get -set 这就表示赋予 get 命令,撤销 set命令。

除了直接指定具体的命令外,还可以对一类命令做限制。比如 +@hash -@zset,这表示可以执行所有的 hash 类的命令,不能执行所有的 zset 类的命令。

redis ACL 还可以限制子命令。比如 CONFIG SET acllog-max-len 128 中,SET 就是 CONFIG 命令的子命令。如果想要限制用户不能修改配置,那ACL可以这样配置 +config -config|set。此时用户可以执行 config set 以外的所有 config 命令。

还有一种用法,允许阻塞命令的第一个参数,不过这个功能自Redis 7.0起已弃用,将来可能会被删除。所以不建议使用了。

用redis官方文档的例子来说

有时,排除或包含命令或子命令作为一个整体的能力是不够的。许多部署可能不愿意为任何DB提供执行SELECT的能力,但可能仍然希望能够运行SELECT 0。

此时的配置 ACL SETUSER myuser -select +select|0。这样,该用户只能执行 select 0 这一个 select 命令。如果想 select 2 等等进入别的库是不允许的。

我个人感觉,要淘汰这个功能的原因,是应用面太少了,而且像上面的这个例子中,并没有完全限制了对库的使用权限。如果先在别的用户下,选择了 1 这个库,然后再 auth myuser 这个用户,虽然这个用户限制了,只能 select 0,但是此时依然可以访问 1 这个库。

redis命令的分类:

  • admin 管理redis服务相关的命令 包含 REPLICAOF CONFIG SAVE MONITOR ACL SHUTDOWN等等
  • bitmap bitmap这个数据类型相关的命令
  • blocking 可能会阻塞连接,直到被另一个命令释放
  • connection 影响连接或其他连接的命令。包含 AUTH SELECT COMMAND CLIENT ECHO PING等等
  • dangerous 有潜在危险的命令(由于各种原因,应该仔细考虑每个命令)。包含 FLUSHALL MIGRATE RESTORE SORT KEYS CLIENT INFO CONFIG SAVE REPLICAOF等等
  • geo geo这个数据类型相关的命令
  • hash hash这个数据类型相关的命令
  • hyperloglog hyperloglog 这个数据类型相关的命令
  • fast 快 O(1) 的命令,可以循环参数的个数,但不能循环键中的元素个数。
  • keyspace 以与类型无关的方式从键、数据库或它们的元数据写入或读取。包含 DEL RESTORE DUMP RENAME EXISTS DBSIZE KEYS EXPIRE TTL FLUSHALL 可能修改键空间、键或元数据的命令也将具有 write 类别。仅读取键空间、键或元数据的命令将具有 read 类别。
  • list list这个数据类型相关的命令
  • pubsub PubSub 订阅发布相关的命令
  • read 从键(值或元数据)读取。不与键交互的命令既没有 read 也没有 write
  • scripting lua脚本执行相关的命令
  • set set 这个数据结构相关的命令
  • sortedset zset数据结构相关的命令
  • slow 慢命令,非 fast的命令
  • stream stream 这个数据类型相关的命令
  • string string 这个数据类型相关的命令
  • transaction WATCH MULTI EXEC 这几个和事务相关的命令
  • write 写入键(值或元数据)的命令

ACL相关命令

使用 ACL HELP 命令可以看到ACL所有的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 1) ACL <subcommand> [<arg> [value] [opt] ...]. Subcommands are:
2) CAT [<category>]
3) List all commands that belong to <category>, or all command categories
4) when no category is specified.
5) DELUSER <username> [<username> ...]
6) Delete a list of users.
7) DRYRUN <username> <command> [<arg> ...]
8) Returns whether the user can execute the given command without executing the command.
9) GETUSER <username>
10) Get the user's details.
11) GENPASS [<bits>]
12) Generate a secure 256-bit user password. The optional `bits` argument can
13) be used to specify a different size.
14) LIST
15) Show users details in config file format.
16) LOAD
17) Reload users from the ACL file.
18) LOG [<count> | RESET]
19) Show the ACL log entries.
20) SAVE
21) Save the current config to the ACL file.
22) SETUSER <username> <attribute> [<attribute> ...]
23) Create or modify a user with the specified attributes.
24) USERS
25) List all the registered usernames.
26) WHOAMI
27) Return the current connection username.
28) HELP
29) Prints this help.

那就一个个来吧

ACL CAT

列出所有的命令分类,如果制定了分类名,就列出当前分类中所有的命令

使用:ACL CAT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 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"

使用:ACL CAT HASH,列出 hash 这个分类下所有的命令。

ACL DELUSER

这个没什么好说的,就是删除指定的用户。例如:ACL DELUSER user1 user2

ACL DRYRUN

用来测试指定用户是否可以执行特定的命令。

比如测试 user1 是否可以执行 hset hkey field1 1111 命令如下

ACL DRYRUN user1 hset hkey field1 1111 如果有权限执行,会返回 OK,否则会提示具体的错误。

ACL GETUSER

就如字面意思,获取指定用户的详细信息,例:ACL GETUSER user1

ACL GENPASS

生成一个随机密码,默认长度是 256 位的密码,也可以指定长度。

ACL LIST

使用 ACL 配置文件中的格式,列出当前系统中所有的用户的详细信息

ACL LOAD

从配置中重新加载ACL的配置,如果redis的配置文件中,没有配置 aclfile 的文件路径,那么这个命令会报错。

ACL LOG

查询所有没有通过校验的行为,比如 user1 没有 hash 类型数据操作的权限,在使用 hash 类型的命令后,会记录一条log

log记录的最大值,从 配置文件中的 acllog-max-len 中读取。

这个命令可以通过参数,来指定一次获取的log数量,例:ACL LOG 10 只获取10条

还可以重置所有log,例:ACL LOG reset

ACL SAVE

ACL LOAD 命令相反,这个是把当前的ACL规则保存到文件中。这个命令也需要在配置了 aclfile 后才能执行,否则也会报错。

ACL SETUSER

这个是ACL中最常用的命令了,用来创建和设置ACL用户属性。创建和修改用户,使用 ACL 语法,同配置中的语法是一致的。

例:ACL SETUSER user1 on >123 ~app1* +@all 会修改 user1 这个用户的属性,如果之前没有这个用户,那么会创建这个用户,并设置属性。

ACL还支持子属性,例:ACL SETUSER user1 on >123 ~app1* +@all (+@read ~app2) 在这个规则下,user1 用户对 app1 前缀的key拥有读写权限,对 app2 前缀的key只有读的权限。

ACL USERS

只列出当前系统所有的用户名,相当于是 ACL LIST 命令的简化版

ACL WHOAMI

获取当前用户的名字,类似Linux系统中的 whoami 命令。

到这整个ACL命令使用差不多就介绍完了。整个ACL就是命令多点,使用起来也没有那么复杂吗。