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 的默认状态。可以配置 allchannels
或 resetchannels
。
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
来设置密码,5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 是 password 的 sha1 值。为了密码安全,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 | 1) ACL <subcommand> [<arg> [value] [opt] ...]. Subcommands are: |
那就一个个来吧
ACL CAT
列出所有的命令分类,如果制定了分类名,就列出当前分类中所有的命令
使用:ACL CAT
1 | 1) "keyspace" |
使用: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就是命令多点,使用起来也没有那么复杂吗。