nixVersions.stable: 2.15 -> 2.17
[NixPkgs.git] / nixos / tests / gnupg.nix
blob65a9a93007fd95a20671314b7d0178dbe32b2863
1 import ./make-test-python.nix ({ pkgs, lib, ...}:
4   name = "gnupg";
5   meta = with lib.maintainers; {
6     maintainers = [ rnhmjoj ];
7   };
9   # server for testing SSH
10   nodes.server = { ... }: {
11     imports = [ ../modules/profiles/minimal.nix ];
13     users.users.alice.isNormalUser = true;
14     services.openssh.enable = true;
15   };
17   # machine for testing GnuPG
18   nodes.machine = { pkgs, ... }: {
19     imports = [ ../modules/profiles/minimal.nix ];
21     users.users.alice.isNormalUser = true;
22     services.getty.autologinUser = "alice";
24     environment.shellInit = ''
25       # preset a key passphrase in gpg-agent
26       preset_key() {
27         # find all keys
28         case "$1" in
29           ssh) grips=$(awk '/^[0-9A-F]/{print $1}' "''${GNUPGHOME:-$HOME/.gnupg}/sshcontrol") ;;
30           pgp) grips=$(gpg --with-keygrip --list-secret-keys | awk '/Keygrip/{print $3}') ;;
31         esac
33         # try to preset the passphrase for each key found
34         for grip in $grips; do
35           "$(gpgconf --list-dirs libexecdir)/gpg-preset-passphrase" -c -P "$2" "$grip"
36         done
37       }
38     '';
40     programs.gnupg.agent.enable = true;
41     programs.gnupg.agent.enableSSHSupport = true;
42   };
44   testScript =
45     ''
46       import shlex
49       def as_alice(command: str) -> str:
50           """
51           Wraps a command to run it as Alice in a login shell
52           """
53           quoted = shlex.quote(command)
54           return "su --login alice --command " + quoted
57       start_all()
59       with subtest("Wait for the autologin"):
60           machine.wait_until_tty_matches("1", "alice@machine")
62       with subtest("Can generate a PGP key"):
63           # Note: this needs a tty because of pinentry
64           machine.send_chars("gpg --gen-key\n")
65           machine.wait_until_tty_matches("1", "Real name:")
66           machine.send_chars("Alice\n")
67           machine.wait_until_tty_matches("1", "Email address:")
68           machine.send_chars("alice@machine\n")
69           machine.wait_until_tty_matches("1", "Change")
70           machine.send_chars("O\n")
71           machine.wait_until_tty_matches("1", "Please enter")
72           machine.send_chars("pgp_p4ssphrase\n")
73           machine.wait_until_tty_matches("1", "Please re-enter")
74           machine.send_chars("pgp_p4ssphrase\n")
75           machine.wait_until_tty_matches("1", "public and secret key created")
77       with subtest("Confirm the key is in the keyring"):
78           machine.wait_until_succeeds(as_alice("gpg --list-secret-keys | grep -q alice@machine"))
80       with subtest("Can generate and add an SSH key"):
81           machine.succeed(as_alice("ssh-keygen -t ed25519 -f alice -N ssh_p4ssphrase"))
83           # Note: apparently this must be run before using the OpenSSH agent
84           # socket for the first time in a tty. It's not needed for `ssh`
85           # because there's a hook that calls it automatically (only in NixOS).
86           machine.send_chars("gpg-connect-agent updatestartuptty /bye\n")
88           # Note: again, this needs a tty because of pinentry
89           machine.send_chars("ssh-add alice\n")
90           machine.wait_until_tty_matches("1", "Enter passphrase")
91           machine.send_chars("ssh_p4ssphrase\n")
92           machine.wait_until_tty_matches("1", "Please enter")
93           machine.send_chars("ssh_agent_p4ssphrase\n")
94           machine.wait_until_tty_matches("1", "Please re-enter")
95           machine.send_chars("ssh_agent_p4ssphrase\n")
97       with subtest("Confirm the SSH key has been registered"):
98           machine.wait_until_succeeds(as_alice("ssh-add -l | grep -q alice@machine"))
100       with subtest("Can preset the key passphrases in the agent"):
101           machine.succeed(as_alice("echo allow-preset-passphrase > .gnupg/gpg-agent.conf"))
102           machine.succeed(as_alice("pkill gpg-agent"))
103           machine.succeed(as_alice("preset_key pgp pgp_p4ssphrase"))
104           machine.succeed(as_alice("preset_key ssh ssh_agent_p4ssphrase"))
106       with subtest("Can encrypt and decrypt a message"):
107           machine.succeed(as_alice("echo Hello | gpg -e -r alice | gpg -d | grep -q Hello"))
109       with subtest("Can log into the server"):
110           # Install Alice's public key
111           public_key = machine.succeed(as_alice("cat alice.pub"))
112           server.succeed("mkdir /etc/ssh/authorized_keys.d")
113           server.succeed(f"printf '{public_key}' > /etc/ssh/authorized_keys.d/alice")
115           server.wait_for_open_port(22)
116           machine.succeed(as_alice("ssh -i alice -o StrictHostKeyChecking=no server exit"))
117     '';