Added authentication failure and access denied metrics (#11288)
Added authentication failure and access denied metrics
This commit is contained in:
parent
210ad2e4db
commit
8e19415343
18
src/acl.c
18
src/acl.c
@ -2479,6 +2479,21 @@ void ACLFreeLogEntry(void *leptr) {
|
||||
zfree(le);
|
||||
}
|
||||
|
||||
/* Update the relevant counter by the reason */
|
||||
void ACLUpdateInfoMetrics(int reason){
|
||||
if (reason == ACL_DENIED_AUTH) {
|
||||
server.acl_info.user_auth_failures++;
|
||||
} else if (reason == ACL_DENIED_CMD) {
|
||||
server.acl_info.invalid_cmd_accesses++;
|
||||
} else if (reason == ACL_DENIED_KEY) {
|
||||
server.acl_info.invalid_key_accesses++;
|
||||
} else if (reason == ACL_DENIED_CHANNEL) {
|
||||
server.acl_info.invalid_channel_accesses++;
|
||||
} else {
|
||||
serverPanic("Unknown ACL_DENIED encoding");
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
* to find similar entries in the current log in order to bump the counter of
|
||||
@ -2495,6 +2510,9 @@ void ACLFreeLogEntry(void *leptr) {
|
||||
* If `object` is not NULL, this functions takes over it.
|
||||
*/
|
||||
void addACLLogEntry(client *c, int reason, int context, int argpos, sds username, sds object) {
|
||||
/* Update ACL info metrics */
|
||||
ACLUpdateInfoMetrics(reason);
|
||||
|
||||
/* Create a new entry. */
|
||||
struct ACLLogEntry *le = zmalloc(sizeof(*le));
|
||||
le->count = 1;
|
||||
|
21
src/server.c
21
src/server.c
@ -2536,6 +2536,12 @@ void initServer(void) {
|
||||
server.repl_good_slaves_count = 0;
|
||||
server.last_sig_received = 0;
|
||||
|
||||
/* Initiate acl info struct */
|
||||
server.acl_info.invalid_cmd_accesses = 0;
|
||||
server.acl_info.invalid_key_accesses = 0;
|
||||
server.acl_info.user_auth_failures = 0;
|
||||
server.acl_info.invalid_channel_accesses = 0;
|
||||
|
||||
/* Create the timer callback, this is our way to process many background
|
||||
* operations incrementally, like clients timeout, eviction of unaccessed
|
||||
* expired keys and so forth. */
|
||||
@ -5167,6 +5173,20 @@ sds genRedisInfoStringCommandStats(sds info, dict *commands) {
|
||||
return info;
|
||||
}
|
||||
|
||||
/* Writes the ACL metrics to the info */
|
||||
sds genRedisInfoStringACLStats(sds info) {
|
||||
info = sdscatprintf(info,
|
||||
"acl_access_denied_auth:%lld\r\n"
|
||||
"acl_access_denied_cmd:%lld\r\n"
|
||||
"acl_access_denied_key:%lld\r\n"
|
||||
"acl_access_denied_channel:%lld\r\n",
|
||||
server.acl_info.user_auth_failures,
|
||||
server.acl_info.invalid_cmd_accesses,
|
||||
server.acl_info.invalid_key_accesses,
|
||||
server.acl_info.invalid_channel_accesses);
|
||||
return info;
|
||||
}
|
||||
|
||||
sds genRedisInfoStringLatencyStats(sds info, dict *commands) {
|
||||
struct redisCommand *c;
|
||||
dictEntry *de;
|
||||
@ -5778,6 +5798,7 @@ sds genRedisInfoString(dict *section_dict, int all_sections, int everything) {
|
||||
server.stat_io_writes_processed,
|
||||
server.stat_reply_buffer_shrinks,
|
||||
server.stat_reply_buffer_expands);
|
||||
info = genRedisInfoStringACLStats(info);
|
||||
}
|
||||
|
||||
/* Replication */
|
||||
|
10
src/server.h
10
src/server.h
@ -1189,6 +1189,14 @@ typedef struct client {
|
||||
char *buf;
|
||||
} client;
|
||||
|
||||
/* ACL information */
|
||||
typedef struct aclInfo {
|
||||
long long user_auth_failures; /* Auth failure counts on user level */
|
||||
long long invalid_cmd_accesses; /* Invalid command accesses that user doesn't have permission to */
|
||||
long long invalid_key_accesses; /* Invalid key accesses that user doesn't have permission to */
|
||||
long long invalid_channel_accesses; /* Invalid channel accesses that user doesn't have permission to */
|
||||
} aclInfo;
|
||||
|
||||
struct saveparam {
|
||||
time_t seconds;
|
||||
int changes;
|
||||
@ -1899,6 +1907,7 @@ struct redisServer {
|
||||
the old "requirepass" directive for
|
||||
backward compatibility with Redis <= 5. */
|
||||
int acl_pubsub_default; /* Default ACL pub/sub channels flag */
|
||||
aclInfo acl_info; /* ACL info */
|
||||
/* Assert & bug reporting */
|
||||
int watchdog_period; /* Software watchdog period in ms. 0 = off */
|
||||
/* System hardware info */
|
||||
@ -2798,6 +2807,7 @@ void ACLFreeUserAndKillClients(user *u);
|
||||
void addACLLogEntry(client *c, int reason, int context, int argpos, sds username, sds object);
|
||||
const char* getAclErrorMessage(int acl_res);
|
||||
void ACLUpdateDefaultUserPassword(sds password);
|
||||
sds genRedisInfoStringACLStats(sds info);
|
||||
|
||||
/* Sorted sets data type */
|
||||
|
||||
|
@ -751,6 +751,71 @@ start_server {tags {"acl external:skip"}} {
|
||||
catch {r ACL load} err
|
||||
set err
|
||||
} {*Redis instance is not configured to use an ACL file*}
|
||||
|
||||
# If there is an AUTH failure the metric increases
|
||||
test {ACL-Metrics user AUTH failure} {
|
||||
set current_auth_failures [s acl_access_denied_auth]
|
||||
set current_invalid_cmd_accesses [s acl_access_denied_cmd]
|
||||
set current_invalid_key_accesses [s acl_access_denied_key]
|
||||
set current_invalid_channel_accesses [s acl_access_denied_channel]
|
||||
assert_error "*WRONGPASS*" {r AUTH notrealuser 1233456}
|
||||
assert {[s acl_access_denied_auth] eq [expr $current_auth_failures + 1]}
|
||||
assert_error "*WRONGPASS*" {r HELLO 3 AUTH notrealuser 1233456}
|
||||
assert {[s acl_access_denied_auth] eq [expr $current_auth_failures + 2]}
|
||||
assert_error "*WRONGPASS*" {r HELLO 2 AUTH notrealuser 1233456}
|
||||
assert {[s acl_access_denied_auth] eq [expr $current_auth_failures + 3]}
|
||||
assert {[s acl_access_denied_cmd] eq $current_invalid_cmd_accesses}
|
||||
assert {[s acl_access_denied_key] eq $current_invalid_key_accesses}
|
||||
assert {[s acl_access_denied_channel] eq $current_invalid_channel_accesses}
|
||||
}
|
||||
|
||||
# If a user try to access an unauthorized command the metric increases
|
||||
test {ACL-Metrics invalid command accesses} {
|
||||
set current_auth_failures [s acl_access_denied_auth]
|
||||
set current_invalid_cmd_accesses [s acl_access_denied_cmd]
|
||||
set current_invalid_key_accesses [s acl_access_denied_key]
|
||||
set current_invalid_channel_accesses [s acl_access_denied_channel]
|
||||
r ACL setuser invalidcmduser on >passwd nocommands
|
||||
r AUTH invalidcmduser passwd
|
||||
assert_error "*no permissions to run the * command*" {r acl list}
|
||||
r AUTH default ""
|
||||
assert {[s acl_access_denied_auth] eq $current_auth_failures}
|
||||
assert {[s acl_access_denied_cmd] eq [expr $current_invalid_cmd_accesses + 1]}
|
||||
assert {[s acl_access_denied_key] eq $current_invalid_key_accesses}
|
||||
assert {[s acl_access_denied_channel] eq $current_invalid_channel_accesses}
|
||||
}
|
||||
|
||||
# If a user try to access an unauthorized key the metric increases
|
||||
test {ACL-Metrics invalid key accesses} {
|
||||
set current_auth_failures [s acl_access_denied_auth]
|
||||
set current_invalid_cmd_accesses [s acl_access_denied_cmd]
|
||||
set current_invalid_key_accesses [s acl_access_denied_key]
|
||||
set current_invalid_channel_accesses [s acl_access_denied_channel]
|
||||
r ACL setuser invalidkeyuser on >passwd resetkeys allcommands
|
||||
r AUTH invalidkeyuser passwd
|
||||
assert_error "*no permissions to access one of the keys*" {r get x}
|
||||
r AUTH default ""
|
||||
assert {[s acl_access_denied_auth] eq $current_auth_failures}
|
||||
assert {[s acl_access_denied_cmd] eq $current_invalid_cmd_accesses}
|
||||
assert {[s acl_access_denied_key] eq [expr $current_invalid_key_accesses + 1]}
|
||||
assert {[s acl_access_denied_channel] eq $current_invalid_channel_accesses}
|
||||
}
|
||||
|
||||
# If a user try to access an unauthorized channel the metric increases
|
||||
test {ACL-Metrics invalid channels accesses} {
|
||||
set current_auth_failures [s acl_access_denied_auth]
|
||||
set current_invalid_cmd_accesses [s acl_access_denied_cmd]
|
||||
set current_invalid_key_accesses [s acl_access_denied_key]
|
||||
set current_invalid_channel_accesses [s acl_access_denied_channel]
|
||||
r ACL setuser invalidchanneluser on >passwd resetchannels allcommands
|
||||
r AUTH invalidkeyuser passwd
|
||||
assert_error "*no permissions to access one of the channels*" {r subscribe x}
|
||||
r AUTH default ""
|
||||
assert {[s acl_access_denied_auth] eq $current_auth_failures}
|
||||
assert {[s acl_access_denied_cmd] eq $current_invalid_cmd_accesses}
|
||||
assert {[s acl_access_denied_key] eq $current_invalid_key_accesses}
|
||||
assert {[s acl_access_denied_channel] eq [expr $current_invalid_channel_accesses + 1]}
|
||||
}
|
||||
}
|
||||
|
||||
set server_path [tmpdir "server.acl"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user