This statement must appear before using directives tagged as experimental or
the config file will be rejected.
-external-check
+external-check [preserve-env]
Allows the use of an external agent to perform health checks. This is
disabled by default as a security precaution, and even when enabled, checks
may still fail unless "insecure-fork-wanted" is enabled as well. If the
program launched makes use of a setuid executable (it should really not),
you may also need to set "insecure-setuid-wanted" in the global section.
- See "option external-check", and "insecure-fork-wanted", and
- "insecure-setuid-wanted".
+ By default, the checks start with a clean environment which only contains
+ variables defined in the "external-check" command in the backend section. It
+ may sometimes be desirable to preserve the environment though, for example
+ when complex scripts retrieve their extra paths or information there. This
+ can be done by appending the "preserve-env" keyword. In this case however it
+ is strongly advised not to run a setuid nor as a privileged user, as this
+ exposes the check program to potential attacks. See "option external-check",
+ and "insecure-fork-wanted", and "insecure-setuid-wanted" for extra details.
fd-hard-limit <number>
Sets an upper bound to the maximum number of file descriptors that the
struct global {
int uid;
int gid;
- int external_check;
+ int external_check; /* 0=disabled, 1=enabled, 2=enabled with env */
int nbthread;
int mode;
unsigned int hard_stop_after; /* maximum time allowed to perform a soft-stop */
}
}
else if (strcmp(args[0], "external-check") == 0) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;
global.external_check = 1;
+ if (strcmp(args[1], "preserve-env") == 0) {
+ global.external_check = 2;
+ } else {
+ ha_alert("parsing [%s:%d] : '%s' only supports 'preserve-env' as an argument, found '%s'.\n", file, linenum, args[0], args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
}
/* user/group name handling */
else if (strcmp(args[0], "user") == 0) {
(unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
}
- environ = check->envp;
+ if (global.external_check < 2) {
+ /* fresh new env for each check */
+ environ = check->envp;
+ }
/* Update some environment variables and command args: curconn, server addr and server port */
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->cur_sess, buf, sizeof(buf)), fail);
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_ADDR, check->argv[3], fail);
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_PORT, check->argv[4], fail);
+ if (global.external_check >= 2) {
+ /* environment is preserved, let's merge new vars */
+ int i;
+
+ for (i = 0; check->envp[i] && *check->envp[i]; i++) {
+ char *delim = strchr(check->envp[i], '=');
+ if (!delim)
+ continue;
+ *(delim++) = 0;
+ if (setenv(check->envp[i], delim, 1) != 0)
+ goto fail;
+ }
+ }
haproxy_unblock_signals();
execvp(px->check_command, check->argv);
ha_alert("Failed to exec process for external health check: %s. Aborting.\n",