diff options
Diffstat (limited to 'test')
| -rwxr-xr-x | test | 237 | 
1 files changed, 237 insertions, 0 deletions
| @@ -0,0 +1,237 @@ +#!/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" ] && [ -f "$t" ]; then +            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" +elif [ "$MODE" = "dev" ]; then +    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 +fi + +ACCOUNT_KEY="$BUILDDIR/account.key" +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 + +    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 -- perl -pi -e \ +        's|\b\Qhttps://acme-v02.api.letsencrypt.org/\E\b|https://acme-staging-v02.api.letsencrypt.org/|' \ +        "/usr/libexec/lacme/client" "/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 +            echo "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" +		    cat <"\$STDERR" >&2 +            echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" +		    [ \$# -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 $? + +    # clean up +    schroot -c "$CHROOT" -e +    CHROOT="" +} + +for t in "${TESTS[@]}"; do +    if ! run "$t"; then +        echo "FAILED: $t" >&2 +        exit 1 +    fi +done | 
