TestScript

The following script can be used to assist with SRU verification of the Certbot family of packages:

#!/bin/bash

# This script tests Certbot packages in proposed-updates repos on Ubuntu. You
# can use the script to test the Certbot packages found in other repositories
# by installing them manually and running this script with the environment
# variable CERTBOT_PREINSTALLED=1.
#
# WARNING: It runs as root and makes many global modifications to the system it
# is run on so it should only be run on a machine temporarily set up for
# testing.

set -eo pipefail
cd ~

if test "$(id -u)" -ne "0"; then
    echo "Must run as root to install packages and use Docker." >&2
    exit 1
fi

apt-get update
apt-get install docker.io gawk gcc git libffi-dev lsb-release net-tools psmisc python3-dev wget -y

wget https://github.com/docker/compose/releases/download/1.15.0-rc1/docker-compose-Linux-x86_64 -O /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

# Add a replacement for coverage which is a tool used by upstream devs. This
# dummy script is a noop unless asked to run Certbot.
cat << EOF > /usr/local/bin/coverage
#!/bin/bash -e
if [ "\$1" != "run" ]; then
    exit 0
fi

while [ "\$1" != "\$(command -v certbot)" ]; do
    shift 1
done

"\$@"
EOF
chmod +x /usr/local/bin/coverage

codename=$(lsb_release -a 2>/dev/null | grep Codename | cut -f2)
if [ "$CERTBOT_PREINSTALLED" != 1 ]; then
    echo "deb http://archive.ubuntu.com/ubuntu/ $codename-proposed restricted main multiverse universe" > /etc/apt/sources.list.d/proposed.list
    echo "Package: *" > /etc/apt/preferences.d/proposed-updates
    echo "Pin: release a=$codename-proposed" >> /etc/apt/preferences.d/proposed-updates
    echo "Pin-Priority: 400" >> /etc/apt/preferences.d/proposed-updates
    apt-get update

    if [ "$codename" = "xenial" ]; then
        apt-get install -y \
            certbot/$codename-proposed \
            letsencrypt/$codename-proposed \
            python-acme/$codename-proposed \
            python-certbot-apache/$codename-proposed \
            python-josepy/$codename-proposed \
            python-letsencrypt-apache/$codename-proposed \
            python-letsencrypt/$codename-proposed
    else
        apt-get install -y \
            certbot/$codename-proposed \
            letsencrypt/$codename-proposed \
            python3-acme/$codename-proposed \
            python3-certbot-apache/$codename-proposed \
            python3-josepy/$codename-proposed
    fi
fi
service apache2 stop

if ! certbot plugins | grep apache; then
    echo "Certbot can't find the Apache plugin!" >&2
    exit 1
fi

if [ "$codename" = "xenial" ]; then
    cat << EOF > shim_test.py
import acme.jose
from acme.jose import b64 as acme_b64
import certbot
import certbot_apache
import josepy
from josepy import b64 as jose_b64
import letsencrypt
import letsencrypt_apache

assert acme.jose is josepy
assert acme.jose.RS512 is josepy.RS512
assert acme.jose.b64 is josepy.b64
assert acme.jose.b64.b64decode is josepy.b64.b64decode
assert acme_b64 is jose_b64
assert acme_b64.b64decode is jose_b64.b64decode
assert letsencrypt is certbot
assert letsencrypt_apache is certbot_apache
EOF
    python shim_test.py
else
    if [ "$CERTBOT_PREINSTALLED" != 1 ]; then
        apt-get install python3-certbot-nginx/$codename-proposed -y
    fi
    service nginx stop

    if ! certbot plugins | grep nginx; then
        echo "Certbot can't find the nginx plugin!" >&2
        exit 1
    fi
fi

if [ "$(realpath $(command -v letsencrypt))" != "$(command -v certbot)" ]; then
    echo "letsencrypt is not a symlink to Certbot!" >&2
    exit 1
fi

if ! grep '^max-log-backups = 0$' /etc/letsencrypt/cli.ini; then
    echo "Certbot's built in log rotation is not disabled!" >&2
    exit 1
fi

if ! systemctl is-enabled certbot.timer; then
    echo "Certbot's systemd timer is not enabled!" >&2
    exit 1
fi

