Show subcommand full name in error log / ACL LOG (#10105)

Use `getFullCommandName` to get the full name of the command.
It can also get the full name of the subcommand, like "script|help".

Before:
```
> SCRIPT HELP
(error) NOPERM this user has no permissions to run the 'help' command or its subcommand

> ACL LOG
    7) "object"
    8) "help"
```

After:
```
> SCRIPT HELP
(error) NOPERM this user has no permissions to run the 'script|help' command

> ACL LOG
    7) "object"
    8) "script|help"
```

Fix #10094
This commit is contained in:
Binbin 2022-01-13 02:05:14 +08:00 committed by GitHub
parent e22146b07a
commit 20c33fe6a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 38 deletions

View File

@ -1904,7 +1904,7 @@ void addACLLogEntry(client *c, int reason, int context, int argpos, sds username
le->object = object;
} else {
switch(reason) {
case ACL_DENIED_CMD: le->object = sdsnew(c->cmd->name); break;
case ACL_DENIED_CMD: le->object = getFullCommandName(c->cmd); break;
case ACL_DENIED_KEY: le->object = sdsdup(c->argv[argpos]->ptr); break;
case ACL_DENIED_CHANNEL: le->object = sdsdup(c->argv[argpos]->ptr); break;
case ACL_DENIED_AUTH: le->object = sdsdup(c->argv[0]->ptr); break;

View File

@ -3439,10 +3439,14 @@ int processCommand(client *c) {
addACLLogEntry(c,acl_retval,(c->flags & CLIENT_MULTI) ? ACL_LOG_CTX_MULTI : ACL_LOG_CTX_TOPLEVEL,acl_errpos,NULL,NULL);
switch (acl_retval) {
case ACL_DENIED_CMD:
{
sds cmdname = getFullCommandName(c->cmd);
rejectCommandFormat(c,
"-NOPERM this user has no permissions to run "
"the '%s' command or its subcommand", c->cmd->name);
"the '%s' command", cmdname);
sdsfree(cmdname);
break;
}
case ACL_DENIED_KEY:
rejectCommandFormat(c,
"-NOPERM this user has no permissions to access "

View File

@ -64,7 +64,7 @@ start_server {tags {"acl external:skip"}} {
test {By default users are not able to access any command} {
catch {r SET foo bar} e
set e
} {*NOPERM*}
} {*NOPERM*set*}
test {By default users are not able to access any key} {
r ACL setuser newuser +set
@ -161,17 +161,14 @@ start_server {tags {"acl external:skip"}} {
test {In transaction queue publish/subscribe/psubscribe to unauthorized channel will fail} {
r ACL setuser psuser +multi +discard
r MULTI
catch {r PUBLISH notexits helloworld} e
assert_error {*NOPERM*channel*} {r PUBLISH notexits helloworld}
r DISCARD
assert_match {*NOPERM*} $e
r MULTI
catch {r SUBSCRIBE notexits foo:1} e
assert_error {*NOPERM*channel*} {r SUBSCRIBE notexits foo:1}
r DISCARD
assert_match {*NOPERM*} $e
r MULTI
catch {r PSUBSCRIBE notexits:* bar:*} e
assert_error {*NOPERM*channel*} {r PSUBSCRIBE notexits:* bar:*}
r DISCARD
assert_match {*NOPERM*} $e
}
test {It's possible to allow subscribing to a subset of channels} {
@ -285,7 +282,7 @@ start_server {tags {"acl external:skip"}} {
r INCR mycounter ; # Should not raise an error
catch {r PING} e
set e
} {*NOPERM*}
} {*NOPERM*ping*}
test {ACLs can include or exclude whole classes of commands} {
r ACL setuser newuser -@all +@set +acl
@ -296,7 +293,7 @@ start_server {tags {"acl external:skip"}} {
catch {r SET foo bar} e
r ACL setuser newuser allcommands; # Undo commands ACL
set e
} {*NOPERM*}
} {*NOPERM*set*}
test {ACLs can include single subcommands} {
r ACL setuser newuser +@all -client
@ -308,7 +305,7 @@ start_server {tags {"acl external:skip"}} {
r CLIENT SETNAME foo ; # Should not fail
catch {r CLIENT KILL type master} e
set e
} {*NOPERM*}
} {*NOPERM*client|kill*}
test {ACLs can exclude single subcommands, case 1} {
r ACL setuser newuser +@all -client|kill
@ -318,7 +315,7 @@ start_server {tags {"acl external:skip"}} {
r CLIENT SETNAME foo ; # Should not fail
catch {r CLIENT KILL type master} e
set e
} {*NOPERM*}
} {*NOPERM*client|kill*}
test {ACLs can exclude single subcommands, case 2} {
r ACL setuser newuser -@all +acl +config -config|set
@ -328,7 +325,7 @@ start_server {tags {"acl external:skip"}} {
r CONFIG GET loglevel; # Should not fail
catch {r CONFIG SET loglevel debug} e
set e
} {*NOPERM*}
} {*NOPERM*config|set*}
test {ACLs can include a subcommand with a specific arg} {
r ACL setuser newuser +@all -config|get
@ -339,7 +336,7 @@ start_server {tags {"acl external:skip"}} {
r CONFIG GET appendonly; # Should not fail
catch {r CONFIG GET loglevel} e
set e
} {*NOPERM*}
} {*NOPERM*config|get*}
test {ACLs including of a type includes also subcommands} {
r ACL setuser newuser -@all +acl +@stream
@ -354,7 +351,7 @@ start_server {tags {"acl external:skip"}} {
r SELECT 0
catch {r SELECT 1} e
set e
} {*NOPERM*}
} {*NOPERM*select*}
test {ACLs can block all DEBUG subcommands except one} {
r ACL setuser newuser -@all +acl +incr +debug|object
@ -364,7 +361,7 @@ start_server {tags {"acl external:skip"}} {
r DEBUG OBJECT key
catch {r DEBUG SEGFAULT} e
set e
} {*NOPERM*}
} {*NOPERM*debug*}
test {ACLs set can include subcommands, if already full command exists} {
r ACL setuser bob +memory|doctor
@ -396,8 +393,7 @@ start_server {tags {"acl external:skip"}} {
r ACL setuser alice >passwd1 on
r AUTH alice passwd1
catch {r MEMORY DOCTOR} e
assert_match {*NOPERM*} $e
assert_error {*NOPERM*memory|doctor*} {r MEMORY DOCTOR}
r MEMORY STATS ;# should work
# Validate the commands have got engulfed to -memory.
@ -405,10 +401,8 @@ start_server {tags {"acl external:skip"}} {
set cmdstr [dict get [r ACL getuser alice] commands]
assert_equal {+@all -memory} $cmdstr
catch {r MEMORY DOCTOR} e
assert_match {*NOPERM*} $e
catch {r MEMORY STATS} e
assert_match {*NOPERM*} $e
assert_error {*NOPERM*memory|doctor*} {r MEMORY DOCTOR}
assert_error {*NOPERM*memory|stats*} {r MEMORY STATS}
# Appending to the existing access string of alice.
r ACL setuser alice -@all
@ -422,10 +416,8 @@ start_server {tags {"acl external:skip"}} {
r AUTH alice passwd1
catch {r GET key} e
assert_match {*NOPERM*} $e
catch {r MEMORY STATS} e
assert_match {*NOPERM*} $e
assert_error {*NOPERM*get*} {r GET key}
assert_error {*NOPERM*memory|stats*} {r MEMORY STATS}
# Auth newuser before the next test
r AUTH newuser passwd1
@ -486,7 +478,7 @@ start_server {tags {"acl external:skip"}} {
r ACL setuser antirez +eval +multi +exec
r ACL setuser antirez resetchannels +publish
r AUTH antirez foo
catch {r GET foo}
assert_error "*NOPERM*get*" {r GET foo}
r AUTH default ""
set entry [lindex [r ACL LOG] 0]
assert {[dict get $entry username] eq {antirez}}
@ -495,14 +487,29 @@ start_server {tags {"acl external:skip"}} {
assert {[dict get $entry object] eq {get}}
}
test "ACL LOG shows failed subcommand executions at toplevel" {
r ACL LOG RESET
r ACL DELUSER demo
r ACL SETUSER demo on nopass
r AUTH demo ""
assert_error "*NOPERM*script|help*" {r SCRIPT HELP}
r AUTH default ""
set entry [lindex [r ACL LOG] 0]
assert_equal [dict get $entry username] {demo}
assert_equal [dict get $entry context] {toplevel}
assert_equal [dict get $entry reason] {command}
assert_equal [dict get $entry object] {script|help}
}
test {ACL LOG is able to test similar events} {
r ACL LOG RESET
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}
assert {[dict get $entry count] == 3}
}
test {ACL LOG is able to log keys access violations and key name} {
@ -662,12 +669,9 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"] tags
test {default: with config acl-pubsub-default resetchannels after reset, can not access any channels} {
r CONFIG SET acl-pubsub-default resetchannels
r ACL setuser default reset on nopass ~* +@all
catch {r SUBSCRIBE foo} e
assert_match {*NOPERM*} $e
catch {r PSUBSCRIBE bar*} e
assert_match {*NOPERM*} $e
catch {r PUBLISH hello world} e
assert_match {*NOPERM*} $e
assert_error {*NOPERM*channel*} {r SUBSCRIBE foo}
assert_error {*NOPERM*channel*} {r PSUBSCRIBE bar*}
assert_error {*NOPERM*channel*} {r PUBLISH hello world}
r CONFIG SET acl-pubsub-default resetchannels
}
@ -683,7 +687,7 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"] tags
assert_equal "3" [r sadd set 1 2 3]
catch {r SET key value} e
set e
} {*NOPERM*}
} {*NOPERM*set*}
test {ACL load and save} {
r ACL setuser eve +get allkeys >eve on
@ -701,7 +705,7 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"] tags
r GET key
catch {r SET key value} e
set e
} {*NOPERM*}
} {*NOPERM*set*}
test {ACL load and save with restricted channels} {
r AUTH alice alice
@ -719,7 +723,7 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"] tags
catch {r publish test1 bar} e
r ACL deluser harry
set e
} {*NOPERM*}
} {*NOPERM*channel*}
}
set server_path [tmpdir "resetchannels.acl"]