nixpkgs/nixos/tests/acme/dns01.nix
Lucas Savva 229640ed3a nixos/tests/acme: Refactor test suite
Split tests up based on certain use cases:

- http01-builtin: Tests most functionality of the core module, such
 as the systemd and hashing components, whilst utilising lego's built
 in http01 resolution mechanis.
- dns01: Tests only that DNS01 renewal works as expected.
- nginx: Tests nginx compatability
- httpd: Tests httpd compatability
- caddy: Tests caddy compatability
2025-02-22 23:58:29 +00:00

118 lines
3.2 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
domain = "example.test";
dnsServerIP = nodes: nodes.dnsserver.networking.primaryIPAddress;
dnsScript = pkgs.writeShellScript "dns-hook.sh" ''
set -euo pipefail
echo '[INFO]' "[$2]" 'dns-hook.sh' $*
if [ "$1" = "present" ]; then
${pkgs.curl}/bin/curl --data @- http://dnsserver.test:8055/set-txt << EOF
{"host": "$2", "value": "$3"}
EOF
else
${pkgs.curl}/bin/curl --data @- http://dnsserver.test:8055/clear-txt << EOF
{"host": "$2"}
EOF
fi
'';
in
{
name = "dns01";
meta = {
maintainers = lib.teams.acme.members;
# Hard timeout in seconds. Average run time is about 60 seconds.
timeout = 180;
};
nodes = {
# The fake ACME server which will respond to client requests
acme =
{ nodes, ... }:
{
imports = [ ../common/acme/server ];
networking.nameservers = lib.mkForce [ (dnsServerIP nodes) ];
};
# A fake DNS server which can be configured with records as desired
# Used to test DNS-01 challenge
dnsserver =
{ nodes, ... }:
{
networking = {
firewall.allowedTCPPorts = [
8055
53
];
firewall.allowedUDPPorts = [ 53 ];
# nixos/lib/testing/network.nix will provide name resolution via /etc/hosts
# for all nodes based on their host names and domain
hostName = "dnsserver";
domain = "test";
};
systemd.services.pebble-challtestsrv = {
enable = true;
description = "Pebble ACME challenge test server";
wantedBy = [ "network.target" ];
serviceConfig = {
ExecStart = "${pkgs.pebble}/bin/pebble-challtestsrv -dns01 ':53' -defaultIPv6 '' -defaultIPv4 '${nodes.client.networking.primaryIPAddress}'";
# Required to bind on privileged ports.
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
};
};
};
client =
{ nodes, ... }:
{
imports = [ ../common/acme/client ];
networking.domain = domain;
networking.nameservers = lib.mkForce [ (dnsServerIP nodes) ];
# OpenSSL will be used for more thorough certificate validation
environment.systemPackages = [ pkgs.openssl ];
security.acme.certs."${domain}" = {
domain = "*.${domain}";
dnsProvider = "exec";
dnsPropagationCheck = false;
environmentFile = pkgs.writeText "wildcard.env" ''
EXEC_PATH=${dnsScript}
EXEC_POLLING_INTERVAL=1
EXEC_PROPAGATION_TIMEOUT=1
EXEC_SEQUENCE_INTERVAL=1
'';
};
};
};
testScript = ''
${(import ./utils.nix).pythonUtils}
cert = "${domain}"
dnsserver.start()
acme.start()
wait_for_running(dnsserver)
dnsserver.wait_for_open_port(53)
wait_for_running(acme)
acme.wait_for_open_port(443)
with subtest("Boot and acquire a new cert"):
client.start()
wait_for_running(client)
check_issuer(client, cert, "pebble")
check_domain(client, cert, cert, fail=True)
check_domain(client, cert, f"toodeep.nesting.{cert}", fail=True)
check_domain(client, cert, f"whatever.{cert}")
'';
}