diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..e7e9d11
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,2 @@
+# Default ignored files
+/workspace.xml
diff --git a/.idea/getssl.iml b/.idea/getssl.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/.idea/getssl.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..5f2e056
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
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
new file mode 100644
index 0000000..b770b44
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,41 @@
+version: '3'
+services:
+ pebble:
+ image: letsencrypt/pebble:latest
+ # TODO enable -strict
+ 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"
+ ports:
+ - 14000:14000 # HTTPS ACME API
+ - 15000:15000 # HTTPS Management API
+ 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-ubuntu
+ container_name: getssl
+ volumes:
+ - .:/getssl
+ networks:
+ acmenet:
+ ipv4_address: 10.30.50.4
+
+networks:
+ acmenet:
+ driver: bridge
+ ipam:
+ driver: default
+ config:
+ - subnet: 10.30.50.0/24
diff --git a/getssl b/getssl
index a6eaac5..2eef8a7 100755
--- a/getssl
+++ b/getssl
@@ -189,10 +189,17 @@
# 2019-10-02 issue #425 Case insensitive processing of agreement url because of HTTP/2 (2.12)
# 2019-10-07 update DNS checks to allow use of CNAMEs (2.13)
# 2019-11-18 Rebased master onto APIv2 and added Content-Type: application/jose+json (2.14)
+# 2019-11-20 #453 and #454 Add User-Agent to all curl requests
+# 2019-11-22 #456 Fix shellcheck issues
+# 2019-11-23 #459 Fix missing chain.crt
+# 2019-12-18 #462 Use POST-as-GET for ACMEv2 endpoints
+# 2020-01-07 #464 and #486 "json was blank" (change all curl request to use POST-as-GET)
+# 2020-01-08 Error and exit if rate limited, exit if curl returns nothing
+# 2020-01-10 Change domain and getssl templates to v2 (2.15)
# ----------------------------------------------------------------------------------------
PROGNAME=${0##*/}
-VERSION="2.14"
+VERSION="2.15"
# defaults
ACCOUNT_KEY_LENGTH=4096
@@ -207,7 +214,7 @@ CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl"
CSR_SUBJECT="/"
CURL_USERAGENT="${PROGNAME}/${VERSION}"
DEACTIVATE_AUTH="false"
-DEFAULT_REVOKE_CA="https://acme-v01.api.letsencrypt.org"
+DEFAULT_REVOKE_CA="https://acme-v02.api.letsencrypt.org"
DNS_EXTRA_WAIT=""
DNS_WAIT=10
DOMAIN_KEY_LENGTH=4096
@@ -279,7 +286,7 @@ check_challenge_completion() { # checks with the ACME server if our challenge is
keyauthorization=$3
debug "sending request to ACME server saying we're ready for challenge"
- send_signed_request "$uri" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}"
+ send_signed_request "$uri" "{}"
# check response from our request to perform challenge
if [[ $API -eq 1 ]]; then
@@ -288,16 +295,15 @@ 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=$(echo "$response" | grep "detail" | awk -F\" '{print $4}')
+ error_exit "$domain:Challenge error: $code:Detail: $detail"
fi
fi
# loop "forever" to keep checking for a response from the ACME server.
while true ; do
- debug "checking"
- if ! get_cr "$uri" ; then
- error_exit "$domain:Verify error:$code"
- fi
+ debug "checking if challenge is complete"
+ send_signed_request "$uri" ""
status=$(json_get "$response" status)
@@ -853,10 +859,10 @@ get_certificate() { # get certificate for csr, if all domains validated.
else # APIv2
send_signed_request "$FinalizeLink" "{\"csr\": \"$der\"}" "needbase64"
debug "order link was $OrderLink"
- cd=$(curl --user-agent "$CURL_USERAGENT" --silent "$OrderLink")
- CertData=$(json_get "$cd" "certificate")
+ send_signed_request "$OrderLink" ""
+ CertData=$(json_get "$response" "certificate")
debug "CertData is at $CertData"
- curl --user-agent "$CURL_USERAGENT" --silent "$CertData" > "$FULL_CHAIN"
+ send_signed_request "$CertData" "" "" "$FULL_CHAIN"
info "Full certificate saved in $FULL_CHAIN"
awk -v CERT_FILE="$CERT_FILE" -v CA_CERT="$CA_CERT" 'BEGIN {outfile=CERT_FILE} split_after==1 {outfile=CA_CERT;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > outfile}' "$FULL_CHAIN"
info "Certificate saved in $CERT_FILE"
@@ -1335,6 +1341,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p
url=$1
payload=$2
needbase64=$3
+ outfile=$4 # save response into this file (certificate data)
debug url "$url"
@@ -1374,8 +1381,8 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p
# Build another header which also contains the previously received nonce and encode it as urlbase64
if [[ $API -eq 1 ]]; then
- protected='{"alg": "'"$jwkalg"'", "jwk": '"$jwk"', "nonce": "'"${nonce}"'", "url": "'"${url}"'"}'
- protected64="$(printf '%s' "${protected}" | urlbase64)"
+ protected='{"alg": "'"$jwkalg"'", "jwk": '"$jwk"', "nonce": "'"${nonce}"'", "url": "'"${url}"'"}'
+ protected64="$(printf '%s' "${protected}" | urlbase64)"
else # APIv2
if [[ -z "$KID" ]]; then
debug "KID is blank, so using jwk"
@@ -1384,7 +1391,6 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p
else
debug "using KID=${KID}"
protected="{\"alg\": \"$jwkalg\", \"kid\": \"$KID\",\"nonce\": \"${nonce}\", \"url\": \"${url}\"}"
- debug "protected = $protected"
protected64="$(printf '%s' "${protected}" | urlbase64)"
fi
fi
@@ -1415,13 +1421,26 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p
code="500"
loop_limit=5
while [[ "$code" -eq 500 ]]; do
- if [[ "$needbase64" ]] ; then
+ if [[ "$outfile" ]] ; then
+ $CURL -X POST -H "Content-Type: application/jose+json" --data "$body" "$url" > "$outfile"
+ response=$(cat "$outfile")
+ elif [[ "$needbase64" ]] ; then
response=$($CURL -X POST -H "Content-Type: application/jose+json" --data "$body" "$url" | urlbase64)
else
response=$($CURL -X POST -H "Content-Type: application/jose+json" --data "$body" "$url")
fi
+ if [[ "$response" == "" ]]; then
+ error_exit "ERROR curl \"$url\" returned nothing"
+ fi
+
responseHeaders=$(cat "$CURL_HEADER")
+ if [[ "$needbase64" && ${response##*()} != "{"* ]]; then
+ # response is in base64 too, decode
+ #!FIXME need to use openssl base64 decoder if it exists
+ response=$(echo "$response" | base64 -d)
+ fi
+
debug responseHeaders "$responseHeaders"
debug response "$response"
code=$(awk ' $1 ~ "^HTTP" {print $2}' "$CURL_HEADER" | tail -1)
@@ -1430,7 +1449,9 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p
response_status=$(json_get "$response" status \
| head -1| awk -F'"' '{print $2}')
else # APIv2
- if [[ ${response##*()} == "{"* ]]; then
+ if [[ "$outfile" && "$response" ]]; then
+ debug "response written to $outfile"
+ elif [[ ${response##*()} == "{"* ]]; then
response_status=$(json_get "$response" status)
else
debug "response not in json format"
@@ -1447,6 +1468,9 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p
error_exit "500 error from ACME server: $response"
fi
fi
+ if [[ "$code" -eq 429 ]]; then
+ error_exit "429 rate limited error from ACME server"
+ fi
done
if [[ $response == *"error:badNonce"* ]]; then
debug "bad nonce"
@@ -1603,7 +1627,7 @@ write_getssl_template() { # write out the main template file
# The staging server is best for testing (hence set as default)
CA="https://acme-staging-v02.api.letsencrypt.org/directory"
# This server issues full certificates, however has rate limits
- #CA="https://acme-v01.api.letsencrypt.org"
+ #CA="https://acme-v02.api.letsencrypt.org"
#AGREEMENT="$AGREEMENT"
@@ -1921,6 +1945,7 @@ else
info "unknown API version"
graceful_exit
fi
+debug "Using API v$API"
# if check_remote is true then connect and obtain the current certificate (if not forcing renewal)
if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then
@@ -2004,7 +2029,7 @@ if [[ -s "$CERT_FILE" ]]; then
enddate_s=$(date_epoc "$enddate")
if [[ $(date_renew) -lt "$enddate_s" ]] && [[ $_FORCE_RENEW -ne 1 ]]; then
issuer=$(openssl x509 -in "$CERT_FILE" -noout -issuer 2>/dev/null)
- if [[ "$issuer" == *"Fake LE Intermediate"* ]] && [[ "$CA" == "https://acme-v01.api.letsencrypt.org" ]]; then
+ if [[ "$issuer" == *"Fake LE Intermediate"* ]] && [[ "$CA" == "https://acme-v02.api.letsencrypt.org" ]]; then
debug "upgrading from fake cert to real"
else
info "${DOMAIN}: certificate is valid for more than $RENEW_ALLOW days (until $enddate)"
@@ -2126,7 +2151,7 @@ if [[ $API -eq 2 ]]; then
for d in $alldomains; do
dstring="${dstring}{\"type\":\"dns\",\"value\":\"$d\"},"
done
- dstring="${dstring: : -1}]"
+ dstring="${dstring::${#dstring}-1}]"
# request NewOrder currently seems to ignore the dates ....
# dstring="${dstring},\"notBefore\": \"$(date -d "-1 hour" --utc +%FT%TZ)\""
# dstring="${dstring},\"notAfter\": \"$(date -d "2 days" --utc +%FT%TZ)\""
@@ -2191,7 +2216,7 @@ for d in $alldomains; do
uri=$(json_get "$response" "uri" "dns-01")
debug uri "$uri"
else # APIv2
- response=$(curl --user-agent "$CURL_USERAGENT" --silent "${AuthLink[$dn]}" 2>/dev/null)
+ send_signed_request "${AuthLink[$dn]}" ""
debug "authlink response = $response"
# get the token from the http-01 component
token=$(json_get "$response" "challenges" "type" "dns-01" "token")
@@ -2248,13 +2273,13 @@ for d in $alldomains; do
uri=$(json_get "$response" "uri" "http-01")
debug uri "$uri"
else # APIv2
- response=$(curl --user-agent "$CURL_USERAGENT" --silent "${AuthLink[$dn]}" 2>/dev/null)
+ send_signed_request "${AuthLink[$dn]}" ""
debug "authlink response = $response"
# get the token from the http-01 component
token=$(json_get "$response" "challenges" "type" "http-01" "token")
debug token "$token"
# get the uri from the http component
- uri=$(json_get "$response" "challenges" "type" "http-01" "url")
+ uri=$(json_get "$response" "challenges" "type" "http-01" "url" | head -n1)
debug uri "$uri"
fi
@@ -2277,7 +2302,7 @@ for d in $alldomains; do
done
umask "$ORIG_UMASK"
- wellknown_url="${CHALLENGE_CHECK_TYPE}://$d/.well-known/acme-challenge/$token"
+ wellknown_url="${CHALLENGE_CHECK_TYPE}://${d}/.well-known/acme-challenge/$token"
debug wellknown_url "$wellknown_url"
if [[ "$SKIP_HTTP_TOKEN_CHECK" == "true" ]]; then
@@ -2494,8 +2519,8 @@ reload_service
if [[ "$DEACTIVATE_AUTH" == "true" ]]; then
debug "in deactivate list is $deactivate_url_list"
for deactivate_url in $deactivate_url_list; do
- resp=$(curl --user-agent "$CURL_USERAGENT" "$deactivate_url" 2>/dev/null)
- d=$(json_get "$resp" "hostname")
+ send_signed_request "$deactivate_url" ""
+ d=$(json_get "$response" "hostname")
info "deactivating domain $d"
debug "deactivating $deactivate_url"
send_signed_request "$deactivate_url" "{\"resource\": \"authz\", \"status\": \"deactivated\"}"
diff --git a/test/Dockerfile-rhel6 b/test/Dockerfile-rhel6
new file mode 100644
index 0000000..019da84
--- /dev/null
+++ b/test/Dockerfile-rhel6
@@ -0,0 +1,22 @@
+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-ubuntu
new file mode 100644
index 0000000..b0f09f8
--- /dev/null
+++ b/test/Dockerfile-ubuntu
@@ -0,0 +1,23 @@
+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 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-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
+
+EXPOSE 80 443
+
+# Run eternal loop - for testing
+CMD ["/bin/bash", "-c", "while :; do sleep 10; done"]
diff --git a/test/README.md b/test/README.md
new file mode 100644
index 0000000..9d0aedd
--- /dev/null
+++ b/test/README.md
@@ -0,0 +1,20 @@
+# Testing
+
+This directory contains a simple test script which tests creating certificates with Pebble (testing version of the LetsEncrypt server)
+
+Start up pebble, the challdnstest server for DNS challenges
+`docker-compose -f "docker-compose.yml" up -d --build`
+
+Run the tests
+`docker exec -it getssl /getssl/test/run-test.sh`
+
+Debug (need to set CURL_CA_BUNDLE as pebble uses a local certificate, otherwise you get a "unknown API version" error)
+`docker exec -it getssl /bin/bash`
+`export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt`
+`/getssl/getssl -d getssl`
+
+# 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
diff --git a/test/run-test.sh b/test/run-test.sh
new file mode 100644
index 0000000..b983899
--- /dev/null
+++ b/test/run-test.sh
@@ -0,0 +1,53 @@
+#! /bin/bash
+
+set -e
+
+# Test setup
+if [[ -d /root/.getssl ]]; then
+ rm -r /root/.getssl
+fi
+
+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
+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
+
+# There's a race condition if renew too soon (authlink returns "valid" instead of "pending")
+echo Sleeping 20s to allow previous validation to expire
+sleep 20
+/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
+
+# There's a race condition if renew too soon (authlink returns "valid" instead of "pending")
+echo Sleeping 30s to allow previous validation to expire
+sleep 30
+
+/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-http01.cfg b/test/test-config/getssl-http01.cfg
new file mode 100644
index 0000000..f3dc5ad
--- /dev/null
+++ b/test/test-config/getssl-http01.cfg
@@ -0,0 +1,53 @@
+# 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"
+
+#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/nginx-ubuntu-no-ssl b/test/test-config/nginx-ubuntu-no-ssl
new file mode 100644
index 0000000..c78d646
--- /dev/null
+++ b/test/test-config/nginx-ubuntu-no-ssl
@@ -0,0 +1,93 @@
+##
+# 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 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
+ #
+ # 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;
+# }
+#}
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;
+# }
+#}