mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-02 02:02:03 +00:00
MINOR: anon: store the anonymizing key in the CLI's appctx
In order to allow users to dump internal states using a specific key without changing the global one, we're introducing a key in the CLI's appctx. This key is preloaded from the global one when "set anon on" is used (and if none exists, a random one is assigned). And the key can optionally be assigned manually for the whole CLI session. A "show anon" command was also added to show the anon state, and the current key if the users has sufficient permissions. In addition, a "debug dev hash" command was added to test the feature.
This commit is contained in:
parent
fad9da83da
commit
54966dffda
@ -2191,6 +2191,22 @@ prompt
|
||||
quit
|
||||
Close the connection when in interactive mode.
|
||||
|
||||
set anon [on|off] [<key>]
|
||||
This command enables or disables the "anonymized mode" for the current CLI
|
||||
session, which replaces certain fields considered sensitive or confidential
|
||||
in command outputs with hashes that preserve sufficient consistency between
|
||||
elements to help developers identify relations between elements when trying
|
||||
to spot bugs, but a low enough bit count (24) to make them non-reversible due
|
||||
to the high number of possible matches. When turned on, if no key is
|
||||
specified, the global key will be used (either specified in the configuration
|
||||
file by "anonkey" or set via the CLI command "set global-key"). If no such
|
||||
key was set, a random one will be generated. Otherwise it's possible to
|
||||
specify the 32-bit key to be used for the current session, for example, to
|
||||
reuse the key that was used in a previous dump to help compare outputs.
|
||||
Developers will never need this key and it's recommended never to share it as
|
||||
it could allow to confirm/infirm some guesses about what certain hashes could
|
||||
be hiding.
|
||||
|
||||
set dynamic-cookie-key backend <backend> <value>
|
||||
Modify the secret key used to generate the dynamic persistent cookies.
|
||||
This will break the existing sessions.
|
||||
@ -2479,6 +2495,10 @@ show acl [[@<ver>] <acl>]
|
||||
count of all the ACL entries, not just the active ones, which means that it
|
||||
also includes entries currently being added.
|
||||
|
||||
show anon
|
||||
Display the current state of the anonymized mode (enabled or disabled) and
|
||||
the current session's key.
|
||||
|
||||
show backend
|
||||
Dump the list of backends available in the running process
|
||||
|
||||
|
@ -70,6 +70,7 @@ struct appctx {
|
||||
if the command is terminated or the session released */
|
||||
int cli_severity_output; /* used within the cli_io_handler to format severity output of informational feedback */
|
||||
int cli_level; /* the level of CLI which can be lowered dynamically */
|
||||
uint32_t cli_anon_key; /* the key to anonymise with the hash in cli */
|
||||
struct buffer_wait buffer_wait; /* position in the list of objects waiting for a buffer */
|
||||
struct task *t; /* task associated to the applet */
|
||||
struct freq_ctr call_rate; /* appctx call rate */
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <haproxy/protocol-t.h>
|
||||
#include <haproxy/tools-t.h>
|
||||
#include <haproxy/xxhash.h>
|
||||
#include <haproxy/cli.h>
|
||||
|
||||
/****** string-specific macros and functions ******/
|
||||
/* if a > max, then bound <a> to <max>. The macro returns the new <a> */
|
||||
@ -68,6 +69,9 @@
|
||||
/* use if you want to return a hash like : PATH('hash'). Key 0 doesn't hash. */
|
||||
#define HA_ANON_PATH(key, str) hash_anon(key, str, "PATH(", ")")
|
||||
|
||||
/* use only in a function that contains an appctx (key comes from appctx). */
|
||||
#define HA_ANON_CLI(str) hash_anon(appctx->cli_anon_key, str, "", "")
|
||||
|
||||
|
||||
/*
|
||||
* copies at most <size-1> chars from <src> to <dst>. Last char is always
|
||||
|
68
src/cli.c
68
src/cli.c
@ -1874,6 +1874,50 @@ int cli_parse_default(char **args, char *payload, struct appctx *appctx, void *p
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* enable or disable the anonymized mode, it returns 1 when it works or displays an error message if it doesn't. */
|
||||
static int cli_parse_set_anon(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
uint32_t tmp;
|
||||
long long key;
|
||||
|
||||
if (strcmp(args[2], "on") == 0) {
|
||||
if (appctx->cli_anon_key != 0)
|
||||
return cli_err(appctx, "Mode already enabled\n");
|
||||
else {
|
||||
if (*args[3]) {
|
||||
key = atoll(args[3]);
|
||||
if (key < 1 || key > UINT_MAX)
|
||||
return cli_err(appctx, "Value out of range (1 to 4294967295 expected).\n");
|
||||
appctx->cli_anon_key = key;
|
||||
}
|
||||
else {
|
||||
tmp = HA_ATOMIC_LOAD(&global.anon_key);
|
||||
if (tmp != 0)
|
||||
appctx->cli_anon_key = tmp;
|
||||
else
|
||||
appctx->cli_anon_key = ha_random32();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcmp(args[2], "off") == 0) {
|
||||
if (appctx->cli_anon_key == 0)
|
||||
return cli_err(appctx, "Mode already disabled\n");
|
||||
else if (*args[3]) {
|
||||
return cli_err(appctx, "Key can't be added while disabling anonymized mode\n");
|
||||
}
|
||||
else {
|
||||
appctx->cli_anon_key = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return cli_err(appctx,
|
||||
"'set anon' only supports :\n"
|
||||
" - 'on' [key] to enable the anonymized mode\n"
|
||||
" - 'off' to disable the anonymized mode");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function set the global anonyzing key, restricted to level 'admin' */
|
||||
static int cli_parse_set_global_key(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
@ -1892,6 +1936,28 @@ static int cli_parse_set_global_key(char **args, char *payload, struct appctx *a
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* shows the anonymized mode state to everyone, and the key except for users, it always returns 1. */
|
||||
static int cli_parse_show_anon(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
char *msg = NULL;
|
||||
char *anon_mode = NULL;
|
||||
uint32_t c_key = appctx->cli_anon_key;
|
||||
|
||||
if (!c_key)
|
||||
anon_mode = "Anonymized mode disabled";
|
||||
else
|
||||
anon_mode = "Anonymized mode enabled";
|
||||
|
||||
if ( !((appctx->cli_level & ACCESS_LVL_MASK) < ACCESS_LVL_OPER) && c_key != 0) {
|
||||
cli_dynmsg(appctx, LOG_INFO, memprintf(&msg, "%s\nKey : %u\n", anon_mode, c_key));
|
||||
}
|
||||
else {
|
||||
cli_dynmsg(appctx, LOG_INFO, memprintf(&msg, "%s\n", anon_mode));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* parse a "set rate-limit" command. It always returns 1. */
|
||||
static int cli_parse_set_ratelimit(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
@ -3200,11 +3266,13 @@ static struct cli_kw_list cli_kws = {{ },{
|
||||
{ { "expert-mode", NULL }, NULL, cli_parse_expert_experimental_mode, NULL, NULL, NULL, ACCESS_MASTER }, // not listed
|
||||
{ { "experimental-mode", NULL }, NULL, cli_parse_expert_experimental_mode, NULL, NULL, NULL, ACCESS_MASTER }, // not listed
|
||||
{ { "mcli-debug-mode", NULL }, NULL, cli_parse_expert_experimental_mode, NULL, NULL, NULL, ACCESS_MASTER_ONLY }, // not listed
|
||||
{ { "set", "anon", NULL }, "set anon <setting> [value] : change the anonymized mode setting", cli_parse_set_anon, NULL, NULL },
|
||||
{ { "set", "global-key", NULL }, "set global-key <value> : change the global anonymizing key", cli_parse_set_global_key, NULL, NULL },
|
||||
{ { "set", "maxconn", "global", NULL }, "set maxconn global <value> : change the per-process maxconn setting", cli_parse_set_maxconn_global, NULL },
|
||||
{ { "set", "rate-limit", NULL }, "set rate-limit <setting> <value> : change a rate limiting value", cli_parse_set_ratelimit, NULL },
|
||||
{ { "set", "severity-output", NULL }, "set severity-output [none|number|string]: set presence of severity level in feedback information", cli_parse_set_severity_output, NULL, NULL },
|
||||
{ { "set", "timeout", NULL }, "set timeout [cli] <delay> : change a timeout setting", cli_parse_set_timeout, NULL, NULL },
|
||||
{ { "show", "anon", NULL }, "show anon : display the current state of anonymized mode", cli_parse_show_anon, NULL },
|
||||
{ { "show", "env", NULL }, "show env [var] : dump environment variables known to the process", cli_parse_show_env, cli_io_handler_show_env, NULL },
|
||||
{ { "show", "cli", "sockets", NULL }, "show cli sockets : dump list of cli sockets", cli_parse_default, cli_io_handler_show_cli_sock, NULL, NULL, ACCESS_MASTER },
|
||||
{ { "show", "cli", "level", NULL }, "show cli level : display the level of the current CLI session", cli_parse_show_lvl, NULL, NULL, NULL, ACCESS_MASTER},
|
||||
|
11
src/debug.c
11
src/debug.c
@ -701,6 +701,15 @@ static int debug_parse_cli_tkill(char **args, char *payload, struct appctx *appc
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* hashes 'word' in "debug dev hash 'word' ". */
|
||||
static int debug_parse_cli_hash(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
char *msg = NULL;
|
||||
|
||||
cli_dynmsg(appctx, LOG_INFO, memprintf(&msg, "%s\n", HA_ANON_CLI(args[3])));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* parse a "debug dev write" command. It always returns 1. */
|
||||
static int debug_parse_cli_write(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
@ -1627,6 +1636,8 @@ static struct cli_kw_list cli_kws = {{ },{
|
||||
{{ "debug", "dev", "tkill", NULL }, "debug dev tkill [thr] [sig] : send signal to thread", debug_parse_cli_tkill, NULL, NULL, NULL, ACCESS_EXPERT },
|
||||
{{ "debug", "dev", "warn", NULL }, "debug dev warn : call WARN_ON() and possibly crash", debug_parse_cli_warn, NULL, NULL, NULL, ACCESS_EXPERT },
|
||||
{{ "debug", "dev", "write", NULL }, "debug dev write [size] : write that many bytes in return", debug_parse_cli_write, NULL, NULL, NULL, ACCESS_EXPERT },
|
||||
{{ "debug", "dev", "hash", NULL }, "debug dev hash [msg] : return msg hashed", debug_parse_cli_hash, NULL, NULL, NULL, ACCESS_EXPERT },
|
||||
|
||||
#if defined(HA_HAVE_DUMP_LIBS)
|
||||
{{ "show", "libs", NULL, NULL }, "show libs : show loaded object files and libraries", debug_parse_cli_show_libs, NULL, NULL },
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user