mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-29 10:23:29 +00:00
982c5a1f0e
- Use an acme user and group, allow group override only - Use hashes to determine when certs actually need to regenerate - Avoid running lego more than necessary - Harden permissions - Support "systemctl clean" for cert regeneration - Support reuse of keys between some configuration changes - Permissions fix services solves for previously root owned certs - Add a note about multiple account creation and emails - Migrate extraDomains to a list - Deprecate user option - Use minica for self-signed certs - Rewrite all tests I thought of a few more cases where things may go wrong, and added tests to cover them. In particular, the web server reload services were depending on the target - which stays alive, meaning that the renewal timer wouldn't be triggering a reload and old certs would stay on the web servers. I encountered some problems ensuring that the reload took place without accidently triggering it as part of the test. The sync commands I added ended up being essential and I'm not sure why, it seems like either node.succeed ends too early or there's an oddity of the vm's filesystem I'm not aware of. - Fix duplicate systemd rules on reload services Since useACMEHost is not unique to every vhost, if one cert was reused many times it would create duplicate entries in ${server}-config-reload.service for wants, before and ConditionPathExists
140 lines
4.2 KiB
Nix
140 lines
4.2 KiB
Nix
# The certificate for the ACME service is exported as:
|
|
#
|
|
# config.test-support.acme.caCert
|
|
#
|
|
# This value can be used inside the configuration of other test nodes to inject
|
|
# the test certificate into security.pki.certificateFiles or into package
|
|
# overlays.
|
|
#
|
|
# Another value that's needed if you don't use a custom resolver (see below for
|
|
# notes on that) is to add the acme node as a nameserver to every node
|
|
# that needs to acquire certificates using ACME, because otherwise the API host
|
|
# for acme.test can't be resolved.
|
|
#
|
|
# A configuration example of a full node setup using this would be this:
|
|
#
|
|
# {
|
|
# acme = import ./common/acme/server;
|
|
#
|
|
# example = { nodes, ... }: {
|
|
# networking.nameservers = [
|
|
# nodes.acme.config.networking.primaryIPAddress
|
|
# ];
|
|
# security.pki.certificateFiles = [
|
|
# nodes.acme.config.test-support.acme.caCert
|
|
# ];
|
|
# };
|
|
# }
|
|
#
|
|
# By default, this module runs a local resolver, generated using resolver.nix
|
|
# from the parent directory to automatically discover all zones in the network.
|
|
#
|
|
# If you do not want this and want to use your own resolver, you can just
|
|
# override networking.nameservers like this:
|
|
#
|
|
# {
|
|
# acme = { nodes, lib, ... }: {
|
|
# imports = [ ./common/acme/server ];
|
|
# networking.nameservers = lib.mkForce [
|
|
# nodes.myresolver.config.networking.primaryIPAddress
|
|
# ];
|
|
# };
|
|
#
|
|
# myresolver = ...;
|
|
# }
|
|
#
|
|
# Keep in mind, that currently only _one_ resolver is supported, if you have
|
|
# more than one resolver in networking.nameservers only the first one will be
|
|
# used.
|
|
#
|
|
# Also make sure that whenever you use a resolver from a different test node
|
|
# that it has to be started _before_ the ACME service.
|
|
{ config, pkgs, lib, ... }:
|
|
let
|
|
testCerts = import ./snakeoil-certs.nix {
|
|
minica = pkgs.minica;
|
|
mkDerivation = pkgs.stdenv.mkDerivation;
|
|
};
|
|
domain = testCerts.domain;
|
|
|
|
resolver = let
|
|
message = "You need to define a resolver for the acme test module.";
|
|
firstNS = lib.head config.networking.nameservers;
|
|
in if config.networking.nameservers == [] then throw message else firstNS;
|
|
|
|
pebbleConf.pebble = {
|
|
listenAddress = "0.0.0.0:443";
|
|
managementListenAddress = "0.0.0.0:15000";
|
|
# These certs and keys are used for the Web Front End (WFE)
|
|
certificate = testCerts.${domain}.cert;
|
|
privateKey = testCerts.${domain}.key;
|
|
httpPort = 80;
|
|
tlsPort = 443;
|
|
ocspResponderURL = "http://0.0.0.0:4002";
|
|
strict = true;
|
|
};
|
|
|
|
pebbleConfFile = pkgs.writeText "pebble.conf" (builtins.toJSON pebbleConf);
|
|
|
|
in {
|
|
imports = [ ../../resolver.nix ];
|
|
|
|
options.test-support.acme = with lib; {
|
|
caDomain = mkOption {
|
|
type = types.str;
|
|
readOnly = true;
|
|
default = domain;
|
|
description = ''
|
|
A domain name to use with the <literal>nodes</literal> attribute to
|
|
identify the CA server.
|
|
'';
|
|
};
|
|
caCert = mkOption {
|
|
type = types.path;
|
|
readOnly = true;
|
|
default = testCerts.ca.cert;
|
|
description = ''
|
|
A certificate file to use with the <literal>nodes</literal> attribute to
|
|
inject the test CA certificate used in the ACME server into
|
|
<option>security.pki.certificateFiles</option>.
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = {
|
|
test-support = {
|
|
resolver.enable = let
|
|
isLocalResolver = config.networking.nameservers == [ "127.0.0.1" ];
|
|
in lib.mkOverride 900 isLocalResolver;
|
|
};
|
|
|
|
# This has priority 140, because modules/testing/test-instrumentation.nix
|
|
# already overrides this with priority 150.
|
|
networking.nameservers = lib.mkOverride 140 [ "127.0.0.1" ];
|
|
networking.firewall.allowedTCPPorts = [ 80 443 15000 4002 ];
|
|
|
|
networking.extraHosts = ''
|
|
127.0.0.1 ${domain}
|
|
${config.networking.primaryIPAddress} ${domain}
|
|
'';
|
|
|
|
systemd.services = {
|
|
pebble = {
|
|
enable = true;
|
|
description = "Pebble ACME server";
|
|
wantedBy = [ "network.target" ];
|
|
|
|
serviceConfig = {
|
|
RuntimeDirectory = "pebble";
|
|
WorkingDirectory = "/run/pebble";
|
|
|
|
# Required to bind on privileged ports.
|
|
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
|
|
|
|
ExecStart = "${pkgs.pebble}/bin/pebble -config ${pebbleConfFile}";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|