ACL LOG: log failed auth attempts.

This commit is contained in:
antirez 2020-02-04 12:55:26 +01:00
parent c60351e489
commit c0de265bfa
5 changed files with 34 additions and 12 deletions

View File

@ -982,6 +982,7 @@ int ACLAuthenticateUser(client *c, robj *username, robj *password) {
moduleNotifyUserChanged(c); moduleNotifyUserChanged(c);
return C_OK; return C_OK;
} else { } else {
addACLLogEntry(c,ACL_DENIED_AUTH,0,username->ptr);
return C_ERR; return C_ERR;
} }
} }
@ -1506,17 +1507,29 @@ void ACLFreeLogEntry(void *leptr) {
* if we reach the maximum length allowed for the log. This function attempts * if we reach the maximum length allowed for the log. This function attempts
* to find similar entries in the current log in order to bump the counter of * to find similar entries in the current log in order to bump the counter of
* the log entry instead of creating many entries for very similar ACL * the log entry instead of creating many entries for very similar ACL
* rules issues. */ * rules issues.
void addACLLogEntry(client *c, int reason, int keypos) { *
* The keypos argument is only used when the reason is ACL_DENIED_KEY, since
* it allows the function to log the key name that caused the problem.
* Similarly the username is only passed when we failed to authenticate the
* user with AUTH or HELLO, for the ACL_DENIED_AUTH reason. Otherwise
* it will just be NULL.
*/
void addACLLogEntry(client *c, int reason, int keypos, sds username) {
/* Create a new entry. */ /* Create a new entry. */
struct ACLLogEntry *le = zmalloc(sizeof(*le)); struct ACLLogEntry *le = zmalloc(sizeof(*le));
le->count = 1; le->count = 1;
le->reason = reason; le->reason = reason;
le->object = (reason == ACL_DENIED_CMD) ? sdsnew(c->cmd->name) : le->username = sdsdup(reason == ACL_DENIED_AUTH ? username : c->user->name);
sdsdup(c->argv[keypos]->ptr);
le->username = sdsdup(c->user->name);
le->ctime = mstime(); le->ctime = mstime();
switch(reason) {
case ACL_DENIED_CMD: le->object = sdsnew(c->cmd->name); break;
case ACL_DENIED_KEY: le->object = sdsnew(c->argv[keypos]->ptr); break;
case ACL_DENIED_AUTH: le->object = sdsnew(c->argv[0]->ptr); break;
default: le->object = sdsempty();
}
client *realclient = c; client *realclient = c;
if (realclient->flags & CLIENT_LUA) realclient = server.lua_caller; if (realclient->flags & CLIENT_LUA) realclient = server.lua_caller;
@ -1803,9 +1816,17 @@ void aclCommand(client *c) {
addReplyMapLen(c,7); addReplyMapLen(c,7);
addReplyBulkCString(c,"count"); addReplyBulkCString(c,"count");
addReplyLongLong(c,le->count); addReplyLongLong(c,le->count);
addReplyBulkCString(c,"reason"); addReplyBulkCString(c,"reason");
addReplyBulkCString(c,(le->reason == ACL_DENIED_CMD) ? char *reasonstr;
"command" : "key"); switch(le->reason) {
case ACL_DENIED_CMD: reasonstr="command"; break;
case ACL_DENIED_KEY: reasonstr="key"; break;
case ACL_DENIED_AUTH: reasonstr="auth"; break;
}
addReplyBulkCString(c,reasonstr);
addReplyBulkCString(c,"context");
char *ctxstr; char *ctxstr;
switch(le->context) { switch(le->context) {
case ACL_LOG_CTX_TOPLEVEL: ctxstr="toplevel"; break; case ACL_LOG_CTX_TOPLEVEL: ctxstr="toplevel"; break;
@ -1813,8 +1834,8 @@ void aclCommand(client *c) {
case ACL_LOG_CTX_LUA: ctxstr="lua"; break; case ACL_LOG_CTX_LUA: ctxstr="lua"; break;
default: ctxstr="unknown"; default: ctxstr="unknown";
} }
addReplyBulkCString(c,"context");
addReplyBulkCString(c,ctxstr); addReplyBulkCString(c,ctxstr);
addReplyBulkCString(c,"object"); addReplyBulkCString(c,"object");
addReplyBulkCBuffer(c,le->object,sdslen(le->object)); addReplyBulkCBuffer(c,le->object,sdslen(le->object));
addReplyBulkCString(c,"username"); addReplyBulkCString(c,"username");

View File

@ -180,7 +180,7 @@ void execCommand(client *c) {
int acl_keypos; int acl_keypos;
int acl_retval = ACLCheckCommandPerm(c,&acl_keypos); int acl_retval = ACLCheckCommandPerm(c,&acl_keypos);
if (acl_retval != ACL_OK) { if (acl_retval != ACL_OK) {
addACLLogEntry(c,acl_retval,acl_keypos); addACLLogEntry(c,acl_retval,acl_keypos,NULL);
addReplyErrorFormat(c, addReplyErrorFormat(c,
"-NOPERM ACLs rules changed between the moment the " "-NOPERM ACLs rules changed between the moment the "
"transaction was accumulated and the EXEC call. " "transaction was accumulated and the EXEC call. "

View File

@ -609,7 +609,7 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) {
int acl_keypos; int acl_keypos;
int acl_retval = ACLCheckCommandPerm(c,&acl_keypos); int acl_retval = ACLCheckCommandPerm(c,&acl_keypos);
if (acl_retval != ACL_OK) { if (acl_retval != ACL_OK) {
addACLLogEntry(c,acl_retval,acl_keypos); addACLLogEntry(c,acl_retval,acl_keypos,NULL);
if (acl_retval == ACL_DENIED_CMD) if (acl_retval == ACL_DENIED_CMD)
luaPushError(lua, "The user executing the script can't run this " luaPushError(lua, "The user executing the script can't run this "
"command or subcommand"); "command or subcommand");

View File

@ -3380,7 +3380,7 @@ int processCommand(client *c) {
int acl_keypos; int acl_keypos;
int acl_retval = ACLCheckCommandPerm(c,&acl_keypos); int acl_retval = ACLCheckCommandPerm(c,&acl_keypos);
if (acl_retval != ACL_OK) { if (acl_retval != ACL_OK) {
addACLLogEntry(c,acl_retval,acl_keypos); addACLLogEntry(c,acl_retval,acl_keypos,NULL);
flagTransaction(c); flagTransaction(c);
if (acl_retval == ACL_DENIED_CMD) if (acl_retval == ACL_DENIED_CMD)
addReplyErrorFormat(c, addReplyErrorFormat(c,

View File

@ -1820,6 +1820,7 @@ void ACLInit(void);
#define ACL_OK 0 #define ACL_OK 0
#define ACL_DENIED_CMD 1 #define ACL_DENIED_CMD 1
#define ACL_DENIED_KEY 2 #define ACL_DENIED_KEY 2
#define ACL_DENIED_AUTH 3 /* Only used for ACL LOG entries. */
int ACLCheckUserCredentials(robj *username, robj *password); int ACLCheckUserCredentials(robj *username, robj *password);
int ACLAuthenticateUser(client *c, robj *username, robj *password); int ACLAuthenticateUser(client *c, robj *username, robj *password);
unsigned long ACLGetCommandID(const char *cmdname); unsigned long ACLGetCommandID(const char *cmdname);
@ -1836,7 +1837,7 @@ void ACLLoadUsersAtStartup(void);
void addReplyCommandCategories(client *c, struct redisCommand *cmd); void addReplyCommandCategories(client *c, struct redisCommand *cmd);
user *ACLCreateUnlinkedUser(); user *ACLCreateUnlinkedUser();
void ACLFreeUserAndKillClients(user *u); void ACLFreeUserAndKillClients(user *u);
void addACLLogEntry(client *c, int reason, int keypos); void addACLLogEntry(client *c, int reason, int keypos, sds username);
/* Sorted sets data type */ /* Sorted sets data type */