mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-07-20 07:31:19 +00:00
shadow: enable running upstream system test suite
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
{ runTest }:
|
||||
{
|
||||
login = runTest ./login.nix;
|
||||
system = runTest ./system.nix;
|
||||
}
|
||||
|
||||
147
nixos/tests/shadow/system.nix
Normal file
147
nixos/tests/shadow/system.nix
Normal file
@@ -0,0 +1,147 @@
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
# Create a Python environment for the controller with all necessary test framework dependencies
|
||||
controllerPython = pkgs.python3.withPackages (ps: [
|
||||
ps.flaky
|
||||
ps.jc
|
||||
ps.pytest
|
||||
ps.pytest-mh
|
||||
ps.pytest-ticket
|
||||
]);
|
||||
|
||||
shadowHostName = "shadowhost";
|
||||
in
|
||||
{
|
||||
name = "shadow-system-tests";
|
||||
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ joaosreis ];
|
||||
|
||||
nodes = {
|
||||
# The target host: runs sshd, has shadow and other test dependencies installed, mutable users, and some specific settings to match the expectations of the test suite
|
||||
shadowhost =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
networking.hostName = shadowHostName;
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PermitRootLogin = "yes";
|
||||
PasswordAuthentication = false;
|
||||
};
|
||||
};
|
||||
|
||||
users.mutableUsers = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
shadow
|
||||
expect
|
||||
];
|
||||
|
||||
users.defaultUserShell = "/bin/sh";
|
||||
|
||||
security.loginDefs.settings = {
|
||||
PASS_MAX_DAYS = 99999;
|
||||
PASS_MIN_DAYS = 0;
|
||||
PASS_WARN_AGE = 7;
|
||||
USERGROUPS_ENAB = "yes";
|
||||
CREATE_HOME = "yes";
|
||||
UID_MIN = 1001;
|
||||
GID_MIN = 1001;
|
||||
};
|
||||
|
||||
security.pam.services = {
|
||||
newusers.text = ''
|
||||
auth required pam_permit.so
|
||||
account required pam_permit.so
|
||||
password required pam_permit.so
|
||||
session required pam_permit.so
|
||||
'';
|
||||
};
|
||||
|
||||
services.envfs.enable = true;
|
||||
};
|
||||
|
||||
# The controller: runs pytest-mh against the shadow host
|
||||
controller =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [
|
||||
controllerPython
|
||||
pkgs.openssh
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
import textwrap
|
||||
|
||||
start_all()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 1. Generate an SSH keypair on the controller and authorise it
|
||||
# on the shadow host
|
||||
# ------------------------------------------------------------------
|
||||
controller.succeed("mkdir -p /root/.ssh && chmod 700 /root/.ssh")
|
||||
controller.succeed(
|
||||
"ssh-keygen -t ed25519 -N \'\' -f /root/.ssh/id_ed25519 2>&1"
|
||||
)
|
||||
pub_key = controller.succeed("cat /root/.ssh/id_ed25519.pub").strip()
|
||||
|
||||
# Inject the generated public key into the shadow host at runtime
|
||||
shadowhost.succeed("mkdir -p /root/.ssh && chmod 700 /root/.ssh")
|
||||
shadowhost.succeed(
|
||||
f"echo '{pub_key}' >> /root/.ssh/authorized_keys && "
|
||||
"chmod 600 /root/.ssh/authorized_keys"
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 2. Make sure the shadow host has a writable /etc/login.defs,
|
||||
# since the test framework expects to be able to write to it.
|
||||
# ------------------------------------------------------------------
|
||||
shadowhost.succeed(
|
||||
"cp --remove-destination $(readlink -f /etc/login.defs) /etc/login.defs && "
|
||||
"chmod 644 /etc/login.defs"
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 3. Copy the upstream test suite onto the controller
|
||||
# ------------------------------------------------------------------
|
||||
controller.succeed(
|
||||
"cp -r ${pkgs.shadow.passthru.testFramework} /root/shadow-tests && "
|
||||
"chmod -R u+w /root/shadow-tests"
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 4. Write the mhc.yaml topology config
|
||||
# This tells pytest-mh where the shadow host is and which role
|
||||
# it plays. The hostname must match the NixOS node name.
|
||||
# ------------------------------------------------------------------
|
||||
controller.succeed(textwrap.dedent("""
|
||||
cat > /root/shadow-tests/mhc.yaml << 'EOF'
|
||||
domains:
|
||||
- id: shadow
|
||||
hosts:
|
||||
- hostname: ${shadowHostName}
|
||||
role: shadow
|
||||
ssh:
|
||||
user: root
|
||||
private_key: /root/.ssh/id_ed25519
|
||||
EOF
|
||||
"""))
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 5. Run the upstream pytest-mh test suite from the controller
|
||||
# ------------------------------------------------------------------
|
||||
shadowhost.wait_for_unit("sshd.service")
|
||||
# gpasswd tests are disabled, since they rely on specific behavior of the gpasswd command that is not applicable to NixOS
|
||||
controller.succeed(
|
||||
"cd /root/shadow-tests && "
|
||||
"${controllerPython}/bin/pytest "
|
||||
"--mh-config=mhc.yaml "
|
||||
"--deselect=tests/test_gpasswd.py "
|
||||
"-v tests/"
|
||||
)
|
||||
'';
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
withTcb ? lib.meta.availableOn stdenv.hostPlatform tcb,
|
||||
tcb,
|
||||
cmocka,
|
||||
fetchpatch,
|
||||
}:
|
||||
let
|
||||
glibc' =
|
||||
@@ -139,7 +140,58 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
passthru = {
|
||||
shellPath = "/bin/nologin";
|
||||
# TODO: Run system tests: https://github.com/shadow-maint/shadow/blob/master/doc/contributions/tests.md#system-tests
|
||||
tests = { inherit (nixosTests) shadow; };
|
||||
# Package the upstream system test framework for use in nixosTests
|
||||
testFramework = stdenv.mkDerivation {
|
||||
name = "shadow-test-framework";
|
||||
inherit (finalAttrs) version;
|
||||
src = "${finalAttrs.src}/tests/system";
|
||||
installPhase = ''
|
||||
cp -r . $out/
|
||||
'';
|
||||
dontBuild = true;
|
||||
patches = [
|
||||
# tests: update useradd tests to expect ID 1001
|
||||
(fetchpatch {
|
||||
name = "update-useradd-tests.patch";
|
||||
url = "https://github.com/shadow-maint/shadow/commit/59fbe8415dab17f1e702fbdee96956886c86c737.patch";
|
||||
hash = "sha256-U0+NSCd4AfTuHMddTx9+wNtpdJt9t8+D5ApW0OCNgsY=";
|
||||
stripLen = 2;
|
||||
})
|
||||
# tests: update usermod tests to expect ID 1001
|
||||
(fetchpatch {
|
||||
name = "update-usermod-tests.patch";
|
||||
url = "https://github.com/shadow-maint/shadow/commit/91c2ad44ababca2e32cdb71152b0f7f2a7c546be.patch";
|
||||
hash = "sha256-v1EEvMfUYoE/ZnBM0k/+kUBK3W1dXr588OQzvFmnXLI=";
|
||||
stripLen = 2;
|
||||
})
|
||||
# tests: update groupadd tests to expect GID 1001
|
||||
(fetchpatch {
|
||||
name = "update-groupadd-tests.patch";
|
||||
url = "https://github.com/shadow-maint/shadow/commit/60568eaec13d1e417f56f0e59ac9573c0e3b9a83.patch";
|
||||
hash = "sha256-tLmGeW4Y7UcZqMhW3IXgygKPhCmbZkkW5XTJ7CFz9vg=";
|
||||
stripLen = 2;
|
||||
})
|
||||
# tests: update newgrp tests to expect GID 1002
|
||||
(fetchpatch {
|
||||
name = "update-newgrp-tests.patch";
|
||||
url = "https://github.com/shadow-maint/shadow/commit/49ff9bf33a7b6af57cb26688c3139f014302c9d9.patch";
|
||||
hash = "sha256-1760t4Ezd5Ke4PFZ70Njb+k+1kp17aT/7uqu1PswVss=";
|
||||
stripLen = 2;
|
||||
})
|
||||
];
|
||||
postPatch = ''
|
||||
# Replace the gshadow existence check in the test framework with a more NixOS-friendly one, since NixOS does not have /etc/gshadow as a regular file
|
||||
substituteInPlace framework/hosts/shadow.py \
|
||||
--replace-fail 'getent gshadow > /dev/null 2>&1' 'test -f /etc/gshadow'
|
||||
|
||||
# Remove the backup entry for gshadow, since it's not being used in the tests running on NixOS
|
||||
sed -i '/{"origin": "\/etc\/gshadow", "backup": "gshadow"}/d' framework/hosts/shadow.py
|
||||
|
||||
# Replace the Debian-specific check in the useradd test with a NixOS-specific one
|
||||
substituteInPlace tests/test_useradd.py \
|
||||
--replace-fail 'if "Debian" in shadow.host.distro_name:' 'if "NixOS" in shadow.host.distro_name:'
|
||||
'';
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user