This is a NixOS test for the security.pki options.launchpad/nixpkgs/master
parent
b9bb98cf49
commit
cc8a4227c1
@ -0,0 +1,161 @@ |
||||
# Checks that `security.pki` options are working in curl and the main browser |
||||
# engines: Gecko (via Firefox), Chromium, QtWebEngine (Falkon) and WebKitGTK |
||||
# (via Midori). The test checks that certificates issued by a custom trusted |
||||
# CA are accepted but those from an unknown CA are rejected. |
||||
|
||||
import ./make-test-python.nix ({ pkgs, lib, ... }: |
||||
|
||||
let |
||||
makeCert = { caName, domain }: pkgs.runCommand "example-cert" |
||||
{ buildInputs = [ pkgs.gnutls ]; } |
||||
'' |
||||
mkdir $out |
||||
|
||||
# CA cert template |
||||
cat >ca.template <<EOF |
||||
organization = "${caName}" |
||||
cn = "${caName}" |
||||
expiration_days = 365 |
||||
ca |
||||
cert_signing_key |
||||
crl_signing_key |
||||
EOF |
||||
|
||||
# server cert template |
||||
cat >server.template <<EOF |
||||
organization = "An example company" |
||||
cn = "${domain}" |
||||
expiration_days = 30 |
||||
dns_name = "${domain}" |
||||
encryption_key |
||||
signing_key |
||||
EOF |
||||
|
||||
# generate CA keypair |
||||
certtool \ |
||||
--generate-privkey \ |
||||
--key-type rsa \ |
||||
--sec-param High \ |
||||
--outfile $out/ca.key |
||||
certtool \ |
||||
--generate-self-signed \ |
||||
--load-privkey $out/ca.key \ |
||||
--template ca.template \ |
||||
--outfile $out/ca.crt |
||||
|
||||
# generate server keypair |
||||
certtool \ |
||||
--generate-privkey \ |
||||
--key-type rsa \ |
||||
--sec-param High \ |
||||
--outfile $out/server.key |
||||
certtool \ |
||||
--generate-certificate \ |
||||
--load-privkey $out/server.key \ |
||||
--load-ca-privkey $out/ca.key \ |
||||
--load-ca-certificate $out/ca.crt \ |
||||
--template server.template \ |
||||
--outfile $out/server.crt |
||||
''; |
||||
|
||||
example-good-cert = makeCert |
||||
{ caName = "Example good CA"; |
||||
domain = "good.example.com"; |
||||
}; |
||||
|
||||
example-bad-cert = makeCert |
||||
{ caName = "Unknown CA"; |
||||
domain = "bad.example.com"; |
||||
}; |
||||
|
||||
in |
||||
|
||||
{ |
||||
name = "custom-ca"; |
||||
meta.maintainers = with lib.maintainers; [ rnhmjoj ]; |
||||
|
||||
enableOCR = true; |
||||
|
||||
machine = { pkgs, ... }: |
||||
{ imports = [ ./common/user-account.nix ./common/x11.nix ]; |
||||
|
||||
# chromium-based browsers refuse to run as root |
||||
test-support.displayManager.auto.user = "alice"; |
||||
# browsers may hang with the default memory |
||||
virtualisation.memorySize = "500"; |
||||
|
||||
networking.hosts."127.0.0.1" = [ "good.example.com" "bad.example.com" ]; |
||||
security.pki.certificateFiles = [ "${example-good-cert}/ca.crt" ]; |
||||
|
||||
services.nginx.enable = true; |
||||
services.nginx.virtualHosts."good.example.com" = |
||||
{ onlySSL = true; |
||||
sslCertificate = "${example-good-cert}/server.crt"; |
||||
sslCertificateKey = "${example-good-cert}/server.key"; |
||||
locations."/".extraConfig = "return 200 'It works!';"; |
||||
}; |
||||
services.nginx.virtualHosts."bad.example.com" = |
||||
{ onlySSL = true; |
||||
sslCertificate = "${example-bad-cert}/server.crt"; |
||||
sslCertificateKey = "${example-bad-cert}/server.key"; |
||||
locations."/".extraConfig = "return 200 'It does not work!';"; |
||||
}; |
||||
|
||||
environment.systemPackages = with pkgs; |
||||
[ xdotool firefox chromium falkon midori ]; |
||||
}; |
||||
|
||||
testScript = '' |
||||
def execute_as(user: str, cmd: str) -> Tuple[int, str]: |
||||
""" |
||||
Run a shell command as a specific user. |
||||
""" |
||||
return machine.execute(f"sudo -u {user} {cmd}") |
||||
|
||||
|
||||
def wait_for_window_as(user: str, cls: str) -> None: |
||||
""" |
||||
Wait until a X11 window of a given user appears. |
||||
""" |
||||
|
||||
def window_is_visible(last_try: bool) -> bool: |
||||
ret, stdout = execute_as(user, f"xdotool search --onlyvisible --class {cls}") |
||||
if last_try: |
||||
machine.log(f"Last chance to match {cls} on the window list") |
||||
return ret == 0 |
||||
|
||||
with machine.nested("Waiting for a window to appear"): |
||||
retry(window_is_visible) |
||||
|
||||
|
||||
machine.start() |
||||
|
||||
with subtest("Good certificate is trusted in curl"): |
||||
machine.wait_for_unit("nginx") |
||||
machine.wait_for_open_port(443) |
||||
machine.succeed("curl -fv https://good.example.com") |
||||
|
||||
with subtest("Unknown CA is untrusted in curl"): |
||||
machine.fail("curl -fv https://bad.example.com") |
||||
|
||||
browsers = ["firefox", "chromium", "falkon", "midori"] |
||||
errors = ["Security Risk", "not private", "Certificate Error", "Security"] |
||||
|
||||
machine.wait_for_x() |
||||
for browser, error in zip(browsers, errors): |
||||
with subtest("Good certificate is trusted in " + browser): |
||||
execute_as( |
||||
"alice", f"env P11_KIT_DEBUG=trust {browser} https://good.example.com & >&2" |
||||
) |
||||
wait_for_window_as("alice", browser) |
||||
machine.wait_for_text("It works!") |
||||
machine.screenshot("good" + browser) |
||||
execute_as("alice", "xdotool key ctrl+w") # close tab |
||||
|
||||
with subtest("Unknown CA is untrusted in " + browser): |
||||
execute_as("alice", f"{browser} https://bad.example.com & >&2") |
||||
machine.wait_for_text(error) |
||||
machine.screenshot("bad" + browser) |
||||
machine.succeed("pkill " + browser) |
||||
''; |
||||
}) |
Loading…
Reference in new issue