if [ ! -f /etc/cron.d/certbot ]; then
    echo "Certbot's cron tab enteries weren't found!" >&2
    exit 1
fi

certbot_version=$(certbot --version 2>&1 | grep "^certbot" | cut -d " " -f 2)
git clone https://github.com/certbot/certbot --branch v$certbot_version --depth 1
cd certbot

# Is Certbot version 0.40.0 or greater?
#
# TODO: The actual version number to check here is older than 0.40.0, but this works for now
if [ "0.40.0" = $(echo -e "$certbot_version\n0.40.0" | sort -V | head -n1) ]; then
    apt install python3-venv -y
    python3 -m venv venv
    . ./venv/bin/activate
    letsencrypt-auto-source/pieces/pipstrap.py
    tools/pip_install_editable.py certbot-ci
    python -m pytest certbot-ci/certbot_integration_tests -n 4
    # Start pebble running locally for apache-conf-test
    run_acme_server >/dev/null 2>&1 &
    export SERVER='https://localhost:14000/dir'
    until curl -k "$SERVER" 2>/dev/null; do
        echo waiting for pebble to start
        sleep 1
    done
    deactivate
else
    export GOPATH=${GOPATH:-$HOME/gopath}
    export BOULDERPATH=${BOULDERPATH:-$GOPATH/src/github.com/letsencrypt/boulder}
    git clone --branch ${BOULDERBRANCH:-master} --depth=1 https://github.com/letsencrypt/boulder ${BOULDERPATH}
    cd "$BOULDERPATH"
    # Turn TLS-SNI-01 back on in boulder because Certbot's old test scripts test
    # support for TLS-SNI-01 as well as other challenge types.
    sed -i 's/tls-alpn-01/tls-sni-01/g' test/config/ra.json
    cd ~-
    # Newer versions of boulder don't let you use example.org
    sed -i 's/example.org/domain.org/g' tests/boulder-integration.sh
    # Accept either output from openssl about must staple extension
    sed -i "s/grep '1.3.6.1.5.5.7.1.24'/grep -E 'status_request|1\\\.3\\\.6\\\.1\\\.5\\\.5\\\.7\\\.1\\\.24\'/" tests/certbot-boulder-integration.sh
    # Give the nginx config a dummy cert and key to use to satisfy newer versions of nginx.
    sed -i "s/listen 5001 ssl;/listen 5001 ssl;\n    ssl_certificate \/etc\/ssl\/certs\/ssl-cert-snakeoil.pem;\n    ssl_certificate_key \/etc\/ssl\/private\/ssl-cert-snakeoil.key;/" certbot-nginx/tests/boulder-integration.conf.sh

    shutdown=true
    for acme_version in "v1" "v2" ; do
        set +e
        FETCH_OUTPUT=$(tests/boulder-fetch.sh)
        if [ "$?" != 0 ] && echo "$FETCH_OUTPUT" | grep -q 'timed out'; then
            until curl http://localhost:4000/directory 2>/dev/null; do
              echo waiting for boulder
              sleep 1
            done
        fi
        set -e
        BOULDER_INTEGRATION="$acme_version" tests/boulder-integration.sh
        if ${shutdown}; then
            # Reset the server to reset rate limits
            cd "$BOULDERPATH"
            docker-compose down
            cd ~-
            # Leave the server running for apache-conf-test
            shutdown=false
        fi
    done
    # Set SERVER for apache-conf-test using boulder that was left running
    # above.
    export SERVER='http://localhost:4001/directory'
fi

# These tests make the assumption that Apache is not already listening on port
# 443.
sed -i 's/Listen 443/Listen 12345/g' /etc/apache2/ports.conf

if ! certbot-apache/certbot_apache/tests/apache-conf-files/apache-conf-test --debian-modules; then
    echo "Apache tests failed!" >&2
    exit 1
fi

echo "Success!"
echo "Package versions tested:"

if [ "$codename" = "xenial" ]; then
    dpkg-query -W certbot letsencrypt python-josepy python-acme python-certbot python-certbot-apache python-letsencrypt python-letsencrypt-apache
else
    dpkg-query -W certbot letsencrypt python3-josepy python3-acme python3-certbot python3-certbot-apache python3-certbot-nginx
fi

StableReleaseUpdates/Certbot/TestScript (last edited 2020-05-05 20:10:14 by bradmwarren)