From 61dffd8669bdc16f26c67c0ec8955a0d8a627ef8 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 28 Jan 2020 18:04:20 +0100 Subject: [PATCH] ACL LOG: actually emit entries. --- src/acl.c | 34 ++++++++++++++++++++++++++++++---- src/server.c | 4 +++- src/server.h | 1 + 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/acl.c b/src/acl.c index a166469d0..5937c069c 100644 --- a/src/acl.c +++ b/src/acl.c @@ -1467,7 +1467,7 @@ void ACLLoadUsersAtStartup(void) { #define ACL_LOG_CTX_MULTI 2 /* This structure defines an entry inside the ACL log. */ -typedef struct aclLogEntry { +typedef struct ACLLogEntry { uint64_t count; /* Number of times this happened recently. */ int reason; /* Reason for denying the command. ACL_DENIED_*. */ int context; /* Toplevel, Lua or MULTI/EXEC? ACL_LOG_CTX_*. */ @@ -1475,7 +1475,7 @@ typedef struct aclLogEntry { sds username; /* User the client is authenticated with. */ mstime_t ctime; /* Milliseconds time of last update to this entry. */ sds cinfo; /* Client info (last client if updated). */ -} aclLogEntry; +} ACLLogEntry; /* Adds a new entry in the ACL log, making sure to delete the old entry * if we reach the maximum length allowed for the log. This function attempts @@ -1484,8 +1484,9 @@ typedef struct aclLogEntry { * rules issues. */ void addACLLogEntry(client *c, int reason, int keypos) { /* Create a new entry. */ - struct aclLogEntry *le = zmalloc(sizeof(*le)); + struct ACLLogEntry *le = zmalloc(sizeof(*le)); le->count = 1; + le->reason = reason; le->object = (reason == ACL_DENIED_CMD) ? sdsnew(c->cmd->name) : sdsdup(c->argv[keypos]->ptr); le->username = sdsdup(c->user->name); @@ -1737,8 +1738,33 @@ void aclCommand(client *c) { listIter li; listNode *ln; listRewind(ACLLog,&li); + mstime_t now = mstime(); while (count-- && (ln = listNext(&li)) != NULL) { - addReplyLongLong(c,1234); + ACLLogEntry *le = listNodeValue(ln); + addReplyMapLen(c,7); + addReplyBulkCString(c,"count"); + addReplyLongLong(c,le->count); + addReplyBulkCString(c,"reason"); + addReplyBulkCString(c,(le->reason == ACL_DENIED_CMD) ? + "command" : "key"); + char *ctxstr; + switch(le->context) { + case ACL_LOG_CTX_TOPLEVEL: ctxstr="toplevel"; break; + case ACL_LOG_CTX_MULTI: ctxstr="multi"; break; + case ACL_LOG_CTX_LUA: ctxstr="lua"; break; + default: ctxstr="unknown"; + } + addReplyBulkCString(c,"context"); + addReplyBulkCString(c,ctxstr); + addReplyBulkCString(c,"object"); + addReplyBulkCBuffer(c,le->object,sdslen(le->object)); + addReplyBulkCString(c,"username"); + addReplyBulkCBuffer(c,le->username,sdslen(le->username)); + addReplyBulkCString(c,"age-seconds"); + double age = (double)(now - le->ctime)/1000; + addReplyDouble(c,age); + addReplyBulkCString(c,"client-info"); + addReplyBulkCBuffer(c,le->cinfo,sdslen(le->cinfo)); } } else if (!strcasecmp(sub,"help")) { const char *help[] = { diff --git a/src/server.c b/src/server.c index b5e27e238..6968f311f 100644 --- a/src/server.c +++ b/src/server.c @@ -3377,8 +3377,10 @@ int processCommand(client *c) { /* Check if the user can run this command according to the current * ACLs. */ - int acl_retval = ACLCheckCommandPerm(c,NULL); + int acl_keypos; + int acl_retval = ACLCheckCommandPerm(c,&acl_keypos); if (acl_retval != ACL_OK) { + addACLLogEntry(c,acl_retval,acl_keypos); flagTransaction(c); if (acl_retval == ACL_DENIED_CMD) addReplyErrorFormat(c, diff --git a/src/server.h b/src/server.h index 6fd0ffc5b..bd4aed192 100644 --- a/src/server.h +++ b/src/server.h @@ -1836,6 +1836,7 @@ void ACLLoadUsersAtStartup(void); void addReplyCommandCategories(client *c, struct redisCommand *cmd); user *ACLCreateUnlinkedUser(); void ACLFreeUserAndKillClients(user *u); +void addACLLogEntry(client *c, int reason, int keypos); /* Sorted sets data type */