diff --git a/doc/management.txt b/doc/management.txt index d56a031a0..890f26058 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1586,6 +1586,18 @@ enable server / This command is restricted and can only be issued on sockets configured for level "admin". +expert-mode [on|off] + Without options, this indicates whether the expert mode is enabled or + disabled on the current connection. When passed "on", it turns the expert + mode on for the current CLI connection only. With "off" it turns it off. The + expert mode enables displaying of expert commands that can be extremely + dangerous for the process and which may occasionally help developers collect + important information about complex bugs. Any misuse of these features will + likely lead to a process crash. Do not use this option without being invited + to do so. Note that this command is purposely not listed in the help message. + This command is only accessible in admin level. Changing to another level + automatically resets the expert mode. + get map get acl Lookup the value in the map or in the ACL . or @@ -1841,11 +1853,11 @@ show cli level operator Decrease the CLI level of the current CLI session to operator. It can't be - increase. See also "show cli level" + increased. It also drops expert mode. See also "show cli level". user Decrease the CLI level of the current CLI session to user. It can't be - increase. See also "show cli level" + increased. It also drops expert mode. See also "show cli level". show activity Reports some counters about internal events that will help developers and diff --git a/include/types/cli.h b/include/types/cli.h index 3dee3f830..8a4412415 100644 --- a/include/types/cli.h +++ b/include/types/cli.h @@ -34,6 +34,8 @@ #define ACCESS_MASTER 0x8 /* works with the master (and every other processes) */ #define ACCESS_MASTER_ONLY 0x10 /* only works with the worker */ +#define ACCESS_EXPERT 0x20 /* access to dangerous commands reserved to experts */ + struct cli_kw { const char *str_kw[5]; /* keywords ended by NULL, limited to 5 separated keywords combination */ diff --git a/src/cli.c b/src/cli.c index 6b0b5e761..6037e9698 100644 --- a/src/cli.c +++ b/src/cli.c @@ -125,6 +125,10 @@ static char *cli_gen_usage_msg(struct appctx *appctx) if (master == 1 && !(kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER))) goto next_kw; + /* only show expert commands in expert mode */ + if ((kw->level & ~appctx->cli_level) & ACCESS_EXPERT) + goto next_kw; + if (kw->usage) chunk_appendf(tmp, " %s\n", kw->usage); @@ -567,6 +571,10 @@ static int cli_parse_request(struct appctx *appctx) if (master == 1 && !(kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER))) return 0; + /* only accept expert commands in expert mode */ + if ((kw->level & ~appctx->cli_level) & ACCESS_EXPERT) + return 0; + appctx->io_handler = kw->io_handler; appctx->io_release = kw->io_release; /* kw->parse could set its own io_handler or ip_release handler */ @@ -1441,6 +1449,25 @@ static int cli_parse_set_lvl(char **args, char *payload, struct appctx *appctx, appctx->cli_level &= ~ACCESS_LVL_MASK; appctx->cli_level |= ACCESS_LVL_USER; } + appctx->cli_level &= ~ACCESS_EXPERT; + return 1; +} + + +/* parse and set the CLI expert-mode dynamically */ +static int cli_parse_expert_mode(char **args, char *payload, struct appctx *appctx, void *private) +{ + if (!cli_has_level(appctx, ACCESS_LVL_ADMIN)) + return 1; + + if (!*args[1]) + return (appctx->cli_level & ACCESS_EXPERT) + ? cli_msg(appctx, LOG_INFO, "expert-mode is ON\n") + : cli_msg(appctx, LOG_INFO, "expert-mode is OFF\n"); + + appctx->cli_level &= ~ACCESS_EXPERT; + if (strcmp(args[1], "on") == 0) + appctx->cli_level |= ACCESS_EXPERT; return 1; } @@ -2671,6 +2698,7 @@ static struct cli_kw_list cli_kws = {{ },{ { { "operator", NULL }, "operator : lower the level of the current CLI session to operator", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER}, { { "user", NULL }, "user : lower the level of the current CLI session to user", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER}, { { "_getsocks", NULL }, NULL, _getsocks, NULL }, + { { "expert-mode", NULL }, NULL, cli_parse_expert_mode, NULL }, // not listed {{},} }};