目录
1. 前言
在使用 Redis 6.0 之前的版本时,通常会遇到如下问题:
- 执行 FLUSHALL 命令,整个 Redis 数据库就清空了
- 执行 DEBUG SEGFAULT 命令,导致 Redis 崩溃
- 执行 KEYS 命令,引起 Redis 的阻塞甚至宕机
- ......
针对以上问题,我们解决的办法可能是使用 Redis 的 rename-command 将这些危险命令禁用或者重命名。也就是说,我们是有办法防止上述情况发生的。
但是,对于另外一种情况:多个项目公用一套 Redis 集群,多项目的 KEY 实际上是共享的,这样便存在安全风险。
我们如何解决多项目之间互相操作对方 KEY 的问题呢?
Redis 6.0 提供了一种新的特性 ACL ,可以方便的解决上述的各类问题。
Redis Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。
Debug Segfault 命令执行一个非法的内存访问从而让 Redis 崩溃,仅在开发时用于 BUG 调试。
Keys 命令用于查找所有符合给定模式 pattern 的 key
redis.conf 中加入如下内容,禁用相应的命令
rename-command KEYS ""
rename-command FLUSHALL ""
rename-command DEBUG ""
2. 什么是 ACL
Redis ACL 是 Access Control List(访问控制列表)的缩写,该功能允许对访问 Redis 的连接做一些可执行命令和可访问的 KEY 的限制。
它的工作方式是,在连接之后,要求客户端进行身份验证,以提供用户名和有效密码:如果身份验证成功,该客户端连接与给定用户绑定,并具有该用户的访问权限。
为了保证 Redis 向下兼容,Redis 6.0 中定义了一个默认的 “default” 用户,该用户拥有操作 Redis 的所有权限。也就是说,每个连接都能够调用每个命令并访问每个 KEY。同样,使用 requirepass 设置访问密码的方式与旧版本也保持一致,只不过 Redis 6.0 的这个密码仅对用户 “default” 有效。
Redis AUTH 命令也在 Redis 6.0 中进行了扩展,现在支持两个参数的访问
AUTO <username> <password>
当按照旧版本的方式访问时(在不输入用户名时,默认使用 default 用户,做到向下兼容)
AUTO <password> 等价于 AUTO default <password>
2. 什么时候使用 ACLs
在使用 ACL 前,我们应该考虑一下,使用 ACL 我们想要达到什么目的。
主要有下面两种目的,我们可以通过使用 ACLs 来达成 :
- 希望通过限制对命令和 KEY 的访问来提高安全性。以便不受信任的客户端无法访问,而受信任的客户端仅具有满足要求的最低操作权限。如:某些客户端可能仅能执行只读命令。
- 想提高操作安全性,以防止由于软件或人为错误而导致非授权情况的操作,导致数据或配置的损坏。例如,不应该让所有客户端都能够调用 FLUSHALL 命令。
3. ACL 规则
ACLS 是使用 DSL(Domain specific language,领域专用语言)来定义的。
可以通过两种方式配置 ACL
- 在命令行通过 ACL 命令配置
- 开启 Redis 配置文件中开启 aclfile 配置项,通过配置文件的方式加载
redis.conf 默认配置中, 使用外部 aclfile 是不开启的
我们通过配置来启用:aclfile /usr/local/redis6/users.acl
/usr/local/redis6/users.acl 即 acl 的配置文件
启动或禁用用户
- on 启用。可以使用该用户进行身份认证
- off 禁用。不能使用该用户进行身份认证,但已通过身份认证的连接仍然可以使用。
启用或禁用命令
- +<command> 将 <command> 命令添加到用户可调用的命令列表中
- -<command> 从可调用的命令列表中移除 <command> 命令
- +@<category> 允许用户调用 <category> 分类中的所有命令(可通过 ACL CAT 命令查看完成分类列表)
- -@<category> 禁止用户调用 <category> 分类中的所有命令
- +<command>|subcommand 允许使用原本禁用的特定类别下的特定子命令
- +@all 允许调用所有命令,与使用 allcommands 效果相同。包括当前存在的命令以及将来通过模块加载的命令
- -@all 禁止调用所有命令
允许或禁止访问某些 KEY
- ~<pattern> 添加符合条件的模式。如: ~* 允许所有 KEY,使用 ~* 与 allkeys 效果相同
- resetkeys 使用当前模式覆盖所有允许的模式。如: ~foo:* ~bar:* resetkeys ~objects:* ,最终客户端只允许访问匹配 ~object:* 模式的 KEY
为用户配置有效密码
- ><password> 将密码添加到用户有效密码列表中。例如:>mypassword 将会把 mypassword 添加到用户的密码列表中。该操作会清除用户的 nopass 标记。每个用户可由拥有多个有效密码
- <<password> 将密码从用户有效密码列表中移除。列表中不存在改密码时,会报错。
- #<hash> 将此 SHA-256 哈希值添加到用户的有效密码列表中。该哈希值将与 ACL 用户输入的密码的哈希值进行比较。这将允许用户将此哈希值存储在 acl 配置文件中,而不是存储明文密码。仅接受 SHA-256 哈希值,因为密码的哈希必须由 64 个字符长度的小写的十六进制字符组成。
- !<hash> 从有效密码列表中删除该哈希值。(适用于不知道哈希值指定的密码但又想从用户中删除密码的情况)
- nopass 删除用户所有密码,并将该用户标记为不需要密码。如果此指令引用于 default 用户,则每个新的连接都将立即通过 default 用户进行连接,而无需任何显示的 AUTH 命令。
- resetpass 清除用户可用密码列表的数据,并清除 nopass 状态。之后该用户将没有任何关联的有效密码,将不允许登录,直到为该用户设置了有效密码或将用户设置成 nopass 状态
- reset 重置用户到初始状态。该命令会执行以下操作:resetpass,resetkeys,off,-@ all。
未使用 nopass 标记且没有有效密码列表的用户,实际上是无法使用的。因为无法以该用户的身份登录。
4. ACL 常用命令
ACL LIST
检查当前活动的 ACL 列表
-
127
.0
.0
.1
:6379>
ACL
LIST
-
1) "
user
default
on
nopass ~* +@
all"
首次安装后只有一个默认的 default 用户,其具有如下状态:
- 用户名为 default
- 用户处于启用状态
- 访问不需要密码
- 可以访问所有 KEY
- 可以执行所有命令
ACL SETUSER
ACL SETUSER <username> 用户不存在,则按默认规则创建用户。用户存在,则该命令不执行任何操作。
ACL SETUSER <username> <rules> 用户不存在,则按默认规则创建用户,并增加 <rules> 。用户存在则在原有规则上增加 <rules>。
<username> 用户名区分大小写
-
// 创建一个名为 lnrcoder 的用户
-
127.0
.0
.1:
6379> ACL SETUSER lnrcoder
-
OK
-
-
// 查询所有活动的 ACL
-
127.0
.0
.1:
6379> ACL
LIST
-
1)
"user default on nopass ~* +@all"
-
2)
"user lnrcoder off -@all"
我们创建的 lnrcoder 用户默认规则为:
- 处于关闭状态
- 无法执行任何命令
- 没有匹配的访问 KEY 的模式
- 没有有效的密码
我们为其配置一些 ACL 规则
-
// 用户状态设置为启用,密码为 mypassword,允许访问以 cached: 开头的 KEY,允许执行 get 命令
-
127.0
.0
.1:
6379> ACL SETUSER lnrcoder
on >mypassword ~cached:* +
get
-
OK
-
-
127.0
.0
.1:
6379> ACL LIST
-
1)
"user default on nopass ~* +@all"
-
2)
"user lnrcoder on #89e01536ac207279409d4de1e5253e01f4a1769e696db0d6062ca9b8f56767c8 ~cached:* -@all +get"
-
-
// set 一个以 cached: 开头的 KEY 用来测试
-
127.0
.0
.1:
6379>
set cached:test test
-
OK
使用 AUTH 命令切换到 lnrcoder 用户下,进行测试
-
// 使用 AUTH 切换到 lnrcoder 用户下
-
127.0
.0
.1:
6379> AUTH lnrcoder mypassword
-
OK
-
-
// 使用 set 命令设置不符合匹配规则的 KEY
-
127.0
.0
.1:
6379>
set a
1
-
(error) NOPERM
this user has no permissions to run the
'set' command or its subcommand
-
-
// 使用 set 命令设置符合匹配规则的 KEY
-
127.0
.0
.1:
6379>
set cached:aaa
1
-
(error) NOPERM
this user has no permissions to run the
'set' command or its subcommand
-
-
// 使用 get 命令获取不符合匹配的 KEY 值
-
127.0
.0
.1:
6379>
get a
-
(error) NOPERM
this user has no permissions to access one of the keys used
as arguments
-
-
// 使用 get 命令获取符合匹配规则的 KEY 值
-
127.0
.0
.1:
6379>
get cached:test
-
"test"
测试结果与我们配置的 ACL 规则相符。
ACL GETUSER <username>
同 ACL LIST 作用类似。ACL GETUSER 用来获取指定用户的 ACL 状态信息
-
127.0
.0
.1:
6379> ACL GETUSER
default
-
1)
"flags"
// 标记数组(启用、可操作所有 KEY、可执行所有命令、无密码)
-
2)
1)
"on"
-
2)
"allkeys"
-
3)
"allcommands"
-
4)
"nopass"
-
3)
"passwords"
// 密码
-
4) (
empty
array)
-
5)
"commands"
// 命令匹配规则
-
6)
"+@all"
-
7)
"keys"
// KEY 的模式匹配规则
-
8)
1)
"*"
-
-
127.0
.0
.1:
6379> ACL GETUSER lnrcoder
-
1)
"flags"
-
2)
1)
"on"
-
3)
"passwords"
-
4)
1)
"89e01536ac207279409d4de1e5253e01f4a1769e696db0d6062ca9b8f56767c8"
-
5)
"commands"
-
6)
"-@all +get"
-
7)
"keys"
-
8)
1)
"cached:*"
-
ACL DELUSER
删除用户 ACL DELUSER <username>
-
// 创建一个测试用户
-
127.0
.0
.1:
6379> ACL SETUSER testuser
-
OK
-
127.0
.0
.1:
6379> ACL
LIST
-
1)
"user default on nopass ~* +@all"
-
2)
"user lnrcoder on +@all"
-
3)
"user testuser off -@all"
-
-
// 删除用户
-
127.0
.0
.1:
6379> ACL DELUSER testuser
-
(integer)
1
-
-
// 查看结果
-
127.0
.0
.1:
6379> ACL
LIST
-
1)
"user default on nopass ~* +@all"
-
2)
"user lnrcoder on +@all"
ACL USERS
查看 ACL 的所有用户
-
127
.0
.0
.1
:6379>
ACL
USERS
-
1) "
default"
-
2) "
lnrcoder"
ACL WHOAMI
查看当前操作的用户
-
127
.0
.0
.1
:6379>
ACL
WHOAMI
-
"
default"
ACL CAT
ACL CAT 显示所有的 ACL 类别
ACL CAT <类别> 显示指定类别中所有的 Redis 命令
-
127.0.0.1:6379> 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"
以 dangerous 为例,查看该类别包含的所有命令:
-
127.0.0.1:6379> ACL CAT dangerous
-
1)
"bgsave"
-
2)
"module"
-
3)
"replconf"
-
4)
"info"
-
5)
"role"
-
6)
"debug"
-
7)
"slaveof"
-
8)
"keys"
-
9)
"flushdb"
-
10)
"bgrewriteaof"
-
11)
"lastsave"
-
12)
"acl"
-
13)
"psync"
-
14)
"client"
-
15)
"latency"
-
16)
"save"
-
17)
"migrate"
-
18)
"pfselftest"
-
19)
"swapdb"
-
20)
"restore-asking"
-
21)
"sync"
-
22)
"shutdown"
-
23)
"monitor"
-
24)
"slowlog"
-
25)
"pfdebug"
-
26)
"flushall"
-
27)
"sort"
-
28)
"config"
-
29)
"replicaof"
-
30)
"cluster"
-
31)
"restore"
ACL SAVE
前提:redis 配置中启用了 aclfile 选项
将当前所有的 ACL 存入 aclfile,覆盖 aclfile 内容
ACL LOAD
前提:redis 配置中启用了 aclfile 选项
从 acl 文件中加载定义的 acl 规则
该命令保证所有的规则都有效时才能执行成功:
-
如果 aclfile 文件中每一行都有效,则将所有内容加载到内存替换内存中现有的 ACL 规则
-
如果文件中有一行或多行无效,则不会加载任何内容,继续使用现有内存中的规则
ACL GENPASS
可以使用该命令来生成 Redis 密码
该命令默认创建一个 256 bit 的 32 字节的伪随机字符串,并将其转换为 64 字节的字母+数字的字符串。如有有参数,则使用指定的位数长度
-
127
.0
.0
.1
:6379>
ACL
GENPASS
-
"
e2ceb52e866908c2706e521b7d145eb78ec4b5806ef1fd0bcb4482687d2c82f7"
-
127
.0
.0
.1
:6379>
ACL
GENPASS 32
-
"
fbcc163c"
-
127
.0
.0
.1
:6379>
ACL
GENPASS 64
-
"3
ab469e7c659c19a"
ACL LOG
查看安全事件日志
该命令记录如下 ACL 安全事件
- 无法通过 AUTH 身份验证的
- 违背当前 ACL 规则,执行命令被拒绝
- 访问当前 ACL 规则中不允许的键,被拒绝访问
-
127.0.0.1:6379> ACL LOG
-
1)
1)
"count"
-
2) (integer)
1
-
3)
"reason"
-
4)
"auth"
-
5)
"context"
-
6)
"toplevel"
-
7)
"object"
-
8)
"AUTH"
-
9)
"username"
-
10)
"lnrcoder"
-
11)
"age-seconds"
-
12)
"3076.3829999999998"
-
13)
"client-info"
-
14)
"id=4 addr=127.0.0.1:53462 fd=7 name= age=12138 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=40 qbuf-free=32728 obl=0 oll=0 omem=0 events=r cmd=auth user=default"
使用 RESET 命令清空 LOG
-
127
.0
.0
.1
:6379>
ACL
LOG
RESET
-
OK
-
127
.0
.0
.1
:6379>
ACL
LOG
-
(
empty
array)
-
127
.0
.0
.1
:6379>
ACL HELP
ACL 命令帮助
-
127
.0
.0
.1
:6379>
ACL
HELP
-
1)
ACL <
subcommand>
arg
arg ...
arg.
Subcommands
are:
-
2)
LOAD
--
Reload
users
from
the
ACL
file.
-
3)
SAVE
--
Save
the
current
config
to
the
ACL
file.
-
4)
LIST
--
Show
user
details
in
config
file
format.
-
5)
USERS
--
List
all
the
registered
usernames.
-
6)
SETUSER <
username>
[attribs ...]
--
Create
or
modify
a
user.
-
7)
GETUSER <
username>
--
Get
the
user
details.
-
8)
DELUSER <
username>
[...]
--
Delete
a
list
of
users.
-
9)
CAT
--
List
available
categories.
-
10)
CAT <
category>
--
List
commands
inside
category.
-
11)
GENPASS
[<bits>]
--
Generate
a
secure
user
password.
-
12)
WHOAMI
--
Return
the
current
connection
username.
-
13)
LOG
[<count> | RESET]
--
Show
the
ACL
log
entries.
转载:https://blog.csdn.net/sl285720967/article/details/106440838