From 2f3e5da3e81f18d95994120586b1d3c199b579e2 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 7 Jan 2020 13:02:45 +0000 Subject: [PATCH] Improved test script (http01 and dns01) --- dns_scripts/dns_add_challtestsrv | 7 ++ dns_scripts/dns_del_challtestsrv | 6 ++ docker-compose.yml | 12 ++- getssl | 14 +-- test/Dockerfile-rhel6 | 27 ++++++ test/{Dockerfile => Dockerfile-ubuntu} | 12 +-- test/run-test.sh | 46 +++++++++- test/test-config/getssl-dns01.cfg | 54 +++++++++++ .../{getssl-ubuntu.cfg => getssl-http01.cfg} | 8 +- ...es-enabled-default => nginx-ubuntu-no-ssl} | 9 +- test/test-config/nginx-ubuntu-ssl | 92 +++++++++++++++++++ 11 files changed, 263 insertions(+), 24 deletions(-) create mode 100644 dns_scripts/dns_add_challtestsrv create mode 100644 dns_scripts/dns_del_challtestsrv create mode 100644 test/Dockerfile-rhel6 rename test/{Dockerfile => Dockerfile-ubuntu} (61%) create mode 100644 test/test-config/getssl-dns01.cfg rename test/test-config/{getssl-ubuntu.cfg => getssl-http01.cfg} (91%) rename test/test-config/{nginx-ubuntu-sites-enabled-default => nginx-ubuntu-no-ssl} (93%) create mode 100644 test/test-config/nginx-ubuntu-ssl diff --git a/dns_scripts/dns_add_challtestsrv b/dns_scripts/dns_add_challtestsrv new file mode 100644 index 0000000..601bcfc --- /dev/null +++ b/dns_scripts/dns_add_challtestsrv @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Simple script to update the challtestserv mock DNS server when testing DNS responses + +fulldomain="${1}" +token="${2}" + +curl -X POST -d "{\"host\":\"_acme-challenge.${fulldomain}.\", \"value\": \"${token}\"}" http://10.30.50.3:8055/set-txt diff --git a/dns_scripts/dns_del_challtestsrv b/dns_scripts/dns_del_challtestsrv new file mode 100644 index 0000000..832b136 --- /dev/null +++ b/dns_scripts/dns_del_challtestsrv @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Simple script to update the challtestserv mock DNS server when testing DNS responses + +fulldomain="${1}" + +curl -X POST -d "{\"host\":\"_acme-challenge.${fulldomain}.\"}" http://10.30.50.3:8055/clear-txt diff --git a/docker-compose.yml b/docker-compose.yml index 67e21a6..b770b44 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ services: pebble: image: letsencrypt/pebble:latest # TODO enable -strict - command: pebble -config /test/config/pebble-config.json + command: pebble -config /test/config/pebble-config.json -dnsserver 10.30.50.3:8053 environment: # with Go 1.13.x which defaults TLS 1.3 to on GODEBUG: "tls13=1" @@ -13,10 +13,18 @@ services: networks: acmenet: ipv4_address: 10.30.50.2 + challtestsrv: + image: letsencrypt/pebble-challtestsrv:latest + command: pebble-challtestsrv -defaultIPv6 "" -defaultIPv4 10.30.50.3 + ports: + - 8055:8055 # HTTP Management API + networks: + acmenet: + ipv4_address: 10.30.50.3 getssl: build: context: . - dockerfile: test/Dockerfile + dockerfile: test/Dockerfile-ubuntu container_name: getssl volumes: - .:/getssl diff --git a/getssl b/getssl index 0f1ef47..991f6d8 100755 --- a/getssl +++ b/getssl @@ -288,7 +288,8 @@ check_challenge_completion() { # checks with the ACME server if our challenge is fi else # APIv2 if [[ -n "$code" ]] && [[ ! "$code" == '200' ]] ; then - error_exit "$domain:Challenge error: $code" + detail=$(json_get "$response" detail) + error_exit "$domain:Challenge error: $code:Detail: $detail" fi fi @@ -1323,7 +1324,6 @@ set_server_type() { # uses SERVER_TYPE to set REMOTE_PORT and REMOTE_EXTRA REMOTE_PORT=636 elif [[ ${SERVER_TYPE} =~ ^[0-9]+$ ]]; then REMOTE_PORT=${SERVER_TYPE} - REMOTE_EXTRA="CUSTOM-HTTP-PORT" else info "${DOMAIN}: unknown server type \"$SERVER_TYPE\" in SERVER_TYPE" config_errors=true @@ -2282,11 +2282,7 @@ for d in $alldomains; do done umask "$ORIG_UMASK" - if [[ "$REMOTE_EXTRA" = "CUSTOM-HTTP-PORT" ]]; then - wellknown_url="${CHALLENGE_CHECK_TYPE}://${d}:${REMOTE_PORT}/.well-known/acme-challenge/$token" - else - wellknown_url="${CHALLENGE_CHECK_TYPE}://${d}/.well-known/acme-challenge/$token" - fi + wellknown_url="${CHALLENGE_CHECK_TYPE}://${d}/.well-known/acme-challenge/$token" debug wellknown_url "$wellknown_url" if [[ "$SKIP_HTTP_TOKEN_CHECK" == "true" ]]; then @@ -2522,6 +2518,8 @@ fi if [[ ${CHECK_REMOTE} == "true" ]]; then sleep "$CHECK_REMOTE_WAIT" # shellcheck disable=SC2086 + debug openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} + CERT_REMOTE=$(echo \ | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null \ | openssl x509 -noout -fingerprint 2>/dev/null) @@ -2529,6 +2527,8 @@ if [[ ${CHECK_REMOTE} == "true" ]]; then if [[ "$CERT_LOCAL" == "$CERT_REMOTE" ]]; then info "${DOMAIN} - certificate installed OK on server" else + debug Fingerprint on server ${CERT_REMOTE} + debug Fingerprint in file ${CERT_LOCAL} error_exit "${DOMAIN} - certificate obtained but certificate on server is different from the new certificate" fi fi diff --git a/test/Dockerfile-rhel6 b/test/Dockerfile-rhel6 new file mode 100644 index 0000000..5ebb278 --- /dev/null +++ b/test/Dockerfile-rhel6 @@ -0,0 +1,27 @@ +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"] + +# with Pebble +# docker-compose -f "docker-compose.yml" up -d --build +# docker exec -it getssl /bin/bash +# /getssl/test/run-test.sh diff --git a/test/Dockerfile b/test/Dockerfile-ubuntu similarity index 61% rename from test/Dockerfile rename to test/Dockerfile-ubuntu index 419d4d0..7f1a8e5 100644 --- a/test/Dockerfile +++ b/test/Dockerfile-ubuntu @@ -1,30 +1,28 @@ -FROM ubuntu:bionic +FROM ubuntu:xenial # bionic = latest 18 version # Update and install required software RUN apt-get update # TODO work out why default version of awk fails -RUN apt-get install -y git curl dnsutils wget linux-libc-dev make gcc binutils nginx-light gawk +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 # TODO test with drill, dig, host 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 +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 -COPY test/test-config/getssl-ubuntu.cfg getssl.cfg - EXPOSE 80 443 # Run eternal loop - for testing CMD ["/bin/bash", "-c", "while :; do sleep 10; done"] # with Pebble -# docker-compose -f "test\docker-compose.yml" up -d --build -# docker exec -it test_getssl /bin/bash +# docker-compose -f "docker-compose.yml" up -d --build +# docker exec -it getssl /bin/bash # /getssl/test/run-test.sh diff --git a/test/run-test.sh b/test/run-test.sh index 5e0ba8d..e93ae89 100644 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -1,9 +1,47 @@ -#! /bin/sh +#! /bin/bash + +set -e + +# Test setup +rm -r /root/.getssl wget --no-clobber https://raw.githubusercontent.com/letsencrypt/pebble/master/test/certs/pebble.minica.pem -export CURL_CA_BUNDLE=/root/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 +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 -service nginx start +cp /getssl/test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default +service nginx restart /getssl/getssl -c getssl -cp getssl.cfg /root/.getssl/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 + +sleep 5 # There's a race condition if renew too soon (authlink returns "valid" instead of "pending") +/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 + +sleep 5 # There's a race condition if renew too soon (authlink returns "valid" instead of "pending") +/getssl/getssl getssl -f diff --git a/test/test-config/getssl-dns01.cfg b/test/test-config/getssl-dns01.cfg new file mode 100644 index 0000000..49c58b5 --- /dev/null +++ b/test/test-config/getssl-dns01.cfg @@ -0,0 +1,54 @@ +# 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 +# +# The staging server is best for testing +#CA="https://acme-staging.api.letsencrypt.org" +# This server issues full certificates, however has rate limits +#CA="https://acme-v01.api.letsencrypt.org" +CA="https://pebble:14000/dir" + +VALIDATE_VIA_DNS=true +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" +# AUTH_DNS_SERVER=10.30.50.3 + +#PRIVATE_KEY_ALG="rsa" + +# 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="" + +# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. +# If these start with ssh: then the next variable is assumed to be the hostname and the rest the location. +# An ssh key will be needed to provide you with access to the remote server. +# Optionally, you can specify a different userid for ssh/scp to use on the remote server before the @ sign. +# If left blank, the username on the local server will be used to authenticate against the remote server. +# If these start with ftp: then the next variables are ftpuserid:ftppassword:servername:ACL_location +# These should be of the form "/path/to/your/website/folder/.well-known/acme-challenge" +# where "/path/to/your/website/folder/" is the path, on your web server, to the web root for your domain. +ACL=('/var/www/html/.well-known/acme-challenge') +# 'ssh:server5:/var/www/getssltest.hopto.org/web/.well-known/acme-challenge' +# 'ssh:sshuserid@server5:/var/www/getssltest.hopto.org/web/.well-known/acme-challenge' +# 'ftp:ftpuserid:ftppassword:getssltest.hopto.org:/web/.well-known/acme-challenge') + +#Set USE_SINGLE_ACL="true" to use a single ACL for all checks +USE_SINGLE_ACL="false" + +# Location for all your certs, these can either be on the server (full path name) +# or using ssh /sftp as for the ACL +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 /etc/nginx/sites-enabled/default && service nginx restart" + +# 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" diff --git a/test/test-config/getssl-ubuntu.cfg b/test/test-config/getssl-http01.cfg similarity index 91% rename from test/test-config/getssl-ubuntu.cfg rename to test/test-config/getssl-http01.cfg index a4db20f..f3dc5ad 100644 --- a/test/test-config/getssl-ubuntu.cfg +++ b/test/test-config/getssl-http01.cfg @@ -7,7 +7,11 @@ # This server issues full certificates, however has rate limits #CA="https://acme-v01.api.letsencrypt.org" CA="https://pebble:14000/dir" -SERVER_TYPE="5002" + +#VALIDATE_VIA_DNS=true +#DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" +#DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" + #PRIVATE_KEY_ALG="rsa" # Additional domains - this could be multiple domains / subdomains in a comma separated list @@ -39,7 +43,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="service nginx restart" +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl /etc/nginx/sites-enabled/default && service nginx restart" # 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/nginx-ubuntu-sites-enabled-default b/test/test-config/nginx-ubuntu-no-ssl similarity index 93% rename from test/test-config/nginx-ubuntu-sites-enabled-default rename to test/test-config/nginx-ubuntu-no-ssl index fe02c8d..c78d646 100644 --- a/test/test-config/nginx-ubuntu-sites-enabled-default +++ b/test/test-config/nginx-ubuntu-no-ssl @@ -14,13 +14,18 @@ # Default server configuration # server { + listen 80 default_server; listen 5002 default_server; listen [::]:5002 default_server; # SSL configuration # - listen 5001 ssl default_server; - listen [::]:5001 ssl default_server; + listen 443 default_server; + listen [::]:443 default_server; + + listen 5001 default_server; + listen [::]:5001 default_server; + # # Note: You should disable gzip for SSL traffic. # See: https://bugs.debian.org/773332 diff --git a/test/test-config/nginx-ubuntu-ssl b/test/test-config/nginx-ubuntu-ssl new file mode 100644 index 0000000..9f79407 --- /dev/null +++ b/test/test-config/nginx-ubuntu-ssl @@ -0,0 +1,92 @@ +## +# 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 { + listen 80 default_server; + listen 5002 default_server; + listen [::]:5002 default_server; + + # SSL configuration + # + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + + listen 5001 ssl default_server; + listen [::]:5001 ssl 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 + index index.html index.htm index.nginx-debian.html; + + server_name _; + ssl_certificate /etc/nginx/pki/server.crt; + ssl_certificate_key /etc/nginx/pki/private/server.key; + + location / { + # First attempt to serve request as file, then + # 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; +# } +#}