diff options
author | Alyssa Ross <hi@alyssa.is> | 2019-01-07 02:18:36 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2019-01-07 02:18:47 +0000 |
commit | 36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2 (patch) | |
tree | b3faaf573407b32aa645237a4d16b82778a39a92 /nixpkgs/nixos/tests/common | |
parent | 4e31070265257dc67d120c27e0f75c2344fdfa9a (diff) | |
parent | abf060725d7614bd3b9f96764262dfbc2f9c2199 (diff) | |
download | nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.gz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.bz2 nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.lz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.xz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.zst nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.zip |
Add 'nixpkgs/' from commit 'abf060725d7614bd3b9f96764262dfbc2f9c2199'
git-subtree-dir: nixpkgs git-subtree-mainline: 4e31070265257dc67d120c27e0f75c2344fdfa9a git-subtree-split: abf060725d7614bd3b9f96764262dfbc2f9c2199
Diffstat (limited to 'nixpkgs/nixos/tests/common')
-rw-r--r-- | nixpkgs/nixos/tests/common/letsencrypt/common.nix | 27 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/common/letsencrypt/default.nix | 445 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/common/letsencrypt/mkcerts.nix | 69 | ||||
-rwxr-xr-x | nixpkgs/nixos/tests/common/letsencrypt/mkcerts.sh | 6 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/common/letsencrypt/snakeoil-certs.nix | 253 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/common/resolver.nix | 141 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/common/user-account.nix | 14 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/common/webroot/news-rss.xml | 15 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/common/x11.nix | 12 |
9 files changed, 982 insertions, 0 deletions
diff --git a/nixpkgs/nixos/tests/common/letsencrypt/common.nix b/nixpkgs/nixos/tests/common/letsencrypt/common.nix new file mode 100644 index 000000000000..798a749f7f9b --- /dev/null +++ b/nixpkgs/nixos/tests/common/letsencrypt/common.nix @@ -0,0 +1,27 @@ +{ lib, nodes, ... }: { + networking.nameservers = [ + nodes.letsencrypt.config.networking.primaryIPAddress + ]; + + nixpkgs.overlays = lib.singleton (self: super: { + cacert = super.cacert.overrideDerivation (drv: { + installPhase = (drv.installPhase or "") + '' + cat "${nodes.letsencrypt.config.test-support.letsencrypt.caCert}" \ + >> "$out/etc/ssl/certs/ca-bundle.crt" + ''; + }); + + # Override certifi so that it accepts fake certificate for Let's Encrypt + # Need to override the attribute used by simp_le, which is python3Packages + python3Packages = (super.python3.override { + packageOverrides = lib.const (pysuper: { + certifi = pysuper.certifi.overridePythonAttrs (attrs: { + postPatch = (attrs.postPatch or "") + '' + cat "${self.cacert}/etc/ssl/certs/ca-bundle.crt" \ + > certifi/cacert.pem + ''; + }); + }); + }).pkgs; + }); +} diff --git a/nixpkgs/nixos/tests/common/letsencrypt/default.nix b/nixpkgs/nixos/tests/common/letsencrypt/default.nix new file mode 100644 index 000000000000..73aac51a0126 --- /dev/null +++ b/nixpkgs/nixos/tests/common/letsencrypt/default.nix @@ -0,0 +1,445 @@ +# Fully pluggable module to have Letsencrypt's Boulder ACME service running in +# a test environment. +# +# The certificate for the ACME service is exported as: +# +# config.test-support.letsencrypt.caCert +# +# This value can be used inside the configuration of other test nodes to inject +# the snakeoil 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 letsencrypt node as a nameserver to every node +# that needs to acquire certificates using ACME, because otherwise the API host +# for letsencrypt.org can't be resolved. +# +# A configuration example of a full node setup using this would be this: +# +# { +# letsencrypt = import ./common/letsencrypt; +# +# example = { nodes, ... }: { +# networking.nameservers = [ +# nodes.letsencrypt.config.networking.primaryIPAddress +# ]; +# security.pki.certificateFiles = [ +# nodes.letsencrypt.config.test-support.letsencrypt.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: +# +# { +# letsencrypt = { nodes, ... }: { +# imports = [ ./common/letsencrypt ]; +# networking.nameservers = [ +# 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 + softhsm = pkgs.stdenv.mkDerivation rec { + name = "softhsm-${version}"; + version = "1.3.8"; + + src = pkgs.fetchurl { + url = "https://dist.opendnssec.org/source/${name}.tar.gz"; + sha256 = "0flmnpkgp65ym7w3qyg78d3fbmvq3aznmi66rgd420n33shf7aif"; + }; + + configureFlags = [ "--with-botan=${pkgs.botan}" ]; + buildInputs = [ pkgs.sqlite ]; + }; + + pkcs11-proxy = pkgs.stdenv.mkDerivation { + name = "pkcs11-proxy"; + + src = pkgs.fetchFromGitHub { + owner = "SUNET"; + repo = "pkcs11-proxy"; + rev = "944684f78bca0c8da6cabe3fa273fed3db44a890"; + sha256 = "1nxgd29y9wmifm11pjcdpd2y293p0dgi0x5ycis55miy97n0f5zy"; + }; + + postPatch = "patchShebangs mksyscalls.sh"; + + nativeBuildInputs = [ pkgs.cmake ]; + buildInputs = [ pkgs.openssl pkgs.libseccomp ]; + }; + + mkGoDep = { goPackagePath, url ? "https://${goPackagePath}", rev, sha256 }: { + inherit goPackagePath; + src = pkgs.fetchgit { inherit url rev sha256; }; + }; + + goose = let + owner = "liamstask"; + repo = "goose"; + rev = "8488cc47d90c8a502b1c41a462a6d9cc8ee0a895"; + version = "20150116"; + + in pkgs.buildGoPackage rec { + name = "${repo}-${version}"; + + src = pkgs.fetchFromBitbucket { + name = "${name}-src"; + inherit rev owner repo; + sha256 = "1jy0pscxjnxjdg3hj111w21g8079rq9ah2ix5ycxxhbbi3f0wdhs"; + }; + + goPackagePath = "bitbucket.org/${owner}/${repo}"; + subPackages = [ "cmd/goose" ]; + extraSrcs = map mkGoDep [ + { goPackagePath = "github.com/go-sql-driver/mysql"; + rev = "2e00b5cd70399450106cec6431c2e2ce3cae5034"; + sha256 = "085g48jq9hzmlcxg122n0c4pi41sc1nn2qpx1vrl2jfa8crsppa5"; + } + { goPackagePath = "github.com/kylelemons/go-gypsy"; + rev = "08cad365cd28a7fba23bb1e57aa43c5e18ad8bb8"; + sha256 = "1djv7nii3hy451n5jlslk0dblqzb1hia1cbqpdwhnps1g8hqjy8q"; + } + { goPackagePath = "github.com/lib/pq"; + rev = "ba5d4f7a35561e22fbdf7a39aa0070f4d460cfc0"; + sha256 = "1mfbqw9g00bk24bfmf53wri5c2wqmgl0qh4sh1qv2da13a7cwwg3"; + } + { goPackagePath = "github.com/mattn/go-sqlite3"; + rev = "2acfafad5870400156f6fceb12852c281cbba4d5"; + sha256 = "1rpgil3w4hh1cibidskv1js898hwz83ps06gh0hm3mym7ki8d5h7"; + } + { goPackagePath = "github.com/ziutek/mymysql"; + rev = "0582bcf675f52c0c2045c027fd135bd726048f45"; + sha256 = "0bkc9x8sgqbzgdimsmsnhb0qrzlzfv33fgajmmjxl4hcb21qz3rf"; + } + { goPackagePath = "golang.org/x/net"; + url = "https://go.googlesource.com/net"; + rev = "10c134ea0df15f7e34d789338c7a2d76cc7a3ab9"; + sha256 = "14cbr2shl08gyg85n5gj7nbjhrhhgrd52h073qd14j97qcxsakcz"; + } + ]; + }; + + boulder = let + owner = "letsencrypt"; + repo = "boulder"; + rev = "9c6a1f2adc4c26d925588f5ae366cfd4efb7813a"; + version = "20180129"; + + in pkgs.buildGoPackage rec { + name = "${repo}-${version}"; + + src = pkgs.fetchFromGitHub { + name = "${name}-src"; + inherit rev owner repo; + sha256 = "09kszswrifm9rc6idfaq0p1mz5w21as2qbc8gd5pphrq9cf9pn55"; + }; + + postPatch = '' + # compat for go < 1.8 + sed -i -e 's/time\.Until(\([^)]\+\))/\1.Sub(time.Now())/' \ + test/ocsp/helper/helper.go + + find test -type f -exec sed -i -e '/libpkcs11-proxy.so/ { + s,/usr/local,${pkcs11-proxy}, + }' {} + + + sed -i -r \ + -e '/^def +install/a \ return True' \ + -e 's,exec \./bin/,,' \ + test/startservers.py + + cat ${lib.escapeShellArg snakeOilCerts.ca.key} > test/test-ca.key + cat ${lib.escapeShellArg snakeOilCerts.ca.cert} > test/test-ca.pem + ''; + + # Until vendored pkcs11 is go 1.9 compatible + preBuild = '' + rm -r go/src/github.com/letsencrypt/boulder/vendor/github.com/miekg/pkcs11 + ''; + + # XXX: Temporarily brought back putting the source code in the output, + # since e95f17e2720e67e2eabd59d7754c814d3e27a0b2 was removing that from + # buildGoPackage. + preInstall = '' + mkdir -p $out + pushd "$NIX_BUILD_TOP/go" + while read f; do + echo "$f" | grep -q '^./\(src\|pkg/[^/]*\)/${goPackagePath}' \ + || continue + mkdir -p "$(dirname "$out/share/go/$f")" + cp "$NIX_BUILD_TOP/go/$f" "$out/share/go/$f" + done < <(find . -type f) + popd + ''; + + extraSrcs = map mkGoDep [ + { goPackagePath = "github.com/miekg/pkcs11"; + rev = "6dbd569b952ec150d1425722dbbe80f2c6193f83"; + sha256 = "1m8g6fx7df6hf6q6zsbyw1icjmm52dmsx28rgb0h930wagvngfwb"; + } + ]; + + goPackagePath = "github.com/${owner}/${repo}"; + buildInputs = [ pkgs.libtool ]; + }; + + boulderSource = "${boulder.out}/share/go/src/${boulder.goPackagePath}"; + + softHsmConf = pkgs.writeText "softhsm.conf" '' + 0:/var/lib/softhsm/slot0.db + 1:/var/lib/softhsm/slot1.db + ''; + + snakeOilCerts = import ./snakeoil-certs.nix; + + wfeDomain = "acme-v01.api.letsencrypt.org"; + wfeCertFile = snakeOilCerts.${wfeDomain}.cert; + wfeKeyFile = snakeOilCerts.${wfeDomain}.key; + + siteDomain = "letsencrypt.org"; + siteCertFile = snakeOilCerts.${siteDomain}.cert; + siteKeyFile = snakeOilCerts.${siteDomain}.key; + + # Retrieved via: + # curl -s -I https://acme-v01.api.letsencrypt.org/terms \ + # | sed -ne 's/^[Ll]ocation: *//p' + tosUrl = "https://letsencrypt.org/documents/2017.11.15-LE-SA-v1.2.pdf"; + tosPath = builtins.head (builtins.match "https?://[^/]+(.*)" tosUrl); + + tosFile = pkgs.fetchurl { + url = tosUrl; + sha256 = "0yvyckqzj0b1xi61sypcha82nanizzlm8yqy828h2jbza7cxi26c"; + }; + + resolver = let + message = "You need to define a resolver for the letsencrypt test module."; + firstNS = lib.head config.networking.nameservers; + in if config.networking.nameservers == [] then throw message else firstNS; + + cfgDir = pkgs.stdenv.mkDerivation { + name = "boulder-config"; + src = "${boulderSource}/test/config"; + nativeBuildInputs = [ pkgs.jq ]; + phases = [ "unpackPhase" "patchPhase" "installPhase" ]; + postPatch = '' + sed -i -e 's/5002/80/' -e 's/5002/443/' va.json + sed -i -e '/listenAddress/s/:4000/:80/' wfe.json + sed -i -r \ + -e ${lib.escapeShellArg "s,http://boulder:4000/terms/v1,${tosUrl},g"} \ + -e 's,http://(boulder|127\.0\.0\.1):4000,https://${wfeDomain},g' \ + -e '/dnsResolver/s/127\.0\.0\.1:8053/${resolver}:53/' \ + *.json + if grep 4000 *.json; then exit 1; fi + + # Change all ports from 1909X to 909X, because the 1909X range of ports is + # allocated by startservers.py in order to intercept gRPC communication. + sed -i -e 's/\<1\(909[0-9]\)\>/\1/' *.json + + # Patch out all additional issuer certs + jq '. + {ca: (.ca + {Issuers: + [.ca.Issuers[] | select(.CertFile == "test/test-ca.pem")] + })}' ca.json > tmp + mv tmp ca.json + ''; + installPhase = "cp -r . \"$out\""; + }; + + components = { + gsb-test-srv.args = "-apikey my-voice-is-my-passport"; + gsb-test-srv.waitForPort = 6000; + gsb-test-srv.first = true; + boulder-sa.args = "--config ${cfgDir}/sa.json"; + boulder-wfe.args = "--config ${cfgDir}/wfe.json"; + boulder-ra.args = "--config ${cfgDir}/ra.json"; + boulder-ca.args = "--config ${cfgDir}/ca.json"; + boulder-va.args = "--config ${cfgDir}/va.json"; + boulder-publisher.args = "--config ${cfgDir}/publisher.json"; + boulder-publisher.waitForPort = 9091; + ocsp-updater.args = "--config ${cfgDir}/ocsp-updater.json"; + ocsp-updater.after = [ "boulder-publisher" ]; + ocsp-responder.args = "--config ${cfgDir}/ocsp-responder.json"; + ct-test-srv = {}; + mail-test-srv.args = let + key = "${boulderSource}/test/mail-test-srv/minica-key.pem"; + crt = "${boulderSource}/test/mail-test-srv/minica.pem"; + in + "--closeFirst 5 --cert ${crt} --key ${key}"; + }; + + commonPath = [ softhsm pkgs.mariadb goose boulder ]; + + mkServices = a: b: with lib; listToAttrs (concatLists (mapAttrsToList a b)); + + componentServices = mkServices (name: attrs: let + mkSrvName = n: "boulder-${n}.service"; + firsts = lib.filterAttrs (lib.const (c: c.first or false)) components; + firstServices = map mkSrvName (lib.attrNames firsts); + firstServicesNoSelf = lib.remove "boulder-${name}.service" firstServices; + additionalAfter = firstServicesNoSelf ++ map mkSrvName (attrs.after or []); + needsPort = attrs ? waitForPort; + inits = map (n: "boulder-init-${n}.service") [ "mysql" "softhsm" ]; + portWaiter = { + name = "boulder-${name}"; + value = { + description = "Wait For Port ${toString attrs.waitForPort} (${name})"; + after = [ "boulder-real-${name}.service" "bind.service" ]; + requires = [ "boulder-real-${name}.service" ]; + requiredBy = [ "boulder.service" ]; + serviceConfig.Type = "oneshot"; + serviceConfig.RemainAfterExit = true; + script = let + netcat = "${pkgs.libressl.nc}/bin/nc"; + portCheck = "${netcat} -z 127.0.0.1 ${toString attrs.waitForPort}"; + in "while ! ${portCheck}; do :; done"; + }; + }; + in lib.optional needsPort portWaiter ++ lib.singleton { + name = if needsPort then "boulder-real-${name}" else "boulder-${name}"; + value = { + description = "Boulder ACME Component (${name})"; + after = inits ++ additionalAfter; + requires = inits; + requiredBy = [ "boulder.service" ]; + path = commonPath; + environment.GORACE = "halt_on_error=1"; + environment.SOFTHSM_CONF = softHsmConf; + environment.PKCS11_PROXY_SOCKET = "tcp://127.0.0.1:5657"; + serviceConfig.WorkingDirectory = boulderSource; + serviceConfig.ExecStart = "${boulder}/bin/${name} ${attrs.args or ""}"; + serviceConfig.Restart = "on-failure"; + }; + }) components; + +in { + imports = [ ../resolver.nix ]; + + options.test-support.letsencrypt.caCert = lib.mkOption { + type = lib.types.path; + description = '' + A certificate file to use with the <literal>nodes</literal> attribute to + inject the snakeoil 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; + letsencrypt.caCert = snakeOilCerts.ca.cert; + }; + + # 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.enable = false; + + networking.extraHosts = '' + 127.0.0.1 ${toString [ + "sa.boulder" "ra.boulder" "wfe.boulder" "ca.boulder" "va.boulder" + "publisher.boulder" "ocsp-updater.boulder" "admin-revoker.boulder" + "boulder" "boulder-mysql" wfeDomain + ]} + ${config.networking.primaryIPAddress} ${wfeDomain} ${siteDomain} + ''; + + services.mysql.enable = true; + services.mysql.package = pkgs.mariadb; + + services.nginx.enable = true; + services.nginx.recommendedProxySettings = true; + # This fixes the test on i686 + services.nginx.commonHttpConfig = '' + server_names_hash_bucket_size 64; + ''; + services.nginx.virtualHosts.${wfeDomain} = { + onlySSL = true; + enableACME = false; + sslCertificate = wfeCertFile; + sslCertificateKey = wfeKeyFile; + locations."/".proxyPass = "http://127.0.0.1:80"; + }; + services.nginx.virtualHosts.${siteDomain} = { + onlySSL = true; + enableACME = false; + sslCertificate = siteCertFile; + sslCertificateKey = siteKeyFile; + locations.${tosPath}.extraConfig = "alias ${tosFile};"; + }; + + systemd.services = { + pkcs11-daemon = { + description = "PKCS11 Daemon"; + after = [ "boulder-init-softhsm.service" ]; + before = map (n: "${n}.service") (lib.attrNames componentServices); + wantedBy = [ "multi-user.target" ]; + environment.SOFTHSM_CONF = softHsmConf; + environment.PKCS11_DAEMON_SOCKET = "tcp://127.0.0.1:5657"; + serviceConfig.ExecStart = let + softhsmLib = "${softhsm}/lib/softhsm/libsofthsm.so"; + in "${pkcs11-proxy}/bin/pkcs11-daemon ${softhsmLib}"; + }; + + boulder-init-mysql = { + description = "Boulder ACME Init (MySQL)"; + after = [ "mysql.service" ]; + serviceConfig.Type = "oneshot"; + serviceConfig.RemainAfterExit = true; + serviceConfig.WorkingDirectory = boulderSource; + path = commonPath; + script = "${pkgs.bash}/bin/sh test/create_db.sh"; + }; + + boulder-init-softhsm = { + description = "Boulder ACME Init (SoftHSM)"; + environment.SOFTHSM_CONF = softHsmConf; + serviceConfig.Type = "oneshot"; + serviceConfig.RemainAfterExit = true; + serviceConfig.WorkingDirectory = boulderSource; + preStart = "mkdir -p /var/lib/softhsm"; + path = commonPath; + script = '' + softhsm --slot 0 --init-token \ + --label intermediate --pin 5678 --so-pin 1234 + softhsm --slot 0 --import test/test-ca.key \ + --label intermediate_key --pin 5678 --id FB + softhsm --slot 1 --init-token \ + --label root --pin 5678 --so-pin 1234 + softhsm --slot 1 --import test/test-root.key \ + --label root_key --pin 5678 --id FA + ''; + }; + + boulder = { + description = "Boulder ACME Server"; + after = map (n: "${n}.service") (lib.attrNames componentServices); + wantedBy = [ "multi-user.target" ]; + serviceConfig.Type = "oneshot"; + serviceConfig.RemainAfterExit = true; + script = let + ports = lib.range 8000 8005 ++ lib.singleton 80; + netcat = "${pkgs.libressl.nc}/bin/nc"; + mkPortCheck = port: "${netcat} -z 127.0.0.1 ${toString port}"; + checks = "(${lib.concatMapStringsSep " && " mkPortCheck ports})"; + in "while ! ${checks}; do :; done"; + }; + } // componentServices; + }; +} diff --git a/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.nix b/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.nix new file mode 100644 index 000000000000..3b4a589e4142 --- /dev/null +++ b/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.nix @@ -0,0 +1,69 @@ +{ pkgs ? import <nixpkgs> {} +, lib ? pkgs.lib + +, domains ? [ "acme-v01.api.letsencrypt.org" "letsencrypt.org" ] +}: + +pkgs.runCommand "letsencrypt-snakeoil-ca" { + nativeBuildInputs = [ pkgs.openssl ]; +} '' + addpem() { + local file="$1"; shift + local storeFileName="$(IFS=.; echo "$*")" + + echo -n " " >> "$out" + + # Every following argument is an attribute, so let's recurse and check + # every attribute whether it must be quoted and write it into $out. + while [ -n "$1" ]; do + if expr match "$1" '^[a-zA-Z][a-zA-Z0-9]*$' > /dev/null; then + echo -n "$1" >> "$out" + else + echo -n '"' >> "$out" + echo -n "$1" | sed -e 's/["$]/\\&/g' >> "$out" + echo -n '"' >> "$out" + fi + shift + [ -z "$1" ] || echo -n . >> "$out" + done + + echo " = builtins.toFile \"$storeFileName\" '''" >> "$out" + sed -e 's/^/ /' "$file" >> "$out" + + echo " ''';" >> "$out" + } + + echo '# Generated via mkcert.sh in the same directory.' > "$out" + echo '{' >> "$out" + + openssl req -newkey rsa:4096 -x509 -sha256 -days 36500 \ + -subj '/CN=Snakeoil CA' -nodes -out ca.pem -keyout ca.key + + addpem ca.key ca key + addpem ca.pem ca cert + + ${lib.concatMapStrings (fqdn: let + opensslConfig = pkgs.writeText "snakeoil.cnf" '' + [req] + default_bits = 4096 + prompt = no + default_md = sha256 + req_extensions = req_ext + distinguished_name = dn + [dn] + CN = ${fqdn} + [req_ext] + subjectAltName = DNS:${fqdn} + ''; + in '' + export OPENSSL_CONF=${lib.escapeShellArg opensslConfig} + openssl genrsa -out snakeoil.key 4096 + openssl req -new -key snakeoil.key -out snakeoil.csr + openssl x509 -req -in snakeoil.csr -sha256 -set_serial 666 \ + -CA ca.pem -CAkey ca.key -out snakeoil.pem -days 36500 + addpem snakeoil.key ${lib.escapeShellArg fqdn} key + addpem snakeoil.pem ${lib.escapeShellArg fqdn} cert + '') domains} + + echo '}' >> "$out" +'' diff --git a/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.sh b/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.sh new file mode 100755 index 000000000000..cc7f8ca650dd --- /dev/null +++ b/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env nix-shell +#!nix-shell -p nix bash -i bash +set -e +cd "$(dirname "$0")" +storepath="$(nix-build --no-out-link mkcerts.nix)" +cat "$storepath" > snakeoil-certs.nix diff --git a/nixpkgs/nixos/tests/common/letsencrypt/snakeoil-certs.nix b/nixpkgs/nixos/tests/common/letsencrypt/snakeoil-certs.nix new file mode 100644 index 000000000000..c3d29ab8f163 --- /dev/null +++ b/nixpkgs/nixos/tests/common/letsencrypt/snakeoil-certs.nix @@ -0,0 +1,253 @@ +# Generated via mkcert.sh in the same directory. +{ + ca.key = builtins.toFile "ca.key" '' + -----BEGIN PRIVATE KEY----- + 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 + Gvfq54FbDuB10XP8JdLrsy9Z6GEsmoE= + -----END PRIVATE KEY----- + ''; + ca.cert = builtins.toFile "ca.cert" '' + -----BEGIN CERTIFICATE----- + MIIFATCCAumgAwIBAgIJANydi4uFZr0LMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNV + BAMMC1NuYWtlb2lsIENBMCAXDTE4MDcxMjAwMjIxNloYDzIxMTgwNjE4MDAyMjE2 + WjAWMRQwEgYDVQQDDAtTbmFrZW9pbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP + ADCCAgoCggIBAN91XEL/gfCG7MP2iv0IMO7dMFATmWKskjkpiZ8xm1+B3MSOA7OZ + H0BVKSfatB4KrMzmb5gLM877bLvQV2Tu8M5GLU52Fh9RAhbr9NnbvESPHi3zaP2L + vTnJSpMlkqMxsPzfSB5ciYnpUaM2/9aKxMebAGylYp59hA83rxm9g0KfR3mtgmD2 + 5E5k8kdIjQxiP2IRFYg837GFmhLE3vggsnSsQ5B/HYYcOFOv329lgAWpsAh+Hfl9 + i6VFZqtRJ6Qj6sPFrzcUPyr1wyA4/zgqQt6nZ1FddNtRYSsZQ6kc/nkz0zvCzRFU + 12X09RJsOAKGXvJiUcJ17fbrWr/Manl0xX+3+Ndc1SBG6u9dziBQoqNLhJ9++DRd + Wc+zewyVngk2bJwr2SWAhJWZtMpVyNFEm/wG9rY1BWwn1MivJXRAST3gO5yCwLct + uFB9B2adZVwR3PCtkc2mT1rPmafDjZG69lb0vX1PvGkit0tIdo6KzhUSq5mORYiF + 8jPQNUx5e1gRCbCoUbbdbDS61ymYJbgU++nJizkYA+YZZ+uUzGwsP/t616i3cCF4 + L7npkGhUGcjwUW8hfapyL6B9UO4KO8OZvJL/Q2/Esaq9ILUZQ+ZY/dNHkVvUfxGn + 7f3MkdGYf6phaWFy/qnsWVjb/p31GTDxYpFNIIHvJ5R000+I+imTo3g3AgMBAAGj + UDBOMB0GA1UdDgQWBBQ3vPWzjLmu5krbSpfhBAht9KL3czAfBgNVHSMEGDAWgBQ3 + vPWzjLmu5krbSpfhBAht9KL3czAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA + A4ICAQDF9HyC1ZFN3Ob+JA9Dj5+Rcobi7JIA5F8uW3Q92LfPoVaUGEkBrwJSiTFX + 47zvP/ySBJIpZ9rzHMbJ+1L+eJgczF1uQ91inthCKo1THTPo5TgBrpJj0YAIunsj + 9eH1tBnfWFYdVIDZoTSiwPtgIvglpyuK/eJXEe+FRzubhtdc9w1Hlzox1sd0TQuy + Pl9KFHg7BlFZfCPig1mkB8pfwjBDgVhv5DKJ9cJXh3R5zSoiyuS2b+qYSvw8YTHq + 0WNKWUthb7BVAYE3OmcbOHgUAUjtJ6EIGIB9z/SoLe90CofXLXFR5dppuVLKCMBA + kgL4luBIu7t8mcnN2yzobvcGHy8RVY6F5abCCy6gackLzjOzvH1SYOxP8yN74aKB + ANgcqdWspb8JYoU8lEbA8dhBVrsgBf7XeJlrZvMdcUENlJ2PI0JWr9WvlRAM9rYY + EY1alJqBCp6530Ggd6/f0V64cEqptejUdmN9L0zboxKjQf4LjpUNraGvg8tw/xkY + 4dT1U2HlVnhOyBVkx/tE6zIK/RU16oMqwpjCdfbK/TuWCNc/emJz5PMlp81zm83+ + dExpWwuV4rt6OQbZ/GSatNLJXOw+pkLjaEhnHgrsgI+HqAUXg3ByKol+1e76wN51 + k1ZKpB6mk4kejySGPYBHiJwED0IyXu9gUfalSczXFO4ySAvhCg== + -----END CERTIFICATE----- + ''; + "acme-v01.api.letsencrypt.org".key = builtins.toFile "acme-v01.api.letsencrypt.org.key" '' + -----BEGIN RSA PRIVATE KEY----- + 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 + -----END RSA PRIVATE KEY----- + ''; + "acme-v01.api.letsencrypt.org".cert = builtins.toFile "acme-v01.api.letsencrypt.org.cert" '' + -----BEGIN CERTIFICATE----- + MIIEtDCCApwCAgKaMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNVBAMMC1NuYWtlb2ls + IENBMCAXDTE4MDcxMjAwMjIxN1oYDzIxMTgwNjE4MDAyMjE3WjAnMSUwIwYDVQQD + DBxhY21lLXYwMS5hcGkubGV0c2VuY3J5cHQub3JnMIICIjANBgkqhkiG9w0BAQEF + AAOCAg8AMIICCgKCAgEAvG+sL4q0VkgSClBTn4NkPiUrtXx5oLyZ+CCM1jrQx/xo + tUt5X2S4/7vMnAK/yRLsR7R2PhXO8CZPqJ7B6OfAgaDTgvipJkZYPZQSMP3KOinM + 3WJLssqKh7/HOxZIf0iyUXewrnX5eTAo/CLsUnhBjBD7E99nmQz/leLWSl82sSYD + kO3nUk3/1qJZA8iddb4uH0IEQWcNKev3WoQQzwiVrXBiftlRQOJy5JJXm5m8229M + CpMA1AUWmpdu6sl3/gFFdsDhUFq/a7LFrVyaUCMRIHg9szAB7ZFkixr9umQs8jKw + uo983JHB11h2SirwgfIzHHmyhaWhCt22ucTwEXGhq63LtrzZvLsfP8Ql5S+AuqGT + H0v8meuc784leAjulBZjkpuIFwDnVv9+YeUEbqJeo1hSHrILddora3nkH4E2dJWm + LpqpiPr++GRi+BNgYKW/BQLTJ7C6v+vUs+kdPgYJH5z7oP6f0YZkT0Wkubp/UEz7 + UV2dfjz57d77DYx5rFWGYzJriWR/xltgL1zDpjwjwG1FDpRqwlyYbBFpjQhxI+X0 + aT98m6fCzBDQHDb/+JgvsjTHh6OZatahFAwzFIEfrceDv1BG8sBWIaZGhLzYiWQx + afl8oXbWv1T6I1jpsTlCdCSkWzaJb4ZjxI9Ga1ynVu8F16+GR2a71wKWu7UbZQsC + AwEAATANBgkqhkiG9w0BAQsFAAOCAgEAzeGlFMz1Bo+bbpZDQ60HLdw7qDp3SPJi + x5LYG860yzbh9ghvyc59MIm5E6vB140LRJAs+Xo6VdVSTC4jUA2kI9k1BQsbZKds + XT0RqA7HkqcLS3t3JWFkkKbCshMGZTSZ//hpbaUG1qEAfUfmZw1lAxqSa0kqavbP + awf7k8qHbqcj7WORCdH7fjKAjntEQwIpl1GEkAdCSghOJz2/o9aWmiGZt27OM/sG + MLSrcmL3QBElCjOxg14P8rnsmZ+VEp6MO93otoJ4dJL7fN7vTIh5ThbS384at/4l + 4KK/y7XctUzAtWzhnodjk/NSgrrGX2kseOGOWEM1sZc9xtinHH2tpOMqtLVOkgHD + Lul+TArqgqeoOdEM/9OL64kgOrO/JzxBq+egLUi4wgAul2wmtecKZK1dkwYZHeqW + 74i55yeBp+TTomnPr0ZBns6xKFYldJVzC34OB+2YVDxe8y9XtWtuQOxFw0LQHhNb + zy5aBverWzZFwiIIjJoVHTQq848uKBJec0YILfMinS1Wjif4xqW/IMfi+GFS0oka + sKCGNE/8ur9u/Jm6cbto3f2dtV8/vkhiITQgwzM2jalyuVJ9jyPxG7EvbTvZORgw + pRvBRTd4/eE7I1L+UDe6x8EjR/MrqfF9FWVGOZo4vPTyNbrSWYBh6s9kYy56ds1l + IRxst1BXEfI= + -----END CERTIFICATE----- + ''; + "letsencrypt.org".key = builtins.toFile "letsencrypt.org.key" '' + -----BEGIN RSA PRIVATE KEY----- + MIIJKAIBAAKCAgEAwPvhlwemgPi6919sSD7Pz6l6CRfU1G/fDc0AvsMN/nTmiGND + pqn9ef1CA+RtLtOuPc1LLyEovcfu75/V+6KSgO4k19E2CrFCFwjEOWDGF4DgclT3 + 751WGmFJgzPEfZfhbOrmQfQau86KxAtNZVp9FxcKbuLyQ/sNNxfNMB+7IHbVhwvz + VcndHpYZEP6kdnwvNLP22bouX5q3avxWStln01uZ0BfUm4XwxaUNIU7t0Dv56FK9 + C9hW9AZae0do0BJBWRF7xSwLeDJqn9uZz+sX0X/tIaaSQSBuZySj0He5ZKzdUO0t + px2xTS2Brl3Y2BOJaOE98HubWvdKoslLt4X2rVrMxGa86SmFzcyDL1RSowcP/ruy + y555l7pepL5s4cmMgRBBXj5tXhqUTVOn5WO+JClLk+rtvtAT4rogJmMqEKmMw2t7 + LNy1W9ri/378QG/i3AGaLIL/7GsPbuRO51Sdti4QMVe2zNFze72mzNmj1SXokWy7 + +ZvjUMp55oEjRRsTPUZdNOEHJWy6Os2znuqL7ZpIHCxBG8FKnkCViXRJqAA8bzcE + hR+pLamLIOHlv4kdzJ6phHkSvK68qvbRReUmOjJgSupVBI9jhK+fHay/UWR4zfJQ + ed99H8ZOoiXlrLCVs+VPDynUUKrzF1nYyolNzi/NS4e4AbnfWgyC5JKRpjUCAwEA + AQKCAgB0fNYL+zM3MGxy+2d6KGf6GnuuV3NBlBGY3ACyJT0iNmAdPYXNaVi2tPeP + L+fz1xSa+3uBhEt6Wt/QRrO8g8JZDuawWvl69MpG6yS+2bpY35MbkExkl50sqULd + bncRtIb+3r+EWht099RtR8E9B6TwNhk3G8hO3pB4i+ZwQQcMLo7vSHhmdUYCu2mA + B6UwW/+GmYbMoARz8wj6DDzuS1LPksBCis/r3KqcMue9Dk6gXkOYR7ETIFBEVj1x + ooYS6qIFaHdEajS2JgCUY9LxXR/wdn6lzE0GANSDb+tt34bJzUp+Gdxvvo2SX4Ci + xsUokIpmA2gG7CW3gAPORSFuMu/VYZtvt+owNYlODXRPuGi/eLDknFRB/S4Nx0J0 + WZZq5uTgJdQainyKYtDZALia5X4cc5I2hNetCorG9jNZIsSunbIAG+htx2FI3eqK + jwOUiHE8SCZ6YdXoDQjg2w+g8jeB23eqkPyzunpZphYiKay7VFeLwQEMC2a791ln + +MbHhhpRAc1uAoU2reB2fxKyaPlOfAWVMgUOGlgpVOuEVeMoc1CwjajaFztGG7fI + 8EHNoyAftCdXnTaLZk2KZnnIDHHzFXR62TE1GJFD1fdI1pHAloCbgA4h+Dtwm1Uu + iAEEfvVU/E5wbtAzv6pY32+OKX5kyHAbM5/e918B8ZxmHG1J9QKCAQEA6FwxsRG3 + 526NnZak540yboht5kV12BNBChjmARv/XgZ7o1VsfwjaosErMvasUBcHDEYOC/oE + ZgPAyrMVsYm0xe/5FSIFLJVeYXTr0rmCNhVtBCHx3IS94BCXreNnz0qoEWnb5E09 + Z1O42D0yGcLXklg6QaJfb7EdHh03F3dSVMHyDR3JlAQHRINeuP6LlQpbvRD3adH5 + QWr2M3k+Stuq2OJdG7eUS1dreCxRShLuDjDhiZekdl/TB3LM0prOaWrKBrryN2g6 + mjiasH6I5zRD3LQP5zg57Thb8afHqA4Fb85Frt6ltfFlPTIoxXZ5drVhmRWfXXnQ + POnj8T+w4zVjvwKCAQEA1J4ivyFkCL0JTSY3/PtwAQvBBj3GazzU6P+urWeH74Vh + WK17Ae40iOUHGyy80Db/fVY4VLQTpxvAeG91Gj5Nd/AucXJgOrisabcEz6N/xUs5 + sjJNgXuNKTAgjYBu0bqLXxgZj43zT8JhA6KW7RuYU0PtHMRragz4RbK9NWDaVvJb + xSR5QoVLS00PerUa0SfupEYKCrlSTP6FOM5YNkCuSMt7X6/m9cR0WwVINKvUQBiT + ObrN+KeBmF9awpQQnQOq/GbCl3kf6VyPQqYFhdrWSg52w33c2tBVYrtHJpeXGcin + akw4KKcj4rdU2qxMuuRiD5paagshbLdGsYMTbSzjCwKCAQEAh89DGAyUIcfDLAWd + st0bSfGh0oJsw3NVg3JUFPfpRWqiny/Rr1pcd95RwoLc6h7bdrgHg8aJBZtR9ue/ + WTp0l3CQdGKjBZD0TiAJqevViIjzZAP3Gn3XgPwRu4f75/Pp0eu+o2zl49vSYUk7 + XEU+vIGm4y/leiHaM/y9c5DBZVrKgBIV/NZx7QCfv56/tMgOIK6m/YnFlw/OgP1v + hE9qR0PfSdD98x9QaDf290WjMFYvrL0eWjXd4S+fOcVTude55z8jTXE1N2i4OUpr + +D7bH0d7OBjr+pQDYXZAQyCW2ueEYRYvYu2Jz7/ehrOdgN25AsHZmMgXB1NpcFta + pyJQfwKCAQByoPMwworRH0GVg4Zp8RFYrwKZH9MK29gZ6kc9m/Sw0OND0PvhdZCD + QZ8MKpl9VDl4VHS4TgHOdWrWQ5kJ1g8kG6yeY0C4R/pEYHTKkWaAcucfSHl61qar + TxQt1dFpZz5evXqCZ9CG7tApCo5+NQNx2MxMVyVmHqn3wb66uYXdnHqXlet+Tqji + ZyByUpOrsfC6RjyBvZo+gnZGwxDR5xtPiczxML+/PvRQYk+kfgNHrzgoxqrnZT+8 + a6ReBT/TtzeHLsu4qIfo44slLqcJnIstkBC9ouzgV7PBMCDTEKVZNFH2QDOCz2HM + iHTKFFyl4h1wNhKK24dguor1hyqBENMzAoIBAAQvQHwRWIVlfCMRI170Ls8AXB9Z + MMdZJ37bh6kmJpkV3+HB1ZkKwofHKR9h/3xLt5iYXzqT+/zA4EAsFFs1A93+tkzh + yPrN5iTSJicophZSlA4ObX1hMkgshvl7ZB1fRM5WyiszBOfm8W7eAxaK8nY2oAoP + tI7rioo6CFBNMCGbOl4gEX6YJ4OsVSm+efCRSDDw+3HW8H2YgqufBzAULk1Jcj5t + ZvraXpC5qZ92VtsH0cGA1ovNDAmoOV4AAvtZVpLQsXwaphad/Fbn/ItGrrluvvFC + HuldRzYtl/AQtoirK86LTY3aAmcwVFuiYvDQMzjzkJvVMmRCFZBcUIaz2oI= + -----END RSA PRIVATE KEY----- + ''; + "letsencrypt.org".cert = builtins.toFile "letsencrypt.org.cert" '' + -----BEGIN CERTIFICATE----- + MIIEpzCCAo8CAgKaMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNVBAMMC1NuYWtlb2ls + IENBMCAXDTE4MDcxMjAwMjIxOVoYDzIxMTgwNjE4MDAyMjE5WjAaMRgwFgYDVQQD + DA9sZXRzZW5jcnlwdC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC + AQDA++GXB6aA+Lr3X2xIPs/PqXoJF9TUb98NzQC+ww3+dOaIY0Omqf15/UID5G0u + 0649zUsvISi9x+7vn9X7opKA7iTX0TYKsUIXCMQ5YMYXgOByVPfvnVYaYUmDM8R9 + l+Fs6uZB9Bq7zorEC01lWn0XFwpu4vJD+w03F80wH7sgdtWHC/NVyd0elhkQ/qR2 + fC80s/bZui5fmrdq/FZK2WfTW5nQF9SbhfDFpQ0hTu3QO/noUr0L2Fb0Blp7R2jQ + EkFZEXvFLAt4Mmqf25nP6xfRf+0hppJBIG5nJKPQd7lkrN1Q7S2nHbFNLYGuXdjY + E4lo4T3we5ta90qiyUu3hfatWszEZrzpKYXNzIMvVFKjBw/+u7LLnnmXul6kvmzh + yYyBEEFePm1eGpRNU6flY74kKUuT6u2+0BPiuiAmYyoQqYzDa3ss3LVb2uL/fvxA + b+LcAZosgv/saw9u5E7nVJ22LhAxV7bM0XN7vabM2aPVJeiRbLv5m+NQynnmgSNF + GxM9Rl004QclbLo6zbOe6ovtmkgcLEEbwUqeQJWJdEmoADxvNwSFH6ktqYsg4eW/ + iR3MnqmEeRK8rryq9tFF5SY6MmBK6lUEj2OEr58drL9RZHjN8lB5330fxk6iJeWs + sJWz5U8PKdRQqvMXWdjKiU3OL81Lh7gBud9aDILkkpGmNQIDAQABMA0GCSqGSIb3 + DQEBCwUAA4ICAQAkx3jcryukAuYP7PQxMy3LElOl65ZFVqxDtTDlr7DvAkWJzVCb + g08L6Tu+K0rKh2RbG/PqS0+8/jBgc4IwSOPfDDAX+sinfj0kwXG34WMzB0G3fQzU + 2BMplJDOaBcNqHG8pLP1BG+9HAtR/RHe9p2Jw8LG2qmZs6uemPT/nCTNoyIL4oxh + UncjETV4ayCHDKD1XA7/icgddYsnfLQHWuIMuCrmQCHo0uQAd7qVHfUWZ+gcsZx0 + jTNCcaI8OTS2S65Bjaq2HaM7GMcUYNUD2vSyNQeQbha4ZeyZ9bPyFzznPMmrPXQe + MJdkbJ009RQIG9As79En4m+l+/6zrdx4DNdROqaL6YNiSebWMnuFHpMW/rCnhrT/ + HYadijHOiJJGj9tWSdC4XJs7fvZW3crMPUYxpOvl01xW2ZlgaekILi1FAjSMQVoV + NhWstdGCKJdthJqLL5MtNdfgihKcmgkJqKFXTkPv7sgAQCopu6X+S+srCgn856Lv + 21haRWZa8Ml+E0L/ticT8Fd8Luysc6K9TJ4mT8ENC5ywvgDlEkwBD3yvINXm5lg1 + xOIxv/Ye5gFk1knuM7OzpUFBrXUHdVVxflCUqNAhFPbcXwjgEQ+A+S5B0vI6Ohue + ZnR/wuiou6Y+Yzh8XfqL/3H18mGDdjyMXI1B6l4Judk000UVyr46cnI7mw== + -----END CERTIFICATE----- + ''; +} diff --git a/nixpkgs/nixos/tests/common/resolver.nix b/nixpkgs/nixos/tests/common/resolver.nix new file mode 100644 index 000000000000..6be8d1d18e62 --- /dev/null +++ b/nixpkgs/nixos/tests/common/resolver.nix @@ -0,0 +1,141 @@ +# This module automatically discovers zones in BIND and NSD NixOS +# configurations and creates zones for all definitions of networking.extraHosts +# (except those that point to 127.0.0.1 or ::1) within the current test network +# and delegates these zones using a fake root zone served by a BIND recursive +# name server. +{ config, nodes, pkgs, lib, ... }: + +{ + options.test-support.resolver.enable = lib.mkOption { + type = lib.types.bool; + default = true; + internal = true; + description = '' + Whether to enable the resolver that automatically discovers zone in the + test network. + + This option is <literal>true</literal> by default, because the module + defining this option needs to be explicitly imported. + + The reason this option exists is for the + <filename>nixos/tests/common/letsencrypt</filename> module, which + needs that option to disable the resolver once the user has set its own + resolver. + ''; + }; + + config = lib.mkIf config.test-support.resolver.enable { + networking.firewall.enable = false; + services.bind.enable = true; + services.bind.cacheNetworks = lib.mkForce [ "any" ]; + services.bind.forwarders = lib.mkForce []; + services.bind.zones = lib.singleton { + name = "."; + file = let + addDot = zone: zone + lib.optionalString (!lib.hasSuffix "." zone) "."; + mkNsdZoneNames = zones: map addDot (lib.attrNames zones); + mkBindZoneNames = zones: map (zone: addDot zone.name) zones; + getZones = cfg: mkNsdZoneNames cfg.services.nsd.zones + ++ mkBindZoneNames cfg.services.bind.zones; + + getZonesForNode = attrs: { + ip = attrs.config.networking.primaryIPAddress; + zones = lib.filter (zone: zone != ".") (getZones attrs.config); + }; + + zoneInfo = lib.mapAttrsToList (lib.const getZonesForNode) nodes; + + # A and AAAA resource records for all the definitions of + # networking.extraHosts except those for 127.0.0.1 or ::1. + # + # The result is an attribute set with keys being the host name and the + # values are either { ipv4 = ADDR; } or { ipv6 = ADDR; } where ADDR is + # the IP address for the corresponding key. + recordsFromExtraHosts = let + getHostsForNode = lib.const (n: n.config.networking.extraHosts); + allHostsList = lib.mapAttrsToList getHostsForNode nodes; + allHosts = lib.concatStringsSep "\n" allHostsList; + + reIp = "[a-fA-F0-9.:]+"; + reHost = "[a-zA-Z0-9.-]+"; + + matchAliases = str: let + matched = builtins.match "[ \t]+(${reHost})(.*)" str; + continue = lib.singleton (lib.head matched) + ++ matchAliases (lib.last matched); + in if matched == null then [] else continue; + + matchLine = str: let + result = builtins.match "[ \t]*(${reIp})[ \t]+(${reHost})(.*)" str; + in if result == null then null else { + ipAddr = lib.head result; + hosts = lib.singleton (lib.elemAt result 1) + ++ matchAliases (lib.last result); + }; + + skipLine = str: let + rest = builtins.match "[^\n]*\n(.*)" str; + in if rest == null then "" else lib.head rest; + + getEntries = str: acc: let + result = matchLine str; + next = getEntries (skipLine str); + newEntry = acc ++ lib.singleton result; + continue = if result == null then next acc else next newEntry; + in if str == "" then acc else continue; + + isIPv6 = str: builtins.match ".*:.*" str != null; + loopbackIps = [ "127.0.0.1" "::1" ]; + filterLoopback = lib.filter (e: !lib.elem e.ipAddr loopbackIps); + + allEntries = lib.concatMap (entry: map (host: { + inherit host; + ${if isIPv6 entry.ipAddr then "ipv6" else "ipv4"} = entry.ipAddr; + }) entry.hosts) (filterLoopback (getEntries (allHosts + "\n") [])); + + mkRecords = entry: let + records = lib.optional (entry ? ipv6) "AAAA ${entry.ipv6}" + ++ lib.optional (entry ? ipv4) "A ${entry.ipv4}"; + mkRecord = typeAndData: "${entry.host}. IN ${typeAndData}"; + in lib.concatMapStringsSep "\n" mkRecord records; + + in lib.concatMapStringsSep "\n" mkRecords allEntries; + + # All of the zones that are subdomains of existing zones. + # For example if there is only "example.com" the following zones would + # be 'subZones': + # + # * foo.example.com. + # * bar.example.com. + # + # While the following would *not* be 'subZones': + # + # * example.com. + # * com. + # + subZones = let + allZones = lib.concatMap (zi: zi.zones) zoneInfo; + isSubZoneOf = z1: z2: lib.hasSuffix z2 z1 && z1 != z2; + in lib.filter (z: lib.any (isSubZoneOf z) allZones) allZones; + + # All the zones without 'subZones'. + filteredZoneInfo = map (zi: zi // { + zones = lib.filter (x: !lib.elem x subZones) zi.zones; + }) zoneInfo; + + in pkgs.writeText "fake-root.zone" '' + $TTL 3600 + . IN SOA ns.fakedns. admin.fakedns. ( 1 3h 1h 1w 1d ) + ns.fakedns. IN A ${config.networking.primaryIPAddress} + . IN NS ns.fakedns. + ${lib.concatImapStrings (num: { ip, zones }: '' + ns${toString num}.fakedns. IN A ${ip} + ${lib.concatMapStrings (zone: '' + ${zone} IN NS ns${toString num}.fakedns. + '') zones} + '') (lib.filter (zi: zi.zones != []) filteredZoneInfo)} + ${recordsFromExtraHosts} + ''; + }; + }; +} diff --git a/nixpkgs/nixos/tests/common/user-account.nix b/nixpkgs/nixos/tests/common/user-account.nix new file mode 100644 index 000000000000..9cd531a1f96c --- /dev/null +++ b/nixpkgs/nixos/tests/common/user-account.nix @@ -0,0 +1,14 @@ +{ ... }: + +{ users.users.alice = + { isNormalUser = true; + description = "Alice Foobar"; + password = "foobar"; + }; + + users.users.bob = + { isNormalUser = true; + description = "Bob Foobar"; + password = "foobar"; + }; +} diff --git a/nixpkgs/nixos/tests/common/webroot/news-rss.xml b/nixpkgs/nixos/tests/common/webroot/news-rss.xml new file mode 100644 index 000000000000..28e6fa7da1f3 --- /dev/null +++ b/nixpkgs/nixos/tests/common/webroot/news-rss.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<rss xmlns:blogChannel="http://backend.userland.com/blogChannelModule" version="2.0"><channel><title>NixOS News</title><link>https://nixos.org</link><description>News for NixOS, the purely functional Linux distribution.</description><image><title>NixOS</title><url>https://nixos.org/logo/nixos-logo-only-hires.png</url><link>https://nixos.org/</link></image><item><title> + NixOS 18.09 released + </title><link>https://nixos.org/news.html</link><description> + <a href="https://github.com/NixOS/nixos-artwork/blob/master/releases/18.09-jellyfish/jellyfish.png"> + <img class="inline" src="logo/nixos-logo-18.09-jellyfish-lores.png" alt="18.09 Jellyfish logo" with="100" height="87"/> + </a> + NixOS 18.09 “Jellyfish” has been released, the tenth stable release branch. + See the <a href="/nixos/manual/release-notes.html#sec-release-18.09">release notes</a> + for details. You can get NixOS 18.09 ISOs and VirtualBox appliances + from the <a href="nixos/download.html">download page</a>. + For information on how to upgrade from older release branches + to 18.09, check out the + <a href="/nixos/manual/index.html#sec-upgrading">manual section on upgrading</a>. + </description><pubDate>Sat Oct 06 2018 00:00:00 GMT</pubDate></item></channel></rss> diff --git a/nixpkgs/nixos/tests/common/x11.nix b/nixpkgs/nixos/tests/common/x11.nix new file mode 100644 index 000000000000..c5a7c165d126 --- /dev/null +++ b/nixpkgs/nixos/tests/common/x11.nix @@ -0,0 +1,12 @@ +{ services.xserver.enable = true; + + # Automatically log in. + services.xserver.displayManager.auto.enable = true; + + # Use IceWM as the window manager. + services.xserver.windowManager.default = "icewm"; + services.xserver.windowManager.icewm.enable = true; + + # Don't use a desktop manager. + services.xserver.desktopManager.default = "none"; +} |