diff --git a/docker-compose.yml b/docker-compose.yml index f4b3567..cbe52e2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,8 +7,8 @@ services: environment: # with Go 1.13.x which defaults TLS 1.3 to on GODEBUG: "tls13=1" - # don't reuse authorizations (breaks testing force renew) - PEBBLE_AUTHZREUSE: 0 + # Don't re-use authorisations (breaks force renew test scripts) + # PEBBLE_AUTHZREUSE: "0" ports: - 14000:14000 # HTTPS ACME API - 15000:15000 # HTTPS Management API @@ -23,16 +23,60 @@ services: networks: acmenet: ipv4_address: 10.30.50.3 - getssl: + getssl-ubuntu18: build: context: . - dockerfile: test/Dockerfile-ubuntu - container_name: getssl + dockerfile: test/Dockerfile-ubuntu18 + container_name: getssl-ubuntu18 volumes: - .:/getssl + environment: + GETSSL_HOST: ubuntu18.getssl.test + GETSSL_IP: 10.30.50.4 + NGINX_CONFIG: /etc/nginx/sites-enabled/default networks: acmenet: ipv4_address: 10.30.50.4 + aliases: + - ubuntu18.getssl.test + - a.ubuntu18.getssl.test + - b.ubuntu18.getssl.test + - c.ubuntu18.getssl.test + - d.ubuntu18.getssl.test + - e.ubuntu18.getssl.test + - f.ubuntu18.getssl.test + - g.ubuntu18.getssl.test + - h.ubuntu18.getssl.test + - i.ubuntu18.getssl.test + - j.ubuntu18.getssl.test + - k.ubuntu18.getssl.test + getssl-centos6: + build: + context: . + dockerfile: test/Dockerfile-centos6 + container_name: getssl-centos6 + volumes: + - .:/getssl + environment: + GETSSL_HOST: centos6.getssl.test + GETSSL_IP: 10.30.50.5 + NGINX_CONFIG: /etc/nginx/conf.d/default.conf + networks: + acmenet: + ipv4_address: 10.30.50.5 + aliases: + - centos6.getssl.test + - a.centos6.getssl.test + - b.centos6.getssl.test + - c.centos6.getssl.test + - d.centos6.getssl.test + - e.centos6.getssl.test + - f.centos6.getssl.test + - g.centos6.getssl.test + - h.centos6.getssl.test + - i.centos6.getssl.test + - j.centos6.getssl.test + - k.centos6.getssl.test networks: acmenet: diff --git a/test/1-simple-http01.bats b/test/1-simple-http01.bats new file mode 100644 index 0000000..40416b2 --- /dev/null +++ b/test/1-simple-http01.bats @@ -0,0 +1,28 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +# This is run for every test +setup() { + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt +} + + +@test "Create new certificate using HTTP-01 verification" { + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate + assert_success +} + + +@test "Force renewal of certificate using HTTP-01" { + #!FIXME test certificate has been updated + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success + cleanup_environment +} diff --git a/test/2-simple-dns01.bats b/test/2-simple-dns01.bats new file mode 100644 index 0000000..e1a37ec --- /dev/null +++ b/test/2-simple-dns01.bats @@ -0,0 +1,28 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +# This is run for every test +setup() { + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt +} + + +@test "Create new certificate using DNS-01 verification" { + CONFIG_FILE="getssl-dns01.cfg" + setup_environment + init_getssl + create_certificate + assert_success +} + + +@test "Force renewal of certificate using DNS-01" { + #!FIXME test certificate has been updated + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success + cleanup_environment +} diff --git a/test/4-more-than-10-hosts.bats b/test/4-more-than-10-hosts.bats new file mode 100644 index 0000000..0493197 --- /dev/null +++ b/test/4-more-than-10-hosts.bats @@ -0,0 +1,39 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +# This is run for every test +setup() { + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt +} + + +@test "Create certificates for more than 10 hosts using HTTP-01 verification" { + CONFIG_FILE="getssl-http01-10-hosts.cfg" + setup_environment + + # Add 11 hosts to DNS (also need to be added as aliases in docker-compose.yml) + for prefix in a b c d e f g h i j k; do + curl -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + done + + init_getssl + create_certificate + assert_success +} + + +@test "Force renewal of more than 10 certificates using HTTP-01" { + #!FIXME test certificate has been updated + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success + + # Remove all the dns aliases + cleanup_environment + for prefix in a b c d e f g h i j k; do + curl -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/del-a + done +} diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 new file mode 100644 index 0000000..f370a0b --- /dev/null +++ b/test/Dockerfile-centos6 @@ -0,0 +1,22 @@ +FROM centos:centos6 + +# Update and install required software +RUN yum -y update +RUN yum -y install epel-release +RUN yum -y install git curl dnsutils wget nginx + +WORKDIR /root +RUN mkdir /etc/nginx/pki +RUN mkdir /etc/nginx/pki/private +COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf + +# BATS (Bash Automated Testings) +RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/jasonkarns/bats-support /bats-support +RUN git clone https://github.com/jasonkarns/bats-assert-1 /bats-assert +RUN /bats-core/install.sh /usr/local + +EXPOSE 80 443 + +# Run eternal loop - for testing +CMD ["/bin/bash", "-c", "while :; do sleep 10; done"] diff --git a/test/Dockerfile-rhel6 b/test/Dockerfile-rhel6 deleted file mode 100644 index 019da84..0000000 --- a/test/Dockerfile-rhel6 +++ /dev/null @@ -1,22 +0,0 @@ -FROM roboxes/rhel6 -# FROM centos:centos6 -# bionic = latest 18 version - -# Update and install required software -RUN yum -y update -RUN yum -y install epel-release -RUN yum -y install git curl dnsutils wget # nginx-light - -WORKDIR /root -#RUN mkdir /etc/nginx/pki -#RUN mkdir /etc/nginx/pki/private -#COPY ./test/test-config/nginx-ubuntu-sites-enabled-default /etc/nginx/sites-enabled/default - -# BATS (Bash Automated Testings) -# RUN git clone https://github.com/bats-core/bats-core.git -# RUN bats-core/install.sh /usr/local - -EXPOSE 80 443 - -# Run eternal loop - for testing -CMD ["/bin/bash", "-c", "while :; do sleep 10; done"] diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu18 similarity index 66% rename from test/Dockerfile-ubuntu rename to test/Dockerfile-ubuntu18 index b0f09f8..6dd92c6 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu18 @@ -1,8 +1,8 @@ -FROM ubuntu:xenial +FROM ubuntu:bionic # bionic = latest 18 version # Update and install required software -RUN apt-get update +RUN apt-get update --fix-missing # TODO work out why default version of awk fails RUN apt-get install -y git curl dnsutils wget gawk nginx-light # linux-libc-dev make gcc binutils RUN apt-get install -y vim dos2unix # for debugging @@ -14,8 +14,10 @@ RUN mkdir /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default # BATS (Bash Automated Testings) -# RUN git clone https://github.com/bats-core/bats-core.git -# RUN bats-core/install.sh /usr/local +RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/jasonkarns/bats-support /bats-support +RUN git clone https://github.com/jasonkarns/bats-assert-1 /bats-assert +RUN /bats-core/install.sh /usr/local EXPOSE 80 443 diff --git a/test/README.md b/test/README.md index 086c58a..9157aa8 100644 --- a/test/README.md +++ b/test/README.md @@ -12,21 +12,29 @@ docker-compose -f "docker-compose.yml" up -d --build Run the tests ```sh -docker exec -it getssl /getssl/test/run-test.sh +docker exec -it getssl bats /getssl/test ``` -Debug (need to set `CURL_CA_BUNDLE` as pebble uses a local certificate, +Run individual test + +```sh +docker exec -it getssl bats /getssl/test/ +``` + +Debug (uses helper script to set `CURL_CA_BUNDLE` as pebble uses a local certificate, otherwise you get a "unknown API version" error) ```sh -docker exec -it getssl /bin/bash -export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt -/getssl/getssl -d getssl +docker exec -it getssl- /getssl/test/run-test.sh ` + +eg. + +```sh +docker exec -it getssl-ubuntu18 /getssl/test/run-test.sh getssl-http01.cfg ``` ## TODO -1. Move to BATS (bash automated testing) instead of run-test.sh -2. Test RHEL6, Debian as well -3. Test SSH, SFTP -4. Test wildcards +1. Test RHEL6, Debian as well +2. Test SSH, SFTP +3. Test wildcards diff --git a/test/run-test.sh b/test/run-test.sh index 8051922..b6f7c72 100644 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -1,43 +1,14 @@ -#! /bin/bash +#!/usr/bin/env bash -set -e +# This runs getssl outside of the BATS framework for debugging, etc, against pebble +# Usage: /getssl/test/run-test.sh getssl-http01.cfg -# Test setup -if [[ -d /root/.getssl ]]; then - rm -r /root/.getssl -fi +CONFIG_FILE=$1 +source /getssl/test/test_helper.bash -wget --no-clobber https://raw.githubusercontent.com/letsencrypt/pebble/master/test/certs/pebble.minica.pem -# cat /etc/pki/tls/certs/ca-bundle.crt /root/pebble.minica.pem > /root/pebble-ca-bundle.crt -cat /etc/ssl/certs/ca-certificates.crt /root/pebble.minica.pem > /root/pebble-ca-bundle.crt +setup_environment 3>&1 export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt -curl -X POST -d '{"host":"getssl", "addresses":["10.30.50.4"]}' http://10.30.50.3:8055/add-a - -# Test #1 - http-01 verification -echo Test \#1 - http-01 verification - -cp /getssl/test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default -service nginx restart -/getssl/getssl -c getssl -cp /getssl/test/test-config/getssl-http01.cfg /root/.getssl/getssl/getssl.cfg -/getssl/getssl -f getssl - -# Test #2 - http-01 forced renewal -echo Test \#2 - http-01 forced renewal -/getssl/getssl getssl -f - -# Test cleanup -rm -r /root/.getssl - -# Test #3 - dns-01 verification -echo Test \#3 - dns-01 verification -cp /getssl/test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default -service nginx restart -/getssl/getssl -c getssl -cp /getssl/test/test-config/getssl-dns01.cfg /root/.getssl/getssl/getssl.cfg -/getssl/getssl getssl - -# Test #4 - dns-01 forced renewal -echo Test \#4 - dns-01 forced renewal -/getssl/getssl getssl -f +"${CODE_DIR}/getssl" -c "$GETSSL_HOST" 3>&1 +cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" +"${CODE_DIR}/getssl" -f -d "$GETSSL_HOST" 3>&1 diff --git a/test/test-config/getssl-dns01.cfg b/test/test-config/getssl-dns01.cfg index 49c58b5..790dee2 100644 --- a/test/test-config/getssl-dns01.cfg +++ b/test/test-config/getssl-dns01.cfg @@ -44,7 +44,7 @@ DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert # The command needed to reload apache / nginx or whatever you use -RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl /etc/nginx/sites-enabled/default && service nginx restart" +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && service nginx restart >&3-" # Define the server type. This can be https, ftp, ftpi, imap, imaps, pop3, pop3s, smtp, # smtps_deprecated, smtps, smtp_submission, xmpp, xmpps, ldaps or a port number which diff --git a/test/test-config/getssl-http01-10-hosts.cfg b/test/test-config/getssl-http01-10-hosts.cfg new file mode 100644 index 0000000..f521d52 --- /dev/null +++ b/test/test-config/getssl-http01-10-hosts.cfg @@ -0,0 +1,28 @@ +# Uncomment and modify any variables you need +# see https://github.com/srvrco/getssl/wiki/Config-variables for details +# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs + +CA="https://pebble:14000/dir" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +# Note: this is Additional domains - so should not include the primary domain. +SANS="a.${GETSSL_HOST},b.${GETSSL_HOST},c.${GETSSL_HOST},d.${GETSSL_HOST},e.${GETSSL_HOST},f.${GETSSL_HOST},g.${GETSSL_HOST},h.${GETSSL_HOST},i.${GETSSL_HOST},j.${GETSSL_HOST},k.${GETSSL_HOST}" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') + +# Use a single ACL for all checks +USE_SINGLE_ACL="true" + +# Location for all your certs, these can either be on the server (full path name) +DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt" +DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key" +CA_CERT_LOCATION="/etc/nginx/pki/chain.crt" +DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert +DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert + +# The command needed to reload apache / nginx or whatever you use +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && service nginx restart >&3-" + +#SERVER_TYPE="https" +#CHECK_REMOTE="true" diff --git a/test/test-config/getssl-http01.cfg b/test/test-config/getssl-http01.cfg index f3dc5ad..305dd49 100644 --- a/test/test-config/getssl-http01.cfg +++ b/test/test-config/getssl-http01.cfg @@ -43,11 +43,11 @@ DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert # The command needed to reload apache / nginx or whatever you use -RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl /etc/nginx/sites-enabled/default && service nginx restart" +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && service nginx restart >&3-" # Define the server type. This can be https, ftp, ftpi, imap, imaps, pop3, pop3s, smtp, # smtps_deprecated, smtps, smtp_submission, xmpp, xmpps, ldaps or a port number which # will be checked for certificate expiry and also will be checked after # an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true -#SERVER_TYPE="https" -#CHECK_REMOTE="true" +SERVER_TYPE="https" +CHECK_REMOTE="true" diff --git a/test/test-config/nginx-ubuntu-no-ssl b/test/test-config/nginx-ubuntu-no-ssl index c78d646..e7b046e 100644 --- a/test/test-config/nginx-ubuntu-no-ssl +++ b/test/test-config/nginx-ubuntu-no-ssl @@ -1,16 +1,3 @@ -## -# You should look at the following URL's in order to grasp a solid understanding -# of Nginx configuration files in order to fully unleash the power of Nginx. -# http://wiki.nginx.org/Pitfalls -# http://wiki.nginx.org/QuickStart -# http://wiki.nginx.org/Configuration -# -# Generally, you will want to move this file somewhere, and start with a clean -# file but keep this around for reference. Or just disable in sites-enabled. -# -# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. -## - # Default server configuration # server { @@ -26,18 +13,6 @@ server { listen 5001 default_server; listen [::]:5001 default_server; - # - # Note: You should disable gzip for SSL traffic. - # See: https://bugs.debian.org/773332 - # - # Read up on ssl_ciphers to ensure a secure configuration. - # See: https://bugs.debian.org/765782 - # - # Self signed certs generated by the ssl-cert package - # Don't use them in a production server! - # - # include snippets/snakeoil.conf; - root /var/www/html; # Add index.php to the list if you are using PHP @@ -52,42 +27,4 @@ server { # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } - - # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 - # - #location ~ \.php$ { - # include snippets/fastcgi-php.conf; - # - # # With php7.0-cgi alone: - # fastcgi_pass 127.0.0.1:9000; - # # With php7.0-fpm: - # fastcgi_pass unix:/run/php/php7.0-fpm.sock; - #} - - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} } - - -# Virtual Host configuration for example.com -# -# You can move that to a different file under sites-available/ and symlink that -# to sites-enabled/ to enable it. -# -#server { -# listen 80; -# listen [::]:80; -# -# server_name example.com; -# -# root /var/www/example.com; -# index index.html; -# -# location / { -# try_files $uri $uri/ =404; -# } -#} diff --git a/test/test_helper.bash b/test/test_helper.bash new file mode 100644 index 0000000..6f506fd --- /dev/null +++ b/test/test_helper.bash @@ -0,0 +1,44 @@ +INSTALL_DIR=/root +CODE_DIR=/getssl + + +setup_environment() { + # One-off test setup + if [[ -d ${INSTALL_DIR}/.getssl ]]; then + rm -r ${INSTALL_DIR}/.getssl + fi + + if [ ! -f ${INSTALL_DIR}/pebble.minica.pem ]; then + wget --no-clobber https://raw.githubusercontent.com/letsencrypt/pebble/master/test/certs/pebble.minica.pem 2>&1 + CERT_FILE=/etc/ssl/certs/ca-certificates.crt + if [ ! -f $CERT_FILE ]; then + CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt + fi + cat $CERT_FILE ${INSTALL_DIR}/pebble.minica.pem > ${INSTALL_DIR}/pebble-ca-bundle.crt + fi + + curl -X POST -d '{"host":"'"$GETSSL_HOST"'", "addresses":["'"$GETSSL_IP"'"]}' http://10.30.50.3:8055/add-a + cp ${CODE_DIR}/test/test-config/nginx-ubuntu-no-ssl ${NGINX_CONFIG} + service nginx restart >&3- +} + + +cleanup_environment() { + curl -X POST -d '{"host":"'"$GETSSL_HOST"'", "addresses":["'"$GETSSL_IP"'"]}' http://10.30.50.3:8055/del-a +} + + +init_getssl() { + # Run initialisation (create account key, etc) + run ${CODE_DIR}/getssl -c "$GETSSL_HOST" + assert_success + [ -d "$INSTALL_DIR/.getssl" ] +} + + +create_certificate() { + # Create certificate + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" + run ${CODE_DIR}/getssl "$GETSSL_HOST" + #!FIXME test certificate has been placed in the expected location +}