From 4516f9efc4a8e9bc95b8f625070c2c595d14561f Mon Sep 17 00:00:00 2001 From: h7x4 Date: Sat, 14 Feb 2026 01:11:00 +0900 Subject: [PATCH] nix/nixosTest: fix --- nix/nixosTest.nix | 195 +++++++++++++++++++++++++++------------------- 1 file changed, 113 insertions(+), 82 deletions(-) diff --git a/nix/nixosTest.nix b/nix/nixosTest.nix index d5e4ead87..08ab8da8e 100644 --- a/nix/nixosTest.nix +++ b/nix/nixosTest.nix @@ -1,6 +1,6 @@ { nixpkgs }: ( - { pkgs, ... }: + { pkgs, lib, ... }: { name = "kerberos_server-heimdal"; @@ -66,6 +66,7 @@ { principal = "kadmin/admin@FOO.BAR"; access = "all"; + target = ""; } { principal = "alice/admin@FOO.BAR"; @@ -77,6 +78,7 @@ "list" "modify" ]; + target = ""; } ]; }; @@ -139,6 +141,81 @@ testScript = { nodes, ... }: + let + expectTemplate = program: argc: interaction: + pkgs.writeScriptBin "${program}-auto-password" '' + #!${pkgs.expect}/bin/expect -f + + set timeout 30 + ${lib.concatMapStringsSep "\n" (i: "set arg${toString i} [lindex $argv ${toString i}]") (lib.range 0 (argc - 1))} + set args [lrange $argv ${toString argc} end] + eval spawn ${program} $args + + ${interaction} + + expect eof + set exit_status [lindex [wait] 3] + exit $exit_status + ''; + + kadmin = expectTemplate "kadmin" 1 '' + expect { + "alice/admin@FOO.BAR's Password: " { + send -- "$arg0\n" + } + timeout { + puts stderr "Error: Timeout waiting for password prompt" + exit 2 + } + eof { + puts stderr "Error: kadmin exited unexpectedly" + break + } + } + ''; + + ktutil = expectTemplate "ktutil" 1 '' + expect { + "alice/admin@FOO.BAR's Password: " { + send -- "$arg0\n" + } + timeout { + puts stderr "Error: Timeout waiting for password prompt" + exit 2 + } + eof { + puts stderr "Error: ktutil exited unexpectedly" + break + } + } + ''; + + kpasswd = expectTemplate "kpasswd" 2 '' + set exchanges [list \ + [list "alice@FOO.BAR's Password: " $arg0] \ + [list "New password: " $arg1] \ + [list "Verify password - New password: " $arg1] \ + ] + + foreach pair $exchanges { + lassign $pair prompt reply + + expect { + -exact $prompt { + send -- "$reply\n" + } + timeout { + puts stderr "Error: Timeout waiting for: $prompt" + exit 2 + } + eof { + puts stderr "Error: Unexpected EOF while waiting for: $prompt" + exit 3 + } + } + } + ''; + in '' import string import random @@ -147,7 +224,6 @@ start_all() with subtest("Server: initialize realm"): - # for unit in ["kadmind.service", "kdc.socket", "kpasswdd.socket"]: for unit in ["kadmind.service", "kdc.service", "kpasswdd.service"]: server.wait_for_unit(unit) @@ -162,42 +238,42 @@ bob_krb_pw = "bob_hunter2" def random_password(): - password_chars = string.ascii_letters + string.digits + string.punctuation.replace('"', "") + password_chars = string.ascii_letters + string.digits + "-_" return "".join(random.choice(password_chars) for _ in range(16)) - def clear_tty(node): - node.send_chars("clear\n") - ps1 = r"\[alice@\w+:~\]\$ " - node.wait_until_tty_matches("1", ps1) + def kinit(node, user, password): + node.succeed( + f"echo '{password}' > /tmp/pw.txt", + f"kinit --password-file=/tmp/pw.txt {user}", + "rm /tmp/pw.txt", + ) + tickets = node.succeed("klist") + assert f"Principal: {user}@FOO.BAR" in tickets + + def kadmin(node, command, localAuth=False): + if localAuth: + return node.succeed(f"kadmin -l {command}") + else: + return node.succeed(f"${lib.getExe kadmin} '{alice_krb_admin_pw}' -p alice/admin {command}") with subtest("Server: initialize user principals and keytabs"): - server.succeed(f'kadmin -l add --password="{alice_krb_admin_pw}" --use-defaults alice/admin') - # server.succeed("kadmin -l ext_keytab --keytab=admin.keytab alice/admin") - - server.succeed(f'kadmin -p alice/admin add --password="{alice_krb_pw}" --use-defaults alice') - # server.succeed("kadmin -l ext_keytab --keytab=alice.keytab alice") - - server.succeed("kadmin -p alice/admin add --password={bob_krb_pw} --use-defaults bob") - # server.succeed("kadmin -l ext_keytab --keytab=bob.keytab bob") + kadmin(server, f'add --password="{alice_krb_admin_pw}" --use-defaults alice/admin', localAuth=True) + kadmin(server, f'add --password="{alice_krb_pw}" --use-defaults alice') + kadmin(server, f'add --password="{bob_krb_pw}" --use-defaults bob') + kadmin(server, 'check') server.wait_for_unit("getty@tty1.service") server.wait_until_succeeds("pgrep -f 'agetty.*tty1'") server.wait_for_unit("default.target") with subtest("Server: initialize host principal with keytab"): - server.send_chars("sudo ktutil get -p alice/admin host/server.foo.bar\n") - server.wait_until_tty_matches("1", "password for alice:") - server.send_chars("${nodes.server.config.users.users.alice.password}\n") - server.wait_until_tty_matches("1", "alice/admin@FOO.BAR's Password:") - server.send_chars(f'{alice_krb_admin_pw}\n') + server.succeed(f"${lib.getExe ktutil} '{alice_krb_admin_pw}' get -p alice/admin host/server.foo.bar") server.wait_for_file("/etc/krb5.keytab") - ktutil_list = server.succeed("sudo ktutil list") + ktutil_list = server.succeed("ktutil list") if not "host/server.foo.bar" in ktutil_list: exit(1) - clear_tty(server) - client.systemctl("start network-online.target") client.wait_for_unit("network-online.target") client.wait_for_unit("getty@tty1.service") @@ -205,85 +281,40 @@ client.wait_for_unit("default.target") with subtest("Client: initialize host principal with keytab"): - client.succeed( - f'echo "{alice_krb_admin_pw}" > pw.txt', - "kinit -p --password-file=pw.txt alice/admin", - ) - - client.send_chars("sudo ktutil get -p alice/admin host/client.foo.bar\n") - client.wait_until_tty_matches("1", "password for alice:") - client.send_chars("${nodes.client.config.users.users.alice.password}\n") - client.wait_until_tty_matches("1", "alice/admin@FOO.BAR's Password:") - client.send_chars(f"{alice_krb_admin_pw}\n") + kinit(client, "alice/admin", alice_krb_admin_pw) + client.succeed(f"${lib.getExe ktutil} '{alice_krb_admin_pw}' get -p alice/admin host/client.foo.bar") client.wait_for_file("/etc/krb5.keytab") - ktutil_list = client.succeed("sudo ktutil list") + ktutil_list = client.succeed("ktutil list") if not "host/client.foo.bar" in ktutil_list: exit(1) - clear_tty(client) - with subtest("Client: kinit alice"): - client.succeed( - f"echo '{alice_krb_pw}' > pw.txt", - "kinit -p --password-file=pw.txt alice", - ) - tickets = client.succeed("klist") - assert "Principal: alice@FOO.BAR" in tickets - clear_tty(client) + kinit(client, "alice", alice_krb_pw) with subtest("Client: kpasswd alice"): alice_old_krb_pw = alice_krb_pw alice_krb_pw = random_password() - client.send_chars("kpasswd\n") - client.wait_until_tty_matches("1", "alice@FOO.BAR's Password:") - client.send_chars(f"{alice_old_krb_pw}\n", 0.1) - client.wait_until_tty_matches("1", "New password:") - client.send_chars(f"{alice_krb_pw}\n", 0.1) - client.wait_until_tty_matches("1", "Verify password - New password:") - client.send_chars(f"{alice_krb_pw}\n", 0.1) - - client.wait_until_tty_matches("1", "Success : Password changed") - - clear_tty(client) + output = client.succeed(f"${lib.getExe kpasswd} {alice_old_krb_pw} {alice_krb_pw}") + assert "Success : Password changed" in output with subtest("Client: kadmin get bob"): - client.send_chars("sudo kadmin -p alice/admin -K admin.keytab get bob\n") - client.wait_until_tty_matches("1", "alice/admin@FOO.BAR's Password:") - client.send_chars(f"{alice_krb_admin_pw}\n") - client.wait_until_tty_matches("1", "Principal: bob@FOO.BAR") - clear_tty(client) + output = kadmin(client, "get bob") + print(output) + assert "Principal: bob@FOO.BAR" in output with subtest("Server: kinit alice"): - server.succeed( - "echo 'alice_pw_2' > pw.txt" - "kinit -p --password-file=pw.txt alice", - ) - tickets = client.succeed("klist") - assert "Principal: alice@FOO.BAR" in tickets - clear_tty(server) + kinit(server, "alice", alice_krb_pw) with subtest("Server: kpasswd alice"): alice_old_krb_pw = alice_krb_pw alice_krb_pw = random_password() - server.send_chars("kpasswd\n") - server.wait_until_tty_matches("1", "alice@FOO.BAR's Password:") - server.send_chars(f"{alice_old_krb_pw}\n", 0.1) - server.wait_until_tty_matches("1", "New password:") - server.send_chars(f"{alice_krb_pw}\n", 0.1) - server.wait_until_tty_matches("1", "Verify password - New password:") - server.send_chars(f"{alice_krb_pw}\n", 0.1) - - server.wait_until_tty_matches("1", "Success : Password changed") - - clear_tty(server) + output = server.succeed(f"${lib.getExe kpasswd} {alice_old_krb_pw} {alice_krb_pw}") + assert "Success : Password changed" in output with subtest("Server: kadmin get bob"): - server.send_chars("sudo kadmin -p alice/admin -K admin.keytab get bob\n") - server.wait_until_tty_matches("1", "alice/admin@FOO.BAR's Password:") - server.send_chars(f"{alice_krb_admin_pw}\n") - server.wait_until_tty_matches("1", "Principal: bob@FOO.BAR") - clear_tty(server) + output = kadmin(server, "get bob") + assert "Principal: bob@FOO.BAR" in output ''; meta.maintainers = pkgs.heimdal.meta.maintainers;