Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
a59e75a4
Unverified
Commit
a59e75a4
authored
May 19, 2021
by
Madelyn Olson
Committed by
GitHub
May 19, 2021
Browse files
Hide migrate command from slowlog if they include auth (#8859)
Redact commands that include sensitive data from slowlog and monitor
parent
d67e66de
Changes
12
Hide whitespace changes
Inline
Side-by-side
src/acl.c
View file @
a59e75a4
...
@@ -1892,10 +1892,6 @@ void addACLLogEntry(client *c, int reason, int argpos, sds username) {
...
@@ -1892,10 +1892,6 @@ void addACLLogEntry(client *c, int reason, int argpos, sds username) {
void
aclCommand
(
client
*
c
)
{
void
aclCommand
(
client
*
c
)
{
char
*
sub
=
c
->
argv
[
1
]
->
ptr
;
char
*
sub
=
c
->
argv
[
1
]
->
ptr
;
if
(
!
strcasecmp
(
sub
,
"setuser"
)
&&
c
->
argc
>=
3
)
{
if
(
!
strcasecmp
(
sub
,
"setuser"
)
&&
c
->
argc
>=
3
)
{
/* Consider information about passwords or permissions
* to be sensitive, which will be the arguments for this
* subcommand. */
preventCommandLogging
(
c
);
sds
username
=
c
->
argv
[
2
]
->
ptr
;
sds
username
=
c
->
argv
[
2
]
->
ptr
;
/* Check username validity. */
/* Check username validity. */
if
(
ACLStringHasSpaces
(
username
,
sdslen
(
username
)))
{
if
(
ACLStringHasSpaces
(
username
,
sdslen
(
username
)))
{
...
@@ -1912,6 +1908,12 @@ void aclCommand(client *c) {
...
@@ -1912,6 +1908,12 @@ void aclCommand(client *c) {
user
*
u
=
ACLGetUserByName
(
username
,
sdslen
(
username
));
user
*
u
=
ACLGetUserByName
(
username
,
sdslen
(
username
));
if
(
u
)
ACLCopyUser
(
tempu
,
u
);
if
(
u
)
ACLCopyUser
(
tempu
,
u
);
/* Initially redact all of the arguments to not leak any information
* about the user. */
for
(
int
j
=
2
;
j
<
c
->
argc
;
j
++
)
{
redactClientCommandArgument
(
c
,
j
);
}
for
(
int
j
=
3
;
j
<
c
->
argc
;
j
++
)
{
for
(
int
j
=
3
;
j
<
c
->
argc
;
j
++
)
{
if
(
ACLSetUser
(
tempu
,
c
->
argv
[
j
]
->
ptr
,
sdslen
(
c
->
argv
[
j
]
->
ptr
))
!=
C_OK
)
{
if
(
ACLSetUser
(
tempu
,
c
->
argv
[
j
]
->
ptr
,
sdslen
(
c
->
argv
[
j
]
->
ptr
))
!=
C_OK
)
{
const
char
*
errmsg
=
ACLSetUserStringError
();
const
char
*
errmsg
=
ACLSetUserStringError
();
...
@@ -2245,6 +2247,8 @@ void authCommand(client *c) {
...
@@ -2245,6 +2247,8 @@ void authCommand(client *c) {
addReplyErrorObject
(
c
,
shared
.
syntaxerr
);
addReplyErrorObject
(
c
,
shared
.
syntaxerr
);
return
;
return
;
}
}
/* Always redact the second argument */
redactClientCommandArgument
(
c
,
1
);
/* Handle the two different forms here. The form with two arguments
/* Handle the two different forms here. The form with two arguments
* will just use "default" as username. */
* will just use "default" as username. */
...
@@ -2264,6 +2268,7 @@ void authCommand(client *c) {
...
@@ -2264,6 +2268,7 @@ void authCommand(client *c) {
}
else
{
}
else
{
username
=
c
->
argv
[
1
];
username
=
c
->
argv
[
1
];
password
=
c
->
argv
[
2
];
password
=
c
->
argv
[
2
];
redactClientCommandArgument
(
c
,
2
);
}
}
if
(
ACLAuthenticateUser
(
c
,
username
,
password
)
==
C_OK
)
{
if
(
ACLAuthenticateUser
(
c
,
username
,
password
)
==
C_OK
)
{
...
...
src/cluster.c
View file @
a59e75a4
...
@@ -5363,13 +5363,16 @@ void migrateCommand(client *c) {
...
@@ -5363,13 +5363,16 @@ void migrateCommand(client *c) {
}
}
j
++
;
j
++
;
password
=
c
->
argv
[
j
]
->
ptr
;
password
=
c
->
argv
[
j
]
->
ptr
;
redactClientCommandArgument
(
c
,
j
);
}
else
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"auth2"
))
{
}
else
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"auth2"
))
{
if
(
moreargs
<
2
)
{
if
(
moreargs
<
2
)
{
addReplyErrorObject
(
c
,
shared
.
syntaxerr
);
addReplyErrorObject
(
c
,
shared
.
syntaxerr
);
return
;
return
;
}
}
username
=
c
->
argv
[
++
j
]
->
ptr
;
username
=
c
->
argv
[
++
j
]
->
ptr
;
redactClientCommandArgument
(
c
,
j
);
password
=
c
->
argv
[
++
j
]
->
ptr
;
password
=
c
->
argv
[
++
j
]
->
ptr
;
redactClientCommandArgument
(
c
,
j
);
}
else
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"keys"
))
{
}
else
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"keys"
))
{
if
(
sdslen
(
c
->
argv
[
3
]
->
ptr
)
!=
0
)
{
if
(
sdslen
(
c
->
argv
[
3
]
->
ptr
)
!=
0
)
{
addReplyError
(
c
,
addReplyError
(
c
,
...
...
src/config.c
View file @
a59e75a4
...
@@ -726,7 +726,7 @@ void configSetCommand(client *c) {
...
@@ -726,7 +726,7 @@ void configSetCommand(client *c) {
(
config
->
alias
&&
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
config
->
alias
))))
(
config
->
alias
&&
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
config
->
alias
))))
{
{
if
(
config
->
flags
&
SENSITIVE_CONFIG
)
{
if
(
config
->
flags
&
SENSITIVE_CONFIG
)
{
p
re
v
entCommand
Logging
(
c
);
re
dactCli
entCommand
Argument
(
c
,
3
);
}
}
if
(
!
config
->
interface
.
set
(
config
->
data
,
o
->
ptr
,
1
,
&
errstr
))
{
if
(
!
config
->
interface
.
set
(
config
->
data
,
o
->
ptr
,
1
,
&
errstr
))
{
goto
badfmt
;
goto
badfmt
;
...
...
src/multi.c
View file @
a59e75a4
...
@@ -153,8 +153,7 @@ void execCommandAbort(client *c, sds error) {
...
@@ -153,8 +153,7 @@ void execCommandAbort(client *c, sds error) {
/* Send EXEC to clients waiting data from MONITOR. We did send a MULTI
/* Send EXEC to clients waiting data from MONITOR. We did send a MULTI
* already, and didn't send any of the queued commands, now we'll just send
* already, and didn't send any of the queued commands, now we'll just send
* EXEC so it is clear that the transaction is over. */
* EXEC so it is clear that the transaction is over. */
if
(
listLength
(
server
.
monitors
)
&&
!
server
.
loading
)
replicationFeedMonitors
(
c
,
server
.
monitors
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
replicationFeedMonitors
(
c
,
server
.
monitors
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
}
}
void
execCommand
(
client
*
c
)
{
void
execCommand
(
client
*
c
)
{
...
@@ -179,7 +178,7 @@ void execCommand(client *c) {
...
@@ -179,7 +178,7 @@ void execCommand(client *c) {
addReply
(
c
,
c
->
flags
&
CLIENT_DIRTY_EXEC
?
shared
.
execaborterr
:
addReply
(
c
,
c
->
flags
&
CLIENT_DIRTY_EXEC
?
shared
.
execaborterr
:
shared
.
nullarray
[
c
->
resp
]);
shared
.
nullarray
[
c
->
resp
]);
discardTransaction
(
c
);
discardTransaction
(
c
);
goto
handle_monitor
;
return
;
}
}
uint64_t
old_flags
=
c
->
flags
;
uint64_t
old_flags
=
c
->
flags
;
...
@@ -266,15 +265,6 @@ void execCommand(client *c) {
...
@@ -266,15 +265,6 @@ void execCommand(client *c) {
}
}
server
.
in_exec
=
0
;
server
.
in_exec
=
0
;
handle_monitor:
/* Send EXEC to clients waiting data from MONITOR. We do it here
* since the natural order of commands execution is actually:
* MUTLI, EXEC, ... commands inside transaction ...
* Instead EXEC is flagged as CMD_SKIP_MONITOR in the command
* table, and we do it here with correct ordering. */
if
(
listLength
(
server
.
monitors
)
&&
!
server
.
loading
)
replicationFeedMonitors
(
c
,
server
.
monitors
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
}
}
/* ===================== WATCH (CAS alike for MULTI/EXEC) ===================
/* ===================== WATCH (CAS alike for MULTI/EXEC) ===================
...
...
src/networking.c
View file @
a59e75a4
...
@@ -1663,9 +1663,6 @@ void resetClient(client *c) {
...
@@ -1663,9 +1663,6 @@ void resetClient(client *c) {
c
->
flags
|=
CLIENT_REPLY_SKIP
;
c
->
flags
|=
CLIENT_REPLY_SKIP
;
c
->
flags
&=
~
CLIENT_REPLY_SKIP_NEXT
;
c
->
flags
&=
~
CLIENT_REPLY_SKIP_NEXT
;
}
}
/* Always clear the prevent logging field. */
c
->
flags
&=
~
CLIENT_PREVENT_LOGGING
;
}
}
/* This function is used when we want to re-enter the event loop but there
/* This function is used when we want to re-enter the event loop but there
...
@@ -2967,7 +2964,8 @@ void helloCommand(client *c) {
...
@@ -2967,7 +2964,8 @@ void helloCommand(client *c) {
int
moreargs
=
(
c
->
argc
-
1
)
-
j
;
int
moreargs
=
(
c
->
argc
-
1
)
-
j
;
const
char
*
opt
=
c
->
argv
[
j
]
->
ptr
;
const
char
*
opt
=
c
->
argv
[
j
]
->
ptr
;
if
(
!
strcasecmp
(
opt
,
"AUTH"
)
&&
moreargs
>=
2
)
{
if
(
!
strcasecmp
(
opt
,
"AUTH"
)
&&
moreargs
>=
2
)
{
preventCommandLogging
(
c
);
redactClientCommandArgument
(
c
,
j
+
1
);
redactClientCommandArgument
(
c
,
j
+
2
);
if
(
ACLAuthenticateUser
(
c
,
c
->
argv
[
j
+
1
],
c
->
argv
[
j
+
2
])
==
C_ERR
)
{
if
(
ACLAuthenticateUser
(
c
,
c
->
argv
[
j
+
1
],
c
->
argv
[
j
+
2
])
==
C_ERR
)
{
addReplyError
(
c
,
"-WRONGPASS invalid username-password pair or user is disabled."
);
addReplyError
(
c
,
"-WRONGPASS invalid username-password pair or user is disabled."
);
return
;
return
;
...
@@ -3054,6 +3052,15 @@ static void retainOriginalCommandVector(client *c) {
...
@@ -3054,6 +3052,15 @@ static void retainOriginalCommandVector(client *c) {
}
}
}
}
/* Redact a given argument to prevent it from being shown
* in the slowlog. This information is stored in the
* original_argv array. */
void
redactClientCommandArgument
(
client
*
c
,
int
argc
)
{
retainOriginalCommandVector
(
c
);
decrRefCount
(
c
->
argv
[
argc
]);
c
->
original_argv
[
argc
]
=
shared
.
redacted
;
}
/* Rewrite the command vector of the client. All the new objects ref count
/* Rewrite the command vector of the client. All the new objects ref count
* is incremented. The old command vector is freed, and the old objects
* is incremented. The old command vector is freed, and the old objects
* ref count is decremented. */
* ref count is decremented. */
...
...
src/replication.c
View file @
a59e75a4
...
@@ -377,6 +377,7 @@ void replicationFeedSlavesFromMasterStream(list *slaves, char *buf, size_t bufle
...
@@ -377,6 +377,7 @@ void replicationFeedSlavesFromMasterStream(list *slaves, char *buf, size_t bufle
}
}
void
replicationFeedMonitors
(
client
*
c
,
list
*
monitors
,
int
dictid
,
robj
**
argv
,
int
argc
)
{
void
replicationFeedMonitors
(
client
*
c
,
list
*
monitors
,
int
dictid
,
robj
**
argv
,
int
argc
)
{
if
(
!
(
listLength
(
server
.
monitors
)
&&
!
server
.
loading
))
return
;
listNode
*
ln
;
listNode
*
ln
;
listIter
li
;
listIter
li
;
int
j
;
int
j
;
...
...
src/scripting.c
View file @
a59e75a4
...
@@ -1699,6 +1699,9 @@ void evalGenericCommand(client *c, int evalsha) {
...
@@ -1699,6 +1699,9 @@ void evalGenericCommand(client *c, int evalsha) {
}
}
void
evalCommand
(
client
*
c
)
{
void
evalCommand
(
client
*
c
)
{
/* Explicitly feed monitor here so that lua commands appear after their
* script command. */
replicationFeedMonitors
(
c
,
server
.
monitors
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
if
(
!
(
c
->
flags
&
CLIENT_LUA_DEBUG
))
if
(
!
(
c
->
flags
&
CLIENT_LUA_DEBUG
))
evalGenericCommand
(
c
,
0
);
evalGenericCommand
(
c
,
0
);
else
else
...
@@ -1710,6 +1713,9 @@ void evalRoCommand(client *c) {
...
@@ -1710,6 +1713,9 @@ void evalRoCommand(client *c) {
}
}
void
evalShaCommand
(
client
*
c
)
{
void
evalShaCommand
(
client
*
c
)
{
/* Explicitly feed monitor here so that lua commands appear after their
* script command. */
replicationFeedMonitors
(
c
,
server
.
monitors
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
if
(
sdslen
(
c
->
argv
[
1
]
->
ptr
)
!=
40
)
{
if
(
sdslen
(
c
->
argv
[
1
]
->
ptr
)
!=
40
)
{
/* We know that a match is not possible if the provided SHA is
/* We know that a match is not possible if the provided SHA is
* not the right length. So we return an error ASAP, this way
* not the right length. So we return an error ASAP, this way
...
...
src/server.c
View file @
a59e75a4
...
@@ -706,7 +706,7 @@ struct redisCommand redisCommandTable[] = {
...
@@ -706,7 +706,7 @@ struct redisCommand redisCommandTable[] = {
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"auth"
,
authCommand
,
-
2
,
{
"auth"
,
authCommand
,
-
2
,
"no-auth no-script ok-loading ok-stale fast
no-monitor no-slowlog
@connection"
,
"no-auth no-script ok-loading ok-stale fast @connection"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
/* We don't allow PING during loading since in Redis PING is used as
/* We don't allow PING during loading since in Redis PING is used as
...
@@ -749,7 +749,7 @@ struct redisCommand redisCommandTable[] = {
...
@@ -749,7 +749,7 @@ struct redisCommand redisCommandTable[] = {
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"exec"
,
execCommand
,
1
,
{
"exec"
,
execCommand
,
1
,
"no-script
no-monitor
no-slowlog ok-loading ok-stale @transaction"
,
"no-script no-slowlog ok-loading ok-stale @transaction"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"discard"
,
discardCommand
,
1
,
{
"discard"
,
discardCommand
,
1
,
...
@@ -901,25 +901,29 @@ struct redisCommand redisCommandTable[] = {
...
@@ -901,25 +901,29 @@ struct redisCommand redisCommandTable[] = {
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"hello"
,
helloCommand
,
-
1
,
{
"hello"
,
helloCommand
,
-
1
,
"no-auth no-script fast
no-monitor
ok-loading ok-stale @connection"
,
"no-auth no-script fast ok-loading ok-stale @connection"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
/* EVAL can modify the dataset, however it is not flagged as a write
/* EVAL can modify the dataset, however it is not flagged as a write
* command since we do the check while running commands from Lua. */
* command since we do the check while running commands from Lua.
*
* EVAL and EVALSHA also feed monitors before the commands are executed,
* as opposed to after.
*/
{
"eval"
,
evalCommand
,
-
3
,
{
"eval"
,
evalCommand
,
-
3
,
"no-script may-replicate @scripting"
,
"no-script
no-monitor
may-replicate @scripting"
,
0
,
evalGetKeys
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
evalGetKeys
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"eval_ro"
,
evalRoCommand
,
-
3
,
{
"eval_ro"
,
evalRoCommand
,
-
3
,
"no-script @scripting"
,
"no-script
no-monitor
@scripting"
,
0
,
evalGetKeys
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
evalGetKeys
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"evalsha"
,
evalShaCommand
,
-
3
,
{
"evalsha"
,
evalShaCommand
,
-
3
,
"no-script may-replicate @scripting"
,
"no-script
no-monitor
may-replicate @scripting"
,
0
,
evalGetKeys
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
evalGetKeys
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"evalsha_ro"
,
evalShaRoCommand
,
-
3
,
{
"evalsha_ro"
,
evalShaRoCommand
,
-
3
,
"no-script @scripting"
,
"no-script
no-monitor
@scripting"
,
0
,
evalGetKeys
,
0
,
0
,
0
,
0
,
0
,
0
},
0
,
evalGetKeys
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"slowlog"
,
slowlogCommand
,
-
2
,
{
"slowlog"
,
slowlogCommand
,
-
2
,
...
@@ -2612,6 +2616,7 @@ void createSharedObjects(void) {
...
@@ -2612,6 +2616,7 @@ void createSharedObjects(void) {
shared
.
getack
=
createStringObject
(
"GETACK"
,
6
);
shared
.
getack
=
createStringObject
(
"GETACK"
,
6
);
shared
.
special_asterick
=
createStringObject
(
"*"
,
1
);
shared
.
special_asterick
=
createStringObject
(
"*"
,
1
);
shared
.
special_equals
=
createStringObject
(
"="
,
1
);
shared
.
special_equals
=
createStringObject
(
"="
,
1
);
shared
.
redacted
=
makeObjectShared
(
createStringObject
(
"(redacted)"
,
10
));
for
(
j
=
0
;
j
<
OBJ_SHARED_INTEGERS
;
j
++
)
{
for
(
j
=
0
;
j
<
OBJ_SHARED_INTEGERS
;
j
++
)
{
shared
.
integers
[
j
]
=
shared
.
integers
[
j
]
=
...
@@ -3634,12 +3639,6 @@ void preventCommandPropagation(client *c) {
...
@@ -3634,12 +3639,6 @@ void preventCommandPropagation(client *c) {
c
->
flags
|=
CLIENT_PREVENT_PROP
;
c
->
flags
|=
CLIENT_PREVENT_PROP
;
}
}
/* Avoid logging any information about this client's arguments
* since they contain sensitive information. */
void
preventCommandLogging
(
client
*
c
)
{
c
->
flags
|=
CLIENT_PREVENT_LOGGING
;
}
/* AOF specific version of preventCommandPropagation(). */
/* AOF specific version of preventCommandPropagation(). */
void
preventCommandAOF
(
client
*
c
)
{
void
preventCommandAOF
(
client
*
c
)
{
c
->
flags
|=
CLIENT_PREVENT_AOF_PROP
;
c
->
flags
|=
CLIENT_PREVENT_AOF_PROP
;
...
@@ -3653,7 +3652,7 @@ void preventCommandReplication(client *c) {
...
@@ -3653,7 +3652,7 @@ void preventCommandReplication(client *c) {
/* Log the last command a client executed into the slowlog. */
/* Log the last command a client executed into the slowlog. */
void
slowlogPushCurrentCommand
(
client
*
c
,
struct
redisCommand
*
cmd
,
ustime_t
duration
)
{
void
slowlogPushCurrentCommand
(
client
*
c
,
struct
redisCommand
*
cmd
,
ustime_t
duration
)
{
/* Some commands may contain sensitive data that should not be available in the slowlog. */
/* Some commands may contain sensitive data that should not be available in the slowlog. */
if
((
c
->
flags
&
CLIENT_PREVENT_LOGGING
)
||
(
cmd
->
flags
&
CMD_SKIP_SLOWLOG
)
)
if
(
cmd
->
flags
&
CMD_SKIP_SLOWLOG
)
return
;
return
;
/* If command argument vector was rewritten, use the original
/* If command argument vector was rewritten, use the original
...
@@ -3709,15 +3708,6 @@ void call(client *c, int flags) {
...
@@ -3709,15 +3708,6 @@ void call(client *c, int flags) {
server
.
fixed_time_expire
++
;
server
.
fixed_time_expire
++
;
/* Send the command to clients in MONITOR mode if applicable.
* Administrative commands are considered too dangerous to be shown. */
if
(
listLength
(
server
.
monitors
)
&&
!
server
.
loading
&&
!
(
c
->
cmd
->
flags
&
(
CMD_SKIP_MONITOR
|
CMD_ADMIN
)))
{
replicationFeedMonitors
(
c
,
server
.
monitors
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
}
/* Initialization: clear the flags that must be set by the command on
/* Initialization: clear the flags that must be set by the command on
* demand, and initialize the array for additional commands propagation. */
* demand, and initialize the array for additional commands propagation. */
c
->
flags
&=
~
(
CLIENT_FORCE_AOF
|
CLIENT_FORCE_REPL
|
CLIENT_PREVENT_PROP
);
c
->
flags
&=
~
(
CLIENT_FORCE_AOF
|
CLIENT_FORCE_REPL
|
CLIENT_PREVENT_PROP
);
...
@@ -3783,6 +3773,14 @@ void call(client *c, int flags) {
...
@@ -3783,6 +3773,14 @@ void call(client *c, int flags) {
if
((
flags
&
CMD_CALL_SLOWLOG
)
&&
!
(
c
->
flags
&
CLIENT_BLOCKED
))
if
((
flags
&
CMD_CALL_SLOWLOG
)
&&
!
(
c
->
flags
&
CLIENT_BLOCKED
))
slowlogPushCurrentCommand
(
c
,
real_cmd
,
duration
);
slowlogPushCurrentCommand
(
c
,
real_cmd
,
duration
);
/* Send the command to clients in MONITOR mode if applicable.
* Administrative commands are considered too dangerous to be shown. */
if
(
!
(
c
->
cmd
->
flags
&
(
CMD_SKIP_MONITOR
|
CMD_ADMIN
)))
{
robj
**
argv
=
c
->
original_argv
?
c
->
original_argv
:
c
->
argv
;
int
argc
=
c
->
original_argv
?
c
->
original_argc
:
c
->
argc
;
replicationFeedMonitors
(
c
,
server
.
monitors
,
c
->
db
->
id
,
argv
,
argc
);
}
/* Clear the original argv.
/* Clear the original argv.
* If the client is blocked we will handle slowlog when it is unblocked. */
* If the client is blocked we will handle slowlog when it is unblocked. */
if
(
!
(
c
->
flags
&
CLIENT_BLOCKED
))
if
(
!
(
c
->
flags
&
CLIENT_BLOCKED
))
...
...
src/server.h
View file @
a59e75a4
...
@@ -279,7 +279,6 @@ extern int configOOMScoreAdjValuesDefaults[CONFIG_OOM_COUNT];
...
@@ -279,7 +279,6 @@ extern int configOOMScoreAdjValuesDefaults[CONFIG_OOM_COUNT];
and AOF client */
and AOF client */
#define CLIENT_REPL_RDBONLY (1ULL<<42)
/* This client is a replica that only wants
#define CLIENT_REPL_RDBONLY (1ULL<<42)
/* This client is a replica that only wants
RDB without replication buffer. */
RDB without replication buffer. */
#define CLIENT_PREVENT_LOGGING (1ULL<<43)
/* Prevent logging of command to slowlog */
/* Client block type (btype field in client structure)
/* Client block type (btype field in client structure)
* if CLIENT_BLOCKED flag is set. */
* if CLIENT_BLOCKED flag is set. */
...
@@ -986,7 +985,7 @@ struct sharedObjectsStruct {
...
@@ -986,7 +985,7 @@ struct sharedObjectsStruct {
*
script
,
*
replconf
,
*
eval
,
*
persist
,
*
set
,
*
pexpireat
,
*
pexpire
,
*
script
,
*
replconf
,
*
eval
,
*
persist
,
*
set
,
*
pexpireat
,
*
pexpire
,
*
time
,
*
pxat
,
*
px
,
*
retrycount
,
*
force
,
*
justid
,
*
time
,
*
pxat
,
*
px
,
*
retrycount
,
*
force
,
*
justid
,
*
lastid
,
*
ping
,
*
setid
,
*
keepttl
,
*
load
,
*
createconsumer
,
*
lastid
,
*
ping
,
*
setid
,
*
keepttl
,
*
load
,
*
createconsumer
,
*
getack
,
*
special_asterick
,
*
special_equals
,
*
default_username
,
*
getack
,
*
special_asterick
,
*
special_equals
,
*
default_username
,
*
redacted
,
*
select
[
PROTO_SHARED_SELECT_CMDS
],
*
select
[
PROTO_SHARED_SELECT_CMDS
],
*
integers
[
OBJ_SHARED_INTEGERS
],
*
integers
[
OBJ_SHARED_INTEGERS
],
*
mbulkhdr
[
OBJ_SHARED_BULKHDR_LEN
],
/* "*<value>\r\n" */
*
mbulkhdr
[
OBJ_SHARED_BULKHDR_LEN
],
/* "*<value>\r\n" */
...
@@ -1863,6 +1862,7 @@ sds getAllClientsInfoString(int type);
...
@@ -1863,6 +1862,7 @@ sds getAllClientsInfoString(int type);
void
rewriteClientCommandVector
(
client
*
c
,
int
argc
,
...);
void
rewriteClientCommandVector
(
client
*
c
,
int
argc
,
...);
void
rewriteClientCommandArgument
(
client
*
c
,
int
i
,
robj
*
newval
);
void
rewriteClientCommandArgument
(
client
*
c
,
int
i
,
robj
*
newval
);
void
replaceClientCommandVector
(
client
*
c
,
int
argc
,
robj
**
argv
);
void
replaceClientCommandVector
(
client
*
c
,
int
argc
,
robj
**
argv
);
void
redactClientCommandArgument
(
client
*
c
,
int
argc
);
unsigned
long
getClientOutputBufferMemoryUsage
(
client
*
c
);
unsigned
long
getClientOutputBufferMemoryUsage
(
client
*
c
);
int
freeClientsInAsyncFreeQueue
(
void
);
int
freeClientsInAsyncFreeQueue
(
void
);
int
closeClientOnOutputBufferLimitReached
(
client
*
c
,
int
async
);
int
closeClientOnOutputBufferLimitReached
(
client
*
c
,
int
async
);
...
@@ -2210,7 +2210,6 @@ void redisOpArrayInit(redisOpArray *oa);
...
@@ -2210,7 +2210,6 @@ void redisOpArrayInit(redisOpArray *oa);
void
redisOpArrayFree
(
redisOpArray
*
oa
);
void
redisOpArrayFree
(
redisOpArray
*
oa
);
void
forceCommandPropagation
(
client
*
c
,
int
flags
);
void
forceCommandPropagation
(
client
*
c
,
int
flags
);
void
preventCommandPropagation
(
client
*
c
);
void
preventCommandPropagation
(
client
*
c
);
void
preventCommandLogging
(
client
*
c
);
void
preventCommandAOF
(
client
*
c
);
void
preventCommandAOF
(
client
*
c
);
void
preventCommandReplication
(
client
*
c
);
void
preventCommandReplication
(
client
*
c
);
void
slowlogPushCurrentCommand
(
client
*
c
,
struct
redisCommand
*
cmd
,
ustime_t
duration
);
void
slowlogPushCurrentCommand
(
client
*
c
,
struct
redisCommand
*
cmd
,
ustime_t
duration
);
...
...
tests/unit/introspection.tcl
View file @
a59e75a4
...
@@ -31,6 +31,52 @@ start_server {tags {"introspection"}} {
...
@@ -31,6 +31,52 @@ start_server {tags {"introspection"}} {
assert_match
{
*lua*
"set"
*
"foo"
*
"bar"
*
}
[
$rd
read
]
assert_match
{
*lua*
"set"
*
"foo"
*
"bar"
*
}
[
$rd
read
]
}
}
test
{
MONITOR supports redacting command arguments
}
{
set rd
[
redis_deferring_client
]
$rd monitor
$rd read
;
# Discard the OK
r migrate
[
srv 0 host
]
[
srv 0 port
]
key 9 5000
r migrate
[
srv 0 host
]
[
srv 0 port
]
key 9 5000 AUTH user
r migrate
[
srv 0 host
]
[
srv 0 port
]
key 9 5000 AUTH2 user password
catch
{
r auth not-real
}
_
catch
{
r auth not-real not-a-password
}
_
catch
{
r hello 2 AUTH not-real not-a-password
}
_
assert_match
{
*
"key"
*
"9"
*
"5000"
*
}
[
$rd
read
]
assert_match
{
*
"key"
*
"9"
*
"5000"
*
"(redacted)"
*
}
[
$rd
read
]
assert_match
{
*
"key"
*
"9"
*
"5000"
*
"(redacted)"
*
"(redacted)"
*
}
[
$rd
read
]
assert_match
{
*
"auth"
*
"(redacted)"
*
}
[
$rd
read
]
assert_match
{
*
"auth"
*
"(redacted)"
*
"(redacted)"
*
}
[
$rd
read
]
assert_match
{
*
"hello"
*
"2"
*
"AUTH"
*
"(redacted)"
*
"(redacted)"
*
}
[
$rd
read
]
$rd close
}
test
{
MONITOR correctly handles multi-exec cases
}
{
set rd
[
redis_deferring_client
]
$rd monitor
$rd read
;
# Discard the OK
# Make sure multi-exec statements are ordered
# correctly
r multi
r set foo bar
r exec
assert_match
{
*
"multi"
*
}
[
$rd
read
]
assert_match
{
*
"set"
*
"foo"
*
"bar"
*
}
[
$rd
read
]
assert_match
{
*
"exec"
*
}
[
$rd
read
]
# Make sure we close multi statements on errors
r multi
catch
{
r syntax error
}
_
catch
{
r exec
}
_
assert_match
{
*
"multi"
*
}
[
$rd
read
]
assert_match
{
*
"exec"
*
}
[
$rd
read
]
$rd close
}
test
{
CLIENT GETNAME should return NIL if name is not assigned
}
{
test
{
CLIENT GETNAME should return NIL if name is not assigned
}
{
r client getname
r client getname
}
{}
}
{}
...
...
tests/unit/other.tcl
View file @
a59e75a4
...
@@ -266,9 +266,6 @@ start_server {overrides {save ""} tags {"other"}} {
...
@@ -266,9 +266,6 @@ start_server {overrides {save ""} tags {"other"}} {
assert_equal
[
$rd
read
]
"OK"
assert_equal
[
$rd
read
]
"OK"
$rd reset
$rd reset
# skip reset ouptut
$rd read
assert_equal
[
$rd
read
]
"RESET"
assert_equal
[
$rd
read
]
"RESET"
assert_no_match
{
*flags=O*
}
[
r client list
]
assert_no_match
{
*flags=O*
}
[
r client list
]
...
...
tests/unit/slowlog.tcl
View file @
a59e75a4
...
@@ -45,18 +45,35 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} {
...
@@ -45,18 +45,35 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} {
r config set slowlog-log-slower-than 0
r config set slowlog-log-slower-than 0
r slowlog reset
r slowlog reset
r config set masterauth
""
r config set masterauth
""
r acl setuser slowlog-test-user
r acl setuser slowlog-test-user
+get +set
r config set slowlog-log-slower-than 0
r config set slowlog-log-slower-than 0
r config set slowlog-log-slower-than 10000
r config set slowlog-log-slower-than 10000
set slowlog_resp
[
r slowlog get
]
set slowlog_resp
[
r slowlog get
]
# Make sure normal configs work, but the two sensitive
# Make sure normal configs work, but the two sensitive
# commands are omitted
# commands are omitted or redacted
assert_equal 2
[
llength $slowlog_resp
]
assert_equal 4
[
llength $slowlog_resp
]
assert_equal
{
slowlog reset
}
[
lindex
[
lindex
[
r slowlog get
]
1
]
3
]
assert_equal
{
slowlog reset
}
[
lindex
[
lindex
[
r slowlog get
]
3
]
3
]
assert_equal
{
config set masterauth
(
redacted
)}
[
lindex
[
lindex
[
r slowlog get
]
2
]
3
]
assert_equal
{
acl setuser
(
redacted
)
(
redacted
)
(
redacted
)}
[
lindex
[
lindex
[
r slowlog get
]
1
]
3
]
assert_equal
{
config set slowlog-log-slower-than 0
}
[
lindex
[
lindex
[
r slowlog get
]
0
]
3
]
assert_equal
{
config set slowlog-log-slower-than 0
}
[
lindex
[
lindex
[
r slowlog get
]
0
]
3
]
}
}
test
{
SLOWLOG - Some commands can redact sensitive fields
}
{
r config set slowlog-log-slower-than 0
r slowlog reset
r migrate
[
srv 0 host
]
[
srv 0 port
]
key 9 5000
r migrate
[
srv 0 host
]
[
srv 0 port
]
key 9 5000 AUTH user
r migrate
[
srv 0 host
]
[
srv 0 port
]
key 9 5000 AUTH2 user password
r config set slowlog-log-slower-than 10000
# Make sure all 3 commands were logged, but the sensitive fields are omitted
assert_equal 4
[
llength
[
r slowlog get
]]
assert_match
{
* key 9 5000
}
[
lindex
[
lindex
[
r slowlog get
]
2
]
3
]
assert_match
{
* key 9 5000 AUTH
(
redacted
)}
[
lindex
[
lindex
[
r slowlog get
]
1
]
3
]
assert_match
{
* key 9 5000 AUTH2
(
redacted
)
(
redacted
)}
[
lindex
[
lindex
[
r slowlog get
]
0
]
3
]
}
test
{
SLOWLOG - Rewritten commands are logged as their original command
}
{
test
{
SLOWLOG - Rewritten commands are logged as their original command
}
{
r config set slowlog-log-slower-than 0
r config set slowlog-log-slower-than 0
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment