depot/third_party/nixpkgs/nixos/tests/common/acme/server/default.nix

142 lines
4.2 KiB
Nix
Raw Normal View History

# 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.networking.primaryIPAddress
# ];
# security.pki.certificateFiles = [
# nodes.acme.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.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;
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://${domain}: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 = lib.mdDoc ''
A domain name to use with the `nodes` attribute to
identify the CA server.
'';
};
caCert = mkOption {
type = types.path;
readOnly = true;
default = testCerts.ca.cert;
description = lib.mdDoc ''
A certificate file to use with the `nodes` attribute to
inject the test CA certificate used in the ACME server into
{option}`security.pki.certificateFiles`.
'';
};
};
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" ];
environment = {
# We're not testing lego, we're just testing our configuration.
# No need to sleep.
PEBBLE_VA_NOSLEEP = "1";
};
serviceConfig = {
RuntimeDirectory = "pebble";
WorkingDirectory = "/run/pebble";
# Required to bind on privileged ports.
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
ExecStart = "${pkgs.pebble}/bin/pebble -config ${pebbleConfFile}";
};
};
};
};
}