acl.tcl 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. start_server {tags {"acl external:skip"}} {
  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 {By default users are able to publish to any channel} {
  72. r ACL setuser psuser on >pspass +acl +client +@pubsub
  73. r AUTH psuser pspass
  74. r PUBLISH foo bar
  75. } {0}
  76. test {By default users are able to subscribe to any channel} {
  77. set rd [redis_deferring_client]
  78. $rd AUTH psuser pspass
  79. $rd read
  80. $rd SUBSCRIBE foo
  81. assert_match {subscribe foo 1} [$rd read]
  82. $rd close
  83. } {0}
  84. test {By default users are able to subscribe to any pattern} {
  85. set rd [redis_deferring_client]
  86. $rd AUTH psuser pspass
  87. $rd read
  88. $rd PSUBSCRIBE bar*
  89. assert_match {psubscribe bar\* 1} [$rd read]
  90. $rd close
  91. } {0}
  92. test {It's possible to allow publishing to a subset of channels} {
  93. r ACL setuser psuser resetchannels &foo:1 &bar:*
  94. assert_equal {0} [r PUBLISH foo:1 somemessage]
  95. assert_equal {0} [r PUBLISH bar:2 anothermessage]
  96. catch {r PUBLISH zap:3 nosuchmessage} e
  97. set e
  98. } {*NOPERM*channel*}
  99. test {Validate subset of channels is prefixed with resetchannels flag} {
  100. r ACL setuser hpuser on nopass resetchannels &foo +@all
  101. # Verify resetchannels flag is prefixed before the channel name(s)
  102. set users [r ACL LIST]
  103. set curruser "hpuser"
  104. foreach user [lshuffle $users] {
  105. if {[string first $curruser $user] != -1} {
  106. assert_equal {user hpuser on nopass resetchannels &foo +@all} $user
  107. }
  108. }
  109. # authenticate as hpuser
  110. r AUTH hpuser pass
  111. assert_equal {0} [r PUBLISH foo bar]
  112. catch {r PUBLISH bar game} e
  113. # Falling back to psuser for the below tests
  114. r AUTH psuser pspass
  115. r ACL deluser hpuser
  116. set e
  117. } {*NOPERM*channel*}
  118. test {In transaction queue publish/subscribe/psubscribe to unauthorized channel will fail} {
  119. r ACL setuser psuser +multi +discard
  120. r MULTI
  121. catch {r PUBLISH notexits helloworld} e
  122. r DISCARD
  123. assert_match {*NOPERM*} $e
  124. r MULTI
  125. catch {r SUBSCRIBE notexits foo:1} e
  126. r DISCARD
  127. assert_match {*NOPERM*} $e
  128. r MULTI
  129. catch {r PSUBSCRIBE notexits:* bar:*} e
  130. r DISCARD
  131. assert_match {*NOPERM*} $e
  132. }
  133. test {It's possible to allow subscribing to a subset of channels} {
  134. set rd [redis_deferring_client]
  135. $rd AUTH psuser pspass
  136. $rd read
  137. $rd SUBSCRIBE foo:1
  138. assert_match {subscribe foo:1 1} [$rd read]
  139. $rd SUBSCRIBE bar:2
  140. assert_match {subscribe bar:2 2} [$rd read]
  141. $rd SUBSCRIBE zap:3
  142. catch {$rd read} e
  143. set e
  144. } {*NOPERM*channel*}
  145. test {It's possible to allow subscribing to a subset of channel patterns} {
  146. set rd [redis_deferring_client]
  147. $rd AUTH psuser pspass
  148. $rd read
  149. $rd PSUBSCRIBE foo:1
  150. assert_match {psubscribe foo:1 1} [$rd read]
  151. $rd PSUBSCRIBE bar:*
  152. assert_match {psubscribe bar:\* 2} [$rd read]
  153. $rd PSUBSCRIBE bar:baz
  154. catch {$rd read} e
  155. set e
  156. } {*NOPERM*channel*}
  157. test {Subscribers are killed when revoked of channel permission} {
  158. set rd [redis_deferring_client]
  159. r ACL setuser psuser resetchannels &foo:1
  160. $rd AUTH psuser pspass
  161. $rd read
  162. $rd CLIENT SETNAME deathrow
  163. $rd read
  164. $rd SUBSCRIBE foo:1
  165. $rd read
  166. r ACL setuser psuser resetchannels
  167. assert_no_match {*deathrow*} [r CLIENT LIST]
  168. $rd close
  169. } {0}
  170. test {Subscribers are killed when revoked of pattern permission} {
  171. set rd [redis_deferring_client]
  172. r ACL setuser psuser resetchannels &bar:*
  173. $rd AUTH psuser pspass
  174. $rd read
  175. $rd CLIENT SETNAME deathrow
  176. $rd read
  177. $rd PSUBSCRIBE bar:*
  178. $rd read
  179. r ACL setuser psuser resetchannels
  180. assert_no_match {*deathrow*} [r CLIENT LIST]
  181. $rd close
  182. } {0}
  183. test {Subscribers are pardoned if literal permissions are retained and/or gaining allchannels} {
  184. set rd [redis_deferring_client]
  185. r ACL setuser psuser resetchannels &foo:1 &bar:*
  186. $rd AUTH psuser pspass
  187. $rd read
  188. $rd CLIENT SETNAME pardoned
  189. $rd read
  190. $rd SUBSCRIBE foo:1
  191. $rd read
  192. $rd PSUBSCRIBE bar:*
  193. $rd read
  194. r ACL setuser psuser resetchannels &foo:1 &bar:* &baz:qaz &zoo:*
  195. assert_match {*pardoned*} [r CLIENT LIST]
  196. r ACL setuser psuser allchannels
  197. assert_match {*pardoned*} [r CLIENT LIST]
  198. $rd close
  199. } {0}
  200. test {Users can be configured to authenticate with any password} {
  201. r ACL setuser newuser nopass
  202. r AUTH newuser zipzapblabla
  203. } {OK}
  204. test {ACLs can exclude single commands} {
  205. r ACL setuser newuser -ping
  206. r INCR mycounter ; # Should not raise an error
  207. catch {r PING} e
  208. set e
  209. } {*NOPERM*}
  210. test {ACLs can include or exclude whole classes of commands} {
  211. r ACL setuser newuser -@all +@set +acl
  212. r SADD myset a b c; # Should not raise an error
  213. r ACL setuser newuser +@all -@string
  214. r SADD myset a b c; # Again should not raise an error
  215. # String commands instead should raise an error
  216. catch {r SET foo bar} e
  217. r ACL setuser newuser allcommands; # Undo commands ACL
  218. set e
  219. } {*NOPERM*}
  220. test {ACLs can include single subcommands} {
  221. r ACL setuser newuser +@all -client
  222. r ACL setuser newuser +client|id +client|setname
  223. set cmdstr [dict get [r ACL getuser newuser] commands]
  224. assert_match {+@all*-client*+client|id*} $cmdstr
  225. assert_match {+@all*-client*+client|setname*} $cmdstr
  226. r CLIENT ID; # Should not fail
  227. r CLIENT SETNAME foo ; # Should not fail
  228. catch {r CLIENT KILL type master} e
  229. set e
  230. } {*NOPERM*}
  231. test {ACLs can exclude single subcommands, case 1} {
  232. r ACL setuser newuser +@all -client|kill
  233. set cmdstr [dict get [r ACL getuser newuser] commands]
  234. assert_equal {+@all -client|kill} $cmdstr
  235. r CLIENT ID; # Should not fail
  236. r CLIENT SETNAME foo ; # Should not fail
  237. catch {r CLIENT KILL type master} e
  238. set e
  239. } {*NOPERM*}
  240. test {ACLs can exclude single subcommands, case 2} {
  241. r ACL setuser newuser -@all +acl +config -config|set
  242. set cmdstr [dict get [r ACL getuser newuser] commands]
  243. assert_match {*+config*} $cmdstr
  244. assert_match {*-config|set*} $cmdstr
  245. r CONFIG GET loglevel; # Should not fail
  246. catch {r CONFIG SET loglevel debug} e
  247. set e
  248. } {*NOPERM*}
  249. test {ACLs can include a subcommand with a specific arg} {
  250. r ACL setuser newuser +@all -config|get
  251. r ACL setuser newuser +config|get|appendonly
  252. set cmdstr [dict get [r ACL getuser newuser] commands]
  253. assert_match {*-config|get*} $cmdstr
  254. assert_match {*+config|get|appendonly*} $cmdstr
  255. r CONFIG GET appendonly; # Should not fail
  256. catch {r CONFIG GET loglevel} e
  257. set e
  258. } {*NOPERM*}
  259. test {ACLs including of a type includes also subcommands} {
  260. r ACL setuser newuser -@all +acl +@stream
  261. r XADD key * field value
  262. r XINFO STREAM key
  263. }
  264. test {ACLs can block SELECT of all but a specific DB} {
  265. r ACL setuser newuser -@all +acl +select|0
  266. set cmdstr [dict get [r ACL getuser newuser] commands]
  267. assert_match {*+select|0*} $cmdstr
  268. r SELECT 0
  269. catch {r SELECT 1} e
  270. set e
  271. } {*NOPERM*}
  272. test {ACLs can block all DEBUG subcommands except one} {
  273. r ACL setuser newuser -@all +acl +incr +debug|object
  274. set cmdstr [dict get [r ACL getuser newuser] commands]
  275. assert_match {*+debug|object*} $cmdstr
  276. r INCR key
  277. r DEBUG OBJECT key
  278. catch {r DEBUG SEGFAULT} e
  279. set e
  280. } {*NOPERM*}
  281. test {ACLs set can include subcommands, if already full command exists} {
  282. r ACL setuser bob +memory|doctor
  283. set cmdstr [dict get [r ACL getuser bob] commands]
  284. assert_equal {-@all +memory|doctor} $cmdstr
  285. # Validate the commands have got engulfed to +memory.
  286. r ACL setuser bob +memory
  287. set cmdstr [dict get [r ACL getuser bob] commands]
  288. assert_equal {-@all +memory} $cmdstr
  289. # Appending to the existing access string of bob.
  290. r ACL setuser bob +@all +client|id
  291. # Validate the new commands has got engulfed to +@all.
  292. set cmdstr [dict get [r ACL getuser bob] commands]
  293. assert_equal {+@all} $cmdstr
  294. r ACL setuser bob >passwd1 on
  295. r AUTH bob passwd1
  296. r CLIENT ID; # Should not fail
  297. r MEMORY DOCTOR; # Should not fail
  298. }
  299. test {ACLs set can exclude subcommands, if already full command exists} {
  300. r ACL setuser alice +@all -memory|doctor
  301. set cmdstr [dict get [r ACL getuser alice] commands]
  302. assert_equal {+@all -memory|doctor} $cmdstr
  303. r ACL setuser alice >passwd1 on
  304. r AUTH alice passwd1
  305. catch {r MEMORY DOCTOR} e
  306. assert_match {*NOPERM*} $e
  307. r MEMORY STATS ;# should work
  308. # Validate the commands have got engulfed to -memory.
  309. r ACL setuser alice +@all -memory
  310. set cmdstr [dict get [r ACL getuser alice] commands]
  311. assert_equal {+@all -memory} $cmdstr
  312. catch {r MEMORY DOCTOR} e
  313. assert_match {*NOPERM*} $e
  314. catch {r MEMORY STATS} e
  315. assert_match {*NOPERM*} $e
  316. # Appending to the existing access string of alice.
  317. r ACL setuser alice -@all
  318. # Now, alice can't do anything, we need to auth newuser to execute ACL GETUSER
  319. r AUTH newuser passwd1
  320. # Validate the new commands has got engulfed to -@all.
  321. set cmdstr [dict get [r ACL getuser alice] commands]
  322. assert_equal {-@all} $cmdstr
  323. r AUTH alice passwd1
  324. catch {r GET key} e
  325. assert_match {*NOPERM*} $e
  326. catch {r MEMORY STATS} e
  327. assert_match {*NOPERM*} $e
  328. # Auth newuser before the next test
  329. r AUTH newuser passwd1
  330. }
  331. # Note that the order of the generated ACL rules is not stable in Redis
  332. # so we need to match the different parts and not as a whole string.
  333. test {ACL GETUSER is able to translate back command permissions} {
  334. # Subtractive
  335. r ACL setuser newuser reset +@all ~* -@string +incr -debug +debug|digest
  336. set cmdstr [dict get [r ACL getuser newuser] commands]
  337. assert_match {*+@all*} $cmdstr
  338. assert_match {*-@string*} $cmdstr
  339. assert_match {*+incr*} $cmdstr
  340. assert_match {*-debug +debug|digest**} $cmdstr
  341. # Additive
  342. r ACL setuser newuser reset +@string -incr +acl +debug|digest +debug|segfault
  343. set cmdstr [dict get [r ACL getuser newuser] commands]
  344. assert_match {*-@all*} $cmdstr
  345. assert_match {*+@string*} $cmdstr
  346. assert_match {*-incr*} $cmdstr
  347. assert_match {*+debug|digest*} $cmdstr
  348. assert_match {*+debug|segfault*} $cmdstr
  349. assert_match {*+acl*} $cmdstr
  350. }
  351. # A regression test make sure that as long as there is a simple
  352. # category defining the commands, that it will be used as is.
  353. test {ACL GETUSER provides reasonable results} {
  354. set categories [r ACL CAT]
  355. # Test that adding each single category will
  356. # result in just that category with both +@all and -@all
  357. foreach category $categories {
  358. # Test for future commands where allowed
  359. r ACL setuser additive reset +@all "-@$category"
  360. set cmdstr [dict get [r ACL getuser additive] commands]
  361. assert_equal "+@all -@$category" $cmdstr
  362. # Test for future commands where disallowed
  363. r ACL setuser restrictive reset -@all "+@$category"
  364. set cmdstr [dict get [r ACL getuser restrictive] commands]
  365. assert_equal "-@all +@$category" $cmdstr
  366. }
  367. }
  368. test {ACL #5998 regression: memory leaks adding / removing subcommands} {
  369. r AUTH default ""
  370. r ACL setuser newuser reset -debug +debug|a +debug|b +debug|c
  371. r ACL setuser newuser -debug
  372. # The test framework will detect a leak if any.
  373. }
  374. test {ACL LOG shows failed command executions at toplevel} {
  375. r ACL LOG RESET
  376. r ACL setuser antirez >foo on +set ~object:1234
  377. r ACL setuser antirez +eval +multi +exec
  378. r ACL setuser antirez resetchannels +publish
  379. r AUTH antirez foo
  380. catch {r GET foo}
  381. r AUTH default ""
  382. set entry [lindex [r ACL LOG] 0]
  383. assert {[dict get $entry username] eq {antirez}}
  384. assert {[dict get $entry context] eq {toplevel}}
  385. assert {[dict get $entry reason] eq {command}}
  386. assert {[dict get $entry object] eq {get}}
  387. }
  388. test {ACL LOG is able to test similar events} {
  389. r AUTH antirez foo
  390. catch {r GET foo}
  391. catch {r GET foo}
  392. catch {r GET foo}
  393. r AUTH default ""
  394. set entry [lindex [r ACL LOG] 0]
  395. assert {[dict get $entry count] == 4}
  396. }
  397. test {ACL LOG is able to log keys access violations and key name} {
  398. r AUTH antirez foo
  399. catch {r SET somekeynotallowed 1234}
  400. r AUTH default ""
  401. set entry [lindex [r ACL LOG] 0]
  402. assert {[dict get $entry reason] eq {key}}
  403. assert {[dict get $entry object] eq {somekeynotallowed}}
  404. }
  405. test {ACL LOG is able to log channel access violations and channel name} {
  406. r AUTH antirez foo
  407. catch {r PUBLISH somechannelnotallowed nullmsg}
  408. r AUTH default ""
  409. set entry [lindex [r ACL LOG] 0]
  410. assert {[dict get $entry reason] eq {channel}}
  411. assert {[dict get $entry object] eq {somechannelnotallowed}}
  412. }
  413. test {ACL LOG RESET is able to flush the entries in the log} {
  414. r ACL LOG RESET
  415. assert {[llength [r ACL LOG]] == 0}
  416. }
  417. test {ACL LOG can distinguish the transaction context (1)} {
  418. r AUTH antirez foo
  419. r MULTI
  420. catch {r INCR foo}
  421. catch {r EXEC}
  422. r AUTH default ""
  423. set entry [lindex [r ACL LOG] 0]
  424. assert {[dict get $entry context] eq {multi}}
  425. assert {[dict get $entry object] eq {incr}}
  426. }
  427. test {ACL LOG can distinguish the transaction context (2)} {
  428. set rd1 [redis_deferring_client]
  429. r ACL SETUSER antirez +incr
  430. r AUTH antirez foo
  431. r MULTI
  432. r INCR object:1234
  433. $rd1 ACL SETUSER antirez -incr
  434. $rd1 read
  435. catch {r EXEC}
  436. $rd1 close
  437. r AUTH default ""
  438. set entry [lindex [r ACL LOG] 0]
  439. assert {[dict get $entry context] eq {multi}}
  440. assert {[dict get $entry object] eq {incr}}
  441. r ACL SETUSER antirez -incr
  442. }
  443. test {ACL can log errors in the context of Lua scripting} {
  444. r AUTH antirez foo
  445. catch {r EVAL {redis.call('incr','foo')} 0}
  446. r AUTH default ""
  447. set entry [lindex [r ACL LOG] 0]
  448. assert {[dict get $entry context] eq {lua}}
  449. assert {[dict get $entry object] eq {incr}}
  450. }
  451. test {ACL LOG can accept a numerical argument to show less entries} {
  452. r AUTH antirez foo
  453. catch {r INCR foo}
  454. catch {r INCR foo}
  455. catch {r INCR foo}
  456. catch {r INCR foo}
  457. r AUTH default ""
  458. assert {[llength [r ACL LOG]] > 1}
  459. assert {[llength [r ACL LOG 2]] == 2}
  460. }
  461. test {ACL LOG can log failed auth attempts} {
  462. catch {r AUTH antirez wrong-password}
  463. set entry [lindex [r ACL LOG] 0]
  464. assert {[dict get $entry context] eq {toplevel}}
  465. assert {[dict get $entry reason] eq {auth}}
  466. assert {[dict get $entry object] eq {AUTH}}
  467. assert {[dict get $entry username] eq {antirez}}
  468. }
  469. test {ACL LOG entries are limited to a maximum amount} {
  470. r ACL LOG RESET
  471. r CONFIG SET acllog-max-len 5
  472. r AUTH antirez foo
  473. for {set j 0} {$j < 10} {incr j} {
  474. catch {r SET obj:$j 123}
  475. }
  476. r AUTH default ""
  477. assert {[llength [r ACL LOG]] == 5}
  478. }
  479. test {When default user is off, new connections are not authenticated} {
  480. r ACL setuser default off
  481. catch {set rd1 [redis_deferring_client]} e
  482. r ACL setuser default on
  483. set e
  484. } {*NOAUTH*}
  485. test {When default user has no command permission, hello command still works for other users} {
  486. r ACL setuser secure-user >supass on +@all
  487. r ACL setuser default -@all
  488. r HELLO 2 AUTH secure-user supass
  489. r ACL setuser default nopass +@all
  490. r AUTH default ""
  491. }
  492. test {ACL HELP should not have unexpected options} {
  493. catch {r ACL help xxx} e
  494. assert_match "*wrong number of arguments*" $e
  495. }
  496. test {Delete a user that the client doesn't use} {
  497. r ACL setuser not_used on >passwd
  498. assert {[r ACL deluser not_used] == 1}
  499. # The client is not closed
  500. assert {[r ping] eq {PONG}}
  501. }
  502. test {Delete a user that the client is using} {
  503. r ACL setuser using on +acl >passwd
  504. r AUTH using passwd
  505. # The client will receive reply normally
  506. assert {[r ACL deluser using] == 1}
  507. # The client is closed
  508. catch {[r ping]} e
  509. assert_match "*I/O error*" $e
  510. }
  511. }
  512. set server_path [tmpdir "server.acl"]
  513. exec cp -f tests/assets/user.acl $server_path
  514. start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"] tags [list "external:skip"]] {
  515. # user alice on allcommands allkeys >alice
  516. # user bob on -@all +@set +acl ~set* >bob
  517. # user default on nopass ~* +@all
  518. test {default: load from include file, can access any channels} {
  519. r SUBSCRIBE foo
  520. r PSUBSCRIBE bar*
  521. r UNSUBSCRIBE
  522. r PUNSUBSCRIBE
  523. r PUBLISH hello world
  524. }
  525. test {default: with config acl-pubsub-default allchannels after reset, can access any channels} {
  526. r ACL setuser default reset on nopass ~* +@all
  527. r SUBSCRIBE foo
  528. r PSUBSCRIBE bar*
  529. r UNSUBSCRIBE
  530. r PUNSUBSCRIBE
  531. r PUBLISH hello world
  532. }
  533. test {default: with config acl-pubsub-default resetchannels after reset, can not access any channels} {
  534. r CONFIG SET acl-pubsub-default resetchannels
  535. r ACL setuser default reset on nopass ~* +@all
  536. catch {r SUBSCRIBE foo} e
  537. assert_match {*NOPERM*} $e
  538. catch {r PSUBSCRIBE bar*} e
  539. assert_match {*NOPERM*} $e
  540. catch {r PUBLISH hello world} e
  541. assert_match {*NOPERM*} $e
  542. r CONFIG SET acl-pubsub-default resetchannels
  543. }
  544. test {Alice: can execute all command} {
  545. r AUTH alice alice
  546. assert_equal "alice" [r acl whoami]
  547. r SET key value
  548. }
  549. test {Bob: just execute @set and acl command} {
  550. r AUTH bob bob
  551. assert_equal "bob" [r acl whoami]
  552. assert_equal "3" [r sadd set 1 2 3]
  553. catch {r SET key value} e
  554. set e
  555. } {*NOPERM*}
  556. test {ACL load and save} {
  557. r ACL setuser eve +get allkeys >eve on
  558. r ACL save
  559. # ACL load will free user and kill clients
  560. r ACL load
  561. catch {r ACL LIST} e
  562. assert_match {*I/O error*} $e
  563. reconnect
  564. r AUTH alice alice
  565. r SET key value
  566. r AUTH eve eve
  567. r GET key
  568. catch {r SET key value} e
  569. set e
  570. } {*NOPERM*}
  571. test {ACL load and save with restricted channels} {
  572. r AUTH alice alice
  573. r ACL setuser harry on nopass resetchannels &test +@all ~*
  574. r ACL save
  575. # ACL load will free user and kill clients
  576. r ACL load
  577. catch {r ACL LIST} e
  578. assert_match {*I/O error*} $e
  579. reconnect
  580. r AUTH harry anything
  581. r publish test bar
  582. catch {r publish test1 bar} e
  583. r ACL deluser harry
  584. set e
  585. } {*NOPERM*}
  586. }
  587. set server_path [tmpdir "resetchannels.acl"]
  588. exec cp -f tests/assets/nodefaultuser.acl $server_path
  589. exec cp -f tests/assets/default.conf $server_path
  590. start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "resetchannels" "aclfile" "nodefaultuser.acl"] tags [list "external:skip"]] {
  591. test {Default user has access to all channels irrespective of flag} {
  592. set channelinfo [dict get [r ACL getuser default] channels]
  593. assert_equal "*" $channelinfo
  594. set channelinfo [dict get [r ACL getuser alice] channels]
  595. assert_equal "" $channelinfo
  596. }
  597. test {Update acl-pubsub-default, existing users shouldn't get affected} {
  598. set channelinfo [dict get [r ACL getuser default] channels]
  599. assert_equal "*" $channelinfo
  600. r CONFIG set acl-pubsub-default allchannels
  601. r ACL setuser mydefault
  602. set channelinfo [dict get [r ACL getuser mydefault] channels]
  603. assert_equal "*" $channelinfo
  604. r CONFIG set acl-pubsub-default resetchannels
  605. set channelinfo [dict get [r ACL getuser mydefault] channels]
  606. assert_equal "*" $channelinfo
  607. }
  608. test {Single channel is valid} {
  609. r ACL setuser onechannel &test
  610. set channelinfo [dict get [r ACL getuser onechannel] channels]
  611. assert_equal test $channelinfo
  612. r ACL deluser onechannel
  613. }
  614. test {Single channel is not valid with allchannels} {
  615. r CONFIG set acl-pubsub-default allchannels
  616. catch {r ACL setuser onechannel &test} err
  617. r CONFIG set acl-pubsub-default resetchannels
  618. set err
  619. } {*start with an empty list of channels*}
  620. }
  621. set server_path [tmpdir "resetchannels.acl"]
  622. exec cp -f tests/assets/nodefaultuser.acl $server_path
  623. exec cp -f tests/assets/default.conf $server_path
  624. start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "resetchannels" "aclfile" "nodefaultuser.acl"] tags [list "external:skip"]] {
  625. test {Only default user has access to all channels irrespective of flag} {
  626. set channelinfo [dict get [r ACL getuser default] channels]
  627. assert_equal "*" $channelinfo
  628. set channelinfo [dict get [r ACL getuser alice] channels]
  629. assert_equal "" $channelinfo
  630. }
  631. }
  632. start_server {overrides {user "default on nopass ~* +@all"} tags {"external:skip"}} {
  633. test {default: load from config file, can access any channels} {
  634. r SUBSCRIBE foo
  635. r PSUBSCRIBE bar*
  636. r UNSUBSCRIBE
  637. r PUNSUBSCRIBE
  638. r PUBLISH hello world
  639. }
  640. }
  641. set server_path [tmpdir "duplicate.acl"]
  642. exec cp -f tests/assets/user.acl $server_path
  643. exec cp -f tests/assets/default.conf $server_path
  644. start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"] tags [list "external:skip"]] {
  645. test {Test loading an ACL file with duplicate users} {
  646. exec cp -f tests/assets/user.acl $server_path
  647. # Corrupt the ACL file
  648. set corruption "\nuser alice on nopass ~* -@all"
  649. exec echo $corruption >> $server_path/user.acl
  650. catch {r ACL LOAD} err
  651. assert_match {*Duplicate user 'alice' found*} $err
  652. # Verify the previous users still exist
  653. # NOTE: A missing user evaluates to an empty
  654. # string.
  655. assert {[r ACL GETUSER alice] != ""}
  656. assert_equal [dict get [r ACL GETUSER alice] commands] "+@all"
  657. assert {[r ACL GETUSER bob] != ""}
  658. assert {[r ACL GETUSER default] != ""}
  659. }
  660. test {Test loading an ACL file with duplicate default user} {
  661. exec cp -f tests/assets/user.acl $server_path
  662. # Corrupt the ACL file
  663. set corruption "\nuser default on nopass ~* -@all"
  664. exec echo $corruption >> $server_path/user.acl
  665. catch {r ACL LOAD} err
  666. assert_match {*Duplicate user 'default' found*} $err
  667. # Verify the previous users still exist
  668. # NOTE: A missing user evaluates to an empty
  669. # string.
  670. assert {[r ACL GETUSER alice] != ""}
  671. assert_equal [dict get [r ACL GETUSER alice] commands] "+@all"
  672. assert {[r ACL GETUSER bob] != ""}
  673. assert {[r ACL GETUSER default] != ""}
  674. }
  675. test {Test loading duplicate users in config on startup} {
  676. catch {exec src/redis-server --user foo --user foo} err
  677. assert_match {*Duplicate user*} $err
  678. catch {exec src/redis-server --user default --user default} err
  679. assert_match {*Duplicate user*} $err
  680. } {} {external:skip}
  681. }