From: Willy Tarreau Date: Thu, 24 Oct 2019 15:55:53 +0000 (+0200) Subject: MINOR: cli: add an expert mode to hide dangerous commands X-Git-Tag: v2.1-dev3~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=abb9f9b0578045ac1507ac4e1d431560ba569286;p=thirdparty%2Fhaproxy.git MINOR: cli: add an expert mode to hide dangerous commands Some commands like the debug ones are not enabled by default but can be useful on some production environments. In order to avoid the temptation of using them incorrectly, let's introduce an "expert" mode for a CLI connection, which allows some commands to appear and be used. It is enabled by command "expert-mode on" which is not listed by default. --- diff --git a/doc/management.txt b/doc/management.txt index d56a031a07..890f26058a 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 3dee3f830d..8a44124151 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 6b0b5e7616..6037e9698b 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 {{},} }};