aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@debian.org>2021-02-22 03:30:32 +0100
committerGuilhem Moulin <guilhem@debian.org>2021-02-22 03:30:32 +0100
commitd1be19ea9484f4c48af2de54266465d49bb1281d (patch)
tree768da9388a9ea6ed42d8d818a6433a4871a1172e /test
parent847ae99fb1ed73fd77c6ffd30f2c554ab5892fde (diff)
parent3eba02ef820a393bd5781be9f8fcda1611ae7c3d (diff)
Merge tag 'v0.8.0' into debian/latest
Release version 0.8.0
Diffstat (limited to 'test')
-rwxr-xr-xtest260
1 files changed, 260 insertions, 0 deletions
diff --git a/test b/test
new file mode 100755
index 0000000..81d910c
--- /dev/null
+++ b/test
@@ -0,0 +1,260 @@
+#!/bin/bash
+
+#----------------------------------------------------------------------
+# ACME client written with process isolation and minimal privileges in mind
+# (test suite)
+# Copyright © 2015-2021 Guilhem Moulin <guilhem@fripost.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#----------------------------------------------------------------------
+
+set -ue
+PATH="/usr/bin:/bin"
+export PATH
+
+usage() {
+ local rv="${1-0}"
+ echo "Usage: $0 [--deb|--dev] [TEST..]" >&2
+ exit $rv
+}
+
+# Setup: for any subdomain under $DOMAINNAME,
+# http://$subdomain.$DOMAINNAME/.well-known/acme-challenge/$challenge
+# must be routed to this machine.
+# This can be done with a wildcard DNS record and opening tcp/80 in firewall.
+DOMAINNAME="lacme-test.guilhem.org"
+
+MODE="dev"
+DISTRIBUTION="sid"
+BUILDDIR="build/test"
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --deb) MODE="deb"; shift;;
+ --dev) MODE="dev"; shift;;
+ --help|-h) usage 0;;
+ -*) echo "Error: Unknown option $1" >&2; usage 1;;
+ --) shift; break;;
+ *) break;
+ esac
+done
+
+cd "$(dirname -- "$0")"
+declare -a TESTS=()
+if [ $# -eq 0 ]; then
+ # always start with registration, the account key might be new
+ TESTS+=( "register" )
+ for t in tests/*; do
+ if [ "$t" != "tests/register" ] && [ "${t#tests/account-encrypted-}" = "$t" ] && [ -f "$t" ]; then
+ # skip registration and non-interactive tests
+ TESTS+=( "${t#tests/}" )
+ fi
+ done
+else
+ for t in "$@"; do
+ if [ -f "tests/$t" ]; then
+ TESTS+=( "$t" )
+ else
+ echo "Error: '$1': no such test" >&2
+ exit 1
+ fi
+ done
+fi
+
+if [ "$MODE" = "deb" ]; then
+ DISTRIBUTION="$(dpkg-parsechangelog -S Distribution)"
+ [ "$DISTRIBUTION" != "UNRELEASED" ] || DISTRIBUTION="sid"
+ PKG_DESTDIR="${XDG_CACHE_HOME:-"$HOME/.cache"}/build-area"
+fi
+
+ACCOUNT_KEY="$BUILDDIR/account.key"
+mkdir -pv -- "$BUILDDIR"
+if [ ! -f "$ACCOUNT_KEY" ]; then
+ # keep the account key (up to `make clean`) to avoid hitting
+ # rate-liming -- currently 50 registrations per 3h per IP, see
+ # https://letsencrypt.org/docs/staging-environment/
+ echo "Generating account key $ACCOUNT_KEY..." >&2
+ openssl genpkey -algorithm RSA -out "$ACCOUNT_KEY"
+fi
+
+ARCH="$(dpkg-architecture -qDEB_BUILD_ARCH)"
+CHROOT=""
+
+cleanup() {
+ if [ -n "$CHROOT" ]; then
+ schroot -c "$CHROOT" -e
+ fi
+}
+trap cleanup EXIT INT TERM
+
+run() {
+ local t="tests/$1" rootdir version sub
+ if [ ! -f "$t" ]; then
+ echo "Error: '$1': no such test" >&2
+ exit 1
+ fi
+
+ # Don't need to rebuild for each test, but editing the code at the
+ # same time might cause `make install` to rebuild a wrong version
+ make all -- \
+ BUILDDIR="$BUILDDIR" \
+ DESTDIR="" \
+ exec_prefix="/usr" \
+ datadir="/usr/share" \
+ runstatedir="/run" \
+ lacme_www_user=_lacme-www \
+ lacme_www_group=nogroup \
+ lacme_client_user=_lacme-client \
+ lacme_client_group=nogroup \
+ acmeapi_server="https://acme-staging-v02.api.letsencrypt.org/directory"
+
+ CHROOT="$(schroot -c "$DISTRIBUTION-$ARCH-sbuild" -b)"
+ rootdir="/run/schroot/mount/$CHROOT"
+
+ if [ "$MODE" = "deb" ]; then
+ version="$(dpkg-parsechangelog -S Version)"
+ echo "Installing lacme $version into $CHROOT..." >&2
+ install -vt "$rootdir/dev/shm" -m0644 -- \
+ "$PKG_DESTDIR/lacme_${version}_all.deb" \
+ "$PKG_DESTDIR/lacme-accountd_${version}_all.deb"
+ sudo schroot -d"/" -c "$CHROOT" -r -- \
+ env DEBIAN_FRONTEND="noninteractive" apt install -y \
+ "/dev/shm/lacme_${version}_all.deb" \
+ "/dev/shm/lacme-accountd_${version}_all.deb"
+
+ elif [ "$MODE" = "dev" ]; then
+ echo "Installing lacme dev into $CHROOT..." >&2
+ sudo make install -- \
+ BUILDDIR="$BUILDDIR" \
+ DESTDIR="$rootdir" \
+ exec_prefix="$rootdir/usr" \
+ datadir="$rootdir/usr/share" \
+ runstatedir="$rootdir/run"
+ sudo schroot -d"/" -c "$CHROOT" -r -- \
+ env DEBIAN_FRONTEND="noninteractive" apt install -y \
+ adduser \
+ libconfig-tiny-perl \
+ libcrypt-openssl-rsa-perl \
+ libjson-perl \
+ libnet-ssleay-perl \
+ libtimedate-perl \
+ libwww-perl \
+ openssl
+ sudo schroot -d"/" -c "$CHROOT" -r -- \
+ adduser --force-badname --system \
+ --home /nonexistent --no-create-home \
+ --gecos "lacme www user" \
+ --quiet _lacme-www
+ sudo schroot -d"/" -c "$CHROOT" -r -- \
+ adduser --force-badname --system \
+ --home /nonexistent --no-create-home \
+ --gecos "lacme client user" \
+ --quiet _lacme-client
+ fi
+
+ # set up staging environment, see https://letsencrypt.org/docs/staging-environment/
+ sudo install -oroot -groot -m0644 -vt "$rootdir/usr/share/lacme" certs-staging/*.pem
+ sudo install -oroot -groot -m0644 -vT "$BUILDDIR/certs-staging/ca-certificates.crt" \
+ "$rootdir/usr/share/lacme/ca-certificates.crt"
+ sudo schroot -d"/" -c "$CHROOT" -r -- \
+ sed -ri '0,/^#?server\s*=.*/ {s||server = https://acme-staging-v02.api.letsencrypt.org/directory|}' \
+ /etc/lacme/lacme.conf
+
+ # install account key and configure lacme accordingly
+ sudo install -oroot -groot -m0600 -vT -- "$BUILDDIR/account.key" \
+ "$rootdir/etc/lacme/account.key"
+ sudo schroot -d"/" -c "$CHROOT" -r -- \
+ sed -ri '0,\|^#?privkey\s*=.*| {s||privkey = file:/etc/lacme/account.key|}' \
+ /etc/lacme/lacme-accountd.conf
+
+ # use lacme's internal webserver bound to INADDR_ANY port 80
+ sudo schroot -d"/" -c "$CHROOT" -r -- \
+ sed -ri 's|^#?listen\s*=.*|listen = 0.0.0.0|' /etc/lacme/lacme.conf
+
+ # use a sample lacme-certs.conf, with a random subdomain so we can
+ # verify that challenges are answered correctly
+ sub="$(head -c10 /dev/urandom | base32 -w0)"
+ sudo tee "$rootdir/etc/lacme/lacme-certs.conf.d/simpletest-rsa.conf" >/dev/null <<- EOF
+ [simpletest-rsa]
+ certificate-key = /etc/lacme/simpletest.rsa.key
+ certificate-chain = /etc/lacme/simpletest.rsa.crt
+ subject = /CN=${sub,,[A-Z]}.$DOMAINNAME
+ EOF
+ sudo schroot -d"/" -c "$CHROOT" -r -- \
+ openssl genpkey -algorithm RSA -out /etc/lacme/simpletest.rsa.key
+
+ # copy test wrapper and unit file
+ local testdir="/dev/shm/lacme.test"
+ sudo install -oroot -groot -m0700 -d -- "$rootdir$testdir"
+ sudo install -oroot -groot -m0755 -T -- /dev/stdin "$rootdir$testdir/run" <<-EOF
+ STDERR="$testdir/stderr"
+ touch "\$STDERR"
+ fail() {
+ set +x
+ local rv=\$? i
+ if [ \$rv -eq 0 ]; then rv=1; fi
+ if [ -s "\$STDERR" ]; then
+ echo "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"
+ cat <"\$STDERR" >&2
+ echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
+ fi
+ [ \$# -eq 0 ] || echo "Error: \$*" >&2
+ exit \$rv
+ }
+ grepstderr() {
+ grep "\$@" <"\$STDERR" || fail
+ }
+ ngrepstderr() {
+ ! grep "\$@" <"\$STDERR" || fail
+ }
+ set -x
+ EOF
+ sudo tee -a "$rootdir$testdir/run" >/dev/null <"$t"
+
+ sudo schroot -d"/" -c "$CHROOT" -r -- env -i \
+ USER="root" \
+ HOME="/root" \
+ SHELL="/bin/sh" \
+ LOGNAME="root" \
+ TERM="$TERM" \
+ PATH="/usr/sbin:/usr/bin:/sbin:/bin" \
+ DOMAINNAME="$DOMAINNAME" \
+ sh -ue "$testdir/run" || return $?
+}
+
+RV=0
+declare -a PASSED=() FAILED=()
+for t in "${TESTS[@]}"; do
+ run "$t" && rv=0 || rv=$?
+ if [ -n "$CHROOT" ]; then
+ # clean up
+ schroot -c "$CHROOT" -e
+ CHROOT=""
+ fi
+ if [ $rv -eq 0 ]; then
+ PASSED+=( "$t" )
+ else
+ FAILED+=( "$t" )
+ RV=$rv
+ break # stop at the first failure
+ fi
+done
+
+echo >&2
+echo "================================================================================" >&2
+
+echo "PASSED: ${PASSED[*]:-"(none)"}" >&2
+if [ ${#FAILED[@]} -gt 0 ]; then
+ echo "FAILED: ${FAILED[*]}" >&2
+fi
+exit $RV