Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/acme: Various fixes #191861

Merged
merged 3 commits into from
Oct 6, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion nixos/modules/security/acme/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ let
'');
} // optionalAttrs (data.listenHTTP != null && toInt (elemAt (splitString ":" data.listenHTTP) 1) < 1024) {
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
winterqt marked this conversation as resolved.
Show resolved Hide resolved
};

# Working directory will be /tmp
Expand Down Expand Up @@ -376,7 +377,8 @@ let

# Check if we can renew.
# We can only renew if the list of domains has not changed.
if cmp -s domainhash.txt certificates/domainhash.txt && [ -e 'certificates/${keyName}.key' -a -e 'certificates/${keyName}.crt' -a -n "$(ls -1 accounts)" ]; then
# We also need an account key. Avoids #190493
if cmp -s domainhash.txt certificates/domainhash.txt && [ -e 'certificates/${keyName}.key' -a -e 'certificates/${keyName}.crt' -a -n "$(find accounts -name '${data.email}.key')" ]; then

# Even if a cert is not expired, it may be revoked by the CA.
# Try to renew, and silently fail if the cert is not expired.
Expand Down
60 changes: 59 additions & 1 deletion nixos/tests/acme.nix
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: let
inherit documentRoot;
};

simpleConfig = {
security.acme = {
certs."http.example.test" = {
listenHTTP = ":80";
};
};

networking.firewall.allowedTCPPorts = [ 80 ];
};

# Base specialisation config for testing general ACME features
webserverBasicConfig = {
services.nginx.enable = true;
Expand Down Expand Up @@ -173,6 +183,26 @@ in {
services.nginx.logError = "stderr info";

specialisation = {
# Tests HTTP-01 verification using Lego's built-in web server
http01lego.configuration = simpleConfig;

renew.configuration = lib.mkMerge [
simpleConfig
{
# Pebble provides 5 year long certs,
# needs to be higher than that to test renewal
security.acme.certs."http.example.test".validMinDays = 9999;
}
];

# Tests that account creds can be safely changed.
accountchange.configuration = lib.mkMerge [
simpleConfig
{
security.acme.certs."http.example.test".email = "admin@example.test";
}
];

# First derivation used to test general ACME features
general.configuration = { ... }: let
caDomain = nodes.acme.config.test-support.acme.caDomain;
Expand Down Expand Up @@ -446,7 +476,35 @@ in {

download_ca_certs(client)

# Perform general tests first
# Perform http-01 w/ lego test first
with subtest("Can request certificate with Lego's built in web server"):
switch_to(webserver, "http01lego")
webserver.wait_for_unit("acme-finished-http.example.test.target")
check_fullchain(webserver, "http.example.test")
check_issuer(webserver, "http.example.test", "pebble")

# Perform renewal test
with subtest("Can renew certificates when they expire"):
hash = webserver.succeed("sha256sum /var/lib/acme/http.example.test/cert.pem")
switch_to(webserver, "renew")
webserver.wait_for_unit("acme-finished-http.example.test.target")
check_fullchain(webserver, "http.example.test")
check_issuer(webserver, "http.example.test", "pebble")
hash_after = webserver.succeed("sha256sum /var/lib/acme/http.example.test/cert.pem")
assert hash != hash_after

# Perform account change test
with subtest("Handles email change correctly"):
hash = webserver.succeed("sha256sum /var/lib/acme/http.example.test/cert.pem")
switch_to(webserver, "accountchange")
webserver.wait_for_unit("acme-finished-http.example.test.target")
check_fullchain(webserver, "http.example.test")
check_issuer(webserver, "http.example.test", "pebble")
hash_after = webserver.succeed("sha256sum /var/lib/acme/http.example.test/cert.pem")
# Has to do a full run to register account, which creates new certs.
assert hash != hash_after

# Perform general tests
switch_to(webserver, "general")

with subtest("Can request certificate with HTTP-01 challenge"):
Expand Down
5 changes: 5 additions & 0 deletions nixos/tests/common/acme/client/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ in {
defaults = {
server = "https://${caDomain}/dir";
email = "hostmaster@example.test";
# Avoid a random 0-8 minute sleep when testing renewals.
# We are not using LE servers in testing so this is not
# going to impact their load.
# See https://github.com/go-acme/lego/issues/1656
extraLegoRenewFlags = ["-no-random-sleep"];
m1cr0man marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering this is removed in the subsequent commit, would it make sense to just not add it in this commit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I'm normally pretty adverse to editing commits because it alerts all the related issues again when you force push. Also I think these commits show a good evolution of the feature?

};
};

Expand Down