[MEDIUM] add user/groupname support
Patch from Marcus Rueckert for 1.2.17 :
"I added the attached patch to haproxy. I don't have a static uid/gid for
haproxy so i need to specify the username/groupname to run it as non
root user."
diff --git a/doc/haproxy-en.txt b/doc/haproxy-en.txt
index ab26df5..dbe78f5 100644
--- a/doc/haproxy-en.txt
+++ b/doc/haproxy-en.txt
@@ -112,6 +112,8 @@
- maxconn <number>
- uid <user id>
- gid <group id>
+ - user <user name>
+ - group <group name>
- chroot <directory>
- nbproc <number>
- daemon
@@ -197,9 +199,14 @@
which the process will switch to after binding its listening sockets. The value
'0', which normally represents the super-user, here indicates that the UID must
not change during startup. It's the default behaviour. The 'gid' parameter does
-the same for the group identifier. It's particularly advised against use of
-generic accounts such as 'nobody' because it has the same consequences as using
-'root' if other services use them.
+the same for the group identifier. If setting an uid is not possible because of
+deployment constraints, it is possible to set a user name with the 'user'
+keyword followed by a valid user name. The same is true for the gid. It is
+possible to specify a group name after the 'group' keyword.
+
+It is particularly advised against use of generic accounts such as 'nobody'
+because it has the same consequences as using 'root' if other services use
+them.
The 'chroot' parameter makes the process isolate itself in an empty directory
just before switching its UID. This type of isolation (chroot) can sometimes
@@ -227,11 +234,18 @@
Example :
---------
+ # with uid/gid
global
uid 30000
gid 30000
chroot /var/chroot/haproxy
+ # with user/group
+ global
+ user haproxy
+ group public
+ chroot /var/chroot/haproxy
+
1.4) Startup modes
------------------
diff --git a/doc/haproxy-fr.txt b/doc/haproxy-fr.txt
index 9282cb4..7f6d231 100644
--- a/doc/haproxy-fr.txt
+++ b/doc/haproxy-fr.txt
@@ -119,6 +119,8 @@
- maxconn <nombre>
- uid <identifiant>
- gid <identifiant>
+ - user <nom d'utilisateur>
+ - group <nom de groupe>
- chroot <répertoire>
- nbproc <nombre>
- daemon
@@ -208,9 +210,14 @@
l'on ne souhaite pas changer cet identifiant et conserver la valeur courante.
C'est la valeur par défaut. De la même manière, le paramètre 'gid' correspond à
un identifiant de groupe, et utilise par défaut la valeur 0 pour ne rien
-changer. Il est particulièrement déconseillé d'utiliser des comptes génériques
-tels que 'nobody' car cette pratique revient à utiliser 'root' si d'autres
-processus utilisent les mêmes identifiants.
+changer. Dans le cas où il ne serait pas possible de spécifier un identifiant
+numérique pour l'uid, il est possible de spécifier un nom d'utilisateur après
+le mot-clé 'user'. De la même manière, il est possible de préciser un nom de
+groupe après le mot-clé 'group'.
+
+Il est particulièrement déconseillé d'utiliser des comptes génériques tels que
+'nobody' car cette pratique revient à utiliser 'root' si d'autres processus
+utilisent les mêmes identifiants.
Le paramètre 'chroot' autorise à changer la racine du processus une fois le
programme lancé, de sorte que ni le processus, ni l'un de ses descendants ne
@@ -246,11 +253,19 @@
Exemple :
---------
+ # with uid/gid
global
uid 30000
gid 30000
chroot /var/chroot/haproxy
+ # with user/group
+ global
+ user haproxy
+ group public
+ chroot /var/chroot/haproxy
+
+
1.4) Modes de fonctionnement
----------------------------
Le service peut fonctionner dans plusieurs modes :
diff --git a/src/cfgparse.c b/src/cfgparse.c
index ae5433e..4c1f032 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -15,6 +15,8 @@
#include <string.h>
#include <netdb.h>
#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
#include <common/cfgparse.h>
#include <common/config.h>
@@ -269,7 +271,7 @@
}
else if (!strcmp(args[0], "uid")) {
if (global.uid != 0) {
- Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
return 0;
}
if (*(args[1]) == 0) {
@@ -280,7 +282,7 @@
}
else if (!strcmp(args[0], "gid")) {
if (global.gid != 0) {
- Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
return 0;
}
if (*(args[1]) == 0) {
@@ -289,6 +291,40 @@
}
global.gid = atol(args[1]);
}
+ /* user/group name handling */
+ else if (!strcmp(args[0], "user")) {
+ struct passwd *ha_user;
+ if (global.uid != 0) {
+ Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
+ return 0;
+ }
+ errno = 0;
+ ha_user = getpwnam(args[1]);
+ if (ha_user != NULL) {
+ global.uid = (int)ha_user->pw_uid;
+ }
+ else {
+ Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
+ exit(1);
+ }
+ }
+ else if (!strcmp(args[0], "group")) {
+ struct group *ha_group;
+ if (global.gid != 0) {
+ Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
+ return 0;
+ }
+ errno = 0;
+ ha_group = getgrnam(args[1]);
+ if (ha_group != NULL) {
+ global.gid = (int)ha_group->gr_gid;
+ }
+ else {
+ Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
+ exit(1);
+ }
+ }
+ /* end of user/group name handling*/
else if (!strcmp(args[0], "nbproc")) {
if (global.nbproc != 0) {
Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);