136 lines
4.8 KiB
Nix
136 lines
4.8 KiB
Nix
{ hostPkgs, lib, ... }:
|
||
|
||
let
|
||
domain = "acme.test";
|
||
|
||
hello_txt =
|
||
name:
|
||
hostPkgs.writeTextFile {
|
||
name = "/hello_${name}.txt";
|
||
text = "Hello, ${name}!";
|
||
};
|
||
|
||
mkH2OServer =
|
||
recommendations:
|
||
{
|
||
pkgs,
|
||
lib,
|
||
config,
|
||
...
|
||
}:
|
||
{
|
||
services.h2o = {
|
||
enable = true;
|
||
package = pkgs.h2o.override (
|
||
lib.optionalAttrs
|
||
(builtins.elem recommendations [
|
||
"intermediate"
|
||
"old"
|
||
])
|
||
{
|
||
openssl = pkgs.openssl_legacy;
|
||
}
|
||
);
|
||
defaultTLSRecommendations = "modern"; # prove overridden
|
||
hosts = {
|
||
"${domain}" = {
|
||
tls = {
|
||
inherit recommendations;
|
||
port = 8443;
|
||
policy = "force";
|
||
identity = [
|
||
{
|
||
key-file = ../../common/acme/server/acme.test.key.pem;
|
||
certificate-file = ../../common/acme/server/acme.test.cert.pem;
|
||
}
|
||
];
|
||
extraSettings = {
|
||
# when using common ACME certs, disable talking to CA
|
||
ocsp-update-interval = 0;
|
||
};
|
||
};
|
||
settings = {
|
||
paths."/"."file.file" = "${hello_txt recommendations}";
|
||
};
|
||
};
|
||
};
|
||
settings = {
|
||
ssl-offload = "kernel";
|
||
};
|
||
};
|
||
|
||
security.pki.certificates = [
|
||
(builtins.readFile ../../common/acme/server/ca.cert.pem)
|
||
];
|
||
|
||
networking = {
|
||
firewall.allowedTCPPorts = [
|
||
config.services.h2o.hosts.${domain}.tls.port
|
||
];
|
||
extraHosts = "127.0.0.1 ${domain}";
|
||
};
|
||
};
|
||
in
|
||
{
|
||
name = "h2o-tls-recommendations";
|
||
|
||
meta = {
|
||
maintainers = with lib.maintainers; [ toastal ];
|
||
};
|
||
|
||
# not using a `client` since it’s easiest to test with acme.test pointing at
|
||
# localhost for these machines
|
||
nodes = {
|
||
server_modern = mkH2OServer "modern";
|
||
server_intermediate = mkH2OServer "intermediate";
|
||
server_old = mkH2OServer "old";
|
||
};
|
||
|
||
testScript =
|
||
{ nodes, ... }:
|
||
let
|
||
inherit (nodes) server_modern server_intermediate server_old;
|
||
modernPortStr = builtins.toString server_modern.services.h2o.hosts.${domain}.tls.port;
|
||
intermediatePortStr = builtins.toString server_intermediate.services.h2o.hosts.${domain}.tls.port;
|
||
oldPortStr = builtins.toString server_old.services.h2o.hosts.${domain}.tls.port;
|
||
in
|
||
# python
|
||
''
|
||
curl_basic = "curl -v --tlsv1.3 --http2 'https://${domain}:{port}/'"
|
||
curl_head = "curl -v --head 'https://${domain}:{port}/'"
|
||
curl_max_tls1_2 ="curl -v --tlsv1.0 --tls-max 1.2 'https://${domain}:{port}/'"
|
||
curl_max_tls1_2_intermediate_cipher ="curl -v --tlsv1.0 --tls-max 1.2 --ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256' 'https://${domain}:{port}/'"
|
||
curl_max_tls1_2_old_cipher ="curl -v --tlsv1.0 --tls-max 1.2 --ciphers 'ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256' 'https://${domain}:{port}/'"
|
||
|
||
start_all()
|
||
|
||
server_modern.wait_for_unit("h2o.service")
|
||
server_modern.wait_for_open_port(${modernPortStr})
|
||
modern_response = server_modern.succeed(curl_basic.format(port="${modernPortStr}"))
|
||
assert "Hello, modern!" in modern_response
|
||
modern_head = server_modern.succeed(curl_head.format(port="${modernPortStr}"))
|
||
assert "strict-transport-security" in modern_head
|
||
server_modern.fail(curl_max_tls1_2.format(port="${modernPortStr}"))
|
||
|
||
server_intermediate.wait_for_unit("h2o.service")
|
||
server_intermediate.wait_for_open_port(${intermediatePortStr})
|
||
intermediate_response = server_intermediate.succeed(curl_basic.format(port="${intermediatePortStr}"))
|
||
assert "Hello, intermediate!" in intermediate_response
|
||
intermediate_head = server_modern.succeed(curl_head.format(port="${intermediatePortStr}"))
|
||
assert "strict-transport-security" in intermediate_head
|
||
server_intermediate.succeed(curl_max_tls1_2.format(port="${intermediatePortStr}"))
|
||
server_intermediate.succeed(curl_max_tls1_2_intermediate_cipher.format(port="${intermediatePortStr}"))
|
||
server_intermediate.fail(curl_max_tls1_2_old_cipher.format(port="${intermediatePortStr}"))
|
||
|
||
server_old.wait_for_unit("h2o.service")
|
||
server_old.wait_for_open_port(${oldPortStr})
|
||
old_response = server_old.succeed(curl_basic.format(port="${oldPortStr}"))
|
||
assert "Hello, old!" in old_response
|
||
old_head = server_modern.succeed(curl_head.format(port="${oldPortStr}"))
|
||
assert "strict-transport-security" in old_head
|
||
server_old.succeed(curl_max_tls1_2.format(port="${oldPortStr}"))
|
||
server_old.succeed(curl_max_tls1_2_intermediate_cipher.format(port="${oldPortStr}"))
|
||
server_old.succeed(curl_max_tls1_2_old_cipher.format(port="${oldPortStr}"))
|
||
'';
|
||
}
|