mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 15:17:01 +02:00
MINOR: config: add command-line -dC to dump the configuration file
This commit adds a new command line option -dC to dump the configuration file. An optional key may be appended to -dC in order to produce an anonymized dump using this key. The anonymizing process uses the same algorithm as the CLI so that the same key will produce the same hashes for the same identifiers. This way an admin may share an anonymized extract of a configuration to match against live dumps. Note that key 0 will not anonymize the output. However, in any case, the configuration is dumped after tokenizing, thus comments are lost.
This commit is contained in:
parent
acfdf7600b
commit
b0c0501516
@ -3226,7 +3226,8 @@ anonkey <key>
|
||||
This sets the global anonymizing key to <key>, which must be a 32-bit number
|
||||
between 0 and 4294967295. This is the key that will be used by default by CLI
|
||||
commands when anonymized mode is enabled. This key may also be set at runtime
|
||||
from the CLI command "set global-key".
|
||||
from the CLI command "set global-key". See also command line argument "-dC"
|
||||
in the management manual.
|
||||
|
||||
quiet
|
||||
Do not display any message during startup. It is equivalent to the command-
|
||||
|
@ -204,6 +204,15 @@ list of options is :
|
||||
in foreground and to show incoming and outgoing events. It must never be
|
||||
used in an init script.
|
||||
|
||||
-dC[key] : dump the configuration file. It is performed after the lines are
|
||||
tokenized, so comments are stripped and indenting is forced. If a non-zero
|
||||
key is specified, lines are truncated before sensitive/confidential fields,
|
||||
and identifiers and addresses are emitted hashed with this key using the
|
||||
same algorithmm as the one used by the anonymized mode on the CLI. This
|
||||
means that the output may safely be shared with a developer who needs it
|
||||
to figure what's happening in a dump that was anonymized using the same
|
||||
key. Please also see the CLI's "set anon" command.
|
||||
|
||||
-dD : enable diagnostic mode. This mode will output extra warnings about
|
||||
suspicious configuration statements. This will never prevent startup even in
|
||||
"zero-warning" mode nor change the exit status code.
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define MODE_STOPPING 0x1000 /* the process is in the deinit phase, the event loop is not running anymore. */
|
||||
#define MODE_DUMP_LIBS 0x2000 /* dump loaded libraries at the end of init phase */
|
||||
#define MODE_DUMP_KWD 0x4000 /* dump registered keywords (see kwd_dump for the list) */
|
||||
#define MODE_DUMP_CFG 0x8000 /* dump the configure file */
|
||||
|
||||
/* list of last checks to perform, depending on config options */
|
||||
#define LSTCHK_CAP_BIND 0x00000001 /* check that we can bind to any port */
|
||||
|
213
src/cfgparse.c
213
src/cfgparse.c
@ -1893,6 +1893,219 @@ int readcfgfile(const char *file)
|
||||
break;
|
||||
}
|
||||
|
||||
/* dump cfg */
|
||||
if (global.mode & MODE_DUMP_CFG) {
|
||||
if (args[0] != NULL) {
|
||||
struct cfg_section *sect;
|
||||
int is_sect = 0;
|
||||
int i = 0;
|
||||
uint32_t g_key = HA_ATOMIC_LOAD(&global.anon_key);
|
||||
|
||||
qfprintf(stdout, "%d\t", linenum);
|
||||
|
||||
/* if a word is in sections list, is_sect = 1 */
|
||||
list_for_each_entry(sect, §ions, list) {
|
||||
if (strcmp(args[0], sect->section_name) == 0) {
|
||||
is_sect = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_key == 0) {
|
||||
/* no anonymizing needed, dump the config as-is (but without comments).
|
||||
* Note: tabs were lost during tokenizing, so we reinsert for non-section
|
||||
* keywords.
|
||||
*/
|
||||
if (!is_sect)
|
||||
qfprintf(stdout, "\t");
|
||||
|
||||
for (i = 0; i < arg; i++) {
|
||||
qfprintf(stdout, "%s ", args[i]);
|
||||
}
|
||||
qfprintf(stdout, "\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We're anonymizing */
|
||||
|
||||
if (is_sect) {
|
||||
/* new sections are optionally followed by an identifier */
|
||||
if (arg >= 2) {
|
||||
qfprintf(stdout, "%s %s\n", args[0], HA_ANON_ID(g_key, args[1]));
|
||||
}
|
||||
else {
|
||||
qfprintf(stdout, "%s\n", args[0]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* non-section keywords start indented */
|
||||
qfprintf(stdout, "\t");
|
||||
|
||||
/* some keywords deserve special treatment */
|
||||
if (!*args[0]) {
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "anonkey") == 0) {
|
||||
qfprintf(stdout, "%s [...]\n", args[0]);
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "maxconn") == 0) {
|
||||
qfprintf(stdout, "%s %s\n", args[0], args[1]);
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "stats") == 0 &&
|
||||
(strcmp(args[1], "timeout") == 0 || strcmp(args[1], "maxconn") == 0)) {
|
||||
qfprintf(stdout, "%s %s %s\n", args[0], args[1], args[2]);
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "stats") == 0 && strcmp(args[1], "socket") == 0) {
|
||||
qfprintf(stdout, "%s %s ", args[0], args[1]);
|
||||
|
||||
if (arg > 1) {
|
||||
qfprintf(stdout, "%s ", args[2]);
|
||||
|
||||
if (arg > 2) {
|
||||
qfprintf(stdout, "[...]\n");
|
||||
}
|
||||
else {
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "timeout") == 0) {
|
||||
qfprintf(stdout, "%s %s %s\n", args[0], args[1], args[2]);
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "mode") == 0) {
|
||||
qfprintf(stdout, "%s %s\n", args[0], args[1]);
|
||||
}
|
||||
|
||||
/* It concerns user in global secion and in userlist */
|
||||
else if (strcmp(args[0], "user") == 0) {
|
||||
qfprintf(stdout, "%s %s ", args[0], HA_ANON_ID(g_key, args[1]));
|
||||
|
||||
if (arg > 2) {
|
||||
qfprintf(stdout, "[...]\n");
|
||||
}
|
||||
else {
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "bind") == 0) {
|
||||
qfprintf(stdout, "%s ", args[0]);
|
||||
qfprintf(stdout, "%s ", hash_ipanon(g_key, args[1]));
|
||||
if (arg > 2) {
|
||||
qfprintf(stdout, "[...]\n");
|
||||
}
|
||||
else {
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "server") == 0) {
|
||||
qfprintf(stdout, "%s ", args[0]);
|
||||
|
||||
if (strcmp(args[1], "localhost") == 0) {
|
||||
qfprintf(stdout, "%s ", args[1]);
|
||||
}
|
||||
else {
|
||||
qfprintf(stdout, "%s ", HA_ANON_ID(g_key, args[1]));
|
||||
}
|
||||
if (arg > 2) {
|
||||
qfprintf(stdout, "%s ", hash_ipanon(g_key, args[2]));
|
||||
}
|
||||
if (arg > 3) {
|
||||
qfprintf(stdout, "[...]\n");
|
||||
}
|
||||
else {
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "redirect") == 0) {
|
||||
qfprintf(stdout, "%s %s ", args[0], args[1]);
|
||||
|
||||
if (strcmp(args[1], "prefix") == 0 || strcmp(args[1], "location") == 0) {
|
||||
qfprintf(stdout, "%s ", HA_ANON_PATH(g_key, args[2]));
|
||||
}
|
||||
else {
|
||||
qfprintf(stdout, "%s ", args[2]);
|
||||
}
|
||||
if (arg > 3) {
|
||||
qfprintf(stdout, "[...]");
|
||||
}
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "acl") == 0) {
|
||||
qfprintf(stdout, "%s %s %s ", args[0], HA_ANON_ID(g_key, args[1]), args[2]);
|
||||
|
||||
if (arg > 3) {
|
||||
qfprintf(stdout, "[...]");
|
||||
}
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "log") == 0) {
|
||||
qfprintf(stdout, "log ");
|
||||
|
||||
if (strcmp(args[1], "global") == 0) {
|
||||
qfprintf(stdout, "%s ", args[1]);
|
||||
}
|
||||
else {
|
||||
qfprintf(stdout, "%s ", hash_ipanon(g_key, args[1]));
|
||||
}
|
||||
if (arg > 2) {
|
||||
qfprintf(stdout, "[...]");
|
||||
}
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "peer") == 0) {
|
||||
qfprintf(stdout, "%s %s ", args[0], HA_ANON_ID(g_key, args[1]));
|
||||
qfprintf(stdout, "%s ", hash_ipanon(g_key, args[2]));
|
||||
|
||||
if (arg > 3) {
|
||||
qfprintf(stdout, "[...]");
|
||||
}
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "use_backend") == 0) {
|
||||
qfprintf(stdout, "%s %s ", args[0], HA_ANON_ID(g_key, args[1]));
|
||||
|
||||
if (arg > 2) {
|
||||
qfprintf(stdout, "[...]");
|
||||
}
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
else if (strcmp(args[0], "default_backend") == 0) {
|
||||
qfprintf(stdout, "%s %s\n", args[0], HA_ANON_ID(g_key, args[1]));
|
||||
}
|
||||
|
||||
else {
|
||||
/* display up to 3 words and mask the rest which might be confidential */
|
||||
for (i = 0; i < MIN(arg, 3); i++) {
|
||||
qfprintf(stdout, "%s ", args[i]);
|
||||
}
|
||||
if (arg > 3) {
|
||||
qfprintf(stdout, "[...]");
|
||||
}
|
||||
qfprintf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* end of config dump */
|
||||
|
||||
/* empty line */
|
||||
if (!**args)
|
||||
continue;
|
||||
|
@ -590,6 +590,7 @@ static void usage(char *name)
|
||||
" -N sets the default, per-proxy maximum # of connections (%d)\n"
|
||||
" -L set local peer name (default to hostname)\n"
|
||||
" -p writes pids of all children to this file\n"
|
||||
" -dC[key] display the configure file, if there is a key, the file will be anonymise\n"
|
||||
#if defined(USE_EPOLL)
|
||||
" -de disables epoll() usage even when available\n"
|
||||
#endif
|
||||
@ -1633,6 +1634,10 @@ static void init_args(int argc, char **argv)
|
||||
global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
|
||||
else if (*flag == 'V')
|
||||
arg_mode |= MODE_VERBOSE;
|
||||
else if (*flag == 'd' && flag[1] == 'C') {
|
||||
arg_mode |= MODE_DUMP_CFG;
|
||||
HA_ATOMIC_STORE(&global.anon_key, atoll(flag + 2));
|
||||
}
|
||||
else if (*flag == 'd' && flag[1] == 'b')
|
||||
arg_mode |= MODE_FOREGROUND;
|
||||
else if (*flag == 'd' && flag[1] == 'D')
|
||||
@ -1904,7 +1909,7 @@ static void init(int argc, char **argv)
|
||||
|
||||
global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
|
||||
| MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
|
||||
| MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD));
|
||||
| MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD | MODE_DUMP_CFG));
|
||||
|
||||
if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
|
||||
unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
|
||||
@ -2226,6 +2231,9 @@ static void init(int argc, char **argv)
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (global.mode & MODE_DUMP_CFG)
|
||||
deinit_and_exit(0);
|
||||
|
||||
if (global.mode & MODE_DIAG) {
|
||||
cfg_run_diagnostics();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user