acl.tcl 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. start_server {tags {"acl"}} {
  2. test {Connections start with the default user} {
  3. r ACL WHOAMI
  4. } {default}
  5. test {It is possible to create new users} {
  6. r ACL setuser newuser
  7. }
  8. test {New users start disabled} {
  9. r ACL setuser newuser >passwd1
  10. catch {r AUTH newuser passwd1} err
  11. set err
  12. } {*WRONGPASS*}
  13. test {Enabling the user allows the login} {
  14. r ACL setuser newuser on +acl
  15. r AUTH newuser passwd1
  16. r ACL WHOAMI
  17. } {newuser}
  18. test {Only the set of correct passwords work} {
  19. r ACL setuser newuser >passwd2
  20. catch {r AUTH newuser passwd1} e
  21. assert {$e eq "OK"}
  22. catch {r AUTH newuser passwd2} e
  23. assert {$e eq "OK"}
  24. catch {r AUTH newuser passwd3} e
  25. set e
  26. } {*WRONGPASS*}
  27. test {It is possible to remove passwords from the set of valid ones} {
  28. r ACL setuser newuser <passwd1
  29. catch {r AUTH newuser passwd1} e
  30. set e
  31. } {*WRONGPASS*}
  32. test {Test password hashes can be added} {
  33. r ACL setuser newuser #34344e4d60c2b6d639b7bd22e18f2b0b91bc34bf0ac5f9952744435093cfb4e6
  34. catch {r AUTH newuser passwd4} e
  35. assert {$e eq "OK"}
  36. }
  37. test {Test password hashes validate input} {
  38. # Validate Length
  39. catch {r ACL setuser newuser #34344e4d60c2b6d639b7bd22e18f2b0b91bc34bf0ac5f9952744435093cfb4e} e
  40. # Validate character outside set
  41. catch {r ACL setuser newuser #34344e4d60c2b6d639b7bd22e18f2b0b91bc34bf0ac5f9952744435093cfb4eq} e
  42. set e
  43. } {*Error in ACL SETUSER modifier*}
  44. test {ACL GETUSER returns the password hash instead of the actual password} {
  45. set passstr [dict get [r ACL getuser newuser] passwords]
  46. assert_match {*34344e4d60c2b6d639b7bd22e18f2b0b91bc34bf0ac5f9952744435093cfb4e6*} $passstr
  47. assert_no_match {*passwd4*} $passstr
  48. }
  49. test {Test hashed passwords removal} {
  50. r ACL setuser newuser !34344e4d60c2b6d639b7bd22e18f2b0b91bc34bf0ac5f9952744435093cfb4e6
  51. set passstr [dict get [r ACL getuser newuser] passwords]
  52. assert_no_match {*34344e4d60c2b6d639b7bd22e18f2b0b91bc34bf0ac5f9952744435093cfb4e6*} $passstr
  53. }
  54. test {By default users are not able to access any command} {
  55. catch {r SET foo bar} e
  56. set e
  57. } {*NOPERM*}
  58. test {By default users are not able to access any key} {
  59. r ACL setuser newuser +set
  60. catch {r SET foo bar} e
  61. set e
  62. } {*NOPERM*key*}
  63. test {It's possible to allow the access of a subset of keys} {
  64. r ACL setuser newuser allcommands ~foo:* ~bar:*
  65. r SET foo:1 a
  66. r SET bar:2 b
  67. catch {r SET zap:3 c} e
  68. r ACL setuser newuser allkeys; # Undo keys ACL
  69. set e
  70. } {*NOPERM*key*}
  71. test {Users can be configured to authenticate with any password} {
  72. r ACL setuser newuser nopass
  73. r AUTH newuser zipzapblabla
  74. } {OK}
  75. test {ACLs can exclude single commands} {
  76. r ACL setuser newuser -ping
  77. r INCR mycounter ; # Should not raise an error
  78. catch {r PING} e
  79. set e
  80. } {*NOPERM*}
  81. test {ACLs can include or exclude whole classes of commands} {
  82. r ACL setuser newuser -@all +@set +acl
  83. r SADD myset a b c; # Should not raise an error
  84. r ACL setuser newuser +@all -@string
  85. r SADD myset a b c; # Again should not raise an error
  86. # String commands instead should raise an error
  87. catch {r SET foo bar} e
  88. r ACL setuser newuser allcommands; # Undo commands ACL
  89. set e
  90. } {*NOPERM*}
  91. test {ACLs can include single subcommands} {
  92. r ACL setuser newuser +@all -client
  93. r ACL setuser newuser +client|id +client|setname
  94. r CLIENT ID; # Should not fail
  95. r CLIENT SETNAME foo ; # Should not fail
  96. catch {r CLIENT KILL type master} e
  97. set e
  98. } {*NOPERM*}
  99. # Note that the order of the generated ACL rules is not stable in Redis
  100. # so we need to match the different parts and not as a whole string.
  101. test {ACL GETUSER is able to translate back command permissions} {
  102. # Subtractive
  103. r ACL setuser newuser reset +@all ~* -@string +incr -debug +debug|digest
  104. set cmdstr [dict get [r ACL getuser newuser] commands]
  105. assert_match {*+@all*} $cmdstr
  106. assert_match {*-@string*} $cmdstr
  107. assert_match {*+incr*} $cmdstr
  108. assert_match {*-debug +debug|digest**} $cmdstr
  109. # Additive
  110. r ACL setuser newuser reset +@string -incr +acl +debug|digest +debug|segfault
  111. set cmdstr [dict get [r ACL getuser newuser] commands]
  112. assert_match {*-@all*} $cmdstr
  113. assert_match {*+@string*} $cmdstr
  114. assert_match {*-incr*} $cmdstr
  115. assert_match {*+debug|digest*} $cmdstr
  116. assert_match {*+debug|segfault*} $cmdstr
  117. assert_match {*+acl*} $cmdstr
  118. }
  119. test {ACL #5998 regression: memory leaks adding / removing subcommands} {
  120. r AUTH default ""
  121. r ACL setuser newuser reset -debug +debug|a +debug|b +debug|c
  122. r ACL setuser newuser -debug
  123. # The test framework will detect a leak if any.
  124. }
  125. test {ACL LOG shows failed command executions at toplevel} {
  126. r ACL LOG RESET
  127. r ACL setuser antirez >foo on +set ~object:1234
  128. r ACL setuser antirez +eval +multi +exec
  129. r AUTH antirez foo
  130. catch {r GET foo}
  131. r AUTH default ""
  132. set entry [lindex [r ACL LOG] 0]
  133. assert {[dict get $entry username] eq {antirez}}
  134. assert {[dict get $entry context] eq {toplevel}}
  135. assert {[dict get $entry reason] eq {command}}
  136. assert {[dict get $entry object] eq {get}}
  137. }
  138. test {ACL LOG is able to test similar events} {
  139. r AUTH antirez foo
  140. catch {r GET foo}
  141. catch {r GET foo}
  142. catch {r GET foo}
  143. r AUTH default ""
  144. set entry [lindex [r ACL LOG] 0]
  145. assert {[dict get $entry count] == 4}
  146. }
  147. test {ACL LOG is able to log keys access violations and key name} {
  148. r AUTH antirez foo
  149. catch {r SET somekeynotallowed 1234}
  150. r AUTH default ""
  151. set entry [lindex [r ACL LOG] 0]
  152. assert {[dict get $entry reason] eq {key}}
  153. assert {[dict get $entry object] eq {somekeynotallowed}}
  154. }
  155. test {ACL LOG RESET is able to flush the entries in the log} {
  156. r ACL LOG RESET
  157. assert {[llength [r ACL LOG]] == 0}
  158. }
  159. test {ACL LOG can distinguish the transaction context (1)} {
  160. r AUTH antirez foo
  161. r MULTI
  162. catch {r INCR foo}
  163. catch {r EXEC}
  164. r AUTH default ""
  165. set entry [lindex [r ACL LOG] 0]
  166. assert {[dict get $entry context] eq {multi}}
  167. assert {[dict get $entry object] eq {incr}}
  168. }
  169. test {ACL LOG can distinguish the transaction context (2)} {
  170. set rd1 [redis_deferring_client]
  171. r ACL SETUSER antirez +incr
  172. r AUTH antirez foo
  173. r MULTI
  174. r INCR object:1234
  175. $rd1 ACL SETUSER antirez -incr
  176. $rd1 read
  177. catch {r EXEC}
  178. $rd1 close
  179. r AUTH default ""
  180. set entry [lindex [r ACL LOG] 0]
  181. assert {[dict get $entry context] eq {multi}}
  182. assert {[dict get $entry object] eq {incr}}
  183. r ACL SETUSER antirez -incr
  184. }
  185. test {ACL can log errors in the context of Lua scripting} {
  186. r AUTH antirez foo
  187. catch {r EVAL {redis.call('incr','foo')} 0}
  188. r AUTH default ""
  189. set entry [lindex [r ACL LOG] 0]
  190. assert {[dict get $entry context] eq {lua}}
  191. assert {[dict get $entry object] eq {incr}}
  192. }
  193. test {ACL LOG can accept a numerical argument to show less entries} {
  194. r AUTH antirez foo
  195. catch {r INCR foo}
  196. catch {r INCR foo}
  197. catch {r INCR foo}
  198. catch {r INCR foo}
  199. r AUTH default ""
  200. assert {[llength [r ACL LOG]] > 1}
  201. assert {[llength [r ACL LOG 2]] == 2}
  202. }
  203. test {ACL LOG can log failed auth attempts} {
  204. catch {r AUTH antirez wrong-password}
  205. set entry [lindex [r ACL LOG] 0]
  206. assert {[dict get $entry context] eq {toplevel}}
  207. assert {[dict get $entry reason] eq {auth}}
  208. assert {[dict get $entry object] eq {AUTH}}
  209. assert {[dict get $entry username] eq {antirez}}
  210. }
  211. test {ACL LOG entries are limited to a maximum amount} {
  212. r ACL LOG RESET
  213. r CONFIG SET acllog-max-len 5
  214. r AUTH antirez foo
  215. for {set j 0} {$j < 10} {incr j} {
  216. catch {r SET obj:$j 123}
  217. }
  218. r AUTH default ""
  219. assert {[llength [r ACL LOG]] == 5}
  220. }
  221. test {When default user is off, new connections are not authenticated} {
  222. r ACL setuser default off
  223. catch {set rd1 [redis_deferring_client]} e
  224. r ACL setuser default on
  225. set e
  226. } {*NOAUTH*}
  227. test {ACL HELP should not have unexpected options} {
  228. catch {r ACL help xxx} e
  229. assert_match "*Unknown subcommand or wrong number of arguments*" $e
  230. }
  231. }