Merge pull request #328926 from nikstur/sysusers-only-for-sysusers
Sysusers only for sysusers
This commit is contained in:
@@ -5,6 +5,8 @@ let
|
|||||||
cfg = config.systemd.sysusers;
|
cfg = config.systemd.sysusers;
|
||||||
userCfg = config.users;
|
userCfg = config.users;
|
||||||
|
|
||||||
|
systemUsers = lib.filterAttrs (_username: opts: !opts.isNormalUser) userCfg.users;
|
||||||
|
|
||||||
sysusersConfig = pkgs.writeTextDir "00-nixos.conf" ''
|
sysusersConfig = pkgs.writeTextDir "00-nixos.conf" ''
|
||||||
# Type Name ID GECOS Home directory Shell
|
# Type Name ID GECOS Home directory Shell
|
||||||
|
|
||||||
@@ -16,7 +18,7 @@ let
|
|||||||
in
|
in
|
||||||
''u ${username} ${uid}:${opts.group} "${opts.description}" ${opts.home} ${utils.toShellPath opts.shell}''
|
''u ${username} ${uid}:${opts.group} "${opts.description}" ${opts.home} ${utils.toShellPath opts.shell}''
|
||||||
)
|
)
|
||||||
userCfg.users)
|
systemUsers)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Groups
|
# Groups
|
||||||
@@ -30,32 +32,12 @@ let
|
|||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
staticSysusersCredentials = pkgs.runCommand "static-sysusers-credentials" { } ''
|
immutableEtc = config.system.etc.overlay.enable && !config.system.etc.overlay.mutable;
|
||||||
mkdir $out; cd $out
|
# The location of the password files when using an immutable /etc.
|
||||||
${lib.concatLines (
|
immutablePasswordFilesLocation = "/var/lib/nixos/etc";
|
||||||
(lib.mapAttrsToList
|
passwordFilesLocation = if immutableEtc then immutablePasswordFilesLocation else "/etc";
|
||||||
(username: opts: "echo -n '${opts.initialHashedPassword}' > 'passwd.hashed-password.${username}'")
|
# The filenames created by systemd-sysusers.
|
||||||
(lib.filterAttrs (_username: opts: opts.initialHashedPassword != null) userCfg.users))
|
passwordFiles = [ "passwd" "group" "shadow" "gshadow" ];
|
||||||
++
|
|
||||||
(lib.mapAttrsToList
|
|
||||||
(username: opts: "echo -n '${opts.initialPassword}' > 'passwd.plaintext-password.${username}'")
|
|
||||||
(lib.filterAttrs (_username: opts: opts.initialPassword != null) userCfg.users))
|
|
||||||
++
|
|
||||||
(lib.mapAttrsToList
|
|
||||||
(username: opts: "cat '${opts.hashedPasswordFile}' > 'passwd.hashed-password.${username}'")
|
|
||||||
(lib.filterAttrs (_username: opts: opts.hashedPasswordFile != null) userCfg.users))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
staticSysusers = pkgs.runCommand "static-sysusers"
|
|
||||||
{
|
|
||||||
nativeBuildInputs = [ pkgs.systemd ];
|
|
||||||
} ''
|
|
||||||
mkdir $out
|
|
||||||
export CREDENTIALS_DIRECTORY=${staticSysusersCredentials}
|
|
||||||
systemd-sysusers --root $out ${sysusersConfig}/00-nixos.conf
|
|
||||||
'';
|
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
@@ -90,95 +72,114 @@ in
|
|||||||
assertion = config.users.mutableUsers -> config.system.etc.overlay.enable;
|
assertion = config.users.mutableUsers -> config.system.etc.overlay.enable;
|
||||||
message = "config.users.mutableUsers requires config.system.etc.overlay.enable.";
|
message = "config.users.mutableUsers requires config.system.etc.overlay.enable.";
|
||||||
}
|
}
|
||||||
];
|
] ++ (lib.mapAttrsToList
|
||||||
|
(_username: opts: {
|
||||||
systemd = lib.mkMerge [
|
assertion = !opts.isNormalUser;
|
||||||
({
|
message = "systemd-sysusers doesn't create normal users. You can currently only use it to create system users.";
|
||||||
|
|
||||||
# Create home directories, do not create /var/empty even if that's a user's
|
|
||||||
# home.
|
|
||||||
tmpfiles.settings.home-directories = lib.mapAttrs'
|
|
||||||
(username: opts: lib.nameValuePair opts.home {
|
|
||||||
d = {
|
|
||||||
mode = opts.homeMode;
|
|
||||||
user = username;
|
|
||||||
group = opts.group;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
(lib.filterAttrs (_username: opts: opts.home != "/var/empty") userCfg.users);
|
|
||||||
|
|
||||||
# Create uid/gid marker files for those without an explicit id
|
|
||||||
tmpfiles.settings.nixos-uid = lib.mapAttrs'
|
|
||||||
(username: opts: lib.nameValuePair "/var/lib/nixos/uid/${username}" {
|
|
||||||
f = {
|
|
||||||
user = username;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
(lib.filterAttrs (_username: opts: opts.uid == null) userCfg.users);
|
|
||||||
|
|
||||||
tmpfiles.settings.nixos-gid = lib.mapAttrs'
|
|
||||||
(groupname: opts: lib.nameValuePair "/var/lib/nixos/gid/${groupname}" {
|
|
||||||
f = {
|
|
||||||
group = groupname;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
(lib.filterAttrs (_groupname: opts: opts.gid == null) userCfg.groups);
|
|
||||||
})
|
})
|
||||||
|
userCfg.users)
|
||||||
|
++ lib.mapAttrsToList
|
||||||
|
(username: opts: {
|
||||||
|
assertion = (opts.password == opts.initialPassword || opts.password == null) &&
|
||||||
|
(opts.hashedPassword == opts.initialHashedPassword || opts.hashedPassword == null);
|
||||||
|
message = "${username} uses password or hashedPassword. systemd-sysupdate only supports initial passwords. It'll never update your passwords.";
|
||||||
|
})
|
||||||
|
systemUsers;
|
||||||
|
|
||||||
(lib.mkIf config.users.mutableUsers {
|
systemd = {
|
||||||
additionalUpstreamSystemUnits = [
|
|
||||||
"systemd-sysusers.service"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.systemd-sysusers = {
|
# Create home directories, do not create /var/empty even if that's a user's
|
||||||
# Enable switch-to-configuration to restart the service.
|
# home.
|
||||||
unitConfig.ConditionNeedsUpdate = [ "" ];
|
tmpfiles.settings.home-directories = lib.mapAttrs'
|
||||||
requiredBy = [ "sysinit-reactivation.target" ];
|
(username: opts: lib.nameValuePair opts.home {
|
||||||
before = [ "sysinit-reactivation.target" ];
|
d = {
|
||||||
restartTriggers = [ "${config.environment.etc."sysusers.d".source}" ];
|
mode = opts.homeMode;
|
||||||
|
user = username;
|
||||||
serviceConfig = {
|
group = opts.group;
|
||||||
LoadCredential = lib.mapAttrsToList
|
|
||||||
(username: opts: "passwd.hashed-password.${username}:${opts.hashedPasswordFile}")
|
|
||||||
(lib.filterAttrs (_username: opts: opts.hashedPasswordFile != null) userCfg.users);
|
|
||||||
SetCredential = (lib.mapAttrsToList
|
|
||||||
(username: opts: "passwd.hashed-password.${username}:${opts.initialHashedPassword}")
|
|
||||||
(lib.filterAttrs (_username: opts: opts.initialHashedPassword != null) userCfg.users))
|
|
||||||
++
|
|
||||||
(lib.mapAttrsToList
|
|
||||||
(username: opts: "passwd.plaintext-password.${username}:${opts.initialPassword}")
|
|
||||||
(lib.filterAttrs (_username: opts: opts.initialPassword != null) userCfg.users))
|
|
||||||
;
|
|
||||||
};
|
};
|
||||||
|
})
|
||||||
|
(lib.filterAttrs (_username: opts: opts.home != "/var/empty") systemUsers);
|
||||||
|
|
||||||
|
# Create uid/gid marker files for those without an explicit id
|
||||||
|
tmpfiles.settings.nixos-uid = lib.mapAttrs'
|
||||||
|
(username: opts: lib.nameValuePair "/var/lib/nixos/uid/${username}" {
|
||||||
|
f = {
|
||||||
|
user = username;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(lib.filterAttrs (_username: opts: opts.uid == null) systemUsers);
|
||||||
|
|
||||||
|
tmpfiles.settings.nixos-gid = lib.mapAttrs'
|
||||||
|
(groupname: opts: lib.nameValuePair "/var/lib/nixos/gid/${groupname}" {
|
||||||
|
f = {
|
||||||
|
group = groupname;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(lib.filterAttrs (_groupname: opts: opts.gid == null) userCfg.groups);
|
||||||
|
|
||||||
|
additionalUpstreamSystemUnits = [
|
||||||
|
"systemd-sysusers.service"
|
||||||
|
];
|
||||||
|
|
||||||
|
services.systemd-sysusers = {
|
||||||
|
# Enable switch-to-configuration to restart the service.
|
||||||
|
unitConfig.ConditionNeedsUpdate = [ "" ];
|
||||||
|
requiredBy = [ "sysinit-reactivation.target" ];
|
||||||
|
before = [ "sysinit-reactivation.target" ];
|
||||||
|
restartTriggers = [ "${config.environment.etc."sysusers.d".source}" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
# When we have an immutable /etc we cannot write the files directly
|
||||||
|
# to /etc so we write it to a different directory and symlink them
|
||||||
|
# into /etc.
|
||||||
|
#
|
||||||
|
# We need to explicitly list the config file, otherwise
|
||||||
|
# systemd-sysusers cannot find it when we also pass another flag.
|
||||||
|
ExecStart = lib.mkIf immutableEtc
|
||||||
|
[ "" "${config.systemd.package}/bin/systemd-sysusers --root ${builtins.dirOf immutablePasswordFilesLocation} /etc/sysusers.d/00-nixos.conf" ];
|
||||||
|
|
||||||
|
# Make the source files writable before executing sysusers.
|
||||||
|
ExecStartPre = lib.mkIf (!userCfg.mutableUsers)
|
||||||
|
(lib.map
|
||||||
|
(file: "-${pkgs.util-linux}/bin/umount ${passwordFilesLocation}/${file}")
|
||||||
|
passwordFiles);
|
||||||
|
# Make the source files read-only after sysusers has finished.
|
||||||
|
ExecStartPost = lib.mkIf (!userCfg.mutableUsers)
|
||||||
|
(lib.map
|
||||||
|
(file: "${pkgs.util-linux}/bin/mount --bind -o ro ${passwordFilesLocation}/${file} ${passwordFilesLocation}/${file}")
|
||||||
|
passwordFiles);
|
||||||
|
|
||||||
|
LoadCredential = lib.mapAttrsToList
|
||||||
|
(username: opts: "passwd.hashed-password.${username}:${opts.hashedPasswordFile}")
|
||||||
|
(lib.filterAttrs (_username: opts: opts.hashedPasswordFile != null) systemUsers);
|
||||||
|
SetCredential = (lib.mapAttrsToList
|
||||||
|
(username: opts: "passwd.hashed-password.${username}:${opts.initialHashedPassword}")
|
||||||
|
(lib.filterAttrs (_username: opts: opts.initialHashedPassword != null) systemUsers))
|
||||||
|
++
|
||||||
|
(lib.mapAttrsToList
|
||||||
|
(username: opts: "passwd.plaintext-password.${username}:${opts.initialPassword}")
|
||||||
|
(lib.filterAttrs (_username: opts: opts.initialPassword != null) systemUsers))
|
||||||
|
;
|
||||||
};
|
};
|
||||||
})
|
};
|
||||||
];
|
|
||||||
|
};
|
||||||
|
|
||||||
environment.etc = lib.mkMerge [
|
environment.etc = lib.mkMerge [
|
||||||
(lib.mkIf (!userCfg.mutableUsers) {
|
({
|
||||||
"passwd" = {
|
|
||||||
source = "${staticSysusers}/etc/passwd";
|
|
||||||
mode = "0644";
|
|
||||||
};
|
|
||||||
"group" = {
|
|
||||||
source = "${staticSysusers}/etc/group";
|
|
||||||
mode = "0644";
|
|
||||||
};
|
|
||||||
"shadow" = {
|
|
||||||
source = "${staticSysusers}/etc/shadow";
|
|
||||||
mode = "0000";
|
|
||||||
};
|
|
||||||
"gshadow" = {
|
|
||||||
source = "${staticSysusers}/etc/gshadow";
|
|
||||||
mode = "0000";
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(lib.mkIf userCfg.mutableUsers {
|
|
||||||
"sysusers.d".source = sysusersConfig;
|
"sysusers.d".source = sysusersConfig;
|
||||||
})
|
})
|
||||||
];
|
|
||||||
|
|
||||||
|
# Statically create the symlinks to immutablePasswordFilesLocation when
|
||||||
|
# using an immutable /etc because we will not be able to do it at
|
||||||
|
# runtime!
|
||||||
|
(lib.mkIf immutableEtc (lib.listToAttrs (lib.map
|
||||||
|
(file: lib.nameValuePair file {
|
||||||
|
source = "${immutablePasswordFilesLocation}/${file}";
|
||||||
|
mode = "direct-symlink";
|
||||||
|
})
|
||||||
|
passwordFiles)))
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
meta.maintainers = with lib.maintainers; [ nikstur ];
|
meta.maintainers = with lib.maintainers; [ nikstur ];
|
||||||
|
|||||||
@@ -32,6 +32,18 @@
|
|||||||
with subtest("direct symlinks point to the target without indirection"):
|
with subtest("direct symlinks point to the target without indirection"):
|
||||||
assert machine.succeed("readlink -n /etc/localtime") == "/etc/zoneinfo/Utc"
|
assert machine.succeed("readlink -n /etc/localtime") == "/etc/zoneinfo/Utc"
|
||||||
|
|
||||||
|
with subtest("Correct mode on the source password files"):
|
||||||
|
assert machine.succeed("stat -c '%a' /var/lib/nixos/etc/passwd") == "644\n"
|
||||||
|
assert machine.succeed("stat -c '%a' /var/lib/nixos/etc/group") == "644\n"
|
||||||
|
assert machine.succeed("stat -c '%a' /var/lib/nixos/etc/shadow") == "0\n"
|
||||||
|
assert machine.succeed("stat -c '%a' /var/lib/nixos/etc/gshadow") == "0\n"
|
||||||
|
|
||||||
|
with subtest("Password files are symlinks to /var/lib/nixos/etc"):
|
||||||
|
assert machine.succeed("readlink -f /etc/passwd") == "/var/lib/nixos/etc/passwd\n"
|
||||||
|
assert machine.succeed("readlink -f /etc/group") == "/var/lib/nixos/etc/group\n"
|
||||||
|
assert machine.succeed("readlink -f /etc/shadow") == "/var/lib/nixos/etc/shadow\n"
|
||||||
|
assert machine.succeed("readlink -f /etc/gshadow") == "/var/lib/nixos/etc/gshadow\n"
|
||||||
|
|
||||||
with subtest("switching to the same generation"):
|
with subtest("switching to the same generation"):
|
||||||
machine.succeed("/run/current-system/bin/switch-to-configuration test")
|
machine.succeed("/run/current-system/bin/switch-to-configuration test")
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
let
|
let
|
||||||
rootPassword = "$y$j9T$p6OI0WN7.rSfZBOijjRdR.$xUOA2MTcB48ac.9Oc5fz8cxwLv1mMqabnn333iOzSA6";
|
rootPassword = "$y$j9T$p6OI0WN7.rSfZBOijjRdR.$xUOA2MTcB48ac.9Oc5fz8cxwLv1mMqabnn333iOzSA6";
|
||||||
normaloPassword = "$y$j9T$3aiOV/8CADAK22OK2QT3/0$67OKd50Z4qTaZ8c/eRWHLIM.o3ujtC1.n9ysmJfv639";
|
sysuserPassword = "$y$j9T$3aiOV/8CADAK22OK2QT3/0$67OKd50Z4qTaZ8c/eRWHLIM.o3ujtC1.n9ysmJfv639";
|
||||||
newNormaloPassword = "mellow";
|
newSysuserPassword = "mellow";
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -16,49 +16,48 @@ in
|
|||||||
systemd.sysusers.enable = true;
|
systemd.sysusers.enable = true;
|
||||||
users.mutableUsers = false;
|
users.mutableUsers = false;
|
||||||
|
|
||||||
# Override the empty root password set by the test instrumentation
|
|
||||||
users.users.root.hashedPasswordFile = lib.mkForce null;
|
# Read this password file at runtime from outside the Nix store.
|
||||||
users.users.root.initialHashedPassword = rootPassword;
|
environment.etc."rootpw.secret".text = rootPassword;
|
||||||
users.users.normalo = {
|
# Override the empty root password set by the test instrumentation.
|
||||||
isNormalUser = true;
|
users.users.root.hashedPasswordFile = lib.mkForce "/etc/rootpw.secret";
|
||||||
initialHashedPassword = normaloPassword;
|
|
||||||
|
users.users.sysuser = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "wheel";
|
||||||
|
home = "/sysuser";
|
||||||
|
initialHashedPassword = sysuserPassword;
|
||||||
};
|
};
|
||||||
|
|
||||||
specialisation.new-generation.configuration = {
|
specialisation.new-generation.configuration = {
|
||||||
users.users.new-normalo = {
|
users.users.new-sysuser = {
|
||||||
isNormalUser = true;
|
isSystemUser = true;
|
||||||
initialPassword = newNormaloPassword;
|
group = "wheel";
|
||||||
|
home = "/new-sysuser";
|
||||||
|
initialPassword = newSysuserPassword;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
with subtest("Users are not created with systemd-sysusers"):
|
|
||||||
machine.fail("systemctl status systemd-sysusers.service")
|
|
||||||
machine.fail("ls /etc/sysusers.d")
|
|
||||||
|
|
||||||
with subtest("Correct mode on the password files"):
|
|
||||||
assert machine.succeed("stat -c '%a' /etc/passwd") == "644\n"
|
|
||||||
assert machine.succeed("stat -c '%a' /etc/group") == "644\n"
|
|
||||||
assert machine.succeed("stat -c '%a' /etc/shadow") == "0\n"
|
|
||||||
assert machine.succeed("stat -c '%a' /etc/gshadow") == "0\n"
|
|
||||||
|
|
||||||
with subtest("root user has correct password"):
|
with subtest("root user has correct password"):
|
||||||
print(machine.succeed("getent passwd root"))
|
print(machine.succeed("getent passwd root"))
|
||||||
assert "${rootPassword}" in machine.succeed("getent shadow root"), "root user password is not correct"
|
assert "${rootPassword}" in machine.succeed("getent shadow root"), "root user password is not correct"
|
||||||
|
|
||||||
with subtest("normalo user is created"):
|
with subtest("sysuser user is created"):
|
||||||
print(machine.succeed("getent passwd normalo"))
|
print(machine.succeed("getent passwd sysuser"))
|
||||||
assert machine.succeed("stat -c '%U' /home/normalo") == "normalo\n"
|
assert machine.succeed("stat -c '%U' /sysuser") == "sysuser\n"
|
||||||
assert "${normaloPassword}" in machine.succeed("getent shadow normalo"), "normalo user password is not correct"
|
assert "${sysuserPassword}" in machine.succeed("getent shadow sysuser"), "sysuser user password is not correct"
|
||||||
|
|
||||||
|
with subtest("Fail to add new user manually"):
|
||||||
|
machine.fail("useradd manual-sysuser")
|
||||||
|
|
||||||
|
|
||||||
machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
|
machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
|
||||||
|
|
||||||
|
|
||||||
with subtest("new-normalo user is created after switching to new generation"):
|
with subtest("new-sysuser user is created after switching to new generation"):
|
||||||
print(machine.succeed("getent passwd new-normalo"))
|
print(machine.succeed("getent passwd new-sysuser"))
|
||||||
print(machine.succeed("getent shadow new-normalo"))
|
assert machine.succeed("stat -c '%U' /new-sysuser") == "new-sysuser\n"
|
||||||
assert machine.succeed("stat -c '%U' /home/new-normalo") == "new-normalo\n"
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
let
|
let
|
||||||
rootPassword = "$y$j9T$p6OI0WN7.rSfZBOijjRdR.$xUOA2MTcB48ac.9Oc5fz8cxwLv1mMqabnn333iOzSA6";
|
rootPassword = "$y$j9T$p6OI0WN7.rSfZBOijjRdR.$xUOA2MTcB48ac.9Oc5fz8cxwLv1mMqabnn333iOzSA6";
|
||||||
normaloPassword = "hello";
|
sysuserPassword = "hello";
|
||||||
newNormaloPassword = "$y$j9T$p6OI0WN7.rSfZBOijjRdR.$xUOA2MTcB48ac.9Oc5fz8cxwLv1mMqabnn333iOzSA6";
|
newSysuserPassword = "$y$j9T$p6OI0WN7.rSfZBOijjRdR.$xUOA2MTcB48ac.9Oc5fz8cxwLv1mMqabnn333iOzSA6";
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -24,15 +24,19 @@ in
|
|||||||
# Override the empty root password set by the test instrumentation
|
# Override the empty root password set by the test instrumentation
|
||||||
users.users.root.hashedPasswordFile = lib.mkForce null;
|
users.users.root.hashedPasswordFile = lib.mkForce null;
|
||||||
users.users.root.initialHashedPassword = rootPassword;
|
users.users.root.initialHashedPassword = rootPassword;
|
||||||
users.users.normalo = {
|
users.users.sysuser = {
|
||||||
isNormalUser = true;
|
isSystemUser = true;
|
||||||
initialPassword = normaloPassword;
|
group = "wheel";
|
||||||
|
home = "/sysuser";
|
||||||
|
initialPassword = sysuserPassword;
|
||||||
};
|
};
|
||||||
|
|
||||||
specialisation.new-generation.configuration = {
|
specialisation.new-generation.configuration = {
|
||||||
users.users.new-normalo = {
|
users.users.new-sysuser = {
|
||||||
isNormalUser = true;
|
isSystemUser = true;
|
||||||
initialHashedPassword = newNormaloPassword;
|
group = "wheel";
|
||||||
|
home = "/new-sysuser";
|
||||||
|
initialHashedPassword = newSysuserPassword;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -43,7 +47,7 @@ in
|
|||||||
with subtest("systemd-sysusers.service contains the credentials"):
|
with subtest("systemd-sysusers.service contains the credentials"):
|
||||||
sysusers_service = machine.succeed("systemctl cat systemd-sysusers.service")
|
sysusers_service = machine.succeed("systemctl cat systemd-sysusers.service")
|
||||||
print(sysusers_service)
|
print(sysusers_service)
|
||||||
assert "SetCredential=passwd.plaintext-password.normalo:${normaloPassword}" in sysusers_service
|
assert "SetCredential=passwd.plaintext-password.sysuser:${sysuserPassword}" in sysusers_service
|
||||||
|
|
||||||
with subtest("Correct mode on the password files"):
|
with subtest("Correct mode on the password files"):
|
||||||
assert machine.succeed("stat -c '%a' /etc/passwd") == "644\n"
|
assert machine.succeed("stat -c '%a' /etc/passwd") == "644\n"
|
||||||
@@ -55,17 +59,20 @@ in
|
|||||||
print(machine.succeed("getent passwd root"))
|
print(machine.succeed("getent passwd root"))
|
||||||
assert "${rootPassword}" in machine.succeed("getent shadow root"), "root user password is not correct"
|
assert "${rootPassword}" in machine.succeed("getent shadow root"), "root user password is not correct"
|
||||||
|
|
||||||
with subtest("normalo user is created"):
|
with subtest("sysuser user is created"):
|
||||||
print(machine.succeed("getent passwd normalo"))
|
print(machine.succeed("getent passwd sysuser"))
|
||||||
assert machine.succeed("stat -c '%U' /home/normalo") == "normalo\n"
|
assert machine.succeed("stat -c '%U' /sysuser") == "sysuser\n"
|
||||||
|
|
||||||
|
with subtest("Manually add new user"):
|
||||||
|
machine.succeed("useradd manual-sysuser")
|
||||||
|
|
||||||
|
|
||||||
machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
|
machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
|
||||||
|
|
||||||
|
|
||||||
with subtest("new-normalo user is created after switching to new generation"):
|
with subtest("new-sysuser user is created after switching to new generation"):
|
||||||
print(machine.succeed("getent passwd new-normalo"))
|
print(machine.succeed("getent passwd new-sysuser"))
|
||||||
assert machine.succeed("stat -c '%U' /home/new-normalo") == "new-normalo\n"
|
assert machine.succeed("stat -c '%U' /new-sysuser") == "new-sysuser\n"
|
||||||
assert "${newNormaloPassword}" in machine.succeed("getent shadow new-normalo"), "new-normalo user password is not correct"
|
assert "${newSysuserPassword}" in machine.succeed("getent shadow new-sysuser"), "new-sysuser user password is not correct"
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user