python312Packages.millheater: 0.11.8 -> 0.12.0
[NixPkgs.git] / nixos / tests / pam / pam-oath-login.nix
blobdd6ef4a0abcb8e426ee95e213040272c09770a97
1 import ../make-test-python.nix ({ ... }:
3 let
4   oathSnakeoilSecret = "cdd4083ef8ff1fa9178c6d46bfb1a3";
6   # With HOTP mode the password is calculated based on a counter of
7   # how many passwords have been made. In this env, we'll always be on
8   # the 0th counter, so the password is static.
9   #
10   # Generated in nix-shell -p oath-toolkit
11   # via: oathtool -v -d6 -w10 cdd4083ef8ff1fa9178c6d46bfb1a3
12   # and picking a the first 4:
13   oathSnakeOilPassword1 = "143349";
14   oathSnakeOilPassword2 = "801753";
16   alicePassword = "foobar";
17   # Generated via: mkpasswd -m sha-512 and passing in "foobar"
18   hashedAlicePassword = "$6$MsMrE1q.1HrCgTS$Vq2e/uILzYjSN836TobAyN9xh9oi7EmCmucnZID25qgPoibkw8qTCugiAPnn4eCGvn1A.7oEBFJaaGUaJsQQY.";
22   name = "pam-oath-login";
24   nodes.machine =
25     { ... }:
26     {
27       security.pam.oath = {
28         enable = true;
29       };
31       users.users.alice = {
32         isNormalUser = true;
33         name = "alice";
34         uid = 1000;
35         hashedPassword = hashedAlicePassword;
36         extraGroups = [ "wheel" ];
37         createHome = true;
38         home = "/home/alice";
39       };
42       systemd.services.setupOathSnakeoilFile = {
43         wantedBy = [ "default.target" ];
44         before = [ "default.target" ];
45         unitConfig = {
46           type = "oneshot";
47           RemainAfterExit = true;
48         };
49         script = ''
50           touch /etc/users.oath
51           chmod 600 /etc/users.oath
52           chown root /etc/users.oath
53           echo "HOTP/E/6 alice - ${oathSnakeoilSecret}" > /etc/users.oath
54         '';
55       };
56     };
58   testScript = ''
59     def switch_to_tty(tty_number):
60         machine.fail(f"pgrep -f 'agetty.*tty{tty_number}'")
61         machine.send_key(f"alt-f{tty_number}")
62         machine.wait_until_succeeds(f"[ $(fgconsole) = {tty_number} ]")
63         machine.wait_for_unit(f"getty@tty{tty_number}.service")
64         machine.wait_until_succeeds(f"pgrep -f 'agetty.*tty{tty_number}'")
67     def enter_user_alice(tty_number):
68         machine.wait_until_tty_matches(tty_number, "login: ")
69         machine.send_chars("alice\n")
70         machine.wait_until_tty_matches(tty_number, "login: alice")
71         machine.wait_until_succeeds("pgrep login")
72         machine.wait_until_tty_matches(tty_number, "One-time password")
75     machine.wait_for_unit("multi-user.target")
76     machine.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
77     machine.screenshot("postboot")
79     with subtest("Invalid password"):
80         switch_to_tty("2")
81         enter_user_alice("2")
83         machine.send_chars("${oathSnakeOilPassword1}\n")
84         machine.wait_until_tty_matches("2", "Password: ")
85         machine.send_chars("blorg\n")
86         machine.wait_until_tty_matches("2", "Login incorrect")
88     with subtest("Invalid oath token"):
89         switch_to_tty("3")
90         enter_user_alice("3")
92         machine.send_chars("000000\n")
93         machine.wait_until_tty_matches("3", "Login incorrect")
94         machine.wait_until_tty_matches("3", "login:")
96     with subtest("Happy path: Both passwords are mandatory to get us in"):
97         switch_to_tty("4")
98         enter_user_alice("4")
100         machine.send_chars("${oathSnakeOilPassword2}\n")
101         machine.wait_until_tty_matches("4", "Password: ")
102         machine.send_chars("${alicePassword}\n")
104         machine.wait_until_succeeds("pgrep -u alice bash")
105         machine.send_chars("touch  done4\n")
106         machine.wait_for_file("/home/alice/done4")
107     '';