From 77a4c15c82a4c16b8d681174e3e874042a1770a9 Mon Sep 17 00:00:00 2001 From: adisbladis Date: Fri, 18 Oct 2019 11:21:50 +0100 Subject: [PATCH 1/5] boulder: init at release-2019-10-13 --- pkgs/tools/admin/boulder/default.nix | 33 ++++++++++++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 ++ 2 files changed, 35 insertions(+) create mode 100644 pkgs/tools/admin/boulder/default.nix diff --git a/pkgs/tools/admin/boulder/default.nix b/pkgs/tools/admin/boulder/default.nix new file mode 100644 index 000000000000..a21a3ebdde11 --- /dev/null +++ b/pkgs/tools/admin/boulder/default.nix @@ -0,0 +1,33 @@ +{ buildGoPackage +, libtool +, fetchFromGitHub +, lib +}: + +let + version = "release-2019-10-13"; + +in buildGoPackage { + + pname = "boulder"; + inherit version; + + goPackagePath = "github.com/letsencrypt/boulder"; + + buildInputs = [ libtool ]; + + src = fetchFromGitHub { + owner = "letsencrypt"; + repo = "boulder"; + rev = version; + sha256 = "0kis23dnjja6jp192rjpv2m9m2zmzfwhs93440nxg354k6fp8jdg"; + }; + + meta = { + homepage = "https://github.com/letsencrypt/boulder"; + description = "An ACME-based CA, written in Go"; + license = [ lib.licenses.mpl20 ]; + maintainers = [ ]; + }; + +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 56830c1fe5fa..c90b71a34f8a 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -765,6 +765,8 @@ in bonfire = callPackage ../tools/misc/bonfire { }; + boulder = callPackage ../tools/admin/boulder { }; + buildbot = with python3Packages; toPythonApplication buildbot; buildbot-ui = with python3Packages; toPythonApplication buildbot-ui; buildbot-full = with python3Packages; toPythonApplication buildbot-full; From 071d181e0a366e5b72b8db4bf0c9980c3a03e671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Baylac-Jacqu=C3=A9?= Date: Thu, 17 Oct 2019 18:07:10 +0200 Subject: [PATCH 2/5] simp_le: 0.9.0 -> 0.16.0 --- pkgs/tools/admin/simp_le/default.nix | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/tools/admin/simp_le/default.nix b/pkgs/tools/admin/simp_le/default.nix index f5be7719d0d2..37f627a18f56 100644 --- a/pkgs/tools/admin/simp_le/default.nix +++ b/pkgs/tools/admin/simp_le/default.nix @@ -2,16 +2,14 @@ python3Packages.buildPythonApplication rec { pname = "simp_le-client"; - version = "0.9.0"; + version = "0.16.0"; src = python3Packages.fetchPypi { inherit pname version; - sha256 = "1yxfznd78zkg2f657v520zj5w4dvq5n594d0kpm4lra8xnpg4zcv"; + sha256 = "17azqlb1xsnh9p0m75apb19j7pramgj00cf5k6fwzz2zqz0x0hpp"; }; postPatch = '' - # drop upper bound of acme requirement - sed -ri "s/'(acme>=[^,]+),<[^']+'/'\1'/" setup.py # drop upper bound of idna requirement sed -ri "s/'(idna)<[^']+'/'\1'/" setup.py substituteInPlace simp_le.py \ From 6ac0e34161f4a3c10787f9556440afc2bd5c719d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Baylac-Jacqu=C3=A9?= Date: Sun, 20 Oct 2019 22:02:48 +0200 Subject: [PATCH 3/5] pebble: init at 2.2.2 --- pkgs/tools/admin/pebble/default.nix | 26 ++++++++++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 ++ 2 files changed, 28 insertions(+) create mode 100644 pkgs/tools/admin/pebble/default.nix diff --git a/pkgs/tools/admin/pebble/default.nix b/pkgs/tools/admin/pebble/default.nix new file mode 100644 index 000000000000..5aa220fd89e6 --- /dev/null +++ b/pkgs/tools/admin/pebble/default.nix @@ -0,0 +1,26 @@ +{ buildGoPackage +, fetchFromGitHub +, lib +}: + +let + version = "v2.2.2"; + pname = "pebble"; +in buildGoPackage { + inherit pname version; + goPackagePath = "github.com/letsencrypt/${pname}"; + + src = fetchFromGitHub { + owner = "letsencrypt"; + repo = pname; + rev = version; + sha256 = "10g6ivdxxp3632wk0gvmp75v9x668kchhmlczbsq8qnsc8sb8pwf"; + }; + + meta = { + homepage = "https://github.com/letsencrypt/boulder"; + description = "A miniature version of Boulder, Pebble is a small RFC 8555 ACME test server not suited for a production CA"; + license = [ lib.licenses.mpl20 ]; + maintainers = [ ]; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index c90b71a34f8a..00cad3c46523 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -939,6 +939,8 @@ in m-cli = callPackage ../os-specific/darwin/m-cli { }; + pebble = callPackage ../tools/admin/pebble { }; + reattach-to-user-namespace = callPackage ../os-specific/darwin/reattach-to-user-namespace {}; skhd = callPackage ../os-specific/darwin/skhd { From 38e84151e04f4b31dd729abb28db4159045bfd41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Baylac-Jacqu=C3=A9?= Date: Fri, 18 Oct 2019 19:11:49 +0200 Subject: [PATCH 4/5] certbot: 0.31.0 -> 0.39.0 Updating: - nixos module to use the new `account_reg.json` file. - use nixpkgs pebble for integration tests. Co-authored-by: Florian Klink Replace certbot-embedded pebble --- nixos/modules/security/acme.nix | 4 +- ...e_artifacts-hardcode-pebble-location.patch | 24 ++++++++++++ pkgs/tools/admin/certbot/default.nix | 38 +++++++++++++++---- 3 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 pkgs/tools/admin/certbot/0001-pebble_artifacts-hardcode-pebble-location.patch diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix index b321c04e574c..e35ea0c7b927 100644 --- a/nixos/modules/security/acme.nix +++ b/nixos/modules/security/acme.nix @@ -69,9 +69,9 @@ let plugins = mkOption { type = types.listOf (types.enum [ "cert.der" "cert.pem" "chain.pem" "external.sh" - "fullchain.pem" "full.pem" "key.der" "key.pem" "account_key.json" + "fullchain.pem" "full.pem" "key.der" "key.pem" "account_key.json" "account_reg.json" ]); - default = [ "fullchain.pem" "full.pem" "key.pem" "account_key.json" ]; + default = [ "fullchain.pem" "full.pem" "key.pem" "account_key.json" "account_reg.json" ]; description = '' Plugins to enable. With default settings simp_le will store public certificate bundle in fullchain.pem, diff --git a/pkgs/tools/admin/certbot/0001-pebble_artifacts-hardcode-pebble-location.patch b/pkgs/tools/admin/certbot/0001-pebble_artifacts-hardcode-pebble-location.patch new file mode 100644 index 000000000000..33f0cd216c1d --- /dev/null +++ b/pkgs/tools/admin/certbot/0001-pebble_artifacts-hardcode-pebble-location.patch @@ -0,0 +1,24 @@ +From 8ddf2697508eca514a0dde4646ad14ac3ba34b2a Mon Sep 17 00:00:00 2001 +From: Florian Klink +Date: Fri, 18 Oct 2019 16:06:50 +0200 +Subject: [PATCH] pebble_artifacts: hardcode pebble location + +--- + certbot-ci/certbot_integration_tests/utils/pebble_artifacts.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/certbot-ci/certbot_integration_tests/utils/pebble_artifacts.py b/certbot-ci/certbot_integration_tests/utils/pebble_artifacts.py +index 2b1557928..d2603c51a 100644 +--- a/certbot-ci/certbot_integration_tests/utils/pebble_artifacts.py ++++ b/certbot-ci/certbot_integration_tests/utils/pebble_artifacts.py +@@ -22,6 +22,7 @@ def fetch(workspace): + + + def _fetch_asset(asset, suffix): ++ return "@pebble@" + asset_path = os.path.join(ASSETS_PATH, '{0}_{1}_{2}'.format(asset, PEBBLE_VERSION, suffix)) + if not os.path.exists(asset_path): + asset_url = ('https://github.com/letsencrypt/pebble/releases/download/{0}/{1}_{2}' +-- +2.23.0 + diff --git a/pkgs/tools/admin/certbot/default.nix b/pkgs/tools/admin/certbot/default.nix index 782af149ed6a..3448e3c81831 100644 --- a/pkgs/tools/admin/certbot/default.nix +++ b/pkgs/tools/admin/certbot/default.nix @@ -1,21 +1,27 @@ -{ stdenv, python3Packages, fetchFromGitHub, dialog }: +{ stdenv, python37Packages, fetchFromGitHub, fetchurl, dialog, autoPatchelfHook, nginx, pebble }: -python3Packages.buildPythonApplication rec { + +python37Packages.buildPythonApplication rec { pname = "certbot"; - version = "0.31.0"; + version = "0.39.0"; src = fetchFromGitHub { owner = pname; repo = pname; rev = "v${version}"; - sha256 = "0rwjxmkpicyc9a5janvj1lfi430nq6ha94nyfgp11ds9fyydbh1s"; + sha256 = "1s32xg2ljz7ci78wc8rqkjvgrz7vprb7fkznrlf9a4blm55pp54c"; }; - propagatedBuildInputs = with python3Packages; [ + patches = [ + ./0001-pebble_artifacts-hardcode-pebble-location.patch + ]; + + propagatedBuildInputs = with python37Packages; [ ConfigArgParse acme configobj cryptography + distro josepy parsedatetime psutil @@ -26,11 +32,19 @@ python3Packages.buildPythonApplication rec { zope_component zope_interface ]; - buildInputs = [ dialog ] ++ (with python3Packages; [ mock gnureadline ]); - patchPhase = '' + buildInputs = [ dialog ] ++ (with python37Packages; [ mock gnureadline ]); + + checkInputs = with python37Packages; [ + pytest_xdist + pytest + dateutil + ]; + + postPatch = '' substituteInPlace certbot/notify.py --replace "/usr/sbin/sendmail" "/run/wrappers/bin/sendmail" substituteInPlace certbot/util.py --replace "sw_vers" "/usr/bin/sw_vers" + substituteInPlace certbot-ci/certbot_integration_tests/utils/pebble_artifacts.py --replace "@pebble@" "${pebble}/bin/pebble" ''; postInstall = '' @@ -40,7 +54,15 @@ python3Packages.buildPythonApplication rec { done ''; - doCheck = !stdenv.isDarwin; # On Hydra Darwin tests fail with "Too many open files". + # tests currently time out, because they're trying to do network access + # Upstream issue: https://github.com/certbot/certbot/issues/7450 + doCheck = false; + + checkPhase = '' + PATH="$out/bin:${nginx}/bin:$PATH" pytest certbot-ci/certbot_integration_tests + ''; + + dontUseSetuptoolsCheck = true; meta = with stdenv.lib; { homepage = src.meta.homepage; From 0c0af28cd59766f961efefea8ad4d14343a82821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Baylac-Jacqu=C3=A9?= Date: Fri, 18 Oct 2019 19:13:04 +0200 Subject: [PATCH 5/5] nixos/tests/letsencrypt: use Pebble instead of Boulder Let's encrypt bumped ACME to V2. We need to update our nixos test to be compatible with this new protocol version. We decided to drop the Boulder ACME server in favor of the more integration test friendly Pebble. - overriding cacert not necessary - this avoids rebuilding lots of packages needlessly - nixos/tests/acme: use pebble's ca for client tests - pebble always generates its own ca which has to be fetched TODO: write proper commit msg :) --- nixos/modules/security/acme.nix | 5 + nixos/tests/acme.nix | 18 +- ...ACME-directory-endpoint-to-directory.patch | 25 + nixos/tests/common/letsencrypt/common.nix | 26 +- nixos/tests/common/letsencrypt/default.nix | 380 ++------------- nixos/tests/common/letsencrypt/mkcerts.nix | 2 +- .../common/letsencrypt/snakeoil-certs.nix | 451 +++++++++--------- 7 files changed, 314 insertions(+), 593 deletions(-) create mode 100644 nixos/tests/common/letsencrypt/0001-Change-ACME-directory-endpoint-to-directory.patch diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix index e35ea0c7b927..e08c7e965eef 100644 --- a/nixos/modules/security/acme.nix +++ b/nixos/modules/security/acme.nix @@ -203,6 +203,11 @@ in description = "Renew ACME Certificate for ${cert}"; after = [ "network.target" "network-online.target" ]; wants = [ "network-online.target" ]; + # simp_le uses requests, which uses certifi under the hood, + # which doesn't respect the system trust store. + # At least in the acme test, we provision a fake CA, impersonating the LE endpoint. + # REQUESTS_CA_BUNDLE is a way to teach python requests to use something else + environment.REQUESTS_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; serviceConfig = { Type = "oneshot"; SuccessExitStatus = [ "0" "1" ]; diff --git a/nixos/tests/acme.nix b/nixos/tests/acme.nix index 8cfdea4a16ef..85d32d109442 100644 --- a/nixos/tests/acme.nix +++ b/nixos/tests/acme.nix @@ -80,7 +80,7 @@ in import ./make-test.nix { client = commonConfig; }; - testScript = {nodes, ...}: + testScript = {nodes, ...}: let newServerSystem = nodes.webserver2.config.system.build.toplevel; switchToNewServer = "${newServerSystem}/bin/switch-to-configuration test"; @@ -91,9 +91,12 @@ in import ./make-test.nix { # get pulled in by the oneshot units. The target units linger after activation, and hence we # can use them to probe that a oneshot fired. It is a bit ugly, but it is the best we can do '' - $client->waitForUnit("default.target"); + $client->start; + $letsencrypt->start; + $acmeStandalone->start; + $letsencrypt->waitForUnit("default.target"); - $letsencrypt->waitForUnit("boulder.service"); + $letsencrypt->waitForUnit("pebble.service"); subtest "can request certificate with HTTPS-01 challenge", sub { $acmeStandalone->waitForUnit("default.target"); @@ -101,15 +104,20 @@ in import ./make-test.nix { $acmeStandalone->waitForUnit("acme-finished-standalone.com.target"); }; + $client->waitForUnit("default.target"); + + $client->succeed('curl https://acme-v02.api.letsencrypt.org:15000/roots/0 > /tmp/ca.crt'); + $client->succeed('curl https://acme-v02.api.letsencrypt.org:15000/intermediate-keys/0 >> /tmp/ca.crt'); + subtest "Can request certificate for nginx service", sub { $webserver->waitForUnit("acme-finished-a.example.com.target"); - $client->succeed('curl https://a.example.com/ | grep -qF "hello world"'); + $client->succeed('curl --cacert /tmp/ca.crt https://a.example.com/ | grep -qF "hello world"'); }; subtest "Can add another certificate for nginx service", sub { $webserver->succeed("/run/current-system/fine-tune/child-1/bin/switch-to-configuration test"); $webserver->waitForUnit("acme-finished-b.example.com.target"); - $client->succeed('curl https://b.example.com/ | grep -qF "hello world"'); + $client->succeed('curl --cacert /tmp/ca.crt https://b.example.com/ | grep -qF "hello world"'); }; ''; } diff --git a/nixos/tests/common/letsencrypt/0001-Change-ACME-directory-endpoint-to-directory.patch b/nixos/tests/common/letsencrypt/0001-Change-ACME-directory-endpoint-to-directory.patch new file mode 100644 index 000000000000..9d4a483dd889 --- /dev/null +++ b/nixos/tests/common/letsencrypt/0001-Change-ACME-directory-endpoint-to-directory.patch @@ -0,0 +1,25 @@ +From c3b4004386074342d22cab5e129c1f7e623f4272 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?F=C3=A9lix=20Baylac-Jacqu=C3=A9?= +Date: Mon, 21 Oct 2019 10:56:13 +0200 +Subject: [PATCH] Change ACME directory endpoint to /directory + +--- + wfe/wfe.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/wfe/wfe.go b/wfe/wfe.go +index e24797f..10d29fb 100644 +--- a/wfe/wfe.go ++++ b/wfe/wfe.go +@@ -39,7 +39,7 @@ const ( + // Note: We deliberately pick endpoint paths that differ from Boulder to + // exercise clients processing of the /directory response + // We export the DirectoryPath so that the pebble binary can reference it +- DirectoryPath = "/dir" ++ DirectoryPath = "/directory" + noncePath = "/nonce-plz" + newAccountPath = "/sign-me-up" + acctPath = "/my-account/" +-- +2.23.0 + diff --git a/nixos/tests/common/letsencrypt/common.nix b/nixos/tests/common/letsencrypt/common.nix index 798a749f7f9b..c530de817bf2 100644 --- a/nixos/tests/common/letsencrypt/common.nix +++ b/nixos/tests/common/letsencrypt/common.nix @@ -1,27 +1,9 @@ -{ lib, nodes, ... }: { +{ lib, nodes, pkgs, ... }: let + letsencrypt-ca = nodes.letsencrypt.config.test-support.letsencrypt.caCert; +in { 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; - }); + security.pki.certificateFiles = [ letsencrypt-ca ]; } diff --git a/nixos/tests/common/letsencrypt/default.nix b/nixos/tests/common/letsencrypt/default.nix index 58d87c64e344..aaf2896f21cb 100644 --- a/nixos/tests/common/letsencrypt/default.nix +++ b/nixos/tests/common/letsencrypt/default.nix @@ -1,6 +1,3 @@ -# 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 @@ -54,277 +51,45 @@ # that it has to be started _before_ the ACME service. { config, pkgs, lib, ... }: + let - softhsm = pkgs.stdenv.mkDerivation rec { - pname = "softhsm"; - version = "1.3.8"; - - src = pkgs.fetchurl { - url = "https://dist.opendnssec.org/source/${pname}-${version}.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"; + wfeDomain = "acme-v02.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"; - }; + pebble = pkgs.pebble.overrideAttrs (attrs: { + # The pebble directory endpoint is /dir when the bouder (official + # ACME server) is /directory. Sadly, this endpoint is hardcoded, + # we have to patch it. + # + # Tried to upstream, that said upstream maintainers rather keep + # this custom endpoint to test ACME clients robustness. See + # https://github.com/letsencrypt/pebble/issues/283#issuecomment-545123242 + patches = [ ./0001-Change-ACME-directory-endpoint-to-directory.patch ]; + }); 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\""; + pebbleConf.pebble = { + listenAddress = "0.0.0.0:443"; + managementListenAddress = "0.0.0.0:15000"; + certificate = snakeOilCerts.${wfeDomain}.cert; + privateKey = snakeOilCerts.${wfeDomain}.key; + httpPort = 80; + tlsPort = 443; + ocspResponderURL = "http://0.0.0.0:4002"; }; - 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; + pebbleConfFile = pkgs.writeText "pebble.conf" (builtins.toJSON pebbleConf); + pebbleDataDir = "/root/pebble"; in { imports = [ ../resolver.nix ]; @@ -352,94 +117,29 @@ in { 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 - ]} + 127.0.0.1 ${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}".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 + pebble = { + enable = true; + description = "Pebble ACME server"; + requires = [ ]; + wantedBy = [ "network.target" ]; + preStart = '' + mkdir ${pebbleDataDir} ''; + script = '' + cd ${pebbleDataDir} + ${pebble}/bin/pebble -config ${pebbleConfFile} + ''; + serviceConfig = { + # Required to bind on privileged ports. + User = "root"; + Group = "root"; + }; }; - - 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/nixos/tests/common/letsencrypt/mkcerts.nix b/nixos/tests/common/letsencrypt/mkcerts.nix index 3b4a589e4142..e7ac2bae46bd 100644 --- a/nixos/tests/common/letsencrypt/mkcerts.nix +++ b/nixos/tests/common/letsencrypt/mkcerts.nix @@ -1,7 +1,7 @@ { pkgs ? import {} , lib ? pkgs.lib -, domains ? [ "acme-v01.api.letsencrypt.org" "letsencrypt.org" ] +, domains ? [ "acme-v02.api.letsencrypt.org" "letsencrypt.org" ] }: pkgs.runCommand "letsencrypt-snakeoil-ca" { diff --git a/nixos/tests/common/letsencrypt/snakeoil-certs.nix b/nixos/tests/common/letsencrypt/snakeoil-certs.nix index c3d29ab8f163..ca4f71ae688a 100644 --- a/nixos/tests/common/letsencrypt/snakeoil-certs.nix +++ b/nixos/tests/common/letsencrypt/snakeoil-certs.nix @@ -2,252 +2,253 @@ { ca.key = builtins.toFile "ca.key" '' -----BEGIN PRIVATE KEY----- - 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 - Gvfq54FbDuB10XP8JdLrsy9Z6GEsmoE= + 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 + Eq4OVTSu/s8gmY94tgbjeOaLUPEPmg== -----END PRIVATE KEY----- ''; ca.cert = builtins.toFile "ca.cert" '' -----BEGIN CERTIFICATE----- - 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 + kgwJ -----END CERTIFICATE----- ''; - "acme-v01.api.letsencrypt.org".key = builtins.toFile "acme-v01.api.letsencrypt.org.key" '' + "acme-v02.api.letsencrypt.org".key = builtins.toFile "acme-v02.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" '' + "acme-v02.api.letsencrypt.org".cert = builtins.toFile "acme-v02.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= + IENBMCAXDTE5MTAxODA3NTQxM1oYDzIxMTkwOTI0MDc1NDEzWjAnMSUwIwYDVQQD + DBxhY21lLXYwMi5hcGkubGV0c2VuY3J5cHQub3JnMIICIjANBgkqhkiG9w0BAQEF + AAOCAg8AMIICCgKCAgEApny0WhfDwEXe6WDTCw8qBuMAPDr88pj6kbhQWfzAW2c0 + TggJEtjs9dktENeTpSl14nnLVMiSYIJPYY3KbOIFQH1qDaOuQ7NaOhj9CdMTm5r9 + bl+CYAyqLIMQ9AAZDhUcQjOy3moiL7ClFHlkFYuEzZBO9DF7hJpfUFIs0Idg50mN + oZh/K/fb4P2skNjfCjjomTRUmZHxT6G00ImSTtSaYbN/WHut1xXwJvOoT1nlEA/P + ghKmJJ9ZuRMSddUJmjL+sT09L8LVkK8CKeHi4r58DHM0D0u8owIFV9qsXd5UvZHa + NgvQ4OAWGukMX+TxRuqkUZkaj84vnNL+ttEMl4jedw0ImzNtCOYehDyTPRkfng5P + LWMSvWbwyP8jDd2578mSbx5BF7ypYX366+vknjIFyZ5WezcC1pscIHxLoEwuhuf+ + knN+kFkLOHeYbqQrU6mxSnu9q0hnNvGUkTP0a/1aLOGRfQ5C/pxpE/Rebi8qfM/O + JFd4mSxGL93JUTXWAItiIeBnQpIne65/Ska9dWynOEfIb0okdet3kfmNHz3zc17d + Z5g4AdOSCgHAlQgFt/Qd8W6xXUe4C5Mfv2ctxRrfQhDwtB6rMByPwzImnciC2h3v + CwD3vS/vjUyWICyhZyi2LZDUQz+sCKBXCYYcYh8ThFO40j5x1OnYMq7XQvyl8QkC + AwEAATANBgkqhkiG9w0BAQsFAAOCAgEAkx0GLPuCvKSLTHxVLh5tP4jxSGG/zN37 + PeZLu3QJTdRdRc8bgeOGXAVEVFbqOLTNTsuY1mvpiv2V6wxR6nns+PIHeLY/UOdc + mOreKPtMU2dWPp3ybec2Jwii6PhAXZJ26AKintmug1psMw7662crR3SCnn85/CvW + 192vhr5gM1PqLBIlbsX0tAqxAwBe1YkxBb9vCq8NVghJlKme49xnwGULMTGs15MW + hIPx6sW93zwrGiTsDImH49ILGF+NcX1AgAq90nG0j/l5zhDgXGJglX+K1xP99X1R + de3I4uoufPa5q+Pjmhy7muL+o4Qt0D0Vm86RqqjTkNPsr7gAJtt66A7TJrYiIoKn + GTIBsgM6egeFLLYQsT0ap/59HJismO2Pjx4Jk/jHOkC8TJsXQNRq1Km76VMBnuc0 + 2CMoD9pb38GjUUH94D4hJK4Ls/gJMF3ftKUyR8Sr/LjE6qU6Yj+ZpeEQP4kW9ANq + Lv9KSNDQQpRTL4LwGLTGomksLTQEekge7/q4J2TQRZNYJ/mxnrBKRcv9EAMgBMXq + Q+7GHtKDv9tJVlMfG/MRD3CMuuSRiT3OVbvMMkFzsPkqxYAP1CqE/JGvh67TzKI+ + MUfXKehA6TKuxrTVqCtoFIfGaqA9IWyoRTtugYq/xssB9ESeEYGeaM1A9Yueqz+h + KkBZO00jHSE= -----END CERTIFICATE----- ''; "letsencrypt.org".key = builtins.toFile "letsencrypt.org.key" '' -----BEGIN RSA PRIVATE KEY----- - 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 -----END RSA PRIVATE KEY----- ''; "letsencrypt.org".cert = builtins.toFile "letsencrypt.org.cert" '' -----BEGIN CERTIFICATE----- MIIEpzCCAo8CAgKaMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNVBAMMC1NuYWtlb2ls - IENBMCAXDTE4MDcxMjAwMjIxOVoYDzIxMTgwNjE4MDAyMjE5WjAaMRgwFgYDVQQD + IENBMCAXDTE5MTAxODA3NTQxNVoYDzIxMTkwOTI0MDc1NDE1WjAaMRgwFgYDVQQD 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== + AQD12l08TLMPf8EF2zu0D/nWz5aYsXJa4WurjIx3ZH6+LmC8rueUs1UqFiCJOYrZ + Sb5QSka5wmpkdxNJkDUHPhL/w0P8Aj0joSbC8GKdjn8+5vEQAuT1iIMD4jMfxkYU + zzBeDt8xtskCzK/5IcC2vaOYKyCCum4Pl+DOzan4XarT6hWh4XAwA5R0B/aM200s + SPZDoyJHler7AU5xG1eU2VdYhfc2ua5s7/E6kM2mzKPJgLkt35bToxLltMdJ2/no + CRSDY+6AwKGPXlM510QkgrzM9cVOUxjJ71IrCOE1Rmi997jFcJpOPaebOty4wovP + 5LewpB5NaOJFxjfDjNOUBuG0ZcONeOEw5usehYzx7dxMvg0ky+201K1d+JzFt5Ns + iJi77t20XSr6JZpmp7Fzo90BoikVnRdLD6LmIt1BmYHDNjs0uUelC6l+HrN7SoNR + VkAwO5ujgkpRMHMfpBO6EfH65Sbstzxh00Cufuj+8xkNDKbUSJrErFm4IZqoW+rx + kricFWwd9xduEX9cPYcyJ3e3siZtERW72qdz4Sf5pxT9IlpoveuMxboctUyvr69C + sLNiS8vMpimhSb0PUpyfp3w5/GXaIJpj0KQyvn/onWnXBxN1w3shVD8MUF5MNq7J + ZvJmQ7+U+hmhqRbJc7H1L22AKXOEWY2BGRm/3A35CC40NwIDAQABMA0GCSqGSIb3 + DQEBCwUAA4ICAQBbJwE+qc0j6JGHWe0TGjv1viJU3WuyJkMRi+ejx0p/k7Ntp5An + 2wLC7b/lVP/Nh+PKY/iXWn/BErv2MUo4POc1g8svgxsmMMh5KGGieIfGs7xT+JMH + dzZZM+pUpIB5fEO5JfjiOEOKDdAvRSs0mTAVYZEokGkXSNWyylvEaA16mHtMgPjo + Lm75d0O66RfJDdd/hTl8umGpF7kEGW1qYk2QmuPr7AqOa8na7olL5fMPh6Q7yRqx + GIS9JKQ0fWl8Ngk09WfwUN/kEMcp9Jl5iunNRkbpUJIM/lHFkSA7yOFFL+dVWzd4 + 2r+ddJXTFzW8Rwt65l8SV2MEhijEamKva3mqKLIRWxDsfFVT1T04LWFtnzMW4Z29 + UHF9Pi7XSyKz0Y/Lz31mNTkjJYbOvbnwok8lc3wFWHc+lummZk8IkCq8xfqzwmwX + Ow6EV+Q6VaQpOHumQZ12pBBLtL8DyDhWaRUgVy2vYpwYsMYa5BFMcKCynjlSewo9 + G2hNoW45cQZP1qHltRR9Xad7SaP7iTETDCiR7AWOqSpDipSh9eMfVW97ZbSfz+vl + xl8PZEZMTRIIRVXsPP+E8gtDUhUQp2+Vcz8r6q71qslXM09xl/501uaNjCc3hH2R + iw2N77Lho1F3FrBbHdML3RYHZI55eC9iQw6R4S+R4b+iWLJoHzHrW61itg== -----END CERTIFICATE----- ''; }