Loading nixos/modules/services/system/userborn.nix +18 −7 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ let userbornStaticFiles = pkgs.runCommand "static-userborn" { } "mkdir -p $out; ${lib.getExe cfg.package} ${userbornConfigJson} $out"; previousConfigPath = "/var/lib/userborn/previous-userborn.json"; immutableEtc = config.system.etc.overlay.enable && !config.system.etc.overlay.mutable; # The filenames created by userborn. Loading Loading @@ -155,6 +156,10 @@ in # This way we don't have to re-declare all the dependencies to other # services again. aliases = [ "systemd-sysusers.service" ]; environment = { USERBORN_MUTABLE_USERS = lib.boolToString userCfg.mutableUsers; USERBORN_PREVIOUS_CONFIG = lib.mkIf userCfg.mutableUsers previousConfigPath; }; unitConfig = { Description = "Manage Users and Groups"; Loading @@ -165,6 +170,7 @@ in Type = "oneshot"; RemainAfterExit = true; TimeoutSec = "90s"; StateDirectory = "userborn"; ExecStart = "${lib.getExe cfg.package} ${userbornConfigJson} ${cfg.passwordFilesLocation}"; Loading @@ -179,13 +185,18 @@ in )) ]; ExecStartPost = if userCfg.mutableUsers then # Store the config somewhere for the next invocation [ "${pkgs.coreutils}/bin/ln -sf ${userbornConfigJson} ${previousConfigPath}" ] else # Make the source files read-only after userborn has finished. ExecStartPost = lib.mkIf (!userCfg.mutableUsers) ( lib.map ( (lib.map ( file: "${pkgs.util-linux}/bin/mount --bind -o ro ${cfg.passwordFilesLocation}/${file} ${cfg.passwordFilesLocation}/${file}" ) passwordFiles ); ) passwordFiles); }; }; }; Loading nixos/tests/userborn-immutable-etc.nix +2 −2 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ in meta.maintainers = with lib.maintainers; [ nikstur ]; nodes.machine = { config, ... }: { pkgs, ... }: { imports = [ common ]; Loading @@ -38,7 +38,7 @@ in inheritParentConfig = false; configuration = { nixpkgs = { inherit (config.nixpkgs) hostPlatform; inherit pkgs; }; imports = [ common ]; Loading nixos/tests/userborn-immutable-users.nix +2 −2 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ in meta.maintainers = with lib.maintainers; [ nikstur ]; nodes.machine = { config, ... }: { pkgs, ... }: { imports = [ common ]; Loading @@ -33,7 +33,7 @@ in inheritParentConfig = false; configuration = { nixpkgs = { inherit (config.nixpkgs) hostPlatform; inherit pkgs; }; imports = [ common ]; Loading nixos/tests/userborn-mutable-etc.nix +2 −2 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ in meta.maintainers = with lib.maintainers; [ nikstur ]; nodes.machine = { config, ... }: { pkgs, ... }: { imports = [ common ]; Loading @@ -37,7 +37,7 @@ in inheritParentConfig = false; configuration = { nixpkgs = { inherit (config.nixpkgs) hostPlatform; inherit pkgs; }; imports = [ common ]; Loading nixos/tests/userborn-mutable-users.nix +23 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ in meta.maintainers = with lib.maintainers; [ nikstur ]; nodes.machine = { config, ... }: { pkgs, ... }: { imports = [ common ]; Loading @@ -34,7 +34,7 @@ in inheritParentConfig = false; configuration = { nixpkgs = { inherit (config.nixpkgs) hostPlatform; inherit pkgs; }; imports = [ common ]; Loading @@ -42,6 +42,10 @@ in new-normalo = { isNormalUser = true; }; mutable-to-declarative = { isNormalUser = true; description = "I'm now declaratively managed"; }; }; }; }; Loading @@ -54,16 +58,25 @@ in assert 1000 == int(machine.succeed("id --user normalo")), "normalo user doesn't have UID 1000" assert "${normaloHashedPassword}" in machine.succeed("getent shadow normalo"), "normalo user password is not correct" with subtest("Add new user manually"): with subtest("Add new user manual-normalo manually"): machine.succeed("useradd manual-normalo") assert 1001 == int(machine.succeed("id --user manual-normalo")), "manual-normalo user doesn't have UID 1001" with subtest("Delete manual--normalo user manually"): machine.succeed("userdel manual-normalo") with subtest("Add new user mutable-to-declarative manually"): machine.succeed("useradd --comment 'I was created imperatively' mutable-to-declarative") assert 1002 == int(machine.succeed("id --user mutable-to-declarative")), "mutable-to-declarative user doesn't have UID 1002" machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch") with subtest("manual-normalo user is still enabled"): manual_normalo_shadow = machine.succeed("getent shadow manual-normalo") print(manual_normalo_shadow) t.assertNotIn("!*", manual_normalo_shadow, "manual-normalo user is falsely disabled") with subtest("mutable-to-declarative user description has changed"): mutable_to_declarative_passwd = machine.succeed("getent passwd mutable-to-declarative") print(mutable_to_declarative_passwd) t.assertIn("I'm now declaratively managed", mutable_to_declarative_passwd, "mutable-to-declarative user description is unchanged") with subtest("normalo user is disabled"): print(machine.succeed("getent shadow normalo")) Loading @@ -71,6 +84,9 @@ in with subtest("new-normalo user is created after switching to new generation"): print(machine.succeed("getent passwd new-normalo")) assert 1001 == int(machine.succeed("id --user new-normalo")), "new-normalo user doesn't have UID 1001" assert 1003 == int(machine.succeed("id --user new-normalo")), "new-normalo user doesn't have UID 1003" with subtest("Delete manual-normalo user manually"): machine.succeed("userdel manual-normalo") ''; } Loading
nixos/modules/services/system/userborn.nix +18 −7 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ let userbornStaticFiles = pkgs.runCommand "static-userborn" { } "mkdir -p $out; ${lib.getExe cfg.package} ${userbornConfigJson} $out"; previousConfigPath = "/var/lib/userborn/previous-userborn.json"; immutableEtc = config.system.etc.overlay.enable && !config.system.etc.overlay.mutable; # The filenames created by userborn. Loading Loading @@ -155,6 +156,10 @@ in # This way we don't have to re-declare all the dependencies to other # services again. aliases = [ "systemd-sysusers.service" ]; environment = { USERBORN_MUTABLE_USERS = lib.boolToString userCfg.mutableUsers; USERBORN_PREVIOUS_CONFIG = lib.mkIf userCfg.mutableUsers previousConfigPath; }; unitConfig = { Description = "Manage Users and Groups"; Loading @@ -165,6 +170,7 @@ in Type = "oneshot"; RemainAfterExit = true; TimeoutSec = "90s"; StateDirectory = "userborn"; ExecStart = "${lib.getExe cfg.package} ${userbornConfigJson} ${cfg.passwordFilesLocation}"; Loading @@ -179,13 +185,18 @@ in )) ]; ExecStartPost = if userCfg.mutableUsers then # Store the config somewhere for the next invocation [ "${pkgs.coreutils}/bin/ln -sf ${userbornConfigJson} ${previousConfigPath}" ] else # Make the source files read-only after userborn has finished. ExecStartPost = lib.mkIf (!userCfg.mutableUsers) ( lib.map ( (lib.map ( file: "${pkgs.util-linux}/bin/mount --bind -o ro ${cfg.passwordFilesLocation}/${file} ${cfg.passwordFilesLocation}/${file}" ) passwordFiles ); ) passwordFiles); }; }; }; Loading
nixos/tests/userborn-immutable-etc.nix +2 −2 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ in meta.maintainers = with lib.maintainers; [ nikstur ]; nodes.machine = { config, ... }: { pkgs, ... }: { imports = [ common ]; Loading @@ -38,7 +38,7 @@ in inheritParentConfig = false; configuration = { nixpkgs = { inherit (config.nixpkgs) hostPlatform; inherit pkgs; }; imports = [ common ]; Loading
nixos/tests/userborn-immutable-users.nix +2 −2 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ in meta.maintainers = with lib.maintainers; [ nikstur ]; nodes.machine = { config, ... }: { pkgs, ... }: { imports = [ common ]; Loading @@ -33,7 +33,7 @@ in inheritParentConfig = false; configuration = { nixpkgs = { inherit (config.nixpkgs) hostPlatform; inherit pkgs; }; imports = [ common ]; Loading
nixos/tests/userborn-mutable-etc.nix +2 −2 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ in meta.maintainers = with lib.maintainers; [ nikstur ]; nodes.machine = { config, ... }: { pkgs, ... }: { imports = [ common ]; Loading @@ -37,7 +37,7 @@ in inheritParentConfig = false; configuration = { nixpkgs = { inherit (config.nixpkgs) hostPlatform; inherit pkgs; }; imports = [ common ]; Loading
nixos/tests/userborn-mutable-users.nix +23 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ in meta.maintainers = with lib.maintainers; [ nikstur ]; nodes.machine = { config, ... }: { pkgs, ... }: { imports = [ common ]; Loading @@ -34,7 +34,7 @@ in inheritParentConfig = false; configuration = { nixpkgs = { inherit (config.nixpkgs) hostPlatform; inherit pkgs; }; imports = [ common ]; Loading @@ -42,6 +42,10 @@ in new-normalo = { isNormalUser = true; }; mutable-to-declarative = { isNormalUser = true; description = "I'm now declaratively managed"; }; }; }; }; Loading @@ -54,16 +58,25 @@ in assert 1000 == int(machine.succeed("id --user normalo")), "normalo user doesn't have UID 1000" assert "${normaloHashedPassword}" in machine.succeed("getent shadow normalo"), "normalo user password is not correct" with subtest("Add new user manually"): with subtest("Add new user manual-normalo manually"): machine.succeed("useradd manual-normalo") assert 1001 == int(machine.succeed("id --user manual-normalo")), "manual-normalo user doesn't have UID 1001" with subtest("Delete manual--normalo user manually"): machine.succeed("userdel manual-normalo") with subtest("Add new user mutable-to-declarative manually"): machine.succeed("useradd --comment 'I was created imperatively' mutable-to-declarative") assert 1002 == int(machine.succeed("id --user mutable-to-declarative")), "mutable-to-declarative user doesn't have UID 1002" machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch") with subtest("manual-normalo user is still enabled"): manual_normalo_shadow = machine.succeed("getent shadow manual-normalo") print(manual_normalo_shadow) t.assertNotIn("!*", manual_normalo_shadow, "manual-normalo user is falsely disabled") with subtest("mutable-to-declarative user description has changed"): mutable_to_declarative_passwd = machine.succeed("getent passwd mutable-to-declarative") print(mutable_to_declarative_passwd) t.assertIn("I'm now declaratively managed", mutable_to_declarative_passwd, "mutable-to-declarative user description is unchanged") with subtest("normalo user is disabled"): print(machine.succeed("getent shadow normalo")) Loading @@ -71,6 +84,9 @@ in with subtest("new-normalo user is created after switching to new generation"): print(machine.succeed("getent passwd new-normalo")) assert 1001 == int(machine.succeed("id --user new-normalo")), "new-normalo user doesn't have UID 1001" assert 1003 == int(machine.succeed("id --user new-normalo")), "new-normalo user doesn't have UID 1003" with subtest("Delete manual-normalo user manually"): machine.succeed("userdel manual-normalo") ''; }