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.
This commit is contained in:
Willy Tarreau 2019-10-24 17:55:53 +02:00
parent 86bfe146c9
commit abb9f9b057
3 changed files with 44 additions and 2 deletions

View File

@ -1586,6 +1586,18 @@ enable server <backend>/<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 <map> <value>
get acl <acl> <value>
Lookup the value <value> in the map <map> or in the ACL <acl>. <map> or <acl>
@ -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

View File

@ -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 */

View File

@ -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
{{},}
}};