Redis 7 中的用户权限管理功能

早期 redis 权限管理功能

在早期 redis 的权限管理非常弱,还发生过大规模的生产系统的 redis 暴露在公网上,无密码保护,被人将数据加密后进行勒索的事件。后来即时加上了密码保护,也仅仅只是一个是否允许连接的控制,不能分用户,分权限,也一直这么用到现在。前些天看到 redis 7 发布,里面提到升级了新的 ACL 功能,赶紧看了一下,发现有一定的改善,但是还是不太够。

旧版本兼容

如果还按照老版本进行配置,那么新版的 redis 还是能够直接通过密码字符串来连接,以便和旧版本兼容。通过执行命令 ACL LIST 可以看出系统中有一个名称叫 default 的用户。默认情况下只输入密码就是指通过这个用户来连接 redis 。

127.0.0.1:37382> acl LIST
1) "user default on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* &* +@all"

新版的用户管理

增加用户

我们增加一个拥有全部权限的 admin 用户。

127.0.0.1:37382> ACL SETUSER admin on >Taf&VFIGHlyW*!4iKq#F*#WsYizHkA# ~* +@all
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user default on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* &* +@all"
127.0.0.1:37382> 

这个命令各个部分的解释如下:

  1. ACL SETUSER 是用来进行用户管理的命令,后面是命令的参数
  2. admin 是要设置的用户的登录名称
  3. on 是指设置用户的状态 。on 表示可用状态,off 表示不可用状态
  4. Taf&VFIGHlyW!4iKq#F#WsYizHkA# 是要设置的用户的密码
  5. ~* 是一个正则表达式,用来指明用户可以对哪些 key 进行访问。这里指明对所有的key都可以访问。这个表达式可以是多个
  6. +@all 是对用户执行命令权限的设置。这里是指的对所有命令都有权限执行

通过 ACL LIST 命令可以查看当前系统中用户的列表信息。这里可以看到除了 default 用户,新增加了一个 admin 的用户

修改用户

ACL SETUSER 命令可以针对一个用户多次执行。第一次执行增加用户,后续执行的时候就是对用户进行修改了。例如我们新建一个 atu 的账号,并渐次完善相关设置

127.0.0.1:37382> ACL SETUSER atu
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user atu off resetchannels -@all"
3) "user default on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* &* +@all"
127.0.0.1:37382> 

这个命令增加了一个 atu 用户,没有设置其他任何信息。通过 ACL LIST 命令查看,可以看到这个用户为不可用状态(off),并且没有任何权限(-@all)

在另一个终端通过 auth 命令进行该用户鉴权,提示如下

127.0.0.1:37382> AUTH atu
(error) WRONGPASS invalid username-password pair or user is disabled.
127.0.0.1:37382> 

现在我们将该用户设置为可以状态并为用户设置密码 123456

127.0.0.1:37382> ACL SETUSER atu >123456
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user atu on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 resetchannels -@all"
3) "user default on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* &* +@all"

在另一个终端用 atu 用户进行连接成功

127.0.0.1:37382> auth atu 123456
OK
127.0.0.1:37382> get name
(error) NOPERM this user has no permissions to run the 'get' command
127.0.0.1:37382> 

但是我们使用 get 命令获取一个 key 的值的时候提示没有权限,所以我们可以通过下面的操作为这个用户增加 get 命令的权限

127.0.0.1:37382> ACL SETUSER atu +get
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user atu on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 resetchannels -@all +get"
3) "user default on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* &* +@all"

但是,当我们在另一个终端用这个 atu 用户获取一个 key 的值的时候失败了。显示如下:

127.0.0.1:37382> get name
(error) NOPERM this user has no permissions to access one of the keys used as arguments

这提示用户没有获取 name key 值的权限。那么我们为增加所有 key 值的访问权限。

127.0.0.1:37382> ACL SETUSER atu ~*
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user atu on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~* resetchannels -@all +get"
3) "user default on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* &* +@all"

这样用 atu 用户访问 name key 值就可以了。当然,还是不能设定 key 的值。

127.0.0.1:37382> get name
"yanggch"
127.0.0.1:37382> set age 10
(error) NOPERM this user has no permissions to run the 'set' command

刚才那样让用户有所有 key 的存储权限显然不太合适,需要让制定的用户对某一些 key 有访问的权限。例如我们想让 atu 这个用对以 cached:开头的这些 key 有访问权限,我们就可以为这个用户设定这个权限。

127.0.0.1:37382> ACL SETUSER atu resetkeys ~cached:*
OK
127.0.0.1:37382> ACL SETUSER atu ~shop:*
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user atu on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~cached:* ~shop:* resetchannels -@all +get"
3) "user default on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* &* +@all"
127.0.0.1:37382> set cached:1001 welcome
OK

这里有一个关键字 resetkeys 表示覆盖设置,因为原来有所有 key 的权限,现在加一个 ~cache 的权限无法生效,所以有所有 key 访问权限的时候必须要加 resetkeys 关键字将所有 key 权限取消掉。不加 resetkeys 关键字的时候,则是追加模式。

这个时候再用 atu 访问 name 和 cached:1001 。结果如下:

127.0.0.1:37382> get name
(error) NOPERM this user has no permissions to access one of the keys used as arguments
127.0.0.1:37382> get cached:1001
"welcome"
127.0.0.1:37382> 

这种带前缀的 key 的设计方法是 redis 中常用的一种方法。前缀可以起到类似数据表的作用。我们通过设置用户能够访问的key的前缀的权限,达到了类似数据库中分库分表设置权限的效果。

对应命令权限则是通过 + 和 - 两个操作来处理,+ 表示增加某个命令的权限,- 表示取消某个命令的权限。@all 则是特殊的标识,标识所有命令。一般情况下,我们是让用户拥有所有的redis 命令,然后将一些敏感命令权限取消的方式来设置用户的命令权限。这样设置比较简单。例如比较危险的 flushdb 和 flushall 这两个删除所有数据的命令,我们一般都不让普通用户使用。这里将 atu 这个用户设置为拥有所有命令权限,但是取消 flushdb 和 flushall 这两个命令的权限,做法如下:

127.0.0.1:37382> ACL SETUSER atu +@all
OK
127.0.0.1:37382> ACL SETUSER atu -flushdb -flushall
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user atu on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~cached:* ~shop:* resetchannels +@all -flushall -flushdb"
3) "user default on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* &* +@all"

这样就不用担心 atu 用户删库跑路了。

启用外部 ACL 文件

上面在命令行中设置的用户权限,不能持久化,redis 重启后就失效了。redis 还采用了一种外部 acl 文件的方式。找到 redis 配置文件中 如下部分并将注释取消掉,设置正确的外部 acl 文件名称。

# Using an external ACL file
#
# Instead of configuring users here in this file, it is possible to use
# a stand-alone file just listing users. The two methods cannot be mixed:
# if you configure users here and at the same time you activate the external
# ACL file, the server will refuse to start.
#
# The format of the external ACL user file is exactly the same as the
# format that is used inside redis.conf to describe users.
#
aclfile /data/redis7/users.acl

设置外部的 acl 文件为 /data/redis7/users.acl。大家根据自己的环境修改对应的路径并建立一个空的 users.acl 文件。然后将上章节中建立的 admin 用户的配置信息拷贝到改文件中。

user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all

然后,重启启动 redis 即可。现在可以用用户 admin 和对应的密码来连接redis 了

[root@hecs-99107 bin]# ./redis-cli -p 37382
127.0.0.1:37382> auth admin Taf&VFIGHlyW*!4iKq#F*#WsYizHkA#
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"

注意:重启后不带用户,直接输入默认用户密码的连接方式就失效了。
我们再增加普通的 atu 用户,并且执行 ACL SAVE 命令,最新的用户配置信息就保持到 users.acl 文件中了。

127.0.0.1:37382> ACL SETUSER atu on >123456 ~cached:* ~shop:* +@all -flushdb -flushall
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user atu on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~cached:* ~shop:* resetchannels +@all -flushdb -flushall"
127.0.0.1:37382> ACL SAVE
OK

查看一下 users.acl 文件,发现多了一行配置

[root@hecs-99107 redis7]# vi users.acl.bak 
user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all
user atu on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~cached:* ~shop:* resetchannels +@all -flushdb -flushall

如果手工在 users.acl 中增加一行配置如下

user atu2 on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~cached:* ~shop:* resetchannels +@all -flushdb -flushall

就增加了一个配置和 atu 一模一样,登录名称为 atu2 的用户。但是这个时候如果 redis 没有重启,这个新配置是不生效的,可以执行 ACL LOAD 命令重新载入最新的 acl 配置信息。

127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user atu on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~cached:* ~shop:* resetchannels +@all -flushdb -flushall"
127.0.0.1:37382> ACL LOAD
OK
127.0.0.1:37382> ACL LIST
1) "user admin on #eb1c66c230df28518559872a792755e1bd7558cb35d58ae9c52689b3dc9ef335 ~* resetchannels +@all"
2) "user atu on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~cached:* ~shop:* resetchannels +@all -flushdb -flushall"
3) "user atu2 on #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ~cached:* ~shop:* resetchannels +@all -flushdb -flushall"

后记

redis 新的用户管理方面的内容就先聊到这里。其中 key 的配置因为支持正则表达式,所以还能给出各种不同的表达式,这个由正则表达式的达人们来去实验吧。
不知道大家学废了没有呢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 228,835评论 6 534
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,676评论 3 419
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 176,730评论 0 380
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,118评论 1 314
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,873评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,266评论 1 324
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,330评论 3 443
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,482评论 0 289
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,036评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,846评论 3 356
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,025评论 1 371
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,575评论 5 362
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,279评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,684评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,953评论 1 289
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,751评论 3 394
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,016评论 2 375

推荐阅读更多精彩内容