Redis6.0新特性之ACL策略介绍
一、ACL简介
Redis ACL(Access Control List),是允许某些被限制的连接可以执行的命令和可以访问的键的一种功能。它的工作方式是在连接之后,需要客户端提供用户名和有效密码进行身份验证:如果身份验证阶段成功,则将该连接与给定的用户及其限制条件关联起来。可以对Redis进行配置,以便新连接通过默认用户进行验证,配置默认的用户,可以向没有明确身份验证的连接提供一个特定子集的功能。在默认配置下,Redis 6(第一个有ACL的版本)的工作方式与旧版本完全一样,每个新连接都能够调用所有可能的命令和访问每个密钥,所以ACL功能向后兼容老客户端和应用程序。另外,使用requirepass配置指令配置密码的旧方法仍然可以正常工作,但是现在它只需要为默认用户设置密码。Redis认证命令在Redis 6中被扩展,所以现在可以使用它在两个参数的形式:
AUTH <username> <password> (对比之前的命令 AUTH <password>)
可以理解成旧的方式里用于身份验证的用户名是“default”,因此仅指定密码就意味着我们希望根据默认用户进行身份验证。这提供了与过去完美的向后兼容性。
通常,acl有两个主要目地:
1、通过限制对命令和密钥的访问来提高安全性,以便不受信任的客户端没有访问权限,而受信任的客户端只有对数据库的最小访问级别,以便执行所需的命令。例如某些客户端只允许执行只读命令。
2、提高操作安全性,避免程序或人员访问Redis产生的软件错误或人工错误造成数据或配置损坏。例如不允许客户端执行keys * 、monitor、flushdb等。
acl的另一个典型用法与管理的Redis实例有关。Redis通常是由公司内部为其他内部客提供的基础设施服务,或者由云厂商以云服务的方式提供。在这两种模式中,我们都不希望客户有执行配置命令的权限。
在过去,由于没有ACL权限管理方法,只能通过命令重命名来实现这一点,但这种方法并不理想。
acl是使用DSL(领域特定语言)定义的,DSL描述给定用户能够做什么或不能做什么。这些规则总是从第一个到最后一个,从左到右实现的。
默认情况下,只有一个定义的用户default。我们可以使用ACL List命令来查看当前的ACL列表,默认配置的Redis实例是:
上述命令以Redis配置文件中使用的相同格式将当前的acl设置转换回用户的描述返回用户列表。
每行的前两个单词是“user”,后面跟着用户名。下一个单词ACL规则。对应例子中的默认用户,它被配置为活动的(on)、不需要密码(nopass)、访问每个可能的密钥(~*)、能够调用每个可能的命令(+@all)。
在默认用户的特殊情况下,使用nopass规则意味着新连接将自动使用默认用户进行身份验证,而不需要任何显式的身份验证调用。
二、ACL规则详解
1、启用或者禁用用户
on: 启用用户,表明该用户可以进行身份验证
off: 禁用用户,表明不允许该用户进行身份验证。在动态设置禁用用户时,已验证过的连接信息不受影响。
2、启用或者禁用命令
+<command>:增加可执行的命令到表单
-<command>: 从执行表单中移除命令
+@<category>:添加某个类别的命令权限,有效类别为@admin,@set,@sortedset等等。可以通过acl cat查看用户可执行的类别,@all表示所有命令。下图是默认用户的可执行命令类别
-@<category>:与+@<category>相反,移除某些类别的执行权限。
+<command>|subcommand:允许执行某些命令(子命令)
allcommands:+@all的别名
nocommands:-@all的别名
3、允许或者禁止执行命令的key
~<pattern>: 允许执行某个特定格式的key。例如~*表示可以对所有的key执行相应的命令, ~object:*可以执行所有符合 object: 格式的key
4、配置密码
><password> : 将密码添加到用户的有效密码列表中。例如>mypass会将“mypass”添加到有效密码列表中。这个指令清除nopass标志。每个用户都可以有任意数量的密码。
<<password> : 从有效密码列表中删除此密码。如果您试图删除的密码实际上没有设置,则会发出错误。
#<hash>: 将SHA-256哈希值添加到用户的有效密码列表中,在进行权限验证时,有效密码表的哈希值将与为ACL用户输入的密码的哈希值进行对比。也可以acl.conf文件中存储哈希值,由于只接受SHA-256哈希值,因此密码哈希必须是小写的十六进制的64个字符
!<hash>: 与#<hash>相反,从有效密码表中移除哈希密码
nopass: 删除用户的所有设置密码,并将该用户标记为不需要密码: 如果用户为默认用户,则所有的新连接都将不需要验证即可访问Redis。
resetpass:刷新密码列表。reset操作将会移除nopass状态。在重置密码之后,用户将没有密码且无法免密验证。(即该用户无法使用)。
重置操作的顺序是重置密码,重置相关keys,禁用用户,禁用命令(resetpass, resetkeys, off, -@all)。用户将恢复创建后的状态。
三、用户创建
用户的创建和修改主要有两种方式:
1、使用ACL及ACL SETUSER子命令
2、修改配置文件,在配置文件中声明用户信息,并重启Redis服务。或者编辑一个ACL授权文件,然后使用ACL LOAD命令。
先来看ACL相关命令
acl setuser zhouqw 创建用户zhouqw。
由于未指定任何的授权信息,使用acl list 查看用户状态并与默认用户default对比发现:
1、用户处于禁用状态,且不能执行任何命令。
2、用户没法执行任何命令
3、用户没有可以访问的模式key
4、用户没有指定密码
接下来我们通过上述四个方面给用户zhouqw进行授权:将用户zhouqw启用,设置密码为pwdzhouqw,允许执行get命令访问cached:开头的key
创建cached:123, cached:456, cached 三个key,并切换到用户zhouqw,可以发现无法访问cached,可以访问cached:123但是无法修改cached:123
当需要获取某个用户的授权信息时,使用acl getuser username会更简洁,输出的格式包含上述的4个方面,更易读。
四、系统命令类别
ACL将Redis的命令分成了多种类别,可以对用户授权可执行的命令类别来添加多个同类别的命令。
ACL CAT命令会显示所有的命令类别,ACL CAT catname会显示catname命令类别下所有的命令,如下图:
五、子命令权限
通常情况下,排除或者包含某个命令对于权限是不够的。许多Redis命令基于参数传递的子命令做多种事情。例如,CLIENT可以用于执行危险和非危险的操作。对于管理员而言,当然不希望为非管理员级别的用户Client KILL的权限,但可能仍然希望他们能够运行客户端的信息。在这种情况下,可以用以下方式修改用户的权限:
ACL SETUSER myuser -client +client|setname +client|getname
即先将myuser的Client命令执行权限禁用,然后再添加Client setname和Client getname的权限。
移除命令权限和添加命令权限的顺序不能对调,Redis加载acl权限的方式是从左到右,如果对换顺序,如:
ACL SETUSER myuser +client|setname +client|getname -client
则先添加两个Client的子命令执行权限,再将所有的Client命令的权限都禁用。禁用的权限当然也包含前面授权的两个子命令,即不给myuser授权任何Client执行命令
六、ACL文件
在前文中,我们提到有两种方式来进行授权。其中一种方式就包含了额外的ACL文件 (或者在Redis的配置文件redis.conf中配置)。ACL文件和redis.conf文件不兼容。
对于一些简单的授权信息,使用redis.conf文件即可。对于较为复杂的授权信息,建议使用单独的acl文件进行配置。acl文件的格式和redis.conf的格式一致。
如果使用单独的acl文件,则需要在redis.conf文件中指定acl文件的路径。
当然,也可以使用ACL LOAD命令加载acl文件的授权信息。
在使用ACL命令添加了授权信息之后,可以使用ACL SAVE命令将当前的授权信息保存到acl文件中。也可以使用CONFIG REWRITE将授权信息更新到redis.conf中,如:
七、副本 &哨兵的ACL规则
对于哨兵而言,因为哨兵不访问任何的key,如果不想提供所有的权限,只需要添加下列权限即可:
AUTH, CLIENT, SUBSCRIBE, SCRIPT, PUBLISH, PING, INFO, MULTI, SLAVEOF, CONFIG, CLIENT, EXEC.
对应的ACL授权命令为:ACL setuser sentinel-user >somepassword +client +subscribe +publish +ping +info +multi +slaveof +config +client +exec on
对于副本而言,只需要PSYNC, REPLCONF, PING权限即可,对应的ACL授权命令为:
ACL setuser replica-user >somepassword +psync +replconf +ping on