at 21.11-pre 3.4 kB view raw
1import ./make-test-python.nix ({ ... }: 2 3let 4 oathSnakeoilSecret = "cdd4083ef8ff1fa9178c6d46bfb1a3"; 5 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 oathToolkit 11 # via: oathtool -v -d6 -w10 cdd4083ef8ff1fa9178c6d46bfb1a3 12 # and picking a the first 4: 13 oathSnakeOilPassword1 = "143349"; 14 oathSnakeOilPassword2 = "801753"; 15 16 alicePassword = "foobar"; 17 # Generated via: mkpasswd -m sha-512 and passing in "foobar" 18 hashedAlicePassword = "$6$MsMrE1q.1HrCgTS$Vq2e/uILzYjSN836TobAyN9xh9oi7EmCmucnZID25qgPoibkw8qTCugiAPnn4eCGvn1A.7oEBFJaaGUaJsQQY."; 19 20in 21{ 22 name = "pam-oath-login"; 23 24 machine = 25 { ... }: 26 { 27 security.pam.oath = { 28 enable = true; 29 }; 30 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 }; 40 41 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 }; 57 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}'") 65 66 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") 73 74 75 machine.wait_for_unit("multi-user.target") 76 machine.wait_until_succeeds("pgrep -f 'agetty.*tty1'") 77 machine.screenshot("postboot") 78 79 with subtest("Invalid password"): 80 switch_to_tty(2) 81 enter_user_alice(2) 82 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") 87 88 with subtest("Invalid oath token"): 89 switch_to_tty(3) 90 enter_user_alice(3) 91 92 machine.send_chars("000000\n") 93 machine.wait_until_tty_matches(3, "Login incorrect") 94 machine.wait_until_tty_matches(3, "login:") 95 96 with subtest("Happy path: Both passwords are mandatory to get us in"): 97 switch_to_tty(4) 98 enter_user_alice(4) 99 100 machine.send_chars("${oathSnakeOilPassword2}\n") 101 machine.wait_until_tty_matches(4, "Password: ") 102 machine.send_chars("${alicePassword}\n") 103 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 ''; 108})