start_server {tags {"acl"}} { test {Connections start with the default user} { r ACL WHOAMI } {default} test {It is possible to create new users} { r ACL setuser newuser } test {New users start disabled} { r ACL setuser newuser >passwd1 catch {r AUTH newuser passwd1} err set err } {*WRONGPASS*} test {Enabling the user allows the login} { r ACL setuser newuser on +acl r AUTH newuser passwd1 r ACL WHOAMI } {newuser} test {Only the set of correct passwords work} { r ACL setuser newuser >passwd2 catch {r AUTH newuser passwd1} e assert {$e eq "OK"} catch {r AUTH newuser passwd2} e assert {$e eq "OK"} catch {r AUTH newuser passwd3} e set e } {*WRONGPASS*} test {It is possible to remove passwords from the set of valid ones} { r ACL setuser newuser foo on +set ~object:1234 r ACL setuser antirez +eval +multi +exec r AUTH antirez foo catch {r GET foo} r AUTH default "" set entry [lindex [r ACL LOG] 0] assert {[dict get $entry username] eq {antirez}} assert {[dict get $entry context] eq {toplevel}} assert {[dict get $entry reason] eq {command}} assert {[dict get $entry object] eq {get}} } test {ACL LOG is able to test similar events} { r AUTH antirez foo catch {r GET foo} catch {r GET foo} catch {r GET foo} r AUTH default "" set entry [lindex [r ACL LOG] 0] assert {[dict get $entry count] == 4} } test {ACL LOG is able to log keys access violations and key name} { r AUTH antirez foo catch {r SET somekeynotallowed 1234} r AUTH default "" set entry [lindex [r ACL LOG] 0] assert {[dict get $entry reason] eq {key}} assert {[dict get $entry object] eq {somekeynotallowed}} } test {ACL LOG RESET is able to flush the entries in the log} { r ACL LOG RESET assert {[llength [r ACL LOG]] == 0} } test {ACL LOG can distinguish the transaction context (1)} { r AUTH antirez foo r MULTI catch {r INCR foo} catch {r EXEC} r AUTH default "" set entry [lindex [r ACL LOG] 0] assert {[dict get $entry context] eq {multi}} assert {[dict get $entry object] eq {incr}} } test {ACL LOG can distinguish the transaction context (2)} { set rd1 [redis_deferring_client] r ACL SETUSER antirez +incr r AUTH antirez foo r MULTI r INCR object:1234 $rd1 ACL SETUSER antirez -incr $rd1 read catch {r EXEC} $rd1 close r AUTH default "" set entry [lindex [r ACL LOG] 0] assert {[dict get $entry context] eq {multi}} assert {[dict get $entry object] eq {incr}} r ACL SETUSER antirez -incr } test {ACL can log errors in the context of Lua scripting} { r AUTH antirez foo catch {r EVAL {redis.call('incr','foo')} 0} r AUTH default "" set entry [lindex [r ACL LOG] 0] assert {[dict get $entry context] eq {lua}} assert {[dict get $entry object] eq {incr}} } test {ACL LOG can accept a numerical argument to show less entries} { r AUTH antirez foo catch {r INCR foo} catch {r INCR foo} catch {r INCR foo} catch {r INCR foo} r AUTH default "" assert {[llength [r ACL LOG]] > 1} assert {[llength [r ACL LOG 2]] == 2} } test {ACL LOG can log failed auth attempts} { catch {r AUTH antirez wrong-password} set entry [lindex [r ACL LOG] 0] assert {[dict get $entry context] eq {toplevel}} assert {[dict get $entry reason] eq {auth}} assert {[dict get $entry object] eq {AUTH}} assert {[dict get $entry username] eq {antirez}} } test {ACL LOG entries are limited to a maximum amount} { r ACL LOG RESET r CONFIG SET acllog-max-len 5 r AUTH antirez foo for {set j 0} {$j < 10} {incr j} { catch {r SET obj:$j 123} } r AUTH default "" assert {[llength [r ACL LOG]] == 5} } test {When default user is off, new connections are not authenticated} { r ACL setuser default off catch {set rd1 [redis_deferring_client]} e r ACL setuser default on set e } {*NOAUTH*} test {ACL HELP should not have unexpected options} { catch {r ACL help xxx} e assert_match "*Unknown subcommand or wrong number of arguments*" $e } test {Delete a user that the client doesn't use} { r ACL setuser not_used on >passwd assert {[r ACL deluser not_used] == 1} # The client is not closed assert {[r ping] eq {PONG}} } test {Delete a user that the client is using} { r ACL setuser using on +acl >passwd r AUTH using passwd # The client will receive reply normally assert {[r ACL deluser using] == 1} # The client is closed catch {[r ping]} e assert_match "*I/O error*" $e } } set server_path [tmpdir "server.acl"] exec cp -f tests/assets/user.acl $server_path start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"]] { # user alice on allcommands allkeys >alice # user bob on -@all +@set +acl ~set* >bob test "Alice: can excute all command" { r AUTH alice alice assert_equal "alice" [r acl whoami] r SET key value } test "Bob: just excute @set and acl command" { r AUTH bob bob assert_equal "bob" [r acl whoami] assert_equal "3" [r sadd set 1 2 3] catch {r SET key value} e set e } {*NOPERM*} test "ACL load and save" { r ACL setuser eve +get allkeys >eve on r ACL save # ACL load will free user and kill clients r ACL load catch {r ACL LIST} e assert_match {*I/O error*} $e reconnect r AUTH alice alice r SET key value r AUTH eve eve r GET key catch {r SET key value} e set e } {*NOPERM*} }