背景
在Redis6.0之前的版本中,登陸Redis Server只需要輸入密碼(前提配置了密碼 requirepass )即可,不需要輸入使用者名稱,而且密碼也是明文配置到配置檔案中,安全性不高。並且應用連線也使用該密碼,導致應用有所有許可權處理資料,風險也極高。在Redis6.0有了ACL之後,終於解決了這些不安全的因素,可以按照不同的需求設定相關的使用者和許可權。本文來介紹下Redis 6.0 ACL相關的配置和使用。具體的說明可以檢視官方文件:ACL
說明
Redis ACL 是向後相容的,即預設情況下使用者為default,使用的是requirepass配置的密碼。要是不使用ACL功能,對舊版客戶端來說完全一樣。Redis Auth可以有2種方式進行工作:
1:舊版本的使用方式,預設使用者。相容舊版本Redis的支援 AUTH <password> 2:新方式,還需要驗證使用者名稱 AUTH <username> <password>
因為需要驗證使用者名稱了,所以客戶端的認證方式也多了引數:
--user <username> 驗證使用者名稱 --pass <password> 驗證密碼,是引數-a的別名;配合--user使用 --askpass 強制使用者輸入帶有STDIN掩碼的密碼
現在開始來說明如何在Redis中根據ACL來定製需要的使用者許可權。首先看ACL的help,瞭解大致的使用方法:ACL help
> ACL help 1) ACL <subcommand> arg arg ... arg. Subcommands are: 2) LOAD -- 從ACL檔案中重新載入使用者資訊. 3) SAVE -- 儲存當前的使用者配置資訊到ACL檔案. 4) LIST -- 以配置檔案格式顯示使用者詳細資訊. 5) USERS -- 列出所有註冊的使用者名稱. 6) SETUSER <username> [attribs ...] -- 建立或則修改一個使用者. 7) GETUSER <username> -- 得到一個使用者的詳細資訊. 8) DELUSER <username> [...] -- 刪除列表中的使用者. 9) CAT -- 列出可用的類別. 10) CAT <category> -- 列出指定類別中的命令. 11) GENPASS [<bits>] -- 生成一個安全的使用者密碼. 12) WHOAMI -- 返回當前的連線使用者. 13) LOG [<count> | RESET] -- 顯示ACL日誌條目.
使用方法:
在建立使用者之前,先說明下ACL的規則,首先看下一個完整的使用者許可權的格式:
> ACL LIST --顯示使用者資訊 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all"
格式說明:
參 數 |
說明 |
user | 使用者 |
default | 表示預設使用者名稱,或則自己定義的使用者名稱 |
on | 表示是否啟用該使用者,預設為off(禁用) |
#... | 表示使用者密碼,nopass表示不需要密碼 |
~* | 表示可以訪問的Key(正則匹配) |
+@ | 表示使用者的許可權,+/-表示授權還是銷權; @為許可權類。+@all 表示所有許可權 |
- 密碼相關:
① 配置密碼:一個使用者可以設定不同的密碼,即一個使用者可以有多個密碼。
-- 新增密碼 ## >開頭: >password,明文密碼; > ACL SETUSER zhoujy on >abc OK # 獲取雜湊值密碼 echo -n "cba" | shasum -a 256 6d970874d0db767a7058798973f22cf6589601edab57996312f2ef7b56e5584d ## #開頭: #hash,SHA-256雜湊值 > ACL SETUSER zhoujy on #6d970874d0db767a7058798973f22cf6589601edab57996312f2ef7b56e5584d OK ## 檢視 > ACL GETUSER zhoujy 1) "flags" 2) 1) "on" 3) "passwords" 4) 1) "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" 2) "6d970874d0db767a7058798973f22cf6589601edab57996312f2ef7b56e5584d" 5) "commands" 6) "-@all" 7) "keys" 8) (empty array) ## 認證密碼 > AUTH zhoujy abc OK > AUTH zhoujy cba OK -- 移除密碼 ## <開頭: <password ,明文密碼 > ACL SETUSER zhoujy <abc OK ## 用!開頭: !hash,SHA-256雜湊值 > ACL SETUSER zhoujy on !6d970874d0db767a7058798973f22cf6589601edab57996312f2ef7b56e5584d OK ## 檢視 > ACL GETUSER zhoujy 1) "flags" 2) 1) "on" 3) "passwords" 4) (empty array) 5) "commands" 6) "-@all" 7) "keys" 8) (empty array) ## 認證密碼 > AUTH zhoujy abc (error) WRONGPASS invalid username-password pair
② 清理/刪除密碼:通過nopass清理使用者的密碼,但是該使用者連線還是需要AUTH,只是密碼可以是任意值
-- 清理/刪除密碼,可以用任意密碼登陸 ## 檢視 > ACL GETUSER zhoujy 1) "flags" 2) 1) "on" 2) "allkeys" 3) "allcommands" 3) "passwords" 4) 1) "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" 2) "6d970874d0db767a7058798973f22cf6589601edab57996312f2ef7b56e5584d" 5) "commands" 6) "+@all" 7) "keys" 8) 1) "*" ## 刪除、清理使用者密碼 > ACL SETUSER zhoujy nopass OK ## 檢視 > ACL GETUSER zhoujy 1) "flags" 2) 1) "on" 2) "allkeys" 3) "allcommands" 4) "nopass" 3) "passwords" 4) (empty array) 5) "commands" 6) "+@all" 7) "keys" 8) 1) "*" ## 驗證 > AUTH zhoujy --需要AUTH (error) WRONGPASS invalid username-password pair > AUTH zhoujy '' --可以輸入任何密碼 OK -- 清理/刪除密碼,不能登陸,需要設定密碼後才能登陸 ## 檢視 > ACL GETUSER zhoujy 1) "flags" 2) 1) "on" 2) "allkeys" 3) "allcommands" 3) "passwords" 4) 1) "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" 2) "6d970874d0db767a7058798973f22cf6589601edab57996312f2ef7b56e5584d" 5) "commands" 6) "+@all" 7) "keys" 8) 1) "*" ## 刪除、清理使用者密碼 > ACL SETUSER zhoujy resetpass OK > ACL GETUSER zhoujy 1) "flags" 2) 1) "on" 2) "allkeys" 3) "allcommands" 3) "passwords" 4) (empty array) 5) "commands" 6) "+@all" 7) "keys" 8) 1) "*" ## 驗證,被resetpass重置密碼之後,不能登陸,只能設定密碼或則設定nopass才能登陸 > AUTH zhoujy (error) WRONGPASS invalid username-password pair > AUTH zhoujy '' (error) WRONGPASS invalid username-password pair
③ 重置使用者和密碼:實際上是執行 resetpass,resetkeys,off,-@all
## 檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" ## 重置使用者 > ACL SETUSER zhoujy reset OK ## 檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy off -@all"
④ 獲取隨機密碼:
-- 生成隨機密碼 > ACL GENPASS "7a3288b05577cb6fea9b1a9a8bcfe10d9589e64be74e8a0e16c131ba896c7bde"
- 鍵模式:~<pattern>,萬用字元模式。比如: ~*表示允許訪問所有key,也可以用
allkeys來表示~*。resetkeys 表示清空它之前所有的鍵模式,之後的鍵模式不影響。
-- 可以操作foo開頭和bar:開頭的所有key > ACL SETUSER zhoujy on >abc ~foo* ~bar:*+@all OK ## 檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~foo* ~bar:*+@all" -- 只能操作ob:開頭的key,前面的key模式被resetkeys清空了 > ACL SETUSER zhoujy on >abc ~foo* ~bar:* resetkeys ~ob:*+@all OK ## 檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~ob:*+@all" -- 操作所有key,allkeys 和 ~* 一樣 > ACL SETUSER zhoujy allkeys +@all OK > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" ## 檢視 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~*+@all"
- 許可權相關:許可權這塊涉及到的比較多:許可權的類別、類別裡包含的命令,以及子許可權。
注意:-@all表示沒有任何許可權;+@all表示有所有許可權;
-- 返回許可權的類別 > 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" -- 返回指定類別中的命令,下面hash是上面返回的一個結果 > ACL CAT hash 1) "hsetnx" 2) "hset" 3) "hlen" 4) "hmget" 5) "hincrbyfloat" 6) "hgetall" 7) "hvals" 8) "hscan" 9) "hkeys" 10) "hstrlen" 11) "hget" 12) "hdel" 13) "hexists" 14) "hincrby" 15) "hmset"
從上面的許可權列表裡看到:許可權對key的型別和命令的型別進行了分類,如有對型別進行分類:string、hash、list、set、sortedset,和對命令型別進行分類:connection、admin、dangerous。 以及對每個分類的方法進行說明,如上面檢視hash型別key的一些方法。
授權方法:+<command>:將命令新增到使用者可以呼叫的命令列表中,如+@hash -<command>: 將命令從使用者可以呼叫的命令列表中移除 +@<category>: 新增一類命令,如:@admin, @set, @hash ... 可以ACL CAT 檢視具體的操作指令。特殊類別@all表示所有命令,包括當前在伺服器中存在的命令,以及將來將通過模組載入的命令 -@<category>: 類似+@<category>,從客戶端可以呼叫的命令列表中刪除命令 +<command>|subcommand: 允許否則禁用特定子命令。注意,這種形式不允許像-DEBUG | SEGFAULT那樣,而只能以“ +”開頭 allcommands:+@all的別名,允許所有命令操作執行。注意,這意味著可以執行將來通過模組系統載入的所有命令。 nocommands:-@all的別名,不允許所有命令操作執行。
① 新增指定型別的許可權:+@hash
-- 新增hash型別key的所有許可權 > ACL SETUSER zhoujy +@hash OK ## 檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* -@all +@hash"
說明:使用者zhoujy只有對hash型別的key有許可權。
② 刪除指定型別的許可權:-@hash
-- 刪除hash型別key的所有許可權 > ACL SETUSER zhoujy -@hash +@string OK ## 檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad -@all +@string"
說明:使用者zhoujy移除對hash型別的key有許可權。
③ 指定特定key的許可權:如sortedset:~z*,z開頭的key-- 訪問指定key的正則 > ACL SETUSER zhoujy ~z* +@sortedset -@string OK ## 檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~z* -@all +@sortedset"
說明:使用者zhoujy只有對z開頭的key有許可權。
④ 授權只讀/只寫的許可權:+@read、+@write
-- 授權所有key的只讀許可權 > ACL SETUSER zhoujy ~* +@read OK ##檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* -@all +@read +@hash +@bitmap +@geo -georadiusbymember -hsetnx -setbit -hset -geoadd -bitop -hincrbyfloat -hdel -bitfield -hincrby -hmset -georadius" -- 授權所有key的只寫許可權 > ACL SETUSER zhoujy +@write OK ##檢視 192.168.163.134:8379> ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* -@all +@write +@list +@string +@stream +@fast +@blocking -dbsize -getrange -scard -xrevrange -zrank -llen -xread -ttl -get -ping -watch -publish -hlen -xrange -stralgo -zcount -getbit -lastsave -readonly -hmget -hello -zcard -discard -hstrlen -xinfo -hget -exists -bitfield_ro -select -role -zlexcount -zrevrank -lolwut -hexists -touch -lindex -unwatch -sismember -strlen -xlen -asking -type -mget -time -xpending -echo -multi -auth -readwrite -lrange -pttl -zscore -substr"
說明:使用者zhoujy對所有key有隻讀或則只寫的許可權,如果下個這對指定key,則替換 ~* 即可。
⑤ 授權管理許可權:@admin-- 授權管理許可權 > ACL SETUSER zhoujy on >abc ~* +@admin OK ## 檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* -@all +@admin +@dangerous -flushall -flushdb -swapdb -keys -role -sort -migrate -restore-asking -restore -info"
說明:使用者zhoujy有管理許可權,包含了危險操作的型別,但排除了-開頭命令的許可權。
⑥ 允許特定型別key的子命令許可權:
-- 設定子命令。 > ACL SETUSER zhoujy on >abc ~* -client +client|getname +client|setname OK ##檢視 > ACL LIST 1) "user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all" 2) "user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* -@all +client|getname +client|setname"
說明:開始刪除CLIENT命令,然後新增了兩個允許的子命令。請注意,不能相反,即不能+在前面,只能新增而不是排除子命令,因為將來可能會新增新的子命令。注意子命令匹配可能會增加一些效能損失。
⑦:特定用途的賬號許可權:Sentinel 和 Replicas-- Sentinel:允許使用者在主和副本例項中都有以下命令許可權 > ACL SETUSER sentinel-user >somepassword +client +subscribe +publish +ping +info +multi +slaveof +config +client +exec on OK -- Replicas:副本需要在主例項上有以下命令許可權 > ACL SETUSER replica-user >somepassword +psync +replconf +ping on OK
- 儲存、載入相關:save、load
通過ACL建立的使用者是儲存在記憶體裡的,如果Redis Server重啟則ACL建立的使用者會丟失,所以在建立完使用者後需要用save儲存,在重啟之後需要用load載入。有兩種方式進行儲存和載入:
1,使用ACL命令:ACL SAVE、ACL LOAD 2,使用Redis配置,使用者被定義,然後重啟伺服器並生效。 或者使用外部ACL檔案,使用ACL LOAD 來匯入ACL資訊
注意:ACL的配合檔案需要事先手動touch,否則例項啟動會失敗。在redis.conf裡配置和acl檔案裡配置的方法互不相容,Redis會要求使用其中一種。 否則例項啟動報錯:
-- 報錯資訊 #Configuring Redis with users defined in redis.conf and at the same setting an ACL file path is invalid. This setup is very likely to lead to configuration errors and security holes, please define either an ACL file or declare users directly in your redis.conf, but not both.
在redis.conf中指定使用者是一種非常簡單的方法,適用於簡單的用例。 當有多個使用者要定義時,在複雜的環境中,強烈建議使用ACL檔案。該2個檔案裡的配置內容是一致的,可以相互進行配置,如格式如下:在redis.conf和users.acl裡的格式
-- 配置檔案 user default on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all user zhoujy on #ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ~* +@all
① 儲存ACL規則
-- 儲存ACL規則 > ACL SAVE OK
② 載入ACL規則
-- 載入ACL規則 > ACL LOAD OK
說明:在使用ACL配置檔案之後,如果設定了預設使用者(default)規則的話,需要看配置檔案中aclfile和requirepass引數的先後順序,密碼以最後出現的為準。
- 日誌相關:顯示最近的ACL安全事件列表
通過ACL LOG [<count> | RESET] 返回ACL的日誌資訊,可以指定條目顯示,也可以進行重置:
-- 顯示日誌資訊 > ACL LOG 1 1) 1) "count" 2) (integer) 1 3) "reason" 4) "auth" 5) "context" 6) "toplevel" 7) "object" 8) "AUTH" 9) "username" 10) "zhoujy" 11) "age-seconds" 12) "282.90499999999997" 13) "client-info" 14) "id=5 addr=192.168.163.134:35246 fd=7 name= age=403 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=36 qbuf-free=32732 obl=0 oll=0 omem=0 events=r cmd=auth user=zhoujy" -- 重置日誌,類似slow > acl log reset OK
到此,大致的許可權介紹已經結束,後續會不定時更新相關內容。
場景說明
- 建立DBA管理賬號
> ACL SETUSER dba on #6d0ac515af9df81653ed0aa3ffa692663c3f556079791e2f00a4578990da66f3 allkeys +@all OK
- 建立讀寫賬號
> ACL SETUSER readwrite on >abc allkeys -@all +@read +@write OK
- 建立只讀賬號
> ACL SETUSER readonly on >abc allkeys -@all +@read OK
- 建立只寫賬號
> ACL SETUSER write_user on >abc allkeys -@all +@write OK
- 建立複製賬號
> ACL SETUSER replica-user >abc -@all +psync +replconf +ping on OK
- 建立哨兵賬號
> ACL SETUSER sentinel-user >abc -@all +client +subscribe +publish +ping +info +multi +slaveof +config +client +exec on OK
- 建立監控賬號
> ACL SETUSER monitor on >abc +monitor OK
- 建立指定key、有指定型別許可權的賬號
-- 指定對h開頭的hash型別的key有許可權 > ACL SETUSER ops_user on >abc ~h* +@hash OK
其中key的模式是正則匹配,需要~開頭,針對許可權則是hash的類,其許可權可以通過ACL CAT hash檢視。
注意:以上操作完只有需要執行ACL SAVE。不然重置之後使用者資訊全部都清空了。
總結
在預設配置中,Redis 6(第一個具有ACL的版本)的工作方式與Redis的舊版本完全相同,即每個新連線都能夠呼叫每個可能的命令並訪問每個鍵,因此ACL功能與舊版本向後相容。同樣使用requirepass配置指令配置密碼的舊方法仍然可以按預期工作(只是為預設使用者設定密碼)。關於ACL更多的操作指南可以看官方文件。PS:如果後續有補充會繼續更新到文章中。
參考文件:
https://redis.io/commands/acl-setuser