* Declarative specification of user accounts. Jobs can now specify a

list of user accounts that the job needs to run.  For instance, the
  SSH daemon job says:

    { name = "sshd";
      uid = (import ../system/ids.nix).uids.sshd;
      description = "SSH privilege separation user";
      home = "/var/empty";
    }

  The activation script creates the system users/groups and updates
  them as well.  So a change in the Nix expression can be realised in
  /etc/{group,passwd} by running nixos-rebuild.

svn path=/nixos/trunk/; revision=8846
This commit is contained in:
Eelco Dolstra 2007-06-08 15:41:12 +00:00
parent 566c723986
commit 29c5178bdf
12 changed files with 228 additions and 61 deletions

View file

@ -0,0 +1,60 @@
cat "$2" | while true; do
read name || break
read gid
if ! curEnt=$(getent group "$name"); then
echo "creating group $name..."
groupadd --system \
"$name" \
${gid:+--gid $gid}
else
echo "updating group $name..."
oldIFS="$IFS"; IFS=:; set -- $curEnt; IFS="$oldIFS"
prevGid=$3
if test "$prevGid" != "$gid"; then
groupmod "$name" --gid $gid
fi
fi
done
cat "$1" | while true; do
read name || break
read description
read uid
read group
read extraGroups
read home
read shell
if ! curEnt=$(getent passwd "$name"); then
echo "creating user $name..."
useradd --system \
"$name" \
--comment "$description" \
${uid:+--uid $uid} \
--gid "$group" \
--groups "$extraGroups" \
--home "$home" \
--shell "$shell"
else
echo "updating user $name..."
oldIFS="$IFS"; IFS=:; set -- $curEnt; IFS="$oldIFS"
prevUid=$3
prevHome=$6
# Don't change the UID if it's the same, otherwise usermod
# will complain.
if test "$prevUid" = "$uid"; then unset uid; fi
# Don't change the home directory if it's the same to prevent
# unnecessary warnings about logged in users.
if test "$prevHome" = "$home"; then unset home; fi
usermod \
"$name" \
--comment "$description" \
${uid:+--uid $uid} \
--gid "$group" \
--groups "$extraGroups" \
${home:+--home "$home"} \
--shell "$shell"
fi
done

View file

@ -64,6 +64,10 @@ touch /var/log/lastlog
chmod 644 /var/log/lastlog
# Empty, read-only home directory of many system accounts.
mkdir -m 0555 -p /var/empty
# If there is no password file yet, create a root account with an
# empty password.
if ! test -e /etc/passwd; then
@ -71,37 +75,21 @@ if ! test -e /etc/passwd; then
touch /etc/passwd; chmod 0644 /etc/passwd
touch /etc/group; chmod 0644 /etc/group
touch /etc/shadow; chmod 0600 /etc/shadow
# Can't use useradd, since it complain that it doesn't know us
# Can't use useradd, since it complains that it doesn't know us
# (bootstrap problem!).
echo "root:x:0:0:System administrator:$rootHome:@defaultShell@" >> /etc/passwd
echo "root::::::::" >> /etc/shadow
groupadd -g 0 root
echo | passwd --stdin root
fi
# Some more required accounts/groups.
if ! getent group nogroup > /dev/null; then
groupadd -g 65534 nogroup
fi
# Create system users and groups.
@shell@ @createUsersGroups@ @usersList@ @groupsList@
# Set up Nix accounts.
# Set up Nix.
if test -z "@readOnlyRoot@"; then
if ! getent group nixbld > /dev/null; then
groupadd -g 30000 nixbld
fi
for i in $(seq 1 10); do
account=nixbld$i
if ! getent passwd $account > /dev/null; then
useradd -u $((i + 30000)) -g nogroup -G nixbld \
-d /var/empty -s /noshell \
-c "Nix build user $i" $account
fi
done
mkdir -p /nix/etc/nix
cat > /nix/etc/nix/nix.conf <<EOF
# WARNING: this file is generated.

21
system/ids.nix Normal file
View file

@ -0,0 +1,21 @@
{
uids = {
root = 0;
nscd = 1;
sshd = 2;
ntp = 3;
messagebus = 4; # D-Bus
haldaemon = 5;
nixbld = 30000; # start of range of uids
nobody = 65534;
};
gids = {
root = 0;
users = 100;
nixbld = 30000;
nogroup = 65534;
};
}

View file

@ -228,6 +228,9 @@ rec {
};
usersGroups = import ./users-groups.nix { inherit pkgs upstartJobs defaultShell; };
defaultShell = "/var/run/current-system/sw/bin/bash";
@ -247,6 +250,8 @@ rec {
config.get ["security" "extraSetuidPrograms"];
maxJobs = config.get ["nix" "maxJobs"];
inherit (usersGroups) createUsersGroups usersList groupsList;
path = [
pkgs.coreutils pkgs.gnugrep pkgs.findutils
pkgs.glibc # needed for getent

72
system/users-groups.nix Normal file
View file

@ -0,0 +1,72 @@
{pkgs, upstartJobs, defaultShell}:
let ids = import ./ids.nix; in
rec {
# System user accounts.
systemUsers =
let
jobUsers = pkgs.lib.concatLists (map (job: job.users) upstartJobs.jobs);
defaultUsers =
[
{ name = "root";
uid = ids.uids.root;
description = "System administrator";
home = "/root";
shell = defaultShell;
}
{ name = "nobody";
uid = ids.uids.nobody;
description = "Unprivileged account (don't use!)";
}
];
makeNixBuildUser = nr:
{ name = "nixbld${toString nr}";
description = "Nix build user ${toString nr}";
uid = builtins.add ids.uids.nixbld nr;
extraGroups = ["nixbld"];
};
nixBuildUsers = map makeNixBuildUser (pkgs.lib.range 1 10);
addAttrs =
{ name
, description
, uid ? ""
, group ? "nogroup"
, extraGroups ? []
, home ? "/var/empty"
, shell ? "/noshell"
}:
{ inherit name description uid group extraGroups home shell; };
in map addAttrs (defaultUsers ++ jobUsers ++ nixBuildUsers);
# System groups.
systemGroups =
[
{ name = "root";
gid = ids.gids.root;
}
{ name = "nogroup";
gid = ids.gids.nogroup;
}
{ name = "users";
gid = ids.gids.users;
}
{ name = "nixbld";
gid = ids.gids.nixbld;
}
];
# Awful hackery necessary to pass the users/groups to the activation script.
createUsersGroups = ../helpers/create-users-groups.sh;
usersList = pkgs.writeText "users" (pkgs.lib.concatStrings (map (u: "${u.name}\n${u.description}\n${toString u.uid}\n${u.group}\n${toString u.extraGroups}\n${u.home}\n${u.shell}\n") systemUsers));
groupsList = pkgs.writeText "groups" (pkgs.lib.concatStrings (map (g: "${g.name}\n${toString g.gid}\n") systemGroups));
}

View file

@ -235,8 +235,6 @@ import ../upstart-jobs/gather.nix {
++ (map makeJob (config.get ["services" "extraJobs"]))
# For the built-in logd job.
++ [
(pkgs.upstart // {extraPath = []; extraEtc = [];})
];
++ [(makeJob { jobDrv = pkgs.upstart; })];
}

View file

@ -81,6 +81,12 @@ in
{
name = "httpd";
users = [
{ name = user;
description = "Apache httpd user";
}
];
job = "
description \"Apache HTTPD\"
@ -92,11 +98,6 @@ start script
${pwdutils}/sbin/groupadd ${group}
fi
if ! ${glibc}/bin/getent passwd ${user} > /dev/null; then
${pwdutils}/sbin/useradd -g ${group} -d /var/empty -s /noshell \\
-c 'Apache httpd user' ${user}
fi
${webServer}/bin/control prepare
end script

View file

@ -1,15 +1,25 @@
{runCommand}: job:
(
runCommand job.name {inherit (job) job;}
"ensureDir $out/etc/event.d; echo \"$job\" > $out/etc/event.d/$name"
if job ? jobDrv then
job.jobDrv
else
(
runCommand job.name {inherit (job) job;}
"ensureDir $out/etc/event.d; echo \"$job\" > $out/etc/event.d/$name"
)
)
//
# Allow jobs to declare extra packages that should be added to the
# system path, as well as extra files that should be added to /etc.
{
# Allow jobs to declare extra packages that should be added to the
# system path.
extraPath = if job ? extraPath then job.extraPath else [];
# Allow jobs to declare extra files that should be added to /etc.
extraEtc = if job ? extraEtc then job.extraEtc else [];
# Allow jobs to declare user accounts that should be created.
users = if job ? users then job.users else [];
}

View file

@ -3,6 +3,13 @@
{
name = "nscd";
users = [
{ name = "nscd";
uid = (import ../system/ids.nix).uids.nscd;
description = "Name service cache daemon user";
}
];
job = "
description \"Name Service Cache Daemon\"
@ -13,11 +20,6 @@ env LD_LIBRARY_PATH=${nssModulesPath}
start script
if ! ${glibc}/bin/getent passwd nscd > /dev/null; then
${pwdutils}/sbin/useradd -g nogroup -d /var/empty -s /noshell \\
-c 'Name service cache daemon user' nscd
fi
mkdir -m 0755 -p /var/run/nscd
mkdir -m 0755 -p /var/db/nscd

View file

@ -19,6 +19,14 @@ in
{
name = "ntpd";
users = [
{ name = ntpUser;
uid = (import ../system/ids.nix).uids.ntp;
description = "NTP daemon user";
home = stateDir;
}
];
job = "
description \"NTP daemon\"
@ -28,11 +36,6 @@ stop on shutdown
start script
if ! ${glibc}/bin/getent passwd ${ntpUser} > /dev/null; then
${pwdutils}/sbin/useradd -g nogroup -d ${stateDir} -s /noshell \\
-c 'NTP daemon user' ${ntpUser}
fi
mkdir -m 0755 -p ${stateDir}
chown ${ntpUser} ${stateDir}

View file

@ -2,13 +2,21 @@
let
user="smbguest";
group="smbguest";
user = "smbguest";
group = "smbguest";
in
{
name = "samba";
users = [
{ name = user;
description = "Samba service user";
group = group;
}
];
job = "
description \"Samba Service\"
@ -18,17 +26,13 @@ stop on network-interfaces/stop
start script
if ! ${glibc}/bin/getent group ${group} > /dev/null; then
${pwdutils}/sbin/groupadd ${group}
fi
if ! ${glibc}/bin/getent group ${group} > /dev/null; then
${pwdutils}/sbin/groupadd ${group}
fi
if ! ${glibc}/bin/getent passwd ${user} > /dev/null; then
${pwdutils}/sbin/useradd -g ${group} -d /var/empty -s /noshell -c 'Samba service user' ${user}
fi
${samba}/sbin/nmbd -D &
${samba}/sbin/smbd -D &
${samba}/sbin/winbindd -B &
${samba}/sbin/nmbd -D &
${samba}/sbin/smbd -D &
${samba}/sbin/winbindd -B &
end script

View file

@ -22,10 +22,20 @@ let
";
sshdUid = (import ../system/ids.nix).uids.sshd;
in
{
name = "sshd";
users = [
{ name = "sshd";
uid = (import ../system/ids.nix).uids.sshd;
description = "SSH privilege separation user";
home = "/var/empty";
}
];
job = "
description \"SSH server\"
@ -36,18 +46,11 @@ stop on network-interfaces/stop
env LD_LIBRARY_PATH=${nssModulesPath}
start script
mkdir -m 0555 -p /var/empty
mkdir -m 0755 -p /etc/ssh
if ! test -f /etc/ssh/ssh_host_dsa_key; then
${openssh}/bin/ssh-keygen -t dsa -b 1024 -f /etc/ssh/ssh_host_dsa_key -N ''
fi
if ! ${glibc}/bin/getent passwd sshd > /dev/null; then
${pwdutils}/sbin/useradd -g nogroup -d /var/empty -s /noshell \\
-c 'SSH privilege separation user' sshd
fi
end script
respawn ${openssh}/sbin/sshd -D -h /etc/ssh/ssh_host_dsa_key -f ${sshdConfig}