[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."
This commit is contained in:
Willy Tarreau 2007-03-25 15:39:23 +02:00
parent b38651a435
commit 95c20aca35
3 changed files with 73 additions and 8 deletions

View File

@ -112,6 +112,8 @@ the following ones :
- maxconn <number> - maxconn <number>
- uid <user id> - uid <user id>
- gid <group id> - gid <group id>
- user <user name>
- group <group name>
- chroot <directory> - chroot <directory>
- nbproc <number> - nbproc <number>
- daemon - daemon
@ -197,9 +199,14 @@ In the 'global' section, the 'uid' parameter sets a numerical user identifier
which the process will switch to after binding its listening sockets. The value 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 '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 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 the same for the group identifier. If setting an uid is not possible because of
generic accounts such as 'nobody' because it has the same consequences as using deployment constraints, it is possible to set a user name with the 'user'
'root' if other services use them. 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 The 'chroot' parameter makes the process isolate itself in an empty directory
just before switching its UID. This type of isolation (chroot) can sometimes just before switching its UID. This type of isolation (chroot) can sometimes
@ -227,11 +234,18 @@ directories. Do not forget to allow core dumps prior to start the process :
Example : Example :
--------- ---------
# with uid/gid
global global
uid 30000 uid 30000
gid 30000 gid 30000
chroot /var/chroot/haproxy chroot /var/chroot/haproxy
# with user/group
global
user haproxy
group public
chroot /var/chroot/haproxy
1.4) Startup modes 1.4) Startup modes
------------------ ------------------

View File

@ -119,6 +119,8 @@ support
- maxconn <nombre> - maxconn <nombre>
- uid <identifiant> - uid <identifiant>
- gid <identifiant> - gid <identifiant>
- user <nom d'utilisateur>
- group <nom de groupe>
- chroot <répertoire> - chroot <répertoire>
- nbproc <nombre> - nbproc <nombre>
- daemon - daemon
@ -208,9 +210,14 @@ utilisateur, poss
l'on ne souhaite pas changer cet identifiant et conserver la valeur courante. 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 à 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 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 changer. Dans le cas où il ne serait pas possible de spécifier un identifiant
tels que 'nobody' car cette pratique revient à utiliser 'root' si d'autres numérique pour l'uid, il est possible de spécifier un nom d'utilisateur après
processus utilisent les mêmes identifiants. 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 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 programme lancé, de sorte que ni le processus, ni l'un de ses descendants ne
@ -246,11 +253,19 @@ lancer le programme :
Exemple : Exemple :
--------- ---------
# with uid/gid
global global
uid 30000 uid 30000
gid 30000 gid 30000
chroot /var/chroot/haproxy chroot /var/chroot/haproxy
# with user/group
global
user haproxy
group public
chroot /var/chroot/haproxy
1.4) Modes de fonctionnement 1.4) Modes de fonctionnement
---------------------------- ----------------------------
Le service peut fonctionner dans plusieurs modes : Le service peut fonctionner dans plusieurs modes :

View File

@ -15,6 +15,8 @@
#include <string.h> #include <string.h>
#include <netdb.h> #include <netdb.h>
#include <ctype.h> #include <ctype.h>
#include <pwd.h>
#include <grp.h>
#include <common/cfgparse.h> #include <common/cfgparse.h>
#include <common/config.h> #include <common/config.h>
@ -269,7 +271,7 @@ int cfg_parse_global(const char *file, int linenum, char **args)
} }
else if (!strcmp(args[0], "uid")) { else if (!strcmp(args[0], "uid")) {
if (global.uid != 0) { 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; return 0;
} }
if (*(args[1]) == 0) { if (*(args[1]) == 0) {
@ -280,7 +282,7 @@ int cfg_parse_global(const char *file, int linenum, char **args)
} }
else if (!strcmp(args[0], "gid")) { else if (!strcmp(args[0], "gid")) {
if (global.gid != 0) { 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; return 0;
} }
if (*(args[1]) == 0) { if (*(args[1]) == 0) {
@ -289,6 +291,40 @@ int cfg_parse_global(const char *file, int linenum, char **args)
} }
global.gid = atol(args[1]); 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")) { else if (!strcmp(args[0], "nbproc")) {
if (global.nbproc != 0) { if (global.nbproc != 0) {
Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]); Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);