From 2f1666b80264365de48018bb0535834684a8a8a8 Mon Sep 17 00:00:00 2001 From: Vincent Haupert Date: Fri, 10 Sep 2021 16:24:24 +0200 Subject: [PATCH 1/3] test/integration: remove erroneous f-string --- test/integration.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration.nix b/test/integration.nix index 8bb234af..7cb840ce 100644 --- a/test/integration.nix +++ b/test/integration.nix @@ -42,9 +42,9 @@ import "${nixpkgs}/nixos/tests/make-test-python.nix" ({ pkgs, ...}: { system1.wait_until_succeeds("pgrep -f 'agetty.*tty1'") system1.sleep(2) system1.send_key("alt-f2") - system1.wait_until_succeeds(f"[ $(fgconsole) = 2 ]") - system1.wait_for_unit(f"getty@tty2.service") - system1.wait_until_succeeds(f"pgrep -f 'agetty.*tty2'") + system1.wait_until_succeeds("[ $(fgconsole) = 2 ]") + system1.wait_for_unit("getty@tty2.service") + system1.wait_until_succeeds("pgrep -f 'agetty.*tty2'") system1.wait_until_tty_matches(2, "login: ") system1.send_chars("${user}\n") system1.wait_until_tty_matches(2, "login: ${user}") From 572dee5c9ca5eed5bef385f2da589bd5577f4216 Mon Sep 17 00:00:00 2001 From: Vincent Haupert Date: Tue, 14 Sep 2021 16:21:07 +0200 Subject: [PATCH 2/3] nixos/age: support dry-activate --- modules/age.nix | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/modules/age.nix b/modules/age.nix index 553e56f6..bd986256 100644 --- a/modules/age.nix +++ b/modules/age.nix @@ -16,16 +16,29 @@ let identities = builtins.concatStringsSep " " (map (path: "-i ${path}") cfg.sshKeyPaths); installSecret = secretType: '' - echo "decrypting ${secretType.file} to ${secretType.path}..." - TMP_FILE="${secretType.path}.tmp" - mkdir -p $(dirname ${secretType.path}) + echo "[agenix] decrypting ${secretType.file} to ${secretType.path}..." + + if [[ "$NIXOS_ACTION" == "dry-activate" ]]; then + OUT_DIR="$(mktemp -d)" + else + OUT_DIR="$(dirname ${secretType.path})" + mkdir -p "$OUT_DIR" + fi + + TMP_FILE="$OUT_DIR/tmp" ( umask u=r,g=,o= LANG=${config.i18n.defaultLocale} ${ageBin} --decrypt ${identities} -o "$TMP_FILE" "${secretType.file}" ) chmod ${secretType.mode} "$TMP_FILE" chown ${secretType.owner}:${secretType.group} "$TMP_FILE" - mv -f "$TMP_FILE" '${secretType.path}' + + if [[ "$NIXOS_ACTION" == "dry-activate" ]]; then + echo "[agenix] dry-run, not moving decrypted secret" + rm -r "$OUT_DIR" + else + mv -f "$TMP_FILE" '${secretType.path}' + fi ''; isRootSecret = st: (st.owner == "root" || st.owner == "0") && (st.group == "root" || st.group == "0"); @@ -112,7 +125,11 @@ in # Secrets with root owner and group can be installed before users # exist. This allows user password files to be encrypted. - system.activationScripts.agenixRoot = stringAfter [ "specialfs" ] installRootOwnedSecrets; + system.activationScripts.agenixRoot = { + deps = [ "specialfs" ]; + supportsDryActivation = true; + text = installRootOwnedSecrets; + }; system.activationScripts.users.deps = [ "agenixRoot" ]; # Other secrets need to wait for users and groups to exist. From 6cb257097677c3f78fa60bca94bd566c1243b605 Mon Sep 17 00:00:00 2001 From: Vincent Haupert Date: Tue, 14 Sep 2021 17:05:23 +0200 Subject: [PATCH 3/3] tests/integration: add dry-activate test --- test/integration.nix | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/test/integration.nix b/test/integration.nix index 7cb840ce..097e1a98 100644 --- a/test/integration.nix +++ b/test/integration.nix @@ -39,20 +39,31 @@ import "${nixpkgs}/nixos/tests/make-test-python.nix" ({ pkgs, ...}: { password = "password1234"; in '' system1.wait_for_unit("multi-user.target") - system1.wait_until_succeeds("pgrep -f 'agetty.*tty1'") - system1.sleep(2) - system1.send_key("alt-f2") - system1.wait_until_succeeds("[ $(fgconsole) = 2 ]") - system1.wait_for_unit("getty@tty2.service") - system1.wait_until_succeeds("pgrep -f 'agetty.*tty2'") - system1.wait_until_tty_matches(2, "login: ") - system1.send_chars("${user}\n") - system1.wait_until_tty_matches(2, "login: ${user}") - system1.wait_until_succeeds("pgrep login") - system1.sleep(2) - system1.send_chars("${password}\n") - system1.send_chars("whoami > /tmp/1\n") - system1.wait_for_file("/tmp/1") - assert "${user}" in system1.succeed("cat /tmp/1") + + with subtest("Decrypting age-encrypted ${user} password works"): + system1.succeed("test -e /run/secrets/passwordfile-user1") + + with subtest("Logging in with ${user} works"): + system1.wait_until_succeeds("pgrep -f 'agetty.*tty1'") + system1.sleep(2) + system1.send_key("alt-f2") + system1.wait_until_succeeds("[ $(fgconsole) = 2 ]") + system1.wait_for_unit("getty@tty2.service") + system1.wait_until_succeeds("pgrep -f 'agetty.*tty2'") + system1.wait_until_tty_matches(2, "login: ") + system1.send_chars("${user}\n") + system1.wait_until_tty_matches(2, "login: ${user}") + system1.wait_until_succeeds("pgrep login") + system1.sleep(2) + system1.send_chars("${password}\n") + system1.send_chars("whoami > /tmp/1\n") + system1.wait_for_file("/tmp/1") + assert "${user}" in system1.succeed("cat /tmp/1") + + with subtest("Decrypted password not moved on dry-activation"): + system1.succeed("rm /run/secrets/passwordfile-user1") + out = system1.succeed("/run/current-system/bin/switch-to-configuration dry-activate") + assert "[agenix] dry-run, not moving decrypted secret" in out + system1.succeed('test -z "$(ls -A /run/secrets)"') ''; }) args