From f2a4f6bfa8b573cb280ff8312cc4f4fa4aa02066 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Mon, 15 May 2017 13:57:22 -0400 Subject: [PATCH 001/308] Initial version of GoDaddy DNS validation support. Uses the GoDaddy "Developer" API to add and remove the ACME challenge records. --- .gitattributes | 3 + .gitignore | 9 + dns_scripts/00GoDaddy-README.txt | 68 ++++++ dns_scripts/dns_add_godaddy | 39 +++ dns_scripts/dns_del_godaddy | 37 +++ dns_scripts/dns_godaddy | 393 +++++++++++++++++++++++++++++++ 6 files changed, 549 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 dns_scripts/00GoDaddy-README.txt create mode 100755 dns_scripts/dns_add_godaddy create mode 100755 dns_scripts/dns_del_godaddy create mode 100755 dns_scripts/dns_godaddy diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..21cd744 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Files not to include in .zip/.tar.gz archives +# +.git* export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8317ebf --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*~ +*# +*.swp +*.tmp +*.bak +*.tdy +*.tar.gz +*.orig +JSON.sh diff --git a/dns_scripts/00GoDaddy-README.txt b/dns_scripts/00GoDaddy-README.txt new file mode 100644 index 0000000..f53ab03 --- /dev/null +++ b/dns_scripts/00GoDaddy-README.txt @@ -0,0 +1,68 @@ +Using GoDaddy DNS for LetsEncrypt domain validation. + +Quick guide to setting up getssl for domain validation of +GoDaddy DNS domains. + +There are two prerequisites to using getssl with GoDaddy DNS: + +1) Obtain an API access key from developer.godaddy.com + At first sign-up, you will be required to take a "test" key. + This is NOT what you need. Accept it, then get a "Production" + key. At this writing, there is no charge - but you must have + a GoDaddy customer account. + + You must get the API key for the account which owns the domain + that you want to get certificates for. If the domains that you + manage are owned by more than one account, get a key for each. + + The access key consists of a "Key" and a "Secret". You need + both. + +2) Obtain JSON.sh - https://github.com/dominictarr/JSON.sh + +With those in hand, the installation procedure is: + +1) Create a "myscripts" directory under ~/.getssl/ + +2) Put JSON.sh in "myscripts" + +3) Copy (or softlink from the distribution directory) the + following files to "myscripts": + dns_godaddy dns_add_godaddy dns_del_godaddy + None of these files need to be customized. + +4) Open your config file (the global file in ~/.getssl/getssl.cfg + or the per-account file in ~/.getssl/example.net/getssl.cfg + +5) Set the following options: + VALIDATE_VIA_DNS="true" + DNS_ADD_COMMAND="/path/to/myscripts/dns_add_godaddy" + DNS_DEL_COMMAND="/path/to/myscripts/dns_del_godaddy" + # The API key for your account/this domain + export GODADDY_KEY="..." GODADDY_SECRET="..." + + Note that ~user/ probably won't work in the path. + +6) Set any other options that you wish (per the standard + directions.) Use the test CA to make sure that + everything is setup correctly. + +That's it. getssl example.net will now validate with DNS. + +To trace record additions and removals, run getssl as +GODADDY_TRACE=Y getssl example.net + +There are additional options, which are documented in the +*godaddy" files and dns_godaddy -h. + +Copyright (2017) Timothe Litt litt at acm _dot org + +This sofware may be freely used providing this notice is included with +all copies. The name of the author may not be used to endorse +any other product or derivative work. No warranty is provided +and the user assumes all responsibility for use of this software. + +Report any issues to https://github.com/tlhackque/getssl/issues. + +Enjoy. + diff --git a/dns_scripts/dns_add_godaddy b/dns_scripts/dns_add_godaddy new file mode 100755 index 0000000..4983ea9 --- /dev/null +++ b/dns_scripts/dns_add_godaddy @@ -0,0 +1,39 @@ +#!/bin/bash + +# Copyright (2017) Timothe Litt litt at acm _dot org + +# Add token to GoDaddy dns using dns_godaddy + +# You do not have to customize this script. +# +# Obtain the Key and Secret from https://developer.godaddy.com/getstarted +# You must obtain a "Production" key - NOT the "Test" key you're required +# to get first. +# +# Obtain JSON.sh from https://github.com/dominictarr/JSON.sh +# Place it in (or softlink it to) the same directory as $GODADDY_SCRIPT, +# or specify its location with GODADDY_JSON +# +# Define GODADDY_KEY and GO_DADDY_SECRET in your account or domain getssl.cfg +# +# See GoDaddy-README.txt for complete instructions. + +fulldomain="$1" +token="$2" + +[ -z "$GODADDY_SCRIPT" ] && GODADDY_SCRIPT="~/.getssl/myscripts/dns_godaddy" +[[ "$GODADDY_SCRIPT" =~ ^~ ]] && \ + eval 'GODADDY_SCRIPT=`readlink -nf ' $GODADDY_SCRIPT '`' + +if [ ! -x "$GODADDY_SCRIPT" ]; then + echo "$GODADDY_SCRIPT: not found. Please install, softlink or set GODADDY_SCRIPT to its full path" + echo "See GoDaddy-README.txt for complete instructions." + exit 3 +fi + +# JSON.sh is not (currently) used by add + +export GODADDY_KEY +export GODADDY_SECRET + +$GODADDY_SCRIPT -q add ${fulldomain} "_acme-challenge.${fulldomain}." "${token}" diff --git a/dns_scripts/dns_del_godaddy b/dns_scripts/dns_del_godaddy new file mode 100755 index 0000000..c261998 --- /dev/null +++ b/dns_scripts/dns_del_godaddy @@ -0,0 +1,37 @@ +#!/bin/bash + +# Copyright (2017) Timothe Litt litt at acm _dot org + +# Remove token from GoDaddy dns using dns_godaddy + +# You do not have to customize this script. +# +# Obtain the Key and Secret from https://developer.godaddy.com/getstarted +# You must obtain a "Production" key - NOT the "Test" key you're required +# to get first. +# +# Obtain JSON.sh from https://github.com/dominictarr/JSON.sh +# Place it in (or softlink it to) the same directory as $GODADDY_SCRIPT, +# or specify its location with GODADDY_JSON +# +# Define GODADDY_KEY and GO_DADDY_SECRET in your account or domain getssl.cfg +# +# See GoDaddy-README.txt for complete instructions. + +fulldomain="$1" +token="$2" + +[ -z "$GODADDY_SCRIPT" ] && GODADDY_SCRIPT="~/.getssl/myscripts/dns_godaddy" +[[ "$GODADDY_SCRIPT" =~ ^~ ]] && \ + eval 'GODADDY_SCRIPT=`readlink -nf ' $GODADDY_SCRIPT '`' + +if ! [ -x "$GODADDY_SCRIPT" ]; then + echo "$GODADDY_SCRIPT: not found. Please install, softlink or set GODADDY_SCRIPT to its full path" + echo "See GoDaddy-README.txt for complete instructions." + exit 3 +fi + +export GODADDY_KEY +export GODADDY_SECRET + +$GODADDY_SCRIPT -q del ${fulldomain} "_acme-challenge.${fulldomain}." "${token}" diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy new file mode 100755 index 0000000..536fdd1 --- /dev/null +++ b/dns_scripts/dns_godaddy @@ -0,0 +1,393 @@ +#!/bin/bash + +# Copyright (2017) Timothe Litt litt at acm _dot org + +VERSION="1.0.0" + +# This script is used to update TXT records in GoDaddy DNS server +# It depends on JSON.sh from https://github.com/dominictarr/JSON.sh +# Place it in (or softlink it to) the same directory as this script, +# or specify its location with GODADDY_JSON +# +# See the usage text below, 00GoDaddy-README.txt, dns_add_godaddy +# and dns_del_godaddy for additional information. +# +# It may be freely used providing this notice is included with +# all copies. The name of the author may not be used to endorse +# any other product or derivative work. No warranty is provided +# and the user assumes all responsibility for use of this software. +# +# Bug reports are welcome at https://github.com/tlhackque/getssl/issues. + +API='https://api.godaddy.com/v1/domains' +APISIGNUP='https://developer.godaddy.com/getstarted' +GETJSON='https://github.com/dominictarr/JSON.sh' + +VERB="y" +DEBUG="$GODADDY_DEBUG" +[ -z "$JSON" ] && JSON="$GODADDY_JSON" +[ -z "$JSON" ] && JSON="`dirname $0`/JSON.sh" + +while getopts 'dhj:k:s:qv' opt; do + case $opt in + d) DEBUG="Y" ;; + j) JSON="$OPTARG" ;; + k) GODADDY_KEY="$OPTARG" ;; + s) GODADDY_SECRET="$OPTARG" ;; + q) VERB= ;; + v) echo "dns_godaddy version $VERSION"; exit 0 ;; + *) + cat <&2 +$0: requires JSON.sh as "$JSON" + +The full path to JSON.sh can be specified with -j, or the +GODADDY_JSON environment variable. + +You can obtain a copy from $GETJSON + +Then place or softlink it to $JSON or set GODADDY_JSON. +EOF + exit 2 +fi + +if [ -z "$GODADDY_KEY" ] || [ -z "$GODADDY_SECRET" ]; then + echo "GODADDY_KEY and GODADDY secret must be defined" >&2 + exit 3 +fi + +[ -n "$DEBUG" ] && VERB="y" +[ -n "$GODADDY_TRACE" ] && VERB="Y" + +# Get parameters & validate + +op="$1" +if ! [[ "$op" =~ ^(add|del)$ ]]; then + echo "Operation must be \"add\" or \"del\"" >&2 + exit 3 +fi +domain="$2" +domain="${domain%'.'}" +if [ -z "$domain" ]; then + echo "'domain' parameter is required, see -h" >&2 + exit 3 +fi +name="$3" +if [ -z "$name" ]; then + echo "'name' parameter is required, see -h" >&2 + exit 3 +fi +! [[ "$name" =~ [.]$ ]] && name="${name}.${domain}." +data="$4" +if [ -z "$data" ]; then + echo "'data' parameter is required, see -h" >&2 + exit 3 +fi + +if [ "$op" = 'del' ]; then + ttl= +elif [ -z "$5" ]; then + ttl="600" # GoDaddy minimum TTL is 600 +elif ! [[ "$5" =~ ^[0-9]+$ ]]; then + echo "TTL $5 is not numeric" >&2 + exit 3 +elif [ $5 -lt 600 ]; then + [ -n "$VERB" ] && \ + echo "$5 is less than GoDaddy minimum of 600; increased to 600" >&2 + ttl="600" +else + ttl="$5" +fi + +# --- Done with parameters + +[ -n "$DEBUG" ] && \ + echo "`basename $0`: $op $domain $name \"$data\" $ttl" >&2 + +# Authorization header has secret and key +# N.B. These will appear in a 'ps' listing since curl only allows +# headers to be provided on the command line. + +authhdr="Authorization: sso-key $GODADDY_KEY:$GODADDY_SECRET" + +[ -n "$DEBUG" ] && echo "$authhdr" >&2 + +if [ "$op" = "add" ]; then + # May need to retry due to zone cuts + + while [[ "$domain" =~ [^.]+\.[^.]+ ]]; do + + url="$API/$domain/records/TXT/$name" + + request='{"data":"'$data'","ttl":'$ttl'}' + [ -n "$DEBUG" ] && cat >&2 <&2 <&2 + exit $sts + fi + if ! echo "$result" | grep -q '^HTTP/.* 200 '; then + code="`echo "$result" | grep '"code":' | sed -e's/^.*"code":"//; s/\".*$//'`" + msg="`echo "$result" | grep '"message":' | sed -e's/^.*"message":"//; s/\".*$//'`" + if [ "$code" = "DUPLICATE_RECORD" ]; then + if [ -n "$VERB" ]; then + echo "$msg in $domain" >&2 + fi + exit 0 # Duplicate record is still success + fi + if [ "$code" = 'UNKNOWN_DOMAIN' ]; then + if [[ "$domain" =~ ^([^.]+)\.([^.]+\.[^.]+.*) ]]; then + [ -n "$DEBUG" ] && \ + echo "$domain unknown, trying ${BASH_REMATCH[2]}" >&2 + domain="${BASH_REMATCH[2]}" + continue; + fi + fi + echo "Request failed $msg" >&2 + exit 1 + fi + [ -n "$VERB" ] && echo "$domain: added $name $ttl TXT \"$data\"" >&2 + exit 0 + done +fi + + +# ----- Delete + +# There is no delete API +# But, it is possible to replace all TXT records. +# +# So, first query for all TXT records + +# May need to retry due to zone cuts + +while [[ "$domain" =~ [^.]+\.[^.]+ ]]; do + + url="$API/$domain/records/TXT" + [ -n "$DEBUG" ] && echo "Query for TXT records to: $url" >&2 + + current="$(curl -i -s -X GET -H "$authhdr" "$url")" + sts=$? + if [ $sts -ne 0 ]; then + echo "curl error $sts for query" >&2 + exit $sts + fi + [ -n "$DEBUG" ] && cat >&2 <&2 + domain="${BASH_REMATCH[2]}" + continue; + fi + fi + echo "Request failed $msg" >&2 + exit 1 + fi + # Remove headers + + current="$(echo "$current" | sed -e'0,/^\r*$/d')" + break +done + + # The zone cut is known, so the replace can't fail due to UNKNOWN domain + +if [ "$current" = '[]' ]; then # No TXT records in zone + [ -n "$VERB" ] && echo "$domain: $name TXT \"$data\" does not exist" >&2 + [ -n "$DEBUG" ] && echo "No TXT records in $domain" >&2 + exit 1 # Intent was to change, so error status +fi + +[ -n "$DEBUG" ] && echo "Response is valid" + +# Prepare request to replace TXT RRSET + +# Parse JSON and select only the record structures, which are [index] { ...} + +current="$(echo "$current" | $JSON | sed -n -e'/^\[[0-9][0-9]*\]/{ s/^\[[0-9][0-9]*\]//; p}')" +base="$current" + +[ -n "$DEBUG" ] && cat >&2 <&2 + exit 1 # Intent was to change DNS, so this is an error +fi + +# Remove whitespace and insert needed commmas +# +fmtnew="$new" +new=$(echo "$new" | sed -e"s/}/},/g; \$s/},/}/;" | tr -d '\t\n') + +if [ -z "$new" ]; then + [ -n "$VERB" ] && echo "Replacing last TXT record with a dummy (see -h)" >&2 + new='{"type":"TXT","name":"_dummy.record_","data":"_This record is not used_","ttl":601}' + dummy="t" + TAB=$'\t' + fmtnew="${TAB}$new" + if [ "$fmtnew" = "$base" ]; then + [ -n "$VERB" ] && echo "This tool can't delete a placeholder when it is the only TXT record" >&2 + exit 0 # Not really success, but retrying won't help. + fi +fi + +request="[$new]" + +[ -n "$DEBUG" ] && cat >&2 <&2 <&2 <&2 + exit $sts +fi +if ! echo "$result" | grep -q '^HTTP/.* 200 '; then + result="$(echo "$result" | sed -e'0,/^\r*$/d')" + code="`echo "$result" | grep '"code":' | sed -e's/^.*"code":"//; s/\".*$//'`" + msg="`echo "$result" | grep '"message":' | sed -e's/^.*"message":"//; s/\".*$//'`" + echo "Request failed $msg" >&2 + exit 1 +fi + +if [ -n "$VERB" ]; then + if [ -n "$dummy" ]; then + echo "$domain: replaced $name TXT \"$data\" with a placeholder" >&2 + else + echo "$domain: deleted $name TXT \"$data\"" >&2 + fi +fi +exit 0 + From 49d837de532e2cb3d21497248d1f834909035602 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Mon, 15 May 2017 14:40:18 -0400 Subject: [PATCH 002/308] Improve message from curl error code 60 Issue #288 --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 7f3713e..5bce35c 100755 --- a/getssl +++ b/getssl @@ -429,7 +429,8 @@ check_getssl_upgrade() { # check if a more recent version of code is available a curl --silent "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" errcode=$? if [[ $errcode -eq 60 ]]; then - error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" + longmsg=$'Can not authenticate SSL peer. Your ca_bundle.crt and/or curl may need\nupdating. ca_bundle.crt can be updates with mk-ca-bundle. Curl should\nsupport SNI (multiple SSL domains on a single IP)' + error_exit "$longmsg" elif [[ $errcode -gt 0 ]]; then error_exit "curl error : $errcode" fi From 134456b9685f5c9f0d69807a8d0db7eb5c9c9abe Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Mon, 15 May 2017 14:49:15 -0400 Subject: [PATCH 003/308] Fix misleading error message saving certificates to file. --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 5bce35c..8b0b7c2 100755 --- a/getssl +++ b/getssl @@ -814,7 +814,7 @@ get_certificate() { # get certificate for csr, if all domains validated. echo -----BEGIN CERTIFICATE----- > "$gc_certfile" curl --silent "$CertData" | openssl base64 -e >> "$gc_certfile" echo -----END CERTIFICATE----- >> "$gc_certfile" - info "Certificate saved in $CERT_FILE" + info "Certificate saved in $gc_certfile" fi # If certificate wasn't a valid certificate, error exit. From 568e3373fcd6a8b92576f9fc059e3a6c08c313b4 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Mon, 15 May 2017 14:53:07 -0400 Subject: [PATCH 004/308] Add delimiter to INVALID PRIVATE_KEY_ALG message --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 8b0b7c2..aadb809 100755 --- a/getssl +++ b/getssl @@ -336,7 +336,7 @@ check_config() { # check the config files for all obvious errors rsa|prime256v1|secp384r1|secp521r1) debug "checked PRIVATE_KEY_ALG " ;; *) - info "${DOMAIN}: invalid PRIVATE_KEY_ALG - $PRIVATE_KEY_ALG" + info "${DOMAIN}: invalid PRIVATE_KEY_ALG - '$PRIVATE_KEY_ALG'" config_errors=true ;; esac if [[ "$DUAL_RSA_ECDSA" == "true" ]] && [[ "$PRIVATE_KEY_ALG" == "rsa" ]]; then From c80f3c86925f328e5696fa090e57a5f9d3e5a4a3 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Mon, 15 May 2017 17:21:33 -0400 Subject: [PATCH 005/308] Replace dns_*_nsupdate scripts Old versions did not return correct exit status. Did not provide for pre/post processing hooks (e.g. to mount a disk) Required custom edits/copies for each instance. These fix all those issues. --- dns_scripts/dns_add_nsupdate | 35 +++++++++++++++++++++++++++++------ dns_scripts/dns_del_nsupdate | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/dns_scripts/dns_add_nsupdate b/dns_scripts/dns_add_nsupdate index 9e8ebfe..03f73d4 100755 --- a/dns_scripts/dns_add_nsupdate +++ b/dns_scripts/dns_add_nsupdate @@ -2,15 +2,38 @@ # example of script to add token to local dns using nsupdate -dnskeyfile="path/to/bla.key" - fulldomain="$1" token="$2" -updatefile=$(mktemp) +# VARIABLES: +# +# DNS_NSUPDATE_KEYFILE - path to a TSIG key file, if required +# DNS_NSUPDATE_GETKEY - command to execute if access to the key file requires +# some special action: mounting a disk, decrypting a file.. +# Called with the operation 'add' and action 'open" / 'close' + + +if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then + if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'open' ; then + exit $(( $? + 128 )) + fi + + options="-k ${DNS_NSUPDATE_KEYFILE}" +fi + +# Note that blank line is a "send" command to nsupdate + +nsupdate ${options} -v < "${updatefile}" +sts=$? -nsupdate -k "${dnskeyfile}" -v "${updatefile}" +if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then + if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'close' ; then + exit $(( ${sts} + ( $? * 10 ) )) + fi +fi -rm -f "${updatefile}" +exit ${sts} \ No newline at end of file diff --git a/dns_scripts/dns_del_nsupdate b/dns_scripts/dns_del_nsupdate index 62291b7..ab9ca28 100755 --- a/dns_scripts/dns_del_nsupdate +++ b/dns_scripts/dns_del_nsupdate @@ -1,15 +1,39 @@ #!/bin/bash -# example of script to add token to local dns using nsupdate +# example of script to remove token from local dns using nsupdate -dnskeyfile="path/to/bla.key" fulldomain="$1" token="$2" -updatefile=$(mktemp) +# VARIABLES: +# +# DNS_NSUPDATE_KEYFILE - path to a TSIG key file, if required +# DNS_NSUPDATE_GETKEY - command to execute if access to the key file requires +# some special action: dismounting a disk, encrypting a +# file... Called with the operation 'del' and action +# 'open" / 'close' -printf "update delete _acme-challenge.%s. 300 in TXT \"%s\"\n\n" "${fulldomain}" "${token}" > "${updatefile}" +if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then + if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'del' 'open'; then + exit $(( $? + 128 )) + fi -nsupdate -k "${dnskeyfile}" -v "${updatefile}" + options="-k ${DNS_NSUPDATE_KEYFILE}" +fi -rm -f "${updatefile}" +# Note that blank line is a "send" command to nsupdate + +nsupdate ${options} -v < Date: Mon, 15 May 2017 17:38:24 -0400 Subject: [PATCH 006/308] Include domain name in dns_nsupdate hooks --- dns_scripts/dns_add_nsupdate | 4 ++-- dns_scripts/dns_del_nsupdate | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dns_scripts/dns_add_nsupdate b/dns_scripts/dns_add_nsupdate index 03f73d4..55178db 100755 --- a/dns_scripts/dns_add_nsupdate +++ b/dns_scripts/dns_add_nsupdate @@ -14,7 +14,7 @@ token="$2" if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then - if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'open' ; then + if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'open' ${fulldomain} ; then exit $(( $? + 128 )) fi @@ -31,7 +31,7 @@ EOF sts=$? if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then - if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'close' ; then + if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'close' ${fulldomain}; then exit $(( ${sts} + ( $? * 10 ) )) fi fi diff --git a/dns_scripts/dns_del_nsupdate b/dns_scripts/dns_del_nsupdate index ab9ca28..b3a553e 100755 --- a/dns_scripts/dns_del_nsupdate +++ b/dns_scripts/dns_del_nsupdate @@ -14,7 +14,7 @@ token="$2" # 'open" / 'close' if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then - if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'del' 'open'; then + if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'del' 'open' ${fulldomain} ; then exit $(( $? + 128 )) fi @@ -31,7 +31,7 @@ EOF sts=$? if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then - if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'del' 'close' ; then + if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'del' 'close' ${fulldomain} ; then exit $(( ${sts} + ( $? * 10 ) )) fi fi From b579af8552e6d5e329777710511721cf631603ea Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Mon, 15 May 2017 21:04:52 -0400 Subject: [PATCH 007/308] Move GoDaddy scripts to installation directory; use install -v for all files Simplifies installation; private directory no longer required since the scripts don't need to be customized. -v makes sure that the installer knows what is happening. --- Makefile | 7 +++---- dns_scripts/00GoDaddy-README.txt | 22 +++++++--------------- dns_scripts/dns_add_godaddy | 5 +++-- dns_scripts/dns_del_godaddy | 5 +++-- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 4f16126..d88e22c 100644 --- a/Makefile +++ b/Makefile @@ -19,10 +19,9 @@ ifneq ($(strip $(DESTDIR)),) mkdir -p $(DESTDIR) endif - install -Dm755 getssl $(DESTDIR)/usr/bin/getssl - - install -dm755 $(DESTDIR)/usr/share/getssl - cp -r *_scripts $(DESTDIR)/usr/share/getssl + install -Dvm755 getssl $(DESTDIR)/usr/bin/getssl + install -dvm755 $(DESTDIR)/usr/share/getssl + for dir in *_scripts; do install -dv $(DESTDIR)/usr/share/getssl/$$dir; install -pv $$dir/* $(DESTDIR)/usr/share/getssl/$$dir/; done .PHONY: install diff --git a/dns_scripts/00GoDaddy-README.txt b/dns_scripts/00GoDaddy-README.txt index f53ab03..d58ba73 100644 --- a/dns_scripts/00GoDaddy-README.txt +++ b/dns_scripts/00GoDaddy-README.txt @@ -22,28 +22,20 @@ There are two prerequisites to using getssl with GoDaddy DNS: With those in hand, the installation procedure is: -1) Create a "myscripts" directory under ~/.getssl/ +1) Put JSON.sh in the getssl DNS scripts directory + Default: /usr/share/getssl/dns_scripts -2) Put JSON.sh in "myscripts" - -3) Copy (or softlink from the distribution directory) the - following files to "myscripts": - dns_godaddy dns_add_godaddy dns_del_godaddy - None of these files need to be customized. - -4) Open your config file (the global file in ~/.getssl/getssl.cfg +2) Open your config file (the global file in ~/.getssl/getssl.cfg or the per-account file in ~/.getssl/example.net/getssl.cfg -5) Set the following options: +3) Set the following options: VALIDATE_VIA_DNS="true" - DNS_ADD_COMMAND="/path/to/myscripts/dns_add_godaddy" - DNS_DEL_COMMAND="/path/to/myscripts/dns_del_godaddy" + DNS_ADD_COMMAND="/usr/share/getssl/dns_scripts/dns_add_godaddy" + DNS_DEL_COMMAND="/usr/share/getssl/dns_scripts/dns_del_godaddy" # The API key for your account/this domain export GODADDY_KEY="..." GODADDY_SECRET="..." - Note that ~user/ probably won't work in the path. - -6) Set any other options that you wish (per the standard + 4) Set any other options that you wish (per the standard directions.) Use the test CA to make sure that everything is setup correctly. diff --git a/dns_scripts/dns_add_godaddy b/dns_scripts/dns_add_godaddy index 4983ea9..f7a871c 100755 --- a/dns_scripts/dns_add_godaddy +++ b/dns_scripts/dns_add_godaddy @@ -12,7 +12,8 @@ # # Obtain JSON.sh from https://github.com/dominictarr/JSON.sh # Place it in (or softlink it to) the same directory as $GODADDY_SCRIPT, -# or specify its location with GODADDY_JSON +# or specify its location with GODADDY_JSON The default is +# /usr/share/getssl/dns_scripts/ # # Define GODADDY_KEY and GO_DADDY_SECRET in your account or domain getssl.cfg # @@ -21,7 +22,7 @@ fulldomain="$1" token="$2" -[ -z "$GODADDY_SCRIPT" ] && GODADDY_SCRIPT="~/.getssl/myscripts/dns_godaddy" +[ -z "$GODADDY_SCRIPT" ] && GODADDY_SCRIPT="/usr/share/getssl/dns_scripts/dns_godaddy" [[ "$GODADDY_SCRIPT" =~ ^~ ]] && \ eval 'GODADDY_SCRIPT=`readlink -nf ' $GODADDY_SCRIPT '`' diff --git a/dns_scripts/dns_del_godaddy b/dns_scripts/dns_del_godaddy index c261998..7ca0da9 100755 --- a/dns_scripts/dns_del_godaddy +++ b/dns_scripts/dns_del_godaddy @@ -12,7 +12,8 @@ # # Obtain JSON.sh from https://github.com/dominictarr/JSON.sh # Place it in (or softlink it to) the same directory as $GODADDY_SCRIPT, -# or specify its location with GODADDY_JSON +# or specify its location with GODADDY_JSON The default is +# /usr/share/getssl/dns_scripts/ # # Define GODADDY_KEY and GO_DADDY_SECRET in your account or domain getssl.cfg # @@ -21,7 +22,7 @@ fulldomain="$1" token="$2" -[ -z "$GODADDY_SCRIPT" ] && GODADDY_SCRIPT="~/.getssl/myscripts/dns_godaddy" +[ -z "$GODADDY_SCRIPT" ] && GODADDY_SCRIPT="/usr/share/getssl/dns_scripts/dns_godaddy" [[ "$GODADDY_SCRIPT" =~ ^~ ]] && \ eval 'GODADDY_SCRIPT=`readlink -nf ' $GODADDY_SCRIPT '`' From 820dec6d3f7b5c272c9ee43de48a6b94a61b9db5 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Mon, 15 May 2017 22:44:24 -0400 Subject: [PATCH 008/308] Have curl read Authrorizaton header from stdin rather than the command line. Prevents GoDaddy secret and key from exposure via ps. There is still an issue if environment variables can be read. --- dns_scripts/dns_godaddy | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy index 536fdd1..0e6454c 100755 --- a/dns_scripts/dns_godaddy +++ b/dns_scripts/dns_godaddy @@ -178,8 +178,6 @@ fi echo "`basename $0`: $op $domain $name \"$data\" $ttl" >&2 # Authorization header has secret and key -# N.B. These will appear in a 'ps' listing since curl only allows -# headers to be provided on the command line. authhdr="Authorization: sso-key $GODADDY_KEY:$GODADDY_SECRET" @@ -199,9 +197,12 @@ Add request to: $url $request" -------- EOF - result="$(curl -i -s -X PUT -H "$authhdr" \ - -H "Content-Type: application/json" \ - -d "$request" "$url")" + + result="$(curl -i -s -X PUT -d "$request" --config - "$url" <&2 <&2 - current="$(curl -i -s -X GET -H "$authhdr" "$url")" + current="$(curl -i -s -X GET --config - "$url" <&2 @@ -357,9 +361,11 @@ $request -------- EOF -result="$(curl -i -s -X PUT -H "$authhdr" \ - -H "Content-Type: application/json" \ - -d "$request" "$url")" +result="$(curl -i -s -X PUT -d "$request" --config - "$url" <&2 < Date: Tue, 16 May 2017 08:05:30 -0400 Subject: [PATCH 009/308] Add option for full protocol trace -t FILE (or GODADDY_TFILE=FILE) will append command arguments and all wire traffic to a file. This provides all the information needed for debugging future issues. --- dns_scripts/dns_godaddy | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy index 0e6454c..ff25449 100755 --- a/dns_scripts/dns_godaddy +++ b/dns_scripts/dns_godaddy @@ -2,7 +2,8 @@ # Copyright (2017) Timothe Litt litt at acm _dot org -VERSION="1.0.0" +VERSION="1.0.1" +PROG="`basename $0`" # This script is used to update TXT records in GoDaddy DNS server # It depends on JSON.sh from https://github.com/dominictarr/JSON.sh @@ -28,19 +29,20 @@ DEBUG="$GODADDY_DEBUG" [ -z "$JSON" ] && JSON="$GODADDY_JSON" [ -z "$JSON" ] && JSON="`dirname $0`/JSON.sh" -while getopts 'dhj:k:s:qv' opt; do +while getopts 'dhj:k:s:t:qv' opt; do case $opt in d) DEBUG="Y" ;; j) JSON="$OPTARG" ;; k) GODADDY_KEY="$OPTARG" ;; s) GODADDY_SECRET="$OPTARG" ;; + t) TRACE="$OPTARG" ;; q) VERB= ;; v) echo "dns_godaddy version $VERSION"; exit 0 ;; *) cat <&2 + echo "$PROG: $op $domain $name \"$data\" $ttl" >&2 # Authorization header has secret and key authhdr="Authorization: sso-key $GODADDY_KEY:$GODADDY_SECRET" +if [ -n "$TRACE" ]; then + function timestamp { local tm="`date '+%T:%S%N'`" + local class="$1"; shift + echo "${tm:0:15} ** ${class}: $*" >>"$TRACE" + } + timestamp 'Info' "$PROG" "V$VERSION" 'Starting new protocol trace' + timestamp 'Args' "$@" + function curl { + command curl --trace-time --trace-ascii % "$@" 2>>"$TRACE" + } + [ -n "$VERB" ] && echo "Appending protocol trace to $TRACE" +fi + [ -n "$DEBUG" ] && echo "$authhdr" >&2 if [ "$op" = "add" ]; then From e5702045b055c3ba9aba440a0769549db52ab41b Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Tue, 16 May 2017 21:01:11 -0400 Subject: [PATCH 010/308] Support views. Also, avoid hangs interrogating remote. rdbath suggested how to implement a timeout on s_client probes. Unfortunately, wait -n is a bash 4.3 feature. So this requires bash 4.3. CHECK_CERT_TIMEOUT can be used to override the default, which is 4 seconds. Fallback is provided for older versions. Views may require the 'nslookup' process to do somthing special, usually provide a TSIG key or bind to a specific local address. Add a hook for that - export the VARIABLE DNS_CHECK_FUNC_OPTIONS with the desired options._Set DNS_CHECK_FUNC to the desired command, which must be one of the supported ones: 'dig', 'drill', 'host' or 'nslookup'. However, this turned up the fact that the dig/drill code had the domain and record type arguments in the wrong order on the command line. (The domain comes first, see the man page.) Fixed. In some cases defining the previously undocumented PUBLIC_DNS_SERVER may work. This commit adds it to the template file, and exports it for the benefit of DNS_UPDATE scripts. Also AUTH_DNS_SERVER. Squashed awk complaints about curl.header in some cases with debugging on. Support older curl (--trace-time is somewhat recent) --- dns_scripts/dns_godaddy | 3 +- getssl | 103 +++++++++++++++++++++++++++++++--------- 2 files changed, 82 insertions(+), 24 deletions(-) diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy index ff25449..5e9aa0b 100755 --- a/dns_scripts/dns_godaddy +++ b/dns_scripts/dns_godaddy @@ -193,8 +193,9 @@ if [ -n "$TRACE" ]; then } timestamp 'Info' "$PROG" "V$VERSION" 'Starting new protocol trace' timestamp 'Args' "$@" + curl --help | grep -q -- --trace-time && CURL_TFLAGS="--trace-time" # 7.14.0 function curl { - command curl --trace-time --trace-ascii % "$@" 2>>"$TRACE" + command curl ${CURL_TFLAGS} --trace-ascii % "$@" 2>>"$TRACE" } [ -n "$VERB" ] && echo "Appending protocol trace to $TRACE" fi diff --git a/getssl b/getssl index aadb809..da7f386 100755 --- a/getssl +++ b/getssl @@ -192,16 +192,20 @@ VERSION="2.10" # defaults ACCOUNT_KEY_LENGTH=4096 ACCOUNT_KEY_TYPE="rsa" +export AUTH_DNS_SERVER="" CA="https://acme-staging.api.letsencrypt.org" CA_CERT_LOCATION="" CHALLENGE_CHECK_TYPE="http" CHECK_ALL_AUTH_DNS="false" +CHECK_CERT_TIMEOUT="4" CHECK_REMOTE="true" CHECK_REMOTE_WAIT=0 CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" CSR_SUBJECT="/" DEACTIVATE_AUTH="false" DEFAULT_REVOKE_CA="https://acme-v01.api.letsencrypt.org" +DNS_CHECK_FUNC="" +DNS_CHECK_OPTIONS="" DNS_EXTRA_WAIT="" DNS_WAIT=10 DOMAIN_KEY_LENGTH=4096 @@ -212,7 +216,7 @@ IGNORE_DIRECTORY_DOMAIN="false" ORIG_UMASK=$(umask) PREVIOUSLY_VALIDATED="true" PRIVATE_KEY_ALG="rsa" -PUBLIC_DNS_SERVER="" +export PUBLIC_DNS_SERVER="" RELOAD_CMD="" RENEW_ALLOW="30" REUSE_PRIVATE_KEY="true" @@ -389,14 +393,14 @@ check_config() { # check the config files for all obvious errors config_errors=true fi # check domain exist - if [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then + if [[ "$DNS_CHECK_FUNC" =~ ^drill ]] || [[ "$DNS_CHECK_FUNC" =~ ^dig ]]; then if [[ "$($DNS_CHECK_FUNC "${d}" SOA|grep -c "^${d}")" -ge 1 ]]; then debug "found IP for ${d}" else info "${DOMAIN}: DNS lookup failed for ${d}" config_errors=true fi - elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then + elif [[ "$DNS_CHECK_FUNC" =~ ^host ]]; then if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c "^${d}")" -ge 1 ]]; then debug "found IP for ${d}" else @@ -716,20 +720,19 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n primary_ns="$all_auth_dns_servers" return fi - - if [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then + if [[ "$DNS_CHECK_FUNC" =~ ^drill ]] || [[ "$DNS_CHECK_FUNC" =~ ^dig ]]; then if [[ -z "$gad_s" ]]; then #checking for CNAMEs - res=$($DNS_CHECK_FUNC CNAME "$gad_d"| grep "^$gad_d") + res=$($DNS_CHECK_FUNC "$gad_d" CNAME| grep "^$gad_d") else - res=$($DNS_CHECK_FUNC CNAME "$gad_d" "@$gad_s"| grep "^$gad_d") + res=$($DNS_CHECK_FUNC "$gad_d" CNAME "@$gad_s"| grep "^$gad_d") fi if [[ ! -z "$res" ]]; then # domain is a CNAME so get main domain gad_d=$(echo "$res"| awk '{print $5}' |sed 's/\.$//g') fi if [[ -z "$gad_s" ]]; then #checking for CNAMEs - res=$($DNS_CHECK_FUNC NS "$gad_d"| grep "^$gad_d") + res=$($DNS_CHECK_FUNC "$gad_d" NS| grep "^$gad_d") else - res=$($DNS_CHECK_FUNC NS "$gad_d" "@$gad_s"| grep "^$gad_d") + res=$($DNS_CHECK_FUNC "$gad_d" NS "@$gad_s"| grep "^$gad_d") fi if [[ -z "$res" ]]; then error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" @@ -744,7 +747,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n return fi - if [[ "$DNS_CHECK_FUNC" == "host" ]]; then + if [[ "$DNS_CHECK_FUNC" =~ ^host ]]; then if [[ -z "$gad_s" ]]; then res=$($DNS_CHECK_FUNC -t NS "$gad_d"| grep "name server") else @@ -1178,6 +1181,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p response=$($CURL -X POST --data "$body" "$url") fi + touch "$CURL_HEADER" responseHeaders=$(cat "$CURL_HEADER") debug responseHeaders "$responseHeaders" debug response "$response" @@ -1325,6 +1329,21 @@ write_domain_template() { # write out a template file for a domain. # an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true #SERVER_TYPE="https" #CHECK_REMOTE="true" + + # Unusual configurations (especially split views) may require these. + # If these (or any variable) apply to all your domains, put them in + # the per-domain getssl.cfg. + # + # If you must use an external DNS Server (e.g. due to split views) + # Specify it here. Otherwise, the default is to find the zone master. + # The default will usually work. + # PUBLIC_DNS_SERVER="8.8.8.8" + + # If getssl is unable to determine the authoritative nameserver for a domain + # it will as you to enter AUTH_DNS_SERVER. This is the primary server that + # getssl will use to check for the acme tokens. It must be visible externally + # as well as internally. It need not be "authoritiative" in the RFC1035 sense. + # AUTH_DNS_SERVER="8.8.8.8" _EOF_domain_ } @@ -1364,6 +1383,19 @@ write_getssl_template() { # write out the main template file #VALIDATE_VIA_DNS="true" #DNS_ADD_COMMAND= #DNS_DEL_COMMAND= + + # Unusual configurations (especially split views) may require these. + # If you have a mixture, these can go in the per-domain getssl.cfg. + # + # If you must use an external DNS Server (e.g. due to split views) + # Specify it here. Otherwise, the default is to find the zone master. + # The default will usually work. + # PUBLIC_DNS_SERVER="8.8.8.8" + + # If getssl is unable to determine the authoritative nameserver for a domain + # it will as you to enter AUTH_DNS_SERVER. This is a server that + # can answer queries for the zone - a master or a slave, not a recursive server. + # AUTH_DNS_SERVER="10.0.0.14" _EOF_getssl_ } @@ -1446,7 +1478,6 @@ get_os requires which requires openssl requires curl -requires nslookup drill dig host DNS_CHECK_FUNC requires awk requires tr requires date @@ -1497,6 +1528,12 @@ if [[ -s "$WORKING_DIR/getssl.cfg" ]]; then . "$WORKING_DIR/getssl.cfg" fi +if [[ -n "$DNS_CHECK_FUNC" ]]; then + requires "${DNS_CHECK_FUNC}" +else + requires nslookup drill dig host DNS_CHECK_FUNC +fi + # Define defaults for variables not set in the main config. ACCOUNT_KEY="${ACCOUNT_KEY:=$WORKING_DIR/account.key}" DOMAIN_STORAGE="${DOMAIN_STORAGE:=$WORKING_DIR}" @@ -1569,11 +1606,17 @@ if [[ ${_CREATE_CONFIG} -eq 1 ]]; then if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then info "domain config already exists $DOMAIN_DIR/getssl.cfg" else - info "creating domain config file in $DOMAIN_DIR/getssl.cfg" - # if domain has an existing cert, copy from domain and use to create defaults. - EX_CERT=$(echo \ - | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:443" 2>/dev/null \ - | openssl x509 2>/dev/null) + info "Contacting ${DOMAIN} to inspect current certificate" + EX_CERT=$( { + if [[ "${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}" -ge 43 ]]; then + openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 /dev/null & PID=$! + sleep ${CHECK_CERT_TIMEOUT} & PIDW=$! + wait -n # Requires bash 4.3+ + kill -9 "$PID" "$PIDW" 2>/dev/null + else + openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 /dev/null + fi + } | openssl x509 2>/dev/null) EX_SANS="www.${DOMAIN}" if [[ ! -z "${EX_CERT}" ]]; then EX_SANS=$(echo "$EX_CERT" \ @@ -1582,6 +1625,7 @@ if [[ ${_CREATE_CONFIG} -eq 1 ]]; then EX_SANS=${EX_SANS//$'\n'/','} fi write_domain_template "$DOMAIN_DIR/getssl.cfg" + info "created domain config file in $DOMAIN_DIR/getssl.cfg" fi TEMP_DIR="$DOMAIN_DIR/tmp" # end of "-c|--create" option, so exit @@ -1609,6 +1653,11 @@ if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then . "$DOMAIN_DIR/getssl.cfg" fi +# In case special options are needed for DNS_CHECK_FUNC, add them +# to the command. E.G. if a TSIG key or bound local IP is required... + +DNS_CHECK_FUNC="${DNS_CHECK_FUNC} ${DNS_CHECK_OPTIONS}" + # from SERVER_TYPE set REMOTE_PORT and REMOTE_EXTRA set_server_type @@ -1629,11 +1678,19 @@ URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') # 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 - debug "getting certificate for $DOMAIN from remote server" + info "Contacting $DOMAIN on port ${REMOTE_PORT} to inspect current certificate" # shellcheck disable=SC2086 - EX_CERT=$(echo \ - | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null \ - | openssl x509 2>/dev/null) + EX_CERT=$( { + if [[ "${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}" -ge 43 ]]; then + echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null & PID=$! + sleep ${CHECK_CERT_TIMEOUT} & PIDW=$! + wait -n # Requires bash 4.3+ + kill -9 "$PID" "$PIDW" 2>/dev/null + else + echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null + fi + } | openssl x509 2>/dev/null ) + if [[ ! -z "$EX_CERT" ]]; then # if obtained a cert if [[ -s "$CERT_FILE" ]]; then # if local exists CERT_LOCAL=$(openssl x509 -noout -fingerprint < "$CERT_FILE" 2>/dev/null) @@ -1980,10 +2037,10 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" \ | grep ^_acme -A2\ | grep '"'|awk -F'"' '{ print $2}') - elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${d}" "@${ns}" \ + elif [[ "$DNS_CHECK_FUNC" =~ ^drill ]] || [[ "$DNS_CHECK_FUNC" =~ ^dig ]]; then + check_result=$($DNS_CHECK_FUNC "_acme-challenge.${d}" TXT "@${ns}" \ | grep ^_acme|awk -F'"' '{ print $2}') - elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then + elif [[ "$DNS_CHECK_FUNC" =~ ^host ]]; then check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${d}" "${ns}" \ | grep ^_acme|awk -F'"' '{ print $2}') else From 676e2cc72d499a1243371ca93872b4600db92b3d Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Thu, 18 May 2017 23:31:20 -0400 Subject: [PATCH 011/308] Correct timestamp in protocol debug. Inadvertently duplicated seconds & truncated fraction. --- dns_scripts/dns_godaddy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy index 5e9aa0b..4443bd4 100755 --- a/dns_scripts/dns_godaddy +++ b/dns_scripts/dns_godaddy @@ -187,7 +187,7 @@ fi authhdr="Authorization: sso-key $GODADDY_KEY:$GODADDY_SECRET" if [ -n "$TRACE" ]; then - function timestamp { local tm="`date '+%T:%S%N'`" + function timestamp { local tm="`LC_TIME=C date '+%T.%N'`" local class="$1"; shift echo "${tm:0:15} ** ${class}: $*" >>"$TRACE" } From 1c7c0276488990d5464e4a218ce39450adbfe15e Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Sat, 5 Aug 2017 10:02:47 -0400 Subject: [PATCH 012/308] When combining .key files with certs, set umask to 077 to protect key --- getssl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/getssl b/getssl index da7f386..e869b86 100755 --- a/getssl +++ b/getssl @@ -1736,11 +1736,15 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then copy_file_to_location "full pem" \ "$TEMP_DIR/${DOMAIN}_chain.pem" \ "$DOMAIN_CHAIN_LOCATION" + umask 077 cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" > "$TEMP_DIR/${DOMAIN}_K_C.pem" + umask "$ORIG_UMASK" copy_file_to_location "private key and domain cert pem" \ "$TEMP_DIR/${DOMAIN}_K_C.pem" \ "$DOMAIN_KEY_CERT_LOCATION" + umask 077 cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" "$CA_CERT" > "$TEMP_DIR/${DOMAIN}.pem" + umask "$ORIG_UMASK" copy_file_to_location "full pem" \ "$TEMP_DIR/${DOMAIN}.pem" \ "$DOMAIN_PEM_LOCATION" @@ -2154,12 +2158,14 @@ if [[ ! -z "$DOMAIN_KEY_CERT_LOCATION" ]]; then else to_location="${DOMAIN_KEY_CERT_LOCATION}" fi + umask 077 cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" > "$TEMP_DIR/${DOMAIN}_K_C.pem" copy_file_to_location "private key and domain cert pem" "$TEMP_DIR/${DOMAIN}_K_C.pem" "$to_location" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then cat "$DOMAIN_DIR/${DOMAIN}.ec.key" "${CERT_FILE::-4}.ec.crt" > "$TEMP_DIR/${DOMAIN}_K_C.pem.ec" copy_file_to_location "private ec key and domain cert pem" "$TEMP_DIR/${DOMAIN}_K_C.pem.ec" "${to_location}.ec" fi + umask "$ORIG_UMASK" fi # if DOMAIN_PEM_LOCATION is not blank, then create and copy file. if [[ ! -z "$DOMAIN_PEM_LOCATION" ]]; then @@ -2168,12 +2174,14 @@ if [[ ! -z "$DOMAIN_PEM_LOCATION" ]]; then else to_location="${DOMAIN_PEM_LOCATION}" fi + umask 077 cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" "$CA_CERT" > "$TEMP_DIR/${DOMAIN}.pem" copy_file_to_location "full key, cert and chain pem" "$TEMP_DIR/${DOMAIN}.pem" "$to_location" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then cat "$DOMAIN_DIR/${DOMAIN}.ec.key" "${CERT_FILE::-4}.ec.crt" "${CA_CERT::-4}.ec.crt" > "$TEMP_DIR/${DOMAIN}.pem.ec" copy_file_to_location "full ec key, cert and chain pem" "$TEMP_DIR/${DOMAIN}.pem.ec" "${to_location}.ec" fi + umask "$ORIG_UMASK" fi # end of copying certs. From b57cad33451889edcdba78aa41a4ee31a03b33ea Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Mon, 14 May 2018 06:41:29 -0400 Subject: [PATCH 013/308] GoDaddy API change requires JSON array to add TXT records The GoDaddy API now strictly requires any array when adding a single TXT record. --- dns_scripts/dns_godaddy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy index 4443bd4..9ebe6dd 100755 --- a/dns_scripts/dns_godaddy +++ b/dns_scripts/dns_godaddy @@ -1,8 +1,8 @@ #!/bin/bash -# Copyright (2017) Timothe Litt litt at acm _dot org +# Copyright (C) 2017,2018) Timothe Litt litt at acm _dot org -VERSION="1.0.1" +VERSION="1.0.2" PROG="`basename $0`" # This script is used to update TXT records in GoDaddy DNS server @@ -209,7 +209,7 @@ if [ "$op" = "add" ]; then url="$API/$domain/records/TXT/$name" - request='{"data":"'$data'","ttl":'$ttl'}' + request='[{"data":"'$data'","ttl":'$ttl'}]' [ -n "$DEBUG" ] && cat >&2 < Date: Wed, 16 May 2018 10:44:16 -0400 Subject: [PATCH 014/308] More GoDaddy API changes PUT now requires a relative domain name. GET changed the order of name and data in the JSON. Note: Due to the API changes, you may need to add GODADDY_BASE to getssl.cfg. This is a space-separated list of base domain names (zones) in which the challenge responses are entered. There doesn't seem to be a way around this that works in all cases, as the GoDaddy API requires that the zone name be known. --- dns_scripts/00GoDaddy-README.txt | 5 ++++- dns_scripts/dns_add_godaddy | 3 ++- dns_scripts/dns_del_godaddy | 3 ++- dns_scripts/dns_godaddy | 36 ++++++++++++++++++++++++++------ 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/dns_scripts/00GoDaddy-README.txt b/dns_scripts/00GoDaddy-README.txt index d58ba73..9973556 100644 --- a/dns_scripts/00GoDaddy-README.txt +++ b/dns_scripts/00GoDaddy-README.txt @@ -34,6 +34,9 @@ With those in hand, the installation procedure is: DNS_DEL_COMMAND="/usr/share/getssl/dns_scripts/dns_del_godaddy" # The API key for your account/this domain export GODADDY_KEY="..." GODADDY_SECRET="..." + # The base domain name(s) in which the challege records are stored + # E.g. if www.example.net is in the example.net zone: + export GODADDY_BASE="example.com example.net" 4) Set any other options that you wish (per the standard directions.) Use the test CA to make sure that @@ -47,7 +50,7 @@ GODADDY_TRACE=Y getssl example.net There are additional options, which are documented in the *godaddy" files and dns_godaddy -h. -Copyright (2017) Timothe Litt litt at acm _dot org +Copyright (C) 2017, 2018 Timothe Litt litt at acm _dot org This sofware may be freely used providing this notice is included with all copies. The name of the author may not be used to endorse diff --git a/dns_scripts/dns_add_godaddy b/dns_scripts/dns_add_godaddy index f7a871c..fc08f09 100755 --- a/dns_scripts/dns_add_godaddy +++ b/dns_scripts/dns_add_godaddy @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (2017) Timothe Litt litt at acm _dot org +# Copyright (C) 2017, 2018 Timothe Litt litt at acm _dot org # Add token to GoDaddy dns using dns_godaddy @@ -36,5 +36,6 @@ fi export GODADDY_KEY export GODADDY_SECRET +export GODADDY_BASE $GODADDY_SCRIPT -q add ${fulldomain} "_acme-challenge.${fulldomain}." "${token}" diff --git a/dns_scripts/dns_del_godaddy b/dns_scripts/dns_del_godaddy index 7ca0da9..120430f 100755 --- a/dns_scripts/dns_del_godaddy +++ b/dns_scripts/dns_del_godaddy @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (2017) Timothe Litt litt at acm _dot org +# Copyright (C) 2017,2018 Timothe Litt litt at acm _dot org # Remove token from GoDaddy dns using dns_godaddy @@ -34,5 +34,6 @@ fi export GODADDY_KEY export GODADDY_SECRET +export GODADDY_BASE $GODADDY_SCRIPT -q del ${fulldomain} "_acme-challenge.${fulldomain}." "${token}" diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy index 9ebe6dd..a89a855 100755 --- a/dns_scripts/dns_godaddy +++ b/dns_scripts/dns_godaddy @@ -1,8 +1,8 @@ #!/bin/bash -# Copyright (C) 2017,2018) Timothe Litt litt at acm _dot org +# Copyright (C) 2017,2018 Timothe Litt litt at acm _dot org -VERSION="1.0.2" +VERSION="1.0.3" PROG="`basename $0`" # This script is used to update TXT records in GoDaddy DNS server @@ -31,6 +31,7 @@ DEBUG="$GODADDY_DEBUG" while getopts 'dhj:k:s:t:qv' opt; do case $opt in + b) GODADDY_BASE="$OPTARG" ;; d) DEBUG="Y" ;; j) JSON="$OPTARG" ;; k) GODADDY_KEY="$OPTARG" ;; @@ -72,6 +73,9 @@ Arguments: For minimal trace output (to override -q), define GODADDY_TRACE="y". Options + -b Domain name(s) in which challenge records are stored + E.g. often, www.example.net is stored in example.net. + Default from GODADDY_BASE -d Provide debugging output - all requests and responses -h This help. -j: Location of JSON.sh Default `dirname $0`/JSON.sh, or @@ -84,6 +88,7 @@ Options All output, except for this help text, is to stderr. Environment variables + GODADDY_BASE Domain name(s) in which challenge records are stored GODADDY_JSON location of the JSOH.sh script GODADDY_KEY default API key GODADDY_SCRIPT location of this script, default location of JSON.sh @@ -92,7 +97,7 @@ Environment variables GODADDY_TFILE appends protocol trace to file. Overrides -t BUGS - Due to a limitation of the gOdADDY API, deleting the last TXT record + Due to a limitation of the GoDaddy API, deleting the last TXT record would be too risky for my taste. So in that case, I replace it with _dummy.record_.domain. TXT "Ihis record is not used". This record is not automatically deleted by this script, though it's perfectly OK to @@ -207,7 +212,23 @@ if [ "$op" = "add" ]; then while [[ "$domain" =~ [^.]+\.[^.]+ ]]; do - url="$API/$domain/records/TXT/$name" + reqname="$name" + # The API doesn't trim the base domain from the name (it used to) + # If specified, remove any listed base. + if [ -n "$GODADDY_BASE" ]; then + for GDB in $GODADDY_BASE; do + gdb="`echo "$GDB" | sed -e's/\\.$//;s/\\./\\\\./g;'`" + gdb="^(.+)\\.$gdb\\.?$" + if [[ "$name" =~ $gdb ]]; then + reqname="${BASH_REMATCH[1]}" + break; + fi + done + else + eval 'reqname="$''{name%'"'.$domain.'}"'"' + fi + + url="$API/$domain/records/TXT/$reqname" request='[{"data":"'$data'","ttl":'$ttl'}]' [ -n "$DEBUG" ] && cat >&2 <&2 exit 1 # Intent was to change DNS, so this is an error From 6a1f4320005fd90d421664b650956ba9565e8208 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Fri, 27 Sep 2019 11:58:04 -0400 Subject: [PATCH 015/308] work-around for http2 syntax differences Newer curl uses http2 by default, results in getssl: Error registering account ... JWS has no anti-replay nonce Force http1.1 as a work-around. Also add debugging info for "error in EC signing".issue opened --- getssl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index e869b86..1453870 100755 --- a/getssl +++ b/getssl @@ -1139,7 +1139,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p CURL_HEADER="$TEMP_DIR/curl.header" dp="$TEMP_DIR/curl.dump" - CURL="curl --silent --dump-header $CURL_HEADER " + CURL="curl --http1.1 --silent --dump-header $CURL_HEADER " if [[ ${_USE_DEBUG} -eq 1 ]]; then CURL="$CURL --trace-ascii $dp " fi @@ -1232,7 +1232,7 @@ sign_string() { # sign a string with a given key and algorithm and return urlbas R=$(echo "$signed" | cut -c 11-142) part2=$(echo "$signed" | cut -c 143-) else - error_exit "error in EC signing couldn't get R from $signed" + error_exit "error in EC signing couldn't get R from $signed ($signalg using $key)" fi debug "R $R" From dd2fe394faef383423737abf4eaaa431232b0fd9 Mon Sep 17 00:00:00 2001 From: nikdow Date: Sat, 26 Oct 2019 18:34:52 +1100 Subject: [PATCH 016/308] Issue #442 looks for a default .cfg file in "$WORKING_DIR/getssl_default.cfg" --- getssl | 104 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 50 deletions(-) diff --git a/getssl b/getssl index f5bf77e..bc20d8e 100755 --- a/getssl +++ b/getssl @@ -1285,56 +1285,60 @@ usage() { # echos out the program usage } write_domain_template() { # write out a template file for a domain. - cat > "$1" <<- _EOF_domain_ - # 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" - - #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="${EX_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/${DOMAIN}/web/.well-known/acme-challenge' - # 'ssh:server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' - # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' - # 'ftp:ftpuserid:ftppassword:${DOMAIN}:/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/ssl/${DOMAIN}.crt" - #DOMAIN_KEY_LOCATION="/etc/ssl/${DOMAIN}.key" - #CA_CERT_LOCATION="/etc/ssl/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="" - - # 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" - _EOF_domain_ + if [[ -s "$WORKING_DIR/getssl_default.cfg" ]]; then + cp "$1" $WORKING_DIR/getssl_default.cfg + else + cat > "$1" <<- _EOF_domain_ + # 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" + + #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="${EX_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/${DOMAIN}/web/.well-known/acme-challenge' + # 'ssh:server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' + # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' + # 'ftp:ftpuserid:ftppassword:${DOMAIN}:/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/ssl/${DOMAIN}.crt" + #DOMAIN_KEY_LOCATION="/etc/ssl/${DOMAIN}.key" + #CA_CERT_LOCATION="/etc/ssl/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="" + + # 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" + _EOF_domain_ + fi } write_getssl_template() { # write out the main template file From 15bfed6ec9d2fc3061ab331d7b0248784310b7ef Mon Sep 17 00:00:00 2001 From: cbdweb Date: Sat, 26 Oct 2019 18:56:32 +1100 Subject: [PATCH 017/308] fix up indents in here file --- getssl | 96 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/getssl b/getssl index bc20d8e..4e86b7b 100755 --- a/getssl +++ b/getssl @@ -1290,54 +1290,54 @@ write_domain_template() { # write out a template file for a domain. else cat > "$1" <<- _EOF_domain_ # 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" - - #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="${EX_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/${DOMAIN}/web/.well-known/acme-challenge' - # 'ssh:server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' - # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' - # 'ftp:ftpuserid:ftppassword:${DOMAIN}:/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/ssl/${DOMAIN}.crt" - #DOMAIN_KEY_LOCATION="/etc/ssl/${DOMAIN}.key" - #CA_CERT_LOCATION="/etc/ssl/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="" - - # 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" - _EOF_domain_ + # 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" + + #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="${EX_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/${DOMAIN}/web/.well-known/acme-challenge' + # 'ssh:server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' + # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' + # 'ftp:ftpuserid:ftppassword:${DOMAIN}:/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/ssl/${DOMAIN}.crt" + #DOMAIN_KEY_LOCATION="/etc/ssl/${DOMAIN}.key" + #CA_CERT_LOCATION="/etc/ssl/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="" + + # 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" + _EOF_domain_ fi } From 254214bd8bb3864d4548cd744d7d7b73fc871880 Mon Sep 17 00:00:00 2001 From: cbdweb Date: Sat, 26 Oct 2019 18:59:44 +1100 Subject: [PATCH 018/308] fix copy command --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 4e86b7b..945a4bd 100755 --- a/getssl +++ b/getssl @@ -1286,7 +1286,7 @@ usage() { # echos out the program usage write_domain_template() { # write out a template file for a domain. if [[ -s "$WORKING_DIR/getssl_default.cfg" ]]; then - cp "$1" $WORKING_DIR/getssl_default.cfg + cp $WORKING_DIR/getssl_default.cfg "$1" else cat > "$1" <<- _EOF_domain_ # Uncomment and modify any variables you need From 9a2ca60c3162dc1f5a328e7236d490c663f1ecf7 Mon Sep 17 00:00:00 2001 From: cbdweb Date: Sat, 26 Oct 2019 19:07:13 +1100 Subject: [PATCH 019/308] use sed to substitute ${domain}. Is there a better way? --- getssl | 1 + 1 file changed, 1 insertion(+) diff --git a/getssl b/getssl index 945a4bd..e8fc270 100755 --- a/getssl +++ b/getssl @@ -1287,6 +1287,7 @@ usage() { # echos out the program usage write_domain_template() { # write out a template file for a domain. if [[ -s "$WORKING_DIR/getssl_default.cfg" ]]; then cp $WORKING_DIR/getssl_default.cfg "$1" + sed -i 's/\$\{domain\}/${domain}/g "$1" else cat > "$1" <<- _EOF_domain_ # Uncomment and modify any variables you need From 4524ca945598cea98fd7671c9742288aef788924 Mon Sep 17 00:00:00 2001 From: aws02 user Date: Sat, 26 Oct 2019 19:49:26 +1100 Subject: [PATCH 020/308] bug fixes; substitute for $domain in default .cfg file --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index e8fc270..44c21f8 100755 --- a/getssl +++ b/getssl @@ -1287,7 +1287,7 @@ usage() { # echos out the program usage write_domain_template() { # write out a template file for a domain. if [[ -s "$WORKING_DIR/getssl_default.cfg" ]]; then cp $WORKING_DIR/getssl_default.cfg "$1" - sed -i 's/\$\{domain\}/${domain}/g "$1" + sed -i -e 's/\$domain/'"${DOMAIN}"'/g' "$1" else cat > "$1" <<- _EOF_domain_ # Uncomment and modify any variables you need From f97f3bfb19dfd179aae0130cac9c9bd218713d9b Mon Sep 17 00:00:00 2001 From: aws02 user Date: Sun, 27 Oct 2019 13:25:27 +1100 Subject: [PATCH 021/308] use envsubst --- getssl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 44c21f8..5b77078 100755 --- a/getssl +++ b/getssl @@ -1287,7 +1287,9 @@ usage() { # echos out the program usage write_domain_template() { # write out a template file for a domain. if [[ -s "$WORKING_DIR/getssl_default.cfg" ]]; then cp $WORKING_DIR/getssl_default.cfg "$1" - sed -i -e 's/\$domain/'"${DOMAIN}"'/g' "$1" + export DOMAIN="$DOMAIN" + export EX_SANS="$EX_SANS" + envsubst < $WORKING_DIR/getssl_default.cfg > "$1" else cat > "$1" <<- _EOF_domain_ # Uncomment and modify any variables you need From e7d1774b41f374d2fe424a5d11a55e5cfcced14c Mon Sep 17 00:00:00 2001 From: aws02 user Date: Sun, 27 Oct 2019 13:34:20 +1100 Subject: [PATCH 022/308] remove cp command --- getssl | 1 - 1 file changed, 1 deletion(-) diff --git a/getssl b/getssl index 5b77078..0469281 100755 --- a/getssl +++ b/getssl @@ -1286,7 +1286,6 @@ usage() { # echos out the program usage write_domain_template() { # write out a template file for a domain. if [[ -s "$WORKING_DIR/getssl_default.cfg" ]]; then - cp $WORKING_DIR/getssl_default.cfg "$1" export DOMAIN="$DOMAIN" export EX_SANS="$EX_SANS" envsubst < $WORKING_DIR/getssl_default.cfg > "$1" From e724424df8e62eafd5993d71f79f0f9f23c21a7c Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 7 Mar 2020 12:21:37 +0000 Subject: [PATCH 023/308] Allow any amount of whitespace in dig/drill output --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 96f7423..c23adea 100755 --- a/getssl +++ b/getssl @@ -997,8 +997,9 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then | grep ^_acme -A2\ | grep '"'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then + debug "$DNS_CHECK_FUNC" TXT "_acme-challenge.${d}" "@${ns}" check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${d}" "@${ns}" \ - | grep 'IN TXT'|awk -F'"' '{ print $2}') + | grep 'IN\WTXT'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${d}" "${ns}" \ | grep 'descriptive text'|awk -F'"' '{ print $2}') From 0ee5f69783558e9f7080d3d9b3a5ac56190c02cb Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 8 Mar 2020 15:03:46 +0000 Subject: [PATCH 024/308] Fix dig CNAME lookup in get_auth_dns --- getssl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/getssl b/getssl index c23adea..d801b26 100755 --- a/getssl +++ b/getssl @@ -1069,10 +1069,10 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n fi if [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - if [[ -z "$gad_s" ]]; then #checking for CNAMEs - res=$($DNS_CHECK_FUNC CNAME "$gad_d"| grep "^$gad_d") + if [[ -z "$gad_s" ]]; then #checking for CNAMEs (grep for CNAME required because if no CNAME then dig returns SOA record) + res=$($DNS_CHECK_FUNC CNAME "$gad_d"| grep "^$gad_d" | grep CNAME) else - res=$($DNS_CHECK_FUNC CNAME "$gad_d" "@$gad_s"| grep "^$gad_d") + res=$($DNS_CHECK_FUNC CNAME "$gad_d" "@$gad_s"| grep "^$gad_d" | grep CNAME) fi if [[ -n "$res" ]]; then # domain is a CNAME so get main domain gad_d=$(echo "$res"| awk '{print $5}' |sed 's/\.$//g') From d0c19f2df45ac0ef0d2f08fd7a0940de2cb36b21 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 10 Mar 2020 15:24:27 +0000 Subject: [PATCH 025/308] Use dig +trace to find primary_ns and fix dig NS parsing (used as fallback) --- getssl | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/getssl b/getssl index d801b26..c222bd2 100755 --- a/getssl +++ b/getssl @@ -1069,18 +1069,35 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n fi if [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - if [[ -z "$gad_s" ]]; then #checking for CNAMEs (grep for CNAME required because if no CNAME then dig returns SOA record) - res=$($DNS_CHECK_FUNC CNAME "$gad_d"| grep "^$gad_d" | grep CNAME) + # Use SOA +trace to find the name server + if [[ -z "$gad_s" ]]; then + res=$($DNS_CHECK_FUNC SOA +trace +nocomments "$gad_d" 2>/dev/null | grep "IN\WNS\W" | tail -1) else - res=$($DNS_CHECK_FUNC CNAME "$gad_d" "@$gad_s"| grep "^$gad_d" | grep CNAME) - fi - if [[ -n "$res" ]]; then # domain is a CNAME so get main domain - gad_d=$(echo "$res"| awk '{print $5}' |sed 's/\.$//g') + res=$($DNS_CHECK_FUNC SOA +trace +nocomments "$gad_d" "@$gad_s" 2>/dev/null | grep "IN\WNS\W" | tail -1) fi - if [[ -z "$gad_s" ]]; then #checking for CNAMEs - res=$($DNS_CHECK_FUNC NS "$gad_d"| grep "^$gad_d") - else - res=$($DNS_CHECK_FUNC NS "$gad_d" "@$gad_s"| grep "^$gad_d") + + # fallback to existing code + if [[ -z "$res" ]]; then + if [[ -z "$gad_s" ]]; then #checking for CNAMEs + res=$($DNS_CHECK_FUNC CNAME "$gad_d"| grep "^$gad_d" ) + else + res=$($DNS_CHECK_FUNC CNAME "$gad_d" "@$gad_s"| grep "^$gad_d" ) + fi + if [[ -n "$res" ]]; then # domain is a CNAME so get main domain + gad_d=$(echo "$res"| awk '{print $5}' |sed 's/\.$//g') + fi + # If gad_d is an A record then this returns the SOA for the root domain, e.g. without the www + # dig NS ubuntu.getssl.text + # > getssl.test. IN SOA ns1.duckdns.org + # If gad_d is a CNAME record then this returns the NS for the domain pointed to by $gad_d + # dig NS www.getssl.text + # > www.getssl.test. IN CNAME getssl.test + # > getssl.test. IN NS ns1.duckdns.org + if [[ -z "$gad_s" ]]; then + res=$($DNS_CHECK_FUNC NS "$gad_d"| grep -E "IN\W(NS|SOA)\W" | tail -1) + else + res=$($DNS_CHECK_FUNC NS "$gad_d" "@$gad_s"| grep -E "IN\W(NS|SOA)\W" | tail -1) + fi fi if [[ -z "$res" ]]; then error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" From 0d9b0f402465855457a8581e384b2d06995db635 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 10 Mar 2020 15:26:07 +0000 Subject: [PATCH 026/308] Add centos7 test --- .github/workflows/run-all-tests.yml | 10 +++++++++- test/2-simple-dns01-nslookup.bats | 8 ++++++-- test/Dockerfile-centos7 | 20 ++++++++++++++++++++ test/debug-test.sh | 2 +- test/test_helper.bash | 5 ++--- 5 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 test/Dockerfile-centos7 diff --git a/.github/workflows/run-all-tests.yml b/.github/workflows/run-all-tests.yml index e6d80ed..1ff795d 100644 --- a/.github/workflows/run-all-tests.yml +++ b/.github/workflows/run-all-tests.yml @@ -21,8 +21,16 @@ jobs: - uses: actions/checkout@v1 - name: Build the docker-compose stack run: docker-compose up -d --build - - name: Run test suite on centos6 + - name: Run test suite on CentOS6 run: test/run-test.sh centos6 + test-centos7: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on CentOS7 + run: test/run-test.sh centos7 test-centos7-duckdns: runs-on: ubuntu-latest steps: diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index f92d817..c8d5cc6 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -8,12 +8,16 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt - mv /usr/bin/dig /usr/bin/dig.getssl.bak + if [ -f /usr/bin/dig ]; then + mv /usr/bin/dig /usr/bin/dig.getssl.bak + fi } teardown() { - mv /usr/bin/dig.getssl.bak /usr/bin/dig + if [ -f /usr/bin/dig.getssl.bak ]; then + mv /usr/bin/dig.getssl.bak /usr/bin/dig + fi } diff --git a/test/Dockerfile-centos7 b/test/Dockerfile-centos7 new file mode 100644 index 0000000..8a34bc5 --- /dev/null +++ b/test/Dockerfile-centos7 @@ -0,0 +1,20 @@ +FROM centos:centos7 + +# Note this image uses drill, does not have dig or nslookup installed + +# Update and install required software +RUN yum -y update +RUN yum -y install epel-release +RUN yum -y install git curl ldns wget which 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 +COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.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 diff --git a/test/debug-test.sh b/test/debug-test.sh index 890366b..ac94b53 100755 --- a/test/debug-test.sh +++ b/test/debug-test.sh @@ -10,7 +10,7 @@ if [ $# -eq 2 ]; then fi #shellcheck disable=SC1091 -source /getssl/test/test_helper.bash +source /getssl/test/test_helper.bash 3>&1 CONFIG_FILE=$1 if [ ! -e "$CONFIG_FILE" ]; then diff --git a/test/test_helper.bash b/test/test_helper.bash index 3ffcf51..f311b18 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -58,15 +58,14 @@ fi # Find IP address if [[ -n "$(command -v ip)" ]]; then - IP=$(ip address) + GETSSL_IP=$(ip address | awk '/10.30.50/ { print $2 }' | awk -F/ '{ print $1 }') elif [[ -n "$(command -v hostname)" ]]; then - IP=$(hostname -I) + GETSSL_IP=$(hostname -I | sed -e 's/[[:space:]]*$//') else echo "Cannot find IP address" exit 1 fi -GETSSL_IP=$(echo "$IP" | awk '/10.30.50/ { print $2 }' | awk -F/ '{ print $1 }') export GETSSL_IP if [ ! -f ${INSTALL_DIR}/pebble.minica.pem ]; then From a5393a58d778ea272b44095de58f2c5f477c1134 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 10 Mar 2020 21:04:55 +0000 Subject: [PATCH 027/308] Added instructions on how to upgrade from v01 to v02 --- README.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c359239..3882b50 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,16 @@ Obtain SSL certificates from the letsencrypt.org ACME server. Suitable for automating the process on remote servers. +## Upgrading from ACME v01 to ACME v02 + +Find the following line in your `getssl.cfg` file: + +```CA="https://acme-v01.api.letsencrypt.org"``` + +and change it to: + +```CA="https://acme-v02.api.letsencrypt.org"``` + ## Features * **Bash** - It runs on virtually all unix machines, including BSD, most @@ -177,9 +187,9 @@ simple bash file containing variables, an example of which is: ```getssl # Uncomment and modify any variables you need # The staging server is best for testing (hence set as default) -CA="https://acme-staging.api.letsencrypt.org" +CA="https://acme-staging-v02.api.letsencrypt.org" # This server issues full certificates, however has rate limits -#CA="https://acme-v01.api.letsencrypt.org" +#CA="https://acme-v02.api.letsencrypt.org" AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf" @@ -206,9 +216,9 @@ config file (again called `getssl.cfg`). An example of which is: # 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" +#CA="https://acme-staging-v02.api.letsencrypt.org" # This server issues full certificates, however has rate limits -#CA="https://acme-v01.api.letsencrypt.org" +#CA="https://acme-v02.api.letsencrypt.org" #AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf" @@ -273,9 +283,9 @@ same server would be: ```getssl # uncomment and modify any variables you need # The staging server is best for testing -CA="https://acme-staging.api.letsencrypt.org" +CA="https://acme-staging-v02.api.letsencrypt.org" # This server issues full certificates, however has rate limits -#CA="https://acme-v01.api.letsencrypt.org" +#CA="https://acme-v02.api.letsencrypt.org" # additional domains - this could be multiple domains / subdomains in a comma separated list SANS="www.example.com" From 080a9ad941904e8572675bfc53029ee3e84af98b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 11 Mar 2020 10:31:51 +0000 Subject: [PATCH 028/308] Update revision history --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index c222bd2..a73a601 100755 --- a/getssl +++ b/getssl @@ -214,10 +214,11 @@ # 2020-02-13 Fix bug with copying to all locations when creating RSA and ECDSA certs (2.20) # 2020-02-22 Change sign_string to use openssl asn1parse (better fix for #424) # 2020-02-23 Add dig to config check for systems without drill (ubuntu) +# 2020-03-11 Use dig +trace to find primary name server and improve dig parsing of CNAME (2.21) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} -VERSION="2.20" +VERSION="2.21" # defaults ACCOUNT_KEY_LENGTH=4096 From 953bfd25c2a07bc52db2326397fc5144724cda88 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 12 Mar 2020 09:33:59 +0000 Subject: [PATCH 029/308] Fix bug with DNS-01 and multiple domains --- dns_scripts/dns_add_challtestsrv | 2 +- getssl | 49 ++++++++++++++----- test/9-multiple-domains-dns01.bats | 47 ++++++++++++++++++ .../getssl-multiple-domains-dns01.cfg | 37 ++++++++++++++ 4 files changed, 121 insertions(+), 14 deletions(-) create mode 100644 test/9-multiple-domains-dns01.bats create mode 100644 test/test-config/getssl-multiple-domains-dns01.cfg diff --git a/dns_scripts/dns_add_challtestsrv b/dns_scripts/dns_add_challtestsrv index 601bcfc..98444b5 100755 --- a/dns_scripts/dns_add_challtestsrv +++ b/dns_scripts/dns_add_challtestsrv @@ -4,4 +4,4 @@ fulldomain="${1}" token="${2}" -curl -X POST -d "{\"host\":\"_acme-challenge.${fulldomain}.\", \"value\": \"${token}\"}" http://10.30.50.3:8055/set-txt +curl --silent -X POST -d "{\"host\":\"_acme-challenge.${fulldomain}.\", \"value\": \"${token}\"}" http://10.30.50.3:8055/set-txt diff --git a/getssl b/getssl index a73a601..93ff02d 100755 --- a/getssl +++ b/getssl @@ -750,13 +750,37 @@ create_order() { OrderLink=$(echo "$responseHeaders" | grep -i location | awk '{print $2}'| tr -d '\r\n ') debug "Order link $OrderLink" FinalizeLink=$(json_get "$response" "finalize") - dn=0 - for d in $alldomains; do - # get authorizations link - AuthLink[$dn]=$(json_get "$response" "identifiers" "value" "$d" "authorizations" "x") - debug "authorizations link for $d - ${AuthLink[$dn]}" - ((dn++)) - done + + if [[ $API -eq 1 ]]; then + dn=0 + for d in $alldomains; do + # get authorizations link + AuthLink[$dn]=$(json_get "$response" "identifiers" "value" "$d" "authorizations" "x") + debug "authorizations link for $d - ${AuthLink[$dn]}" + ((dn++)) + done + else + # Authorization links are unsorted, so fetch the authorization link, find the domain, save response in the correct array position + AuthLinks=$(json_get "$response" "authorizations") + AuthLinkResponse=() + AuthLinkResponseHeader=() + for l in $AuthLinks; do + debug "Requesting authorizations link for $l" + send_signed_request "$l" "" + # Get domain from response + authdomain=$(json_get "$response" "identifier" "value") + # find array position (This is O(n2) but that doubt we'll see performance issues) + dn=0 + for d in $alldomains; do + if [ "$d" == "$authdomain" ]; then + debug "Saving authorization response for $authdomain for domain alldomains[$dn]" + AuthLinkResponse[$dn]=$response + AuthLinkResponseHeader[$dn]=$responseHeaders + fi + ((dn++)) + done + done + fi } date_epoc() { # convert the date into epoch time @@ -823,7 +847,9 @@ for d in $alldomains; do error_exit "new-authz error: $response" fi else - send_signed_request "${AuthLink[$dn]}" "" + response=${AuthLinkResponse[$dn]} + responseHeaders=${AuthLinkResponseHeader[$dn]} + response_status=$(json_get "$response" status) fi if [[ $response_status == "valid" ]]; then @@ -841,16 +867,14 @@ for d in $alldomains; do if [[ $VALIDATE_VIA_DNS == "true" ]]; then # set up the correct DNS token for verification if [[ $API -eq 1 ]]; then # get the dns component of the ACME response - # get the token from the dns component + # get the token and uri from the dns component token=$(json_get "$response" "token" "dns-01") - # get the uri from the dns component uri=$(json_get "$response" "uri" "dns-01") debug uri "$uri" else # APIv2 debug "authlink response = $response" - # get the token from the http-01 component + # get the token and uri from the dns-01 component token=$(json_get "$response" "challenges" "type" "dns-01" "token") - # get the uri from the http component uri=$(json_get "$response" "challenges" "type" "dns-01" "url") debug uri "$uri" fi @@ -901,7 +925,6 @@ for d in $alldomains; do uri=$(json_get "$response" "uri" "http-01") debug uri "$uri" else # APIv2 - 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") diff --git a/test/9-multiple-domains-dns01.bats b/test/9-multiple-domains-dns01.bats new file mode 100644 index 0000000..1b2cd9e --- /dev/null +++ b/test/9-multiple-domains-dns01.bats @@ -0,0 +1,47 @@ +#! /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 multi-level domains using DNS-01 verification" { + # This tests we can create a certificate for .getssl.test and getssl.test (in SANS) + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-multiple-domains-dns01.cfg" + setup_environment + + # Add top level domain from SANS to DNS + curl --silent -X POST -d '{"host":"getssl.test", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + + init_getssl + create_certificate + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' +} + + +@test "Force renewal of multi-level domains using DNS-01" { + # This tests we can renew a certificate for .getssl.test and getssl.test (in SANS) + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + # Remove all the dns aliases + cleanup_environment + curl --silent -X POST -d '{"host":"getssl.tst"}' http://10.30.50.3:8055/clear-a +} diff --git a/test/test-config/getssl-multiple-domains-dns01.cfg b/test/test-config/getssl-multiple-domains-dns01.cfg new file mode 100644 index 0000000..e0d596c --- /dev/null +++ b/test/test-config/getssl-multiple-domains-dns01.cfg @@ -0,0 +1,37 @@ +# 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" + +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 + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="getssl.test" + +# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. +ACL=( + '/var/www/html/.well-known/acme-challenge' + '/var/www/html/.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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" From ba59e4452b74195a518f4a7d5b52e1106178105a Mon Sep 17 00:00:00 2001 From: Heiko Date: Mon, 23 Mar 2020 22:52:34 +0800 Subject: [PATCH 030/308] Fix staging server URL in domain template The trailing slash of the Let's Encrypt staging server URL broke API discovery --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 96f7423..eb41c9d 100755 --- a/getssl +++ b/getssl @@ -1890,7 +1890,7 @@ write_domain_template() { # write out a template file for a domain. # see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs # # The staging server is best for testing - #CA="https://acme-staging-v02.api.letsencrypt.org/" + #CA="https://acme-staging-v02.api.letsencrypt.org" # This server issues full certificates, however has rate limits #CA="https://acme-v02.api.letsencrypt.org" From 6fe3119c90ec99c0c39085f9ea7ef43fe353de73 Mon Sep 17 00:00:00 2001 From: Heiko Date: Mon, 23 Mar 2020 22:56:53 +0800 Subject: [PATCH 031/308] Bump version number and change log --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index eb41c9d..b870e68 100755 --- a/getssl +++ b/getssl @@ -214,10 +214,11 @@ # 2020-02-13 Fix bug with copying to all locations when creating RSA and ECDSA certs (2.20) # 2020-02-22 Change sign_string to use openssl asn1parse (better fix for #424) # 2020-02-23 Add dig to config check for systems without drill (ubuntu) +# 2020-03-23 Fix staging server URL in domain template # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} -VERSION="2.20" +VERSION="2.21" # defaults ACCOUNT_KEY_LENGTH=4096 From 665f72550fa665f6a3d8ed03fc004a329333c4f6 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 24 Mar 2020 21:54:36 +0000 Subject: [PATCH 032/308] Find primary ns using all dns utils (dig, host, nslookup) --- getssl | 169 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 110 insertions(+), 59 deletions(-) diff --git a/getssl b/getssl index 93ff02d..010b755 100755 --- a/getssl +++ b/getssl @@ -214,7 +214,8 @@ # 2020-02-13 Fix bug with copying to all locations when creating RSA and ECDSA certs (2.20) # 2020-02-22 Change sign_string to use openssl asn1parse (better fix for #424) # 2020-02-23 Add dig to config check for systems without drill (ubuntu) -# 2020-03-11 Use dig +trace to find primary name server and improve dig parsing of CNAME (2.21) +# 2020-03-11 Use dig +trace to find primary name server and improve dig parsing of CNAME +# 2020-03-24 Find primary ns using all dns utils (dig, host, nslookup) (2.21) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} @@ -234,7 +235,7 @@ CSR_SUBJECT="/" CURL_USERAGENT="${PROGNAME}/${VERSION}" DEACTIVATE_AUTH="false" DEFAULT_REVOKE_CA="https://acme-v02.api.letsencrypt.org" -DNS_EXTRA_WAIT="" +DNS_EXTRA_WAIT=60 DNS_WAIT=10 DOMAIN_KEY_LENGTH=4096 DUAL_RSA_ECDSA="false" @@ -825,6 +826,29 @@ error_exit() { # give error message on error exit exit 1 } +find_dns_utils() { + HAS_NSLOOKUP=false + HAS_DIG_OR_DRILL="" + HAS_HOST=false + if [[ -n "$(command -v nslookup)" ]]; then + debug "HAS NSLOOKUP=true" + HAS_NSLOOKUP=true + fi + + if [[ -n "$(command -v drill)" ]]; then + debug "HAS DIG_OR_DRILL=drill" + HAS_DIG_OR_DRILL="drill" + elif [[ -n "$(command -v dig)" ]]; then + debug "HAS DIG_OR_DRILL=dig" + HAS_DIG_OR_DRILL="dig" + fi + + if [[ -n "$(command -v host)" ]]; then + debug "HAS HOST=true" + HAS_HOST=true + fi +} + fulfill_challenges() { dn=0 for d in $alldomains; do @@ -1078,10 +1102,11 @@ fi } get_auth_dns() { # get the authoritative dns server for a domain (sets primary_ns ) - gad_d="$1" # domain name + orig_gad_d="$1" # domain name gad_s="$PUBLIC_DNS_SERVER" # start with PUBLIC_DNS_SERVER if [[ "$os" == "cygwin" ]]; then + gad_d="$orig_gad_d" all_auth_dns_servers=$(nslookup -type=soa "${d}" ${PUBLIC_DNS_SERVER} 2>/dev/null \ | grep "primary name server" \ | awk '{print $NF}') @@ -1092,23 +1117,27 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n return fi - if [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then + if [[ -n "$HAS_DIG_OR_DRILL" ]]; then + gad_d="$orig_gad_d" + debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d @$gad_s" to find primary nameserver # Use SOA +trace to find the name server if [[ -z "$gad_s" ]]; then - res=$($DNS_CHECK_FUNC SOA +trace +nocomments "$gad_d" 2>/dev/null | grep "IN\WNS\W" | tail -1) + res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" 2>/dev/null | grep "IN\WNS\W" | tail -1) else - res=$($DNS_CHECK_FUNC SOA +trace +nocomments "$gad_d" "@$gad_s" 2>/dev/null | grep "IN\WNS\W" | tail -1) + res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" "@$gad_s" 2>/dev/null | grep "IN\WNS\W" | tail -1) fi # fallback to existing code if [[ -z "$res" ]]; then - if [[ -z "$gad_s" ]]; then #checking for CNAMEs - res=$($DNS_CHECK_FUNC CNAME "$gad_d"| grep "^$gad_d" ) + debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d @$gad_s" + if [[ -z "$gad_s" ]]; then #checking for CNAMEs (need grep as dig 9.11 sometimes returns everything not just CNAME entries) + res=$($HAS_DIG_OR_DRILL CNAME "$gad_d"| grep "^$gad_d" | grep CNAME) else - res=$($DNS_CHECK_FUNC CNAME "$gad_d" "@$gad_s"| grep "^$gad_d" ) + res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" "@$gad_s"| grep "^$gad_d" | grep CNAME) fi if [[ -n "$res" ]]; then # domain is a CNAME so get main domain gad_d=$(echo "$res"| awk '{print $5}' |sed 's/\.$//g') + debug Domain is a CNAME, actual domain is "$gad_d" fi # If gad_d is an A record then this returns the SOA for the root domain, e.g. without the www # dig NS ubuntu.getssl.text @@ -1117,77 +1146,96 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n # dig NS www.getssl.text # > www.getssl.test. IN CNAME getssl.test # > getssl.test. IN NS ns1.duckdns.org + debug Using "$HAS_DIG_OR_DRILL NS $gad_d @$gad_s" to find primary nameserver if [[ -z "$gad_s" ]]; then - res=$($DNS_CHECK_FUNC NS "$gad_d"| grep -E "IN\W(NS|SOA)\W" | tail -1) + res=$($HAS_DIG_OR_DRILL NS "$gad_d"| grep -E "IN\W(NS|SOA)\W" | tail -1) else - res=$($DNS_CHECK_FUNC NS "$gad_d" "@$gad_s"| grep -E "IN\W(NS|SOA)\W" | tail -1) + res=$($HAS_DIG_OR_DRILL NS "$gad_d" "@$gad_s"| grep -E "IN\W(NS|SOA)\W" | tail -1) fi fi - if [[ -z "$res" ]]; then - error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" - else + if [[ -n "$res" ]]; then all_auth_dns_servers=$(echo "$res" | awk '$4 ~ "NS" {print $5}' | sed 's/\.$//g'|tr '\n' ' ') + if [[ $CHECK_ALL_AUTH_DNS == "true" ]]; then + primary_ns="$all_auth_dns_servers" + else + primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') + fi + return fi - if [[ $CHECK_ALL_AUTH_DNS == "true" ]]; then - primary_ns="$all_auth_dns_servers" - else - primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') - fi - return fi - if [[ "$DNS_CHECK_FUNC" == "host" ]]; then + if [[ "$HAS_HOST" == true ]]; then + gad_d="$orig_gad_d" + debug Using "host -t NS" to find primary name server for "$gad_d" if [[ -z "$gad_s" ]]; then - res=$($DNS_CHECK_FUNC -t NS "$gad_d"| grep "name server") + res=$(host -t NS "$gad_d"| grep "name server") else - res=$($DNS_CHECK_FUNC -t NS "$gad_d" "$gad_s"| grep "name server") + res=$(host -t NS "$gad_d" "$gad_s"| grep "name server") fi - if [[ -z "$res" ]]; then - error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" - else + if [[ -n "$res" ]]; then all_auth_dns_servers=$(echo "$res" | awk '{print $4}' | sed 's/\.$//g'|tr '\n' ' ') + if [[ $CHECK_ALL_AUTH_DNS == "true" ]]; then + primary_ns="$all_auth_dns_servers" + else + primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') + fi + return fi - if [[ $CHECK_ALL_AUTH_DNS == "true" ]]; then - primary_ns="$all_auth_dns_servers" - else - primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') - fi - return fi - res=$(nslookup -debug -type=soa -type=ns "$gad_d" ${gad_s}) + if [[ "$HAS_NSLOOKUP" == true ]]; then + gad_d="$orig_gad_d" + debug Using "nslookup -debug -type=soa -type=ns $gad_d $gad_s" to find primary name server + res=$(nslookup -debug -type=soa -type=ns "$gad_d" ${gad_s}) + + if [[ "$(echo "$res" | grep -c "Non-authoritative")" -gt 0 ]]; then + # this is a Non-authoritative server, need to check for an authoritative one. + gad_s=$(echo "$res" | awk '$2 ~ "nameserver" {print $4; exit }' |sed 's/\.$//g') + if [[ "$(echo "$res" | grep -c "an't find")" -gt 0 ]]; then + # if domain name doesn't exist, then find auth servers for next level up + gad_s=$(echo "$res" | awk '$1 ~ "origin" {print $3; exit }') + gad_d=$(echo "$res" | awk '$1 ~ "->" {print $2; exit}') + # handle scenario where awk returns nothing + if [[ -z "$gad_d" ]]; then + gad_d="$orig_gad_d" + fi + fi - if [[ "$(echo "$res" | grep -c "Non-authoritative")" -gt 0 ]]; then - # this is a Non-authoritative server, need to check for an authoritative one. - gad_s=$(echo "$res" | awk '$2 ~ "nameserver" {print $4; exit }' |sed 's/\.$//g') - if [[ "$(echo "$res" | grep -c "an't find")" -gt 0 ]]; then - # if domain name doesn't exist, then find auth servers for next level up - gad_s=$(echo "$res" | awk '$1 ~ "origin" {print $3; exit }') - gad_d=$(echo "$res" | awk '$1 ~ "->" {print $2; exit}') + # shellcheck disable=SC2086 + res=$(nslookup -debug -type=soa -type=ns "$gad_d" ${gad_s}) fi - fi - if [[ -z "$gad_s" ]]; then - res=$(nslookup -debug -type=soa -type=ns "$gad_d") - else - res=$(nslookup -debug -type=soa -type=ns "$gad_d" "${gad_s}") - fi + if [[ "$(echo "$res" | grep -c "canonical name")" -gt 0 ]]; then + gad_d=$(echo "$res" | awk ' $2 ~ "canonical" {print $5; exit }' |sed 's/\.$//g') + elif [[ "$(echo "$res" | grep -c "an't find")" -gt 0 ]]; then + gad_s=$(echo "$res" | awk ' $1 ~ "origin" {print $3; exit }') + gad_d=$(echo "$res"| awk '$1 ~ "->" {print $2; exit}') + # handle scenario where awk returns nothing + if [[ -z "$gad_d" ]]; then + gad_d="$orig_gad_d" + fi + fi - if [[ "$(echo "$res" | grep -c "canonical name")" -gt 0 ]]; then - gad_d=$(echo "$res" | awk ' $2 ~ "canonical" {print $5; exit }' |sed 's/\.$//g') - elif [[ "$(echo "$res" | grep -c "an't find")" -gt 0 ]]; then - gad_s=$(echo "$res" | awk ' $1 ~ "origin" {print $3; exit }') - gad_d=$(echo "$res"| awk '$1 ~ "->" {print $2; exit}') - fi + # shellcheck disable=SC2086 + # not quoting gad_s fixes the nslookup: couldn't get address for '': not found warning (#332) + all_auth_dns_servers=$(nslookup -debug -type=soa -type=ns "$gad_d" $gad_s \ + | awk '$1 ~ "nameserver" {print $3}' \ + | sed 's/\.$//g'| tr '\n' ' ') - all_auth_dns_servers=$(nslookup -type=soa -type=ns "$gad_d" "$gad_s" \ - | awk ' $2 ~ "nameserver" {print $4}' \ - | sed 's/\.$//g'| tr '\n' ' ') - if [[ $CHECK_ALL_AUTH_DNS == "true" ]]; then - primary_ns="$all_auth_dns_servers" - else - primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') + if [[ -n "$all_auth_dns_servers" ]]; then + if [[ $CHECK_ALL_AUTH_DNS == "true" ]]; then + primary_ns="$all_auth_dns_servers" + else + primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') + fi + return + fi fi + + # nslookup on alpine/ubuntu containers doesn't support -debug, print a warning in this case + # This means getssl cannot check that the DNS record has been updated on the primary name server + info "Warning: Couldn't find primary DNS server - please set PUBLIC_DNS_SERVER or AUTH_DNS_SERVER in config" + info "This means getssl cannot check the DNS entry has been updated" } get_certificate() { # get certificate for csr, if all domains validated. @@ -2289,6 +2337,9 @@ set_server_type # check config for typical errors. check_config +# check what dns utils are installed +find_dns_utils + if [[ -e "$DOMAIN_DIR/FORCE_RENEWAL" ]]; then rm -f "$DOMAIN_DIR/FORCE_RENEWAL" || error_exit "problem deleting file $DOMAIN_DIR/FORCE_RENEWAL" _FORCE_RENEW=1 From 8a8fe446e7f3e527b85642f0396a80aedf0237a9 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 24 Mar 2020 21:55:24 +0000 Subject: [PATCH 033/308] Changes to ensure get_auth_dns is tested --- test/2-simple-dns01-nslookup.bats | 3 +- ...ns-dns01.bats => 7-duckdns-dns01-dig.bats} | 4 +- test/7-duckdns-dns01-nslookup.bats | 49 +++++++++++++++++++ test/8-duckdns-ecdsa.bats | 8 +-- .../getssl-dns01-dual-rsa-ecdsa.cfg | 3 +- test/test-config/getssl-dns01.cfg | 3 +- test/test-config/getssl-duckdns01.cfg | 4 +- .../getssl-multiple-domains-dns01.cfg | 3 +- 8 files changed, 65 insertions(+), 12 deletions(-) rename test/{7-duckdns-dns01.bats => 7-duckdns-dns01-dig.bats} (85%) create mode 100644 test/7-duckdns-dns01-nslookup.bats diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index c8d5cc6..482be2a 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -34,5 +34,6 @@ teardown() { assert_output --partial "nslookup" refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' # don't fail for :error:badNonce - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + # don't check for "Warnings:" as there might be a warning message if nslookup doesn't support -debug (alpine/ubuntu) + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' } diff --git a/test/7-duckdns-dns01.bats b/test/7-duckdns-dns01-dig.bats similarity index 85% rename from test/7-duckdns-dns01.bats rename to test/7-duckdns-dns01-dig.bats index 0c680ea..c6d8f56 100644 --- a/test/7-duckdns-dns01.bats +++ b/test/7-duckdns-dns01-dig.bats @@ -6,7 +6,7 @@ load '/getssl/test/test_helper.bash' -@test "Create new certificate using staging server and DuckDNS" { +@test "Create new certificate using staging server, dig and DuckDNS" { if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi @@ -21,7 +21,7 @@ load '/getssl/test/test_helper.bash' refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' } -@test "Force renewal of certificate using staging server and DuckDNS" { +@test "Force renewal of certificate using staging server, dig and DuckDNS" { if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi diff --git a/test/7-duckdns-dns01-nslookup.bats b/test/7-duckdns-dns01-nslookup.bats new file mode 100644 index 0000000..81c921e --- /dev/null +++ b/test/7-duckdns-dns01-nslookup.bats @@ -0,0 +1,49 @@ +#! /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 + if [ -f /usr/bin/dig ]; then + mv /usr/bin/dig /usr/bin/dig.getssl.bak + fi +} + + +teardown() { + if [ -f /usr/bin/dig.getssl.bak ]; then + mv /usr/bin/dig.getssl.bak /usr/bin/dig + fi +} + + +@test "Create new certificate using staging server, nslookup and DuckDNS" { + if [ -z "$STAGING" ]; then + skip "Running internal tests, skipping external test" + fi + CONFIG_FILE="getssl-duckdns01.cfg" + + setup_environment + init_getssl + create_certificate + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' # ignore nslookup warnings +} + + +@test "Force renewal of certificate using staging server, nslookup and DuckDNS" { + if [ -z "$STAGING" ]; then + skip "Running internal tests, skipping external test" + fi + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' # ignore nslookup warnings + cleanup_environment +} diff --git a/test/8-duckdns-ecdsa.bats b/test/8-duckdns-ecdsa.bats index dfe84fe..2e10512 100644 --- a/test/8-duckdns-ecdsa.bats +++ b/test/8-duckdns-ecdsa.bats @@ -20,7 +20,7 @@ load '/getssl/test/test_helper.bash' assert_success refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' # ignore nslookup warnings } @@ -32,7 +32,7 @@ load '/getssl/test/test_helper.bash' assert_success refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' # ignore nslookup warnings cleanup_environment } @@ -50,7 +50,7 @@ load '/getssl/test/test_helper.bash' assert_success refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' } @@ -62,7 +62,7 @@ load '/getssl/test/test_helper.bash' assert_success refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' cleanup_environment } diff --git a/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg b/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg index 543c201..8f29088 100644 --- a/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg +++ b/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg @@ -7,7 +7,8 @@ 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 +PUBLIC_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT="" DUAL_RSA_ECDSA="true" ACCOUNT_KEY_TYPE="prime256v1" diff --git a/test/test-config/getssl-dns01.cfg b/test/test-config/getssl-dns01.cfg index 7e26b98..0b816b1 100644 --- a/test/test-config/getssl-dns01.cfg +++ b/test/test-config/getssl-dns01.cfg @@ -7,7 +7,8 @@ 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 +PUBLIC_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT="" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="" diff --git a/test/test-config/getssl-duckdns01.cfg b/test/test-config/getssl-duckdns01.cfg index 517aaeb..8c12ee1 100644 --- a/test/test-config/getssl-duckdns01.cfg +++ b/test/test-config/getssl-duckdns01.cfg @@ -5,8 +5,8 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" VALIDATE_VIA_DNS=true DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -AUTH_DNS_SERVER=1.1.1.1 -CHECK_ALL_AUTH_DNS=false +PUBLIC_DNS_SERVER=ns2.duckdns.org +CHECK_ALL_AUTH_DNS=true DNS_EXTRA_WAIT=60 ACCOUNT_KEY_TYPE="rsa" diff --git a/test/test-config/getssl-multiple-domains-dns01.cfg b/test/test-config/getssl-multiple-domains-dns01.cfg index e0d596c..8754677 100644 --- a/test/test-config/getssl-multiple-domains-dns01.cfg +++ b/test/test-config/getssl-multiple-domains-dns01.cfg @@ -7,7 +7,8 @@ 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 +PUBLIC_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT="" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="getssl.test" From 125d9e25e857727c9fde890cdf90349be21d0374 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 24 Mar 2020 21:58:53 +0000 Subject: [PATCH 034/308] Add test for IGNORE_DIRECTORY_DOMAIN --- test/9-multiple-domains-dns01.bats | 19 +++++++++ .../getssl-ignore-directory-domain.cfg | 39 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 test/test-config/getssl-ignore-directory-domain.cfg diff --git a/test/9-multiple-domains-dns01.bats b/test/9-multiple-domains-dns01.bats index 1b2cd9e..2a9344f 100644 --- a/test/9-multiple-domains-dns01.bats +++ b/test/9-multiple-domains-dns01.bats @@ -45,3 +45,22 @@ setup() { cleanup_environment curl --silent -X POST -d '{"host":"getssl.tst"}' http://10.30.50.3:8055/clear-a } + +@test "Test IGNORE_DIRECTORY_DOMAIN using DNS-01 verification" { + # This tests we can create a certificate for getssl.test and .getssl.test (*both* in SANS) + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-ignore-directory-domain.cfg" + setup_environment + + # Add top level domain from SANS to DNS + curl --silent -X POST -d '{"host":"getssl.test", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + + init_getssl + create_certificate + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' +} diff --git a/test/test-config/getssl-ignore-directory-domain.cfg b/test/test-config/getssl-ignore-directory-domain.cfg new file mode 100644 index 0000000..9777891 --- /dev/null +++ b/test/test-config/getssl-ignore-directory-domain.cfg @@ -0,0 +1,39 @@ +# 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" + +VALIDATE_VIA_DNS=true +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" +PUBLIC_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT="" + +# Ignore directory domain (i.e. the domain passed on the command line), and just use the domains in the SANS list +IGNORE_DIRECTORY_DOMAIN="true" +SANS="getssl.test,$GETSSL_HOST" + +# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. +ACL=( + '/var/www/html/.well-known/acme-challenge' + '/var/www/html/.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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" From 804c71ffece2aabb3d7c3b53bbb6fd8691234569 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 25 Mar 2020 21:26:45 +0000 Subject: [PATCH 035/308] Add test for IGNORE_DIRECTORY_DOMAIN --- getssl | 1 + test/9-multiple-domains-dns01.bats | 19 +++++++++ .../getssl-ignore-directory-domain.cfg | 39 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 test/test-config/getssl-ignore-directory-domain.cfg diff --git a/getssl b/getssl index 010b755..fc4924c 100755 --- a/getssl +++ b/getssl @@ -215,6 +215,7 @@ # 2020-02-22 Change sign_string to use openssl asn1parse (better fix for #424) # 2020-02-23 Add dig to config check for systems without drill (ubuntu) # 2020-03-11 Use dig +trace to find primary name server and improve dig parsing of CNAME +# 2020-03-12 Fix bug with DNS validation and multiple domains (#524) # 2020-03-24 Find primary ns using all dns utils (dig, host, nslookup) (2.21) # ---------------------------------------------------------------------------------------- diff --git a/test/9-multiple-domains-dns01.bats b/test/9-multiple-domains-dns01.bats index 1b2cd9e..2a9344f 100644 --- a/test/9-multiple-domains-dns01.bats +++ b/test/9-multiple-domains-dns01.bats @@ -45,3 +45,22 @@ setup() { cleanup_environment curl --silent -X POST -d '{"host":"getssl.tst"}' http://10.30.50.3:8055/clear-a } + +@test "Test IGNORE_DIRECTORY_DOMAIN using DNS-01 verification" { + # This tests we can create a certificate for getssl.test and .getssl.test (*both* in SANS) + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-ignore-directory-domain.cfg" + setup_environment + + # Add top level domain from SANS to DNS + curl --silent -X POST -d '{"host":"getssl.test", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + + init_getssl + create_certificate + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' +} diff --git a/test/test-config/getssl-ignore-directory-domain.cfg b/test/test-config/getssl-ignore-directory-domain.cfg new file mode 100644 index 0000000..9777891 --- /dev/null +++ b/test/test-config/getssl-ignore-directory-domain.cfg @@ -0,0 +1,39 @@ +# 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" + +VALIDATE_VIA_DNS=true +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" +PUBLIC_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT="" + +# Ignore directory domain (i.e. the domain passed on the command line), and just use the domains in the SANS list +IGNORE_DIRECTORY_DOMAIN="true" +SANS="getssl.test,$GETSSL_HOST" + +# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. +ACL=( + '/var/www/html/.well-known/acme-challenge' + '/var/www/html/.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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" From e7a67f39e609940a9169efc2f46743630ee05114 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 30 Mar 2020 22:01:59 +0100 Subject: [PATCH 036/308] Fix problem with domain in mixed case --- getssl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/getssl b/getssl index 010b755..72d3f36 100755 --- a/getssl +++ b/getssl @@ -773,6 +773,9 @@ create_order() { # find array position (This is O(n2) but that doubt we'll see performance issues) dn=0 for d in $alldomains; do + # Convert domain to lowercase as response from server will be in lowercase + # shellcheck disable=SC2018,SC2019 + d=$(echo "$d" | tr A-Z a-z) if [ "$d" == "$authdomain" ]; then debug "Saving authorization response for $authdomain for domain alldomains[$dn]" AuthLinkResponse[$dn]=$response @@ -913,8 +916,10 @@ for d in $alldomains; do | sed -e 's:=*$::g' -e 'y:+/:-_:') debug auth_key "$auth_key" - debug "adding dns via command: $DNS_ADD_COMMAND $d $auth_key" - if ! eval "$DNS_ADD_COMMAND" "$d" "$auth_key" ; then + # shellcheck disable=SC2018,SC2019 + lower_d=$(echo "$d" | tr A-Z a-z) + debug "adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" + if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then error_exit "DNS_ADD_COMMAND failed for domain $d" fi @@ -1091,7 +1096,9 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then check_challenge_completion "$uri" "$d" "$keyauthorization" debug "remove DNS entry" - eval "$DNS_DEL_COMMAND" "$d" "$auth_key" + # shellcheck disable=SC2018,SC2019 + lower_d=$(echo "$d" | tr A-Z a-z) + eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" # remove $dnsfile after each loop. rm -f "$dnsfile" fi From 0dfda4f64dd262c5dd5c2af10b00b7c1b518f903 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 30 Mar 2020 22:02:57 +0100 Subject: [PATCH 037/308] Make "check domain exists" case insensitive --- getssl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index 72d3f36..41663da 100755 --- a/getssl +++ b/getssl @@ -438,29 +438,29 @@ check_config() { # check the config files for all obvious errors fi # check domain exists if [[ "$DNS_CHECK_FUNC" == "drill" ]]; then - if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c "${d}")" -ge 1 ]]; then + if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c -i "${d}")" -ge 1 ]]; then debug "found IP for ${d}" else info "${DOMAIN}: DNS lookup failed for ${d}" config_errors=true fi elif [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - if [[ "$($DNS_CHECK_FUNC "${d}" -t SOA|grep -c "^${d}")" -ge 1 ]]; then + if [[ "$($DNS_CHECK_FUNC "${d}" -t SOA|grep -c -i "^${d}")" -ge 1 ]]; then debug "found SOA IP for ${d}" - elif [[ "$($DNS_CHECK_FUNC "${d}" -t A|grep -c "^${d}")" -ge 1 ]]; then + elif [[ "$($DNS_CHECK_FUNC "${d}" -t A|grep -c -i "^${d}")" -ge 1 ]]; then debug "found A IP for ${d}" else info "${DOMAIN}: DNS lookup failed for ${d}" config_errors=true fi elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then - if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c "^${d}")" -ge 1 ]]; then + if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then debug "found IP for ${d}" else info "${DOMAIN}: DNS lookup failed for ${d}" config_errors=true fi - elif [[ "$(nslookup -query=AAAA "${d}"|grep -c "^${d}.*has AAAA address")" -ge 1 ]]; then + elif [[ "$(nslookup -query=AAAA "${d}"|grep -c -i "^${d}.*has AAAA address")" -ge 1 ]]; then debug "found IPv6 record for ${d}" elif [[ "$(nslookup "${d}"| grep -c ^Name)" -ge 1 ]]; then debug "found IPv4 record for ${d}" From ad28d693716d0e707b146912c509c53c20ea4431 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 30 Mar 2020 22:04:29 +0100 Subject: [PATCH 038/308] Fix error messages in find_dns_utils from older versions of "command" --- getssl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/getssl b/getssl index 41663da..73ca097 100755 --- a/getssl +++ b/getssl @@ -833,20 +833,20 @@ find_dns_utils() { HAS_NSLOOKUP=false HAS_DIG_OR_DRILL="" HAS_HOST=false - if [[ -n "$(command -v nslookup)" ]]; then + if [[ -n "$(command -v nslookup 2>/dev/null)" ]]; then debug "HAS NSLOOKUP=true" HAS_NSLOOKUP=true fi - if [[ -n "$(command -v drill)" ]]; then + if [[ -n "$(command -v drill 2>/dev/null)" ]]; then debug "HAS DIG_OR_DRILL=drill" HAS_DIG_OR_DRILL="drill" - elif [[ -n "$(command -v dig)" ]]; then + elif [[ -n "$(command -v dig 2>/dev/null)" ]]; then debug "HAS DIG_OR_DRILL=dig" HAS_DIG_OR_DRILL="dig" fi - if [[ -n "$(command -v host)" ]]; then + if [[ -n "$(command -v host 2>/dev/null)" ]]; then debug "HAS HOST=true" HAS_HOST=true fi From 125fabdc33708eaf31aade340ab4e6ddd5bb5552 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 30 Mar 2020 22:31:33 +0100 Subject: [PATCH 039/308] Add mixed case tests, rename duckdns tests --- .github/workflows/run-all-tests.yml | 8 ++-- test/10-mixed-case-staging.bats | 24 ++++++++++ test/10-mixed-case.bats | 45 +++++++++++++++++++ ...ns01-dig.bats => 7-staging-dns01-dig.bats} | 2 +- ...kup.bats => 7-staging-dns01-nslookup.bats} | 2 +- ...uckdns-ecdsa.bats => 8-staging-ecdsa.bats} | 4 +- test/9-test--all.bats | 34 ++++++++++++++ ...os7-duckdns => Dockerfile-centos7-staging} | 0 ...untu-duckdns => Dockerfile-ubuntu-staging} | 0 test/run-test.cmd | 10 ++--- test/run-test.sh | 6 +-- ...duckdns01.cfg => getssl-staging-dns01.cfg} | 0 test/test_helper.bash | 9 ++-- 13 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 test/10-mixed-case-staging.bats create mode 100644 test/10-mixed-case.bats rename test/{7-duckdns-dns01-dig.bats => 7-staging-dns01-dig.bats} (95%) rename test/{7-duckdns-dns01-nslookup.bats => 7-staging-dns01-nslookup.bats} (96%) rename test/{8-duckdns-ecdsa.bats => 8-staging-ecdsa.bats} (96%) create mode 100644 test/9-test--all.bats rename test/{Dockerfile-centos7-duckdns => Dockerfile-centos7-staging} (100%) rename test/{Dockerfile-ubuntu-duckdns => Dockerfile-ubuntu-staging} (100%) rename test/test-config/{getssl-duckdns01.cfg => getssl-staging-dns01.cfg} (100%) diff --git a/.github/workflows/run-all-tests.yml b/.github/workflows/run-all-tests.yml index 1ff795d..ff0e121 100644 --- a/.github/workflows/run-all-tests.yml +++ b/.github/workflows/run-all-tests.yml @@ -31,14 +31,14 @@ jobs: run: docker-compose up -d --build - name: Run test suite on CentOS7 run: test/run-test.sh centos7 - test-centos7-duckdns: + test-centos7-staging: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on CentOS7 against Staging using DuckDNS - run: test/run-test.sh centos7-duckdns + run: test/run-test.sh centos7-staging test-debian: runs-on: ubuntu-latest steps: @@ -71,11 +71,11 @@ jobs: run: docker-compose up -d --build - name: Run test suite on Ubuntu18 run: test/run-test.sh ubuntu18 - test-ubuntu-duckdns: + test-ubuntu-staging: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on Ubuntu against Staging using DuckDNS - run: test/run-test.sh ubuntu-duckdns + run: test/run-test.sh ubuntu-staging diff --git a/test/10-mixed-case-staging.bats b/test/10-mixed-case-staging.bats new file mode 100644 index 0000000..c1bac0d --- /dev/null +++ b/test/10-mixed-case-staging.bats @@ -0,0 +1,24 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +@test "Check can create certificate if domain is not lowercase using staging server and DuckDNS" { + if [ -z "$STAGING" ]; then + skip "Running internal tests, skipping external test" + fi + + CONFIG_FILE="getssl-staging-dns01.cfg" + GETSSL_CMD_HOST=$(echo $GETSSL_HOST | tr a-z A-Z) + + setup_environment + init_getssl + create_certificate + + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' +} diff --git a/test/10-mixed-case.bats b/test/10-mixed-case.bats new file mode 100644 index 0000000..2a4d6f3 --- /dev/null +++ b/test/10-mixed-case.bats @@ -0,0 +1,45 @@ +#! /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 "Check that HTTP-01 verification works if the domain is not lowercase" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + CONFIG_FILE="getssl-http01.cfg" + GETSSL_CMD_HOST=$(echo $GETSSL_HOST | tr a-z A-Z) + + setup_environment + init_getssl + create_certificate + + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' +} + +@test "Check that DNS-01 verification works if the domain is not lowercase" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-dns01.cfg" + GETSSL_CMD_HOST=$(echo $GETSSL_HOST | tr a-z A-Z) + setup_environment + + init_getssl + create_certificate + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' +} diff --git a/test/7-duckdns-dns01-dig.bats b/test/7-staging-dns01-dig.bats similarity index 95% rename from test/7-duckdns-dns01-dig.bats rename to test/7-staging-dns01-dig.bats index c6d8f56..8c0d7f1 100644 --- a/test/7-duckdns-dns01-dig.bats +++ b/test/7-staging-dns01-dig.bats @@ -10,7 +10,7 @@ load '/getssl/test/test_helper.bash' if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi - CONFIG_FILE="getssl-duckdns01.cfg" + CONFIG_FILE="getssl-staging-dns01.cfg" setup_environment init_getssl diff --git a/test/7-duckdns-dns01-nslookup.bats b/test/7-staging-dns01-nslookup.bats similarity index 96% rename from test/7-duckdns-dns01-nslookup.bats rename to test/7-staging-dns01-nslookup.bats index 81c921e..027a210 100644 --- a/test/7-duckdns-dns01-nslookup.bats +++ b/test/7-staging-dns01-nslookup.bats @@ -24,7 +24,7 @@ teardown() { if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi - CONFIG_FILE="getssl-duckdns01.cfg" + CONFIG_FILE="getssl-staging-dns01.cfg" setup_environment init_getssl diff --git a/test/8-duckdns-ecdsa.bats b/test/8-staging-ecdsa.bats similarity index 96% rename from test/8-duckdns-ecdsa.bats rename to test/8-staging-ecdsa.bats index 2e10512..92c694a 100644 --- a/test/8-duckdns-ecdsa.bats +++ b/test/8-staging-ecdsa.bats @@ -11,7 +11,7 @@ load '/getssl/test/test_helper.bash' if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi - CONFIG_FILE="getssl-duckdns01.cfg" + CONFIG_FILE="getssl-staging-dns01.cfg" setup_environment init_getssl @@ -41,7 +41,7 @@ load '/getssl/test/test_helper.bash' if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi - CONFIG_FILE="getssl-duckdns01.cfg" + CONFIG_FILE="getssl-staging-dns01.cfg" setup_environment init_getssl diff --git a/test/9-test--all.bats b/test/9-test--all.bats new file mode 100644 index 0000000..94a2c28 --- /dev/null +++ b/test/9-test--all.bats @@ -0,0 +1,34 @@ +#! /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 + export PATH=$PATH:/getssl +} + + +@test "Create new certificate using --all" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + # Setup + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" + + # Run test + run ${CODE_DIR}/getssl --all + + # Check success conditions + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' +} diff --git a/test/Dockerfile-centos7-duckdns b/test/Dockerfile-centos7-staging similarity index 100% rename from test/Dockerfile-centos7-duckdns rename to test/Dockerfile-centos7-staging diff --git a/test/Dockerfile-ubuntu-duckdns b/test/Dockerfile-ubuntu-staging similarity index 100% rename from test/Dockerfile-ubuntu-duckdns rename to test/Dockerfile-ubuntu-staging diff --git a/test/run-test.cmd b/test/run-test.cmd index d1cf263..43c4e40 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -7,8 +7,8 @@ IF %2.==. GOTO NoCmd set COMMAND=%2 %3 :CheckAlias -REM check if OS *contains* duckdns -IF NOT x%OS:duckdns=%==x%OS% GOTO duckdns +REM check if OS *contains* staging +IF NOT x%OS:staging=%==x%OS% GOTO staging set ALIAS=%OS%.getssl.test set STAGING= GOTO Run @@ -22,8 +22,8 @@ REM set COMMAND=/getssl/test/run-bats.sh set COMMAND=bats /getssl/test GOTO CheckAlias -:duckdns -set ALIAS=%OS:-duckdns=%-getssl.duckdns.org +:staging +set ALIAS=%OS:-staging=%-getssl.duckdns.org set STAGING=--env STAGING=true :Run @@ -33,7 +33,7 @@ docker build --rm -f "test\Dockerfile-%OS%" -t getssl-%OS% . @echo on docker run -it ^ --env GETSSL_HOST=%ALIAS% %STAGING% ^ - --env GETSSL_OS=%OS:-duckdns=% ^ + --env GETSSL_OS=%OS:-staging=% ^ -v %cd%:/getssl ^ --rm ^ --network %CurrDirName%_acmenet ^ diff --git a/test/run-test.sh b/test/run-test.sh index 97842a5..d99d5a3 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -14,8 +14,8 @@ else COMMAND="bats /getssl/test" fi -if [[ "$OS" == *"duckdns"* ]]; then - ALIAS="${OS%-duckdns}-getssl.duckdns.org" +if [[ "$OS" == *"staging"* ]]; then + ALIAS="${OS%-staging}-getssl.duckdns.org" STAGING="--env STAGING=true" else ALIAS="$OS.getssl.test" @@ -26,7 +26,7 @@ docker build --rm -f "test/Dockerfile-$OS" -t "getssl-$OS" . # shellcheck disable=SC2086 docker run \ --env GETSSL_HOST=$ALIAS $STAGING \ - --env GETSSL_OS=${OS%-duckdns} \ + --env GETSSL_OS=${OS%-staging} \ -v "$(pwd)":/getssl \ --rm \ --network ${PWD##*/}_acmenet \ diff --git a/test/test-config/getssl-duckdns01.cfg b/test/test-config/getssl-staging-dns01.cfg similarity index 100% rename from test/test-config/getssl-duckdns01.cfg rename to test/test-config/getssl-staging-dns01.cfg diff --git a/test/test_helper.bash b/test/test_helper.bash index f311b18..f4c62af 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -21,7 +21,7 @@ cleanup_environment() { init_getssl() { # Run initialisation (create account key, etc) - run ${CODE_DIR}/getssl -c "$GETSSL_HOST" + run ${CODE_DIR}/getssl -c "$GETSSL_CMD_HOST" assert_success [ -d "$INSTALL_DIR/.getssl" ] } @@ -29,9 +29,9 @@ init_getssl() { create_certificate() { # Create certificate - cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" # shellcheck disable=SC2086 - run ${CODE_DIR}/getssl $1 "$GETSSL_HOST" + run ${CODE_DIR}/getssl $1 "$GETSSL_CMD_HOST" } # start nginx in background on alpine via supervisord @@ -68,6 +68,9 @@ fi export GETSSL_IP +GETSSL_CMD_HOST=$GETSSL_HOST +export GETSSL_CMD_HOST + if [ ! -f ${INSTALL_DIR}/pebble.minica.pem ]; then wget --quiet --no-clobber https://raw.githubusercontent.com/letsencrypt/pebble/master/test/certs/pebble.minica.pem 2>&1 CERT_FILE=/etc/ssl/certs/ca-certificates.crt From e50362501d3bee59fb092891cdd1a84efe6aedb8 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 8 Apr 2020 18:59:16 +0100 Subject: [PATCH 040/308] Update revision history and version number --- getssl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 45d63cd..a0c530c 100755 --- a/getssl +++ b/getssl @@ -218,10 +218,12 @@ # 2020-03-12 Fix bug with DNS validation and multiple domains (#524) # 2020-03-24 Find primary ns using all dns utils (dig, host, nslookup) # 2020-03-23 Fix staging server URL in domain template (2.21) +# 2020-03-30 Fix error message find_dns_utils from over version of "command" +# 2020-03-30 Fix problems if domain name isn't in lowercase (2.22) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} -VERSION="2.21" +VERSION="2.22" # defaults ACCOUNT_KEY_LENGTH=4096 From a73848c60eb3a675ff5f1b11c2f9d1b8db8050ad Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 8 Apr 2020 21:21:15 +0100 Subject: [PATCH 041/308] Check domain exists using all DNS utilities --- getssl | 63 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/getssl b/getssl index a0c530c..4c83b53 100755 --- a/getssl +++ b/getssl @@ -440,39 +440,42 @@ check_config() { # check the config files for all obvious errors info "${DOMAIN}: ACL location not specified for domain $d in $DOMAIN_DIR/getssl.cfg" config_errors=true fi - # check domain exists - if [[ "$DNS_CHECK_FUNC" == "drill" ]]; then - if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c -i "${d}")" -ge 1 ]]; then - debug "found IP for ${d}" - else - info "${DOMAIN}: DNS lookup failed for ${d}" - config_errors=true + + # check domain exists using all DNS utilities + found_ip=false + if [[ -n "$HAS_DIG_OR_DRILL" ]]; then + debug "DNS lookup using $HAS_DIG_OR_DRILL ${d}" + if [[ "$($HAS_DIG_OR_DRILL -t SOA "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then + found_ip=true + elif [[ "$($HAS_DIG_OR_DRILL -t A "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then + found_ip=true + elif [[ "$($HAS_DIG_OR_DRILL -t AAAA "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then + found_ip=true fi - elif [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - if [[ "$($DNS_CHECK_FUNC "${d}" -t SOA|grep -c -i "^${d}")" -ge 1 ]]; then - debug "found SOA IP for ${d}" - elif [[ "$($DNS_CHECK_FUNC "${d}" -t A|grep -c -i "^${d}")" -ge 1 ]]; then - debug "found A IP for ${d}" - else - info "${DOMAIN}: DNS lookup failed for ${d}" - config_errors=true + fi + + if [[ -n "$HAS_HOST" ]]; then + debug "DNS lookup using host ${d}" + if [[ "$(host "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then + found_ip=true fi - elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then - if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then - debug "found IP for ${d}" - else - info "${DOMAIN}: DNS lookup failed for ${d}" - config_errors=true + fi + + if [[ -n "$HAS_NSLOOKUP" ]]; then + debug "DNS lookup using nslookup -query AAAA ${d}" + if [[ "$(nslookup -query=AAAA "${d}"|grep -c -i "^${d}.*has AAAA address")" -ge 1 ]]; then + debug "found IPv6 record for ${d}" + found_ip=true + elif [[ "$(nslookup "${d}"| grep -c ^Name)" -ge 1 ]]; then + debug "found IPv4 record for ${d}" fi - elif [[ "$(nslookup -query=AAAA "${d}"|grep -c -i "^${d}.*has AAAA address")" -ge 1 ]]; then - debug "found IPv6 record for ${d}" - elif [[ "$(nslookup "${d}"| grep -c ^Name)" -ge 1 ]]; then - debug "found IPv4 record for ${d}" - else + fi + + if [[ "$found_ip" == "false" ]]; then info "${DOMAIN}: DNS lookup failed for $d" config_errors=true fi - fi # end using http-01 challenge + fi # end using dns-01 challenge ((dn++)) done @@ -2345,12 +2348,12 @@ fi # from SERVER_TYPE set REMOTE_PORT and REMOTE_EXTRA set_server_type -# check config for typical errors. -check_config - # check what dns utils are installed find_dns_utils +# check config for typical errors. +check_config + if [[ -e "$DOMAIN_DIR/FORCE_RENEWAL" ]]; then rm -f "$DOMAIN_DIR/FORCE_RENEWAL" || error_exit "problem deleting file $DOMAIN_DIR/FORCE_RENEWAL" _FORCE_RENEW=1 From 17203b1ec1e9962d1fcbe88fa87a5efac73707a9 Mon Sep 17 00:00:00 2001 From: Juan Javier Baca Date: Thu, 16 Apr 2020 04:41:44 +0200 Subject: [PATCH 042/308] Add alternative working dirs Despite changing working dir from command line covers most usage cases, others defaults are also usefull like /etc/getssl, SCRIPTDIR/conf or SCRIPTDIR/.getssl. Last candidate (~/.getssl) is used if no config file was found in previous paths. --- getssl | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index a0c530c..a465376 100755 --- a/getssl +++ b/getssl @@ -220,6 +220,7 @@ # 2020-03-23 Fix staging server URL in domain template (2.21) # 2020-03-30 Fix error message find_dns_utils from over version of "command" # 2020-03-30 Fix problems if domain name isn't in lowercase (2.22) +# 2020-04-16 Add alternative working dirs '/etc/getssl/' '${SCRIPTDIR}/conf' '${SCRIPTDIR}/.getssl' # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} @@ -261,7 +262,7 @@ TEMP_UPGRADE_FILE="" TOKEN_USER_ID="" USE_SINGLE_ACL="false" VALIDATE_VIA_DNS="" -WORKING_DIR=~/.getssl +WORKING_DIR_CANDIDATES=('/etc/getssl/' '${SCRIPTDIR}/conf' '${SCRIPTDIR}/.getssl' '~/.getssl') _CHECK_ALL=0 _CREATE_CONFIG=0 _FORCE_RENEW=0 @@ -2179,6 +2180,7 @@ requires which requires openssl requires curl requires dig nslookup drill host DNS_CHECK_FUNC +requires dirname requires awk requires tr requires date @@ -2216,6 +2218,22 @@ if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]]; then graceful_exit fi +# Test working directory candidates if unset. Last candidate defaults (~/getssl/) +if [[ -z "${WORKING_DIR}" ]] +then + SCRIPTDIR="$(cd "$(dirname "$0")"; pwd -P;)" + for WDCC in $(seq 0 $((${#WORKING_DIR_CANDIDATES[@]}-1)) ) + do + WORKING_DIR="$(eval echo "${WORKING_DIR_CANDIDATES[$WDCC]}")" + + debug "Testing working dir location '${WORKING_DIR}'" + if [[ -s "$WORKING_DIR/getssl.cfg" ]] + then + break + fi + done +fi + # if the "working directory" doesn't exist, then create it. if [[ ! -d "$WORKING_DIR" ]]; then debug "Making working directory - $WORKING_DIR" From 9dfff30b9d53e8271e1bc4908ad0704ac593ec5d Mon Sep 17 00:00:00 2001 From: Juan Javier Baca Date: Thu, 16 Apr 2020 04:44:16 +0200 Subject: [PATCH 043/308] Add -i|--install command line option While testing or setting up getssl the installation of certificates could fail. Option -i allows to copy and reload service quicker. --- getssl | 155 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 69 deletions(-) diff --git a/getssl b/getssl index a465376..8251911 100755 --- a/getssl +++ b/getssl @@ -221,6 +221,7 @@ # 2020-03-30 Fix error message find_dns_utils from over version of "command" # 2020-03-30 Fix problems if domain name isn't in lowercase (2.22) # 2020-04-16 Add alternative working dirs '/etc/getssl/' '${SCRIPTDIR}/conf' '${SCRIPTDIR}/.getssl' +# 2020-04-16 Add -i|--install command line option # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} @@ -305,6 +306,79 @@ cert_archive() { # Archive certificate file by copying files to dated archive d purge_archive "$DOMAIN_DIR" } +cert_install() { # copy certs to the correct location (creating concatenated files as required) + umask 077 + + copy_file_to_location "domain certificate" "$CERT_FILE" "$DOMAIN_CERT_LOCATION" + copy_file_to_location "private key" "$DOMAIN_DIR/${DOMAIN}.key" "$DOMAIN_KEY_LOCATION" + copy_file_to_location "CA certificate" "$CA_CERT" "$CA_CERT_LOCATION" + if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then + if [[ -n "$DOMAIN_CERT_LOCATION" ]]; then + copy_file_to_location "ec domain certificate" \ + "${CERT_FILE%.*}.ec.crt" \ + "${DOMAIN_CERT_LOCATION}" \ + "ec" + fi + if [[ -n "$DOMAIN_KEY_LOCATION" ]]; then + copy_file_to_location "ec private key" \ + "$DOMAIN_DIR/${DOMAIN}.ec.key" \ + "${DOMAIN_KEY_LOCATION}" \ + "ec" + fi + if [[ -n "$CA_CERT_LOCATION" ]]; then + copy_file_to_location "ec CA certificate" \ + "${CA_CERT%.*}.ec.crt" \ + "${CA_CERT_LOCATION%.*}.crt" \ + "ec" + fi + fi + + # if DOMAIN_CHAIN_LOCATION is not blank, then create and copy file. + if [[ -n "$DOMAIN_CHAIN_LOCATION" ]]; then + if [[ "$(dirname "$DOMAIN_CHAIN_LOCATION")" == "." ]]; then + to_location="${DOMAIN_DIR}/${DOMAIN_CHAIN_LOCATION}" + else + to_location="${DOMAIN_CHAIN_LOCATION}" + fi + cat "$CERT_FILE" "$CA_CERT" > "$TEMP_DIR/${DOMAIN}_chain.pem" + copy_file_to_location "full chain" "$TEMP_DIR/${DOMAIN}_chain.pem" "$to_location" + if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then + cat "${CERT_FILE%.*}.ec.crt" "${CA_CERT%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}_chain.pem.ec" + copy_file_to_location "full chain" "$TEMP_DIR/${DOMAIN}_chain.pem.ec" "${to_location}" "ec" + fi + fi + # if DOMAIN_KEY_CERT_LOCATION is not blank, then create and copy file. + if [[ -n "$DOMAIN_KEY_CERT_LOCATION" ]]; then + if [[ "$(dirname "$DOMAIN_KEY_CERT_LOCATION")" == "." ]]; then + to_location="${DOMAIN_DIR}/${DOMAIN_KEY_CERT_LOCATION}" + else + to_location="${DOMAIN_KEY_CERT_LOCATION}" + fi + cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" > "$TEMP_DIR/${DOMAIN}_K_C.pem" + copy_file_to_location "private key and domain cert pem" "$TEMP_DIR/${DOMAIN}_K_C.pem" "$to_location" + if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then + cat "$DOMAIN_DIR/${DOMAIN}.ec.key" "${CERT_FILE%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}_K_C.pem.ec" + copy_file_to_location "private ec key and domain cert pem" "$TEMP_DIR/${DOMAIN}_K_C.pem.ec" "${to_location}" "ec" + fi + fi + # if DOMAIN_PEM_LOCATION is not blank, then create and copy file. + if [[ -n "$DOMAIN_PEM_LOCATION" ]]; then + if [[ "$(dirname "$DOMAIN_PEM_LOCATION")" == "." ]]; then + to_location="${DOMAIN_DIR}/${DOMAIN_PEM_LOCATION}" + else + to_location="${DOMAIN_PEM_LOCATION}" + fi + cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" "$CA_CERT" > "$TEMP_DIR/${DOMAIN}.pem" + copy_file_to_location "full key, cert and chain pem" "$TEMP_DIR/${DOMAIN}.pem" "$to_location" + if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then + cat "$DOMAIN_DIR/${DOMAIN}.ec.key" "${CERT_FILE%.*}.ec.crt" "${CA_CERT%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}.pem.ec" + copy_file_to_location "full ec key, cert and chain pem" "$TEMP_DIR/${DOMAIN}.pem.ec" "${to_location}" "ec" + fi + fi + # end of copying certs. + umask "$ORIG_UMASK" +} + check_challenge_completion() { # checks with the ACME server if our challenge is OK uri=$1 domain=$2 @@ -1410,6 +1484,7 @@ help_message() { # print out the help message -c, --create Create default config files -f, --force Force renewal of cert (overrides expiry checks) -h, --help Display this help message and exit + -i, --install Install certificates and reload service -q, --quiet Quiet mode (only outputs on error, success of new cert, or getssl was upgraded) -Q, --mute Like -q, but also mute notification about successful upgrade -r, --revoke "cert" "key" [CA_server] Revoke a certificate (the cert and key are required) @@ -2146,6 +2221,8 @@ while [[ -n ${1+defined} ]]; do _UPGRADE=1 ;; -U | --nocheck) _UPGRADE_CHECK=0 ;; + -i | --install) + _CERT_INSTALL=1 ;; -w) shift; WORKING_DIR="$1" ;; -*) @@ -2369,6 +2446,14 @@ check_config # check what dns utils are installed find_dns_utils +# if -i|--install install certs, reload and exit +if [ "0${_CERT_INSTALL}" -eq 1 ] +then + cert_install + reload_service + graceful_exit +fi + if [[ -e "$DOMAIN_DIR/FORCE_RENEWAL" ]]; then rm -f "$DOMAIN_DIR/FORCE_RENEWAL" || error_exit "problem deleting file $DOMAIN_DIR/FORCE_RENEWAL" _FORCE_RENEW=1 @@ -2647,76 +2732,8 @@ cert_archive debug "Certificates obtained and archived locally, will now copy to specified locations" # copy certs to the correct location (creating concatenated files as required) -umask 077 - -copy_file_to_location "domain certificate" "$CERT_FILE" "$DOMAIN_CERT_LOCATION" -copy_file_to_location "private key" "$DOMAIN_DIR/${DOMAIN}.key" "$DOMAIN_KEY_LOCATION" -copy_file_to_location "CA certificate" "$CA_CERT" "$CA_CERT_LOCATION" -if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - if [[ -n "$DOMAIN_CERT_LOCATION" ]]; then - copy_file_to_location "ec domain certificate" \ - "${CERT_FILE%.*}.ec.crt" \ - "${DOMAIN_CERT_LOCATION}" \ - "ec" - fi - if [[ -n "$DOMAIN_KEY_LOCATION" ]]; then - copy_file_to_location "ec private key" \ - "$DOMAIN_DIR/${DOMAIN}.ec.key" \ - "${DOMAIN_KEY_LOCATION}" \ - "ec" - fi - if [[ -n "$CA_CERT_LOCATION" ]]; then - copy_file_to_location "ec CA certificate" \ - "${CA_CERT%.*}.ec.crt" \ - "${CA_CERT_LOCATION%.*}.crt" \ - "ec" - fi -fi +cert_install -# if DOMAIN_CHAIN_LOCATION is not blank, then create and copy file. -if [[ -n "$DOMAIN_CHAIN_LOCATION" ]]; then - if [[ "$(dirname "$DOMAIN_CHAIN_LOCATION")" == "." ]]; then - to_location="${DOMAIN_DIR}/${DOMAIN_CHAIN_LOCATION}" - else - to_location="${DOMAIN_CHAIN_LOCATION}" - fi - cat "$CERT_FILE" "$CA_CERT" > "$TEMP_DIR/${DOMAIN}_chain.pem" - copy_file_to_location "full chain" "$TEMP_DIR/${DOMAIN}_chain.pem" "$to_location" - if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - cat "${CERT_FILE%.*}.ec.crt" "${CA_CERT%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}_chain.pem.ec" - copy_file_to_location "full chain" "$TEMP_DIR/${DOMAIN}_chain.pem.ec" "${to_location}" "ec" - fi -fi -# if DOMAIN_KEY_CERT_LOCATION is not blank, then create and copy file. -if [[ -n "$DOMAIN_KEY_CERT_LOCATION" ]]; then - if [[ "$(dirname "$DOMAIN_KEY_CERT_LOCATION")" == "." ]]; then - to_location="${DOMAIN_DIR}/${DOMAIN_KEY_CERT_LOCATION}" - else - to_location="${DOMAIN_KEY_CERT_LOCATION}" - fi - cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" > "$TEMP_DIR/${DOMAIN}_K_C.pem" - copy_file_to_location "private key and domain cert pem" "$TEMP_DIR/${DOMAIN}_K_C.pem" "$to_location" - if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - cat "$DOMAIN_DIR/${DOMAIN}.ec.key" "${CERT_FILE%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}_K_C.pem.ec" - copy_file_to_location "private ec key and domain cert pem" "$TEMP_DIR/${DOMAIN}_K_C.pem.ec" "${to_location}" "ec" - fi -fi -# if DOMAIN_PEM_LOCATION is not blank, then create and copy file. -if [[ -n "$DOMAIN_PEM_LOCATION" ]]; then - if [[ "$(dirname "$DOMAIN_PEM_LOCATION")" == "." ]]; then - to_location="${DOMAIN_DIR}/${DOMAIN_PEM_LOCATION}" - else - to_location="${DOMAIN_PEM_LOCATION}" - fi - cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" "$CA_CERT" > "$TEMP_DIR/${DOMAIN}.pem" - copy_file_to_location "full key, cert and chain pem" "$TEMP_DIR/${DOMAIN}.pem" "$to_location" - if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - cat "$DOMAIN_DIR/${DOMAIN}.ec.key" "${CERT_FILE%.*}.ec.crt" "${CA_CERT%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}.pem.ec" - copy_file_to_location "full ec key, cert and chain pem" "$TEMP_DIR/${DOMAIN}.pem.ec" "${to_location}" "ec" - fi -fi -# end of copying certs. -umask "$ORIG_UMASK" # Run reload command to restart apache / nginx or whatever system reload_service From 17b13facdad9ed3cd74ee6da84dd3fb93501c009 Mon Sep 17 00:00:00 2001 From: Juan Javier Baca Date: Thu, 16 Apr 2020 04:45:08 +0200 Subject: [PATCH 044/308] Update revision history and version number --- getssl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 8251911..b278193 100755 --- a/getssl +++ b/getssl @@ -221,11 +221,11 @@ # 2020-03-30 Fix error message find_dns_utils from over version of "command" # 2020-03-30 Fix problems if domain name isn't in lowercase (2.22) # 2020-04-16 Add alternative working dirs '/etc/getssl/' '${SCRIPTDIR}/conf' '${SCRIPTDIR}/.getssl' -# 2020-04-16 Add -i|--install command line option +# 2020-04-16 Add -i|--install command line option (2.23) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} -VERSION="2.22" +VERSION="2.23" # defaults ACCOUNT_KEY_LENGTH=4096 From 7e575fb030bf29a544c4650400667f2be0df384e Mon Sep 17 00:00:00 2001 From: Juan Javier Baca Moreno-Torres Date: Sat, 18 Apr 2020 01:46:02 +0200 Subject: [PATCH 045/308] Update shell-linter to 0.3.0 --- .github/workflows/shellcheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index d5adbf5..37b9cad 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -12,6 +12,6 @@ jobs: steps: - uses: actions/checkout@v1 - name: Lint check - uses: azohra/shell-linter@v0.2.0 + uses: azohra/shell-linter@v0.3.0 with: path: "getssl" From adcb9752065880efc03da23ea03efa4acb176304 Mon Sep 17 00:00:00 2001 From: Juan Javier Baca Moreno-Torres Date: Sat, 18 Apr 2020 02:10:09 +0200 Subject: [PATCH 046/308] Fix shellcheck warning and failures Clean code, avoid indirect variables and single quotes for delayed expansion. --- getssl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/getssl b/getssl index b278193..bcaa37f 100755 --- a/getssl +++ b/getssl @@ -220,11 +220,12 @@ # 2020-03-23 Fix staging server URL in domain template (2.21) # 2020-03-30 Fix error message find_dns_utils from over version of "command" # 2020-03-30 Fix problems if domain name isn't in lowercase (2.22) -# 2020-04-16 Add alternative working dirs '/etc/getssl/' '${SCRIPTDIR}/conf' '${SCRIPTDIR}/.getssl' +# 2020-04-16 Add alternative working dirs '/etc/getssl/' '${PROGDIR}/conf' '${PROGDIR}/.getssl' # 2020-04-16 Add -i|--install command line option (2.23) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} +PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" VERSION="2.23" # defaults @@ -263,7 +264,7 @@ TEMP_UPGRADE_FILE="" TOKEN_USER_ID="" USE_SINGLE_ACL="false" VALIDATE_VIA_DNS="" -WORKING_DIR_CANDIDATES=('/etc/getssl/' '${SCRIPTDIR}/conf' '${SCRIPTDIR}/.getssl' '~/.getssl') +WORKING_DIR_CANDIDATES=("/etc/getssl/" "${PROGDIR}/conf" "${PROGDIR}/.getssl" "${HOME}/.getssl") _CHECK_ALL=0 _CREATE_CONFIG=0 _FORCE_RENEW=0 @@ -2298,7 +2299,6 @@ fi # Test working directory candidates if unset. Last candidate defaults (~/getssl/) if [[ -z "${WORKING_DIR}" ]] then - SCRIPTDIR="$(cd "$(dirname "$0")"; pwd -P;)" for WDCC in $(seq 0 $((${#WORKING_DIR_CANDIDATES[@]}-1)) ) do WORKING_DIR="$(eval echo "${WORKING_DIR_CANDIDATES[$WDCC]}")" From 008a95dba778b2947c408444d93fb121a74621d3 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 18 Apr 2020 14:36:33 +0100 Subject: [PATCH 047/308] Make ubuntu-staging depend on centos7-staging so they don't run at same time causing spurious errors --- .github/workflows/run-all-tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/run-all-tests.yml b/.github/workflows/run-all-tests.yml index ff0e121..08fb41b 100644 --- a/.github/workflows/run-all-tests.yml +++ b/.github/workflows/run-all-tests.yml @@ -72,6 +72,7 @@ jobs: - name: Run test suite on Ubuntu18 run: test/run-test.sh ubuntu18 test-ubuntu-staging: + needs: test-centos7-staging runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 From 3341f674d422bdbc1ce7b5012278ce62b58596c3 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 18 Apr 2020 14:36:59 +0100 Subject: [PATCH 048/308] Add tests for /etc/getssl and --install --- test/11-test--install.bats | 69 ++++++++++++++++++++++++ test/test-config/getssl-etc-template.cfg | 45 ++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 test/11-test--install.bats create mode 100644 test/test-config/getssl-etc-template.cfg diff --git a/test/11-test--install.bats b/test/11-test--install.bats new file mode 100644 index 0000000..0b5bbc7 --- /dev/null +++ b/test/11-test--install.bats @@ -0,0 +1,69 @@ +#! /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 "Check that config files in /etc/getssl works" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + CONFIG_FILE="getssl-http01.cfg" + setup_environment + + # Create /etc/getssl/$DOMAIN + rm -rf /etc/getssl + mkdir -p /etc/getssl/${GETSSL_CMD_HOST} + + # Copy the config file to /etc/getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "/etc/getssl/${GETSSL_CMD_HOST}/getssl.cfg" + cp "${CODE_DIR}/test/test-config/getssl-etc-template.cfg" "/etc/getssl/getssl.cfg" + + # Run getssl + run ${CODE_DIR}/getssl "$GETSSL_CMD_HOST" + + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + assert_line 'Verification completed, obtaining certificate.' + assert_line 'Requesting certificate' + refute [ -d '$HOME/.getssl' ] +} + + +@test "Check that --install doesn't call the ACME server" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + CONFIG_FILE="getssl-http01.cfg" + #setup_environment + + # Create /etc/getssl/$DOMAIN + #mkdir -p /etc/getssl/${GETSSL_CMD_HOST} + + # Copy the config file to /etc/getssl + #cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "/etc/getssl/${GETSSL_CMD_HOST}/getssl.cfg" + #cp "${CODE_DIR}/test/test-config/getssl-etc-template.cfg" "/etc/getssl/getssl.cfg" + + # Run getssl + run ${CODE_DIR}/getssl --install "$GETSSL_CMD_HOST" + + assert_success + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + refute_line 'Verification completed, obtaining certificate.' + refute_line 'Requesting certificate' + assert_line --partial 'copying domain certificate to' + assert_line --partial 'copying private key to' + assert_line --partial 'copying CA certificate to' +} diff --git a/test/test-config/getssl-etc-template.cfg b/test/test-config/getssl-etc-template.cfg new file mode 100644 index 0000000..6bfc8fd --- /dev/null +++ b/test/test-config/getssl-etc-template.cfg @@ -0,0 +1,45 @@ +# vim: filetype=sh +# +# This file is read first and is common to all domains +# +# Uncomment and modify any variables you need +# see https://github.com/srvrco/getssl/wiki/Config-variables for details +# +# The staging server is best for testing (hence set as default) +CA="https://acme-staging-v02.api.letsencrypt.org" +# This server issues full certificates, however has rate limits +#CA="https://acme-v02.api.letsencrypt.org" + +# The agreement that must be signed with the CA, if not defined the default agreement will be used +#AGREEMENT="" + +# Set an email address associated with your account - generally set at account level rather than domain. +#ACCOUNT_EMAIL="me@example.com" +ACCOUNT_KEY_LENGTH=4096 +ACCOUNT_KEY="/etc/getssl/account.key" + +# Account key and private key types - can be rsa, prime256v1, secp384r1 or secp521r1 +#ACCOUNT_KEY_TYPE="rsa" +PRIVATE_KEY_ALG="rsa" +#REUSE_PRIVATE_KEY="true" + +# The command needed to reload apache / nginx or whatever you use +#RELOAD_CMD="" + +# The time period within which you want to allow renewal of a certificate +# this prevents hitting some of the rate limits. +# Creating a file called FORCE_RENEWAL in the domain directory allows one-off overrides +# of this setting +RENEW_ALLOW="30" + +# 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" + +# Use the following 3 variables if you want to validate via DNS +#VALIDATE_VIA_DNS="true" +#DNS_ADD_COMMAND= +#DNS_DEL_COMMAND= From 857ad87b4f21ca7a8f2c78fe727f620c9ad8c7f1 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 18 Apr 2020 14:37:33 +0100 Subject: [PATCH 049/308] Change bats-assert and bats-support to use bats-core repo --- test/Dockerfile-alpine | 4 ++-- test/Dockerfile-centos6 | 4 ++-- test/Dockerfile-centos7 | 4 ++-- test/Dockerfile-centos7-staging | 4 ++-- test/Dockerfile-debian | 4 ++-- test/Dockerfile-ubuntu | 4 ++-- test/Dockerfile-ubuntu-staging | 4 ++-- test/Dockerfile-ubuntu16 | 4 ++-- test/Dockerfile-ubuntu18 | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/test/Dockerfile-alpine b/test/Dockerfile-alpine index 0c166cb..caad22a 100644 --- a/test/Dockerfile-alpine +++ b/test/Dockerfile-alpine @@ -13,8 +13,8 @@ RUN mkdir /etc/nginx/pki/private # 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 git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Use supervisord to run nginx in the background diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index 9149dad..61c8b6b 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -14,8 +14,8 @@ 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 git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local EXPOSE 80 443 diff --git a/test/Dockerfile-centos7 b/test/Dockerfile-centos7 index 8a34bc5..02fbcb7 100644 --- a/test/Dockerfile-centos7 +++ b/test/Dockerfile-centos7 @@ -15,6 +15,6 @@ COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.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 git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-centos7-staging b/test/Dockerfile-centos7-staging index 839ff76..899bf9b 100644 --- a/test/Dockerfile-centos7-staging +++ b/test/Dockerfile-centos7-staging @@ -18,8 +18,8 @@ COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.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 git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local EXPOSE 80 443 diff --git a/test/Dockerfile-debian b/test/Dockerfile-debian index 95ebbac..b5da5dd 100644 --- a/test/Dockerfile-debian +++ b/test/Dockerfile-debian @@ -12,8 +12,8 @@ RUN mkdir /etc/nginx/pki/private # 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 git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index 290100d..720f0b0 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -15,8 +15,8 @@ RUN touch /root/.rnd # 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 git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-staging index 0bdc1f8..84022ca 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-staging @@ -17,8 +17,8 @@ RUN touch /root/.rnd # 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 git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing diff --git a/test/Dockerfile-ubuntu16 b/test/Dockerfile-ubuntu16 index 958bb6f..030d03a 100644 --- a/test/Dockerfile-ubuntu16 +++ b/test/Dockerfile-ubuntu16 @@ -17,8 +17,8 @@ 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 /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 git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing diff --git a/test/Dockerfile-ubuntu18 b/test/Dockerfile-ubuntu18 index ebe7607..1d68cd3 100644 --- a/test/Dockerfile-ubuntu18 +++ b/test/Dockerfile-ubuntu18 @@ -17,8 +17,8 @@ RUN touch /root/.rnd # 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 git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local EXPOSE 80 443 From ac5ef3301107a6e42ebfc105dac405d8bfaf7a52 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 18 Apr 2020 15:12:40 +0100 Subject: [PATCH 050/308] Cleanup after test succeeds --- test/11-test--install.bats | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/test/11-test--install.bats b/test/11-test--install.bats index 0b5bbc7..6949d25 100644 --- a/test/11-test--install.bats +++ b/test/11-test--install.bats @@ -18,8 +18,10 @@ setup() { CONFIG_FILE="getssl-http01.cfg" setup_environment + # Fail if not running in docker and /etc/getssl already exists + refute [ -d /etc/getssl ] + # Create /etc/getssl/$DOMAIN - rm -rf /etc/getssl mkdir -p /etc/getssl/${GETSSL_CMD_HOST} # Copy the config file to /etc/getssl @@ -40,19 +42,12 @@ setup() { @test "Check that --install doesn't call the ACME server" { + # NOTE that this test depends on the previous test! if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi CONFIG_FILE="getssl-http01.cfg" - #setup_environment - - # Create /etc/getssl/$DOMAIN - #mkdir -p /etc/getssl/${GETSSL_CMD_HOST} - - # Copy the config file to /etc/getssl - #cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "/etc/getssl/${GETSSL_CMD_HOST}/getssl.cfg" - #cp "${CODE_DIR}/test/test-config/getssl-etc-template.cfg" "/etc/getssl/getssl.cfg" # Run getssl run ${CODE_DIR}/getssl --install "$GETSSL_CMD_HOST" @@ -66,4 +61,7 @@ setup() { assert_line --partial 'copying domain certificate to' assert_line --partial 'copying private key to' assert_line --partial 'copying CA certificate to' + + # Cleanup previous test + rm -rf /etc/getssl } From 43b82e4fc39f024d05a30abe36df62a9c10a430d Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 18 Apr 2020 15:31:48 +0100 Subject: [PATCH 051/308] Fix cut&paste error --- test/Dockerfile-ubuntu-staging | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-staging index 84022ca..552f096 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-staging @@ -17,7 +17,7 @@ RUN touch /root/.rnd # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local From d8bf2fa14936912071b6069705daf0d02066aabc Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 19 Apr 2020 14:13:29 +0100 Subject: [PATCH 052/308] Remove dependency on seq, ensure clean_up doesn't try to delete /tmp --- getssl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index bcaa37f..0fd4431 100755 --- a/getssl +++ b/getssl @@ -222,11 +222,12 @@ # 2020-03-30 Fix problems if domain name isn't in lowercase (2.22) # 2020-04-16 Add alternative working dirs '/etc/getssl/' '${PROGDIR}/conf' '${PROGDIR}/.getssl' # 2020-04-16 Add -i|--install command line option (2.23) +# 2020-04-19 Remove dependency on seq, ensure clean_up doesn't try to delete /tmp (2.24) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.23" +VERSION="2.24" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -633,7 +634,11 @@ clean_up() { # Perform pre-exit housekeeping shopt -u nullglob fi if [[ -n "$DOMAIN_DIR" ]]; then - rm -rf "${TEMP_DIR:?}" + if [ "${TEMP_DIR}" -ef "/tmp" ]; then + info "Not going to delete TEMP_DIR ${TEMP_DIR} as it appears to be /tmp" + else + rm -rf "${TEMP_DIR:?}" + fi fi if [[ -n "$TEMP_UPGRADE_FILE" ]] && [[ -f "$TEMP_UPGRADE_FILE" ]]; then rm -f "$TEMP_UPGRADE_FILE" @@ -2299,10 +2304,8 @@ fi # Test working directory candidates if unset. Last candidate defaults (~/getssl/) if [[ -z "${WORKING_DIR}" ]] then - for WDCC in $(seq 0 $((${#WORKING_DIR_CANDIDATES[@]}-1)) ) + for WORKING_DIR in "${WORKING_DIR_CANDIDATES[@]}" do - WORKING_DIR="$(eval echo "${WORKING_DIR_CANDIDATES[$WDCC]}")" - debug "Testing working dir location '${WORKING_DIR}'" if [[ -s "$WORKING_DIR/getssl.cfg" ]] then From 462573c8ba17d82730ac69de9b201b377eb7f96d Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 19 Apr 2020 14:13:55 +0100 Subject: [PATCH 053/308] Test if DOMAIN_STORAGE is "/" clean_up doesn't delete /tmp --- test/11-test-no-domain-storage.bats | 19 ++++++++++++ .../getssl-http01-no-domain-storage.cfg | 31 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 test/11-test-no-domain-storage.bats create mode 100644 test/test-config/getssl-http01-no-domain-storage.cfg diff --git a/test/11-test-no-domain-storage.bats b/test/11-test-no-domain-storage.bats new file mode 100644 index 0000000..cefac3f --- /dev/null +++ b/test/11-test-no-domain-storage.bats @@ -0,0 +1,19 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +@test "Check that if domain storage isn't set getssl doesn't try to delete /tmp" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01-no-domain-storage.cfg" + setup_environment + mkdir ${INSTALL_DIR}/.getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" + run ${CODE_DIR}/getssl -a + assert_success + assert_line 'Not going to delete TEMP_DIR ///tmp as it appears to be /tmp' +} diff --git a/test/test-config/getssl-http01-no-domain-storage.cfg b/test/test-config/getssl-http01-no-domain-storage.cfg new file mode 100644 index 0000000..efa5318 --- /dev/null +++ b/test/test-config/getssl-http01-no-domain-storage.cfg @@ -0,0 +1,31 @@ +# 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 +SANS="" + +# Acme Challenge Location. +ACL=('/var/www/html/.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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" + +DOMAIN_STORAGE="/" From f7c196602d2067e5da7171b6f9be2bef01456f39 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 20 Apr 2020 21:26:04 +0100 Subject: [PATCH 054/308] Update revision history and version --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 2c0c794..35cfbe2 100755 --- a/getssl +++ b/getssl @@ -223,11 +223,12 @@ # 2020-04-16 Add alternative working dirs '/etc/getssl/' '${PROGDIR}/conf' '${PROGDIR}/.getssl' # 2020-04-16 Add -i|--install command line option (2.23) # 2020-04-19 Remove dependency on seq, ensure clean_up doesn't try to delete /tmp (2.24) +# 2020-04-20 Check for domain using all DNS utilities (2.25) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.24" +VERSION="2.25" # defaults ACCOUNT_KEY_LENGTH=4096 From a0c6ddf0797334e302405a0ef55deaa3a82ac64a Mon Sep 17 00:00:00 2001 From: Robert Wolf Date: Wed, 22 Apr 2020 09:12:38 +0200 Subject: [PATCH 055/308] fix HAS_HOST and HAS_NSLOOKUP condition --- getssl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 35cfbe2..a6fc1dc 100755 --- a/getssl +++ b/getssl @@ -532,14 +532,14 @@ check_config() { # check the config files for all obvious errors fi fi - if [[ -n "$HAS_HOST" ]]; then + if [[ "$HAS_HOST" == true ]]; then debug "DNS lookup using host ${d}" if [[ "$(host "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then found_ip=true fi fi - if [[ -n "$HAS_NSLOOKUP" ]]; then + if [[ "$HAS_NSLOOKUP" == true ]]; then debug "DNS lookup using nslookup -query AAAA ${d}" if [[ "$(nslookup -query=AAAA "${d}"|grep -c -i "^${d}.*has AAAA address")" -ge 1 ]]; then debug "found IPv6 record for ${d}" From 23d4d6ae65574a83e9cc9369260c80d4c556045f Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 22 Apr 2020 17:55:25 +0100 Subject: [PATCH 056/308] Move test for failed,warning,error to test_helper, add test for "not found" --- test/1-simple-http01.bats | 8 +--- test/10-mixed-case-staging.bats | 4 +- test/10-mixed-case.bats | 8 +--- test/11-test--install.bats | 8 +--- test/11-test-no-domain-storage.bats | 1 + test/2-simple-dns01-dig.bats | 8 +--- test/2-simple-dns01-nslookup.bats | 5 +-- test/3-dual-rsa-ecdsa.bats | 4 ++ test/4-more-than-10-hosts.bats | 8 +--- test/5-secp384-http01.bats | 4 ++ test/6-dual-rsa-ecdsa-copy-2-locations.bats | 1 + test/7-staging-dns01-dig.bats | 8 +--- test/7-staging-dns01-nslookup.bats | 8 +--- test/8-staging-ecdsa.bats | 16 ++------ test/9-multiple-domains-dns01.bats | 12 ++---- test/9-test--all.bats | 4 +- test/test_helper.bash | 41 +++++++++++++-------- 17 files changed, 60 insertions(+), 88 deletions(-) diff --git a/test/1-simple-http01.bats b/test/1-simple-http01.bats index fd96a8a..6b37f86 100644 --- a/test/1-simple-http01.bats +++ b/test/1-simple-http01.bats @@ -20,9 +20,7 @@ setup() { init_getssl create_certificate assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors } @@ -32,8 +30,6 @@ setup() { fi run ${CODE_DIR}/getssl -f $GETSSL_HOST assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors cleanup_environment } diff --git a/test/10-mixed-case-staging.bats b/test/10-mixed-case-staging.bats index c1bac0d..ea622f7 100644 --- a/test/10-mixed-case-staging.bats +++ b/test/10-mixed-case-staging.bats @@ -18,7 +18,5 @@ load '/getssl/test/test_helper.bash' create_certificate assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors } diff --git a/test/10-mixed-case.bats b/test/10-mixed-case.bats index 2a4d6f3..b1d8f07 100644 --- a/test/10-mixed-case.bats +++ b/test/10-mixed-case.bats @@ -23,9 +23,7 @@ setup() { create_certificate assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors } @test "Check that DNS-01 verification works if the domain is not lowercase" { @@ -39,7 +37,5 @@ setup() { init_getssl create_certificate assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors } diff --git a/test/11-test--install.bats b/test/11-test--install.bats index 6949d25..e034326 100644 --- a/test/11-test--install.bats +++ b/test/11-test--install.bats @@ -32,9 +32,7 @@ setup() { run ${CODE_DIR}/getssl "$GETSSL_CMD_HOST" assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors assert_line 'Verification completed, obtaining certificate.' assert_line 'Requesting certificate' refute [ -d '$HOME/.getssl' ] @@ -53,9 +51,7 @@ setup() { run ${CODE_DIR}/getssl --install "$GETSSL_CMD_HOST" assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors refute_line 'Verification completed, obtaining certificate.' refute_line 'Requesting certificate' assert_line --partial 'copying domain certificate to' diff --git a/test/11-test-no-domain-storage.bats b/test/11-test-no-domain-storage.bats index cefac3f..3be0be5 100644 --- a/test/11-test-no-domain-storage.bats +++ b/test/11-test-no-domain-storage.bats @@ -15,5 +15,6 @@ load '/getssl/test/test_helper.bash' cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" run ${CODE_DIR}/getssl -a assert_success + check_output_for_errors assert_line 'Not going to delete TEMP_DIR ///tmp as it appears to be /tmp' } diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index cbac598..6803f15 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -22,9 +22,7 @@ setup() { create_certificate -d assert_success assert_output --partial "dig" - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' # don't fail for :error:badNonce - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors "debug" } @@ -35,8 +33,6 @@ setup() { run ${CODE_DIR}/getssl -d -f $GETSSL_HOST assert_success assert_output --partial "dig" - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' # don't fail for :error:badNonce - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors "debug" cleanup_environment } diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index 482be2a..7e675a8 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -32,8 +32,5 @@ teardown() { create_certificate -d assert_success assert_output --partial "nslookup" - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' # don't fail for :error:badNonce - # don't check for "Warnings:" as there might be a warning message if nslookup doesn't support -debug (alpine/ubuntu) - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' + check_output_for_errors "debug" } diff --git a/test/3-dual-rsa-ecdsa.bats b/test/3-dual-rsa-ecdsa.bats index 7820a96..d5c58f7 100644 --- a/test/3-dual-rsa-ecdsa.bats +++ b/test/3-dual-rsa-ecdsa.bats @@ -20,6 +20,7 @@ setup() { init_getssl create_certificate assert_success + check_output_for_errors } @@ -29,6 +30,7 @@ setup() { fi run ${CODE_DIR}/getssl -f $GETSSL_HOST assert_success + check_output_for_errors } @test "Create dual certificates using DNS-01 verification" { @@ -40,6 +42,7 @@ setup() { init_getssl create_certificate assert_success + check_output_for_errors } @@ -49,5 +52,6 @@ setup() { fi run ${CODE_DIR}/getssl -f $GETSSL_HOST assert_success + check_output_for_errors cleanup_environment } diff --git a/test/4-more-than-10-hosts.bats b/test/4-more-than-10-hosts.bats index bd93adc..f4eb95c 100644 --- a/test/4-more-than-10-hosts.bats +++ b/test/4-more-than-10-hosts.bats @@ -26,9 +26,7 @@ setup() { init_getssl create_certificate assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors } @@ -38,9 +36,7 @@ setup() { fi run ${CODE_DIR}/getssl -f $GETSSL_HOST assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors # Remove all the dns aliases cleanup_environment for prefix in a b c d e f g h i j k; do diff --git a/test/5-secp384-http01.bats b/test/5-secp384-http01.bats index 29da2da..3d05159 100644 --- a/test/5-secp384-http01.bats +++ b/test/5-secp384-http01.bats @@ -20,6 +20,7 @@ setup() { init_getssl create_certificate assert_success + check_output_for_errors } @@ -29,6 +30,7 @@ setup() { fi run ${CODE_DIR}/getssl -f $GETSSL_HOST assert_success + check_output_for_errors } @@ -41,6 +43,7 @@ setup() { init_getssl create_certificate assert_success + check_output_for_errors } @@ -50,4 +53,5 @@ setup() { fi run ${CODE_DIR}/getssl -f $GETSSL_HOST assert_success + check_output_for_errors } diff --git a/test/6-dual-rsa-ecdsa-copy-2-locations.bats b/test/6-dual-rsa-ecdsa-copy-2-locations.bats index 73363ec..394e8d6 100644 --- a/test/6-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/6-dual-rsa-ecdsa-copy-2-locations.bats @@ -32,6 +32,7 @@ teardown() { init_getssl create_certificate assert_success + check_output_for_errors # Check that the RSA chain and key have been copied to both locations assert [ -e "/etc/nginx/pki/domain-chain.crt" ] diff --git a/test/7-staging-dns01-dig.bats b/test/7-staging-dns01-dig.bats index 8c0d7f1..7e21124 100644 --- a/test/7-staging-dns01-dig.bats +++ b/test/7-staging-dns01-dig.bats @@ -16,9 +16,7 @@ load '/getssl/test/test_helper.bash' init_getssl create_certificate assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors } @test "Force renewal of certificate using staging server, dig and DuckDNS" { @@ -27,8 +25,6 @@ load '/getssl/test/test_helper.bash' fi run ${CODE_DIR}/getssl -f $GETSSL_HOST assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors cleanup_environment } diff --git a/test/7-staging-dns01-nslookup.bats b/test/7-staging-dns01-nslookup.bats index 027a210..bd8d9da 100644 --- a/test/7-staging-dns01-nslookup.bats +++ b/test/7-staging-dns01-nslookup.bats @@ -30,9 +30,7 @@ teardown() { init_getssl create_certificate assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' # ignore nslookup warnings + check_output_for_errors "debug" } @@ -42,8 +40,6 @@ teardown() { fi run ${CODE_DIR}/getssl -f $GETSSL_HOST assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' # ignore nslookup warnings + check_output_for_errors "debug" cleanup_environment } diff --git a/test/8-staging-ecdsa.bats b/test/8-staging-ecdsa.bats index 92c694a..127e989 100644 --- a/test/8-staging-ecdsa.bats +++ b/test/8-staging-ecdsa.bats @@ -18,9 +18,7 @@ load '/getssl/test/test_helper.bash' sed -e 's/rsa/prime256v1/g' < "${CODE_DIR}/test/test-config/${CONFIG_FILE}" > "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" run ${CODE_DIR}/getssl -d "$GETSSL_HOST" assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' # ignore nslookup warnings + check_output_for_errors "debug" } @@ -30,9 +28,7 @@ load '/getssl/test/test_helper.bash' fi run ${CODE_DIR}/getssl -d -f $GETSSL_HOST assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' # ignore nslookup warnings + check_output_for_errors "debug" cleanup_environment } @@ -48,9 +44,7 @@ load '/getssl/test/test_helper.bash' sed -e 's/rsa/secp384r1/g' < "${CODE_DIR}/test/test-config/${CONFIG_FILE}" > "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" run ${CODE_DIR}/getssl -d "$GETSSL_HOST" assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' + check_output_for_errors "debug" } @@ -60,9 +54,7 @@ load '/getssl/test/test_helper.bash' fi run ${CODE_DIR}/getssl -d -f $GETSSL_HOST assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' + check_output_for_errors "debug" cleanup_environment } diff --git a/test/9-multiple-domains-dns01.bats b/test/9-multiple-domains-dns01.bats index 2a9344f..c1de91c 100644 --- a/test/9-multiple-domains-dns01.bats +++ b/test/9-multiple-domains-dns01.bats @@ -25,9 +25,7 @@ setup() { init_getssl create_certificate assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors } @@ -38,9 +36,7 @@ setup() { fi run ${CODE_DIR}/getssl -f $GETSSL_HOST assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors # Remove all the dns aliases cleanup_environment curl --silent -X POST -d '{"host":"getssl.tst"}' http://10.30.50.3:8055/clear-a @@ -60,7 +56,5 @@ setup() { init_getssl create_certificate assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors } diff --git a/test/9-test--all.bats b/test/9-test--all.bats index 94a2c28..cb043a5 100644 --- a/test/9-test--all.bats +++ b/test/9-test--all.bats @@ -28,7 +28,5 @@ setup() { # Check success conditions assert_success - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + check_output_for_errors } diff --git a/test/test_helper.bash b/test/test_helper.bash index f4c62af..4af19dd 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -1,23 +1,31 @@ INSTALL_DIR=/root CODE_DIR=/getssl - -setup_environment() { - # One-off test setup - if [[ -d ${INSTALL_DIR}/.getssl ]]; then - rm -r ${INSTALL_DIR}/.getssl +check_output_for_errors() { + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + # less strict tests if running with debug output + if [ -n "$1" ]; then + # don't fail for :error:badNonce + refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' + # don't check for "Warnings:" as there might be a warning message if nslookup doesn't support -debug (alpine/ubuntu) + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' + else + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' fi - - curl --silent -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}" - /getssl/test/restart-nginx + refute_output --partial 'not found' } - cleanup_environment() { curl --silent -X POST -d '{"host":"'"$GETSSL_HOST"'"}' http://10.30.50.3:8055/clear-a } +create_certificate() { + # Create certificate + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + # shellcheck disable=SC2086 + run ${CODE_DIR}/getssl $1 "$GETSSL_CMD_HOST" +} init_getssl() { # Run initialisation (create account key, etc) @@ -26,12 +34,15 @@ init_getssl() { [ -d "$INSTALL_DIR/.getssl" ] } +setup_environment() { + # One-off test setup + if [[ -d ${INSTALL_DIR}/.getssl ]]; then + rm -r ${INSTALL_DIR}/.getssl + fi -create_certificate() { - # Create certificate - cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" - # shellcheck disable=SC2086 - run ${CODE_DIR}/getssl $1 "$GETSSL_CMD_HOST" + curl --silent -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}" + /getssl/test/restart-nginx } # start nginx in background on alpine via supervisord From 065356bcc8670df944d79855046b13d8532caaa9 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 22 Apr 2020 20:25:05 +0100 Subject: [PATCH 057/308] Tweak the 'not found' check --- test/test_helper.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_helper.bash b/test/test_helper.bash index 4af19dd..0aafa93 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -13,7 +13,7 @@ check_output_for_errors() { refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' fi - refute_output --partial 'not found' + refute_line --partial 'command not found' } cleanup_environment() { From 135fcece9253466f297bda627ace79042d8464d9 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 22 Apr 2020 20:29:31 +0100 Subject: [PATCH 058/308] Fix domain case conversion for different locales --- getssl | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/getssl b/getssl index a6fc1dc..f877ed5 100755 --- a/getssl +++ b/getssl @@ -224,11 +224,13 @@ # 2020-04-16 Add -i|--install command line option (2.23) # 2020-04-19 Remove dependency on seq, ensure clean_up doesn't try to delete /tmp (2.24) # 2020-04-20 Check for domain using all DNS utilities (2.25) +# 2020-04-22 Fix HAS_HOST and HAS_NSLOOKUP checks - wolfaba +# 2020-04-22 Fix domain case conversion for different locales (2.26) - glynge # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.25" +VERSION="2.26" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -532,14 +534,14 @@ check_config() { # check the config files for all obvious errors fi fi - if [[ "$HAS_HOST" == true ]]; then + if [[ "$HAS_HOST" == "true" ]]; then debug "DNS lookup using host ${d}" if [[ "$(host "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then found_ip=true fi fi - if [[ "$HAS_NSLOOKUP" == true ]]; then + if [[ "$HAS_NSLOOKUP" == "true" ]]; then debug "DNS lookup using nslookup -query AAAA ${d}" if [[ "$(nslookup -query=AAAA "${d}"|grep -c -i "^${d}.*has AAAA address")" -ge 1 ]]; then debug "found IPv6 record for ${d}" @@ -863,8 +865,7 @@ create_order() { dn=0 for d in $alldomains; do # Convert domain to lowercase as response from server will be in lowercase - # shellcheck disable=SC2018,SC2019 - d=$(echo "$d" | tr A-Z a-z) + d=$(echo "$d" | tr "[:upper:]" "[:lower:]") if [ "$d" == "$authdomain" ]; then debug "Saving authorization response for $authdomain for domain alldomains[$dn]" AuthLinkResponse[$dn]=$response @@ -1260,7 +1261,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n fi fi - if [[ "$HAS_HOST" == true ]]; then + if [[ "$HAS_HOST" == "true" ]]; then gad_d="$orig_gad_d" debug Using "host -t NS" to find primary name server for "$gad_d" if [[ -z "$gad_s" ]]; then @@ -1279,7 +1280,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n fi fi - if [[ "$HAS_NSLOOKUP" == true ]]; then + if [[ "$HAS_NSLOOKUP" == "true" ]]; then gad_d="$orig_gad_d" debug Using "nslookup -debug -type=soa -type=ns $gad_d $gad_s" to find primary name server res=$(nslookup -debug -type=soa -type=ns "$gad_d" ${gad_s}) From 472ea2312fdbe6766c8b7953d42a7c0ceb70a979 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 25 Apr 2020 12:37:24 +0100 Subject: [PATCH 059/308] Set noninteractive so tests don't hang --- test/Dockerfile-ubuntu | 3 +++ test/Dockerfile-ubuntu-staging | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index 720f0b0..66d7a35 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -2,6 +2,9 @@ FROM ubuntu:latest # Note this image uses mawk1.3 +# Set noninteractive otherwise tzdata hangs +ENV DEBIAN_FRONTEND noninteractive + # Update and install required software RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils wget nginx-light diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-staging index 552f096..58762d0 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-staging @@ -2,8 +2,13 @@ FROM ubuntu:latest # Note this image uses mawk1.3 +# Set noninteractive otherwise tzdata hangs +ENV DEBIAN_FRONTEND noninteractive + +# Ensure tests in this image use the staging server ENV staging "true" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb + # Update and install required software RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils wget nginx-light From 62e7cfce0fc6b28ad62675d0b916832c41b0a866 Mon Sep 17 00:00:00 2001 From: rhinoduck Date: Sun, 26 Apr 2020 09:57:41 +0000 Subject: [PATCH 060/308] Fix changelog formatting --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index f877ed5..54c95b1 100755 --- a/getssl +++ b/getssl @@ -225,7 +225,7 @@ # 2020-04-19 Remove dependency on seq, ensure clean_up doesn't try to delete /tmp (2.24) # 2020-04-20 Check for domain using all DNS utilities (2.25) # 2020-04-22 Fix HAS_HOST and HAS_NSLOOKUP checks - wolfaba -# 2020-04-22 Fix domain case conversion for different locales (2.26) - glynge +# 2020-04-22 Fix domain case conversion for different locales - glynge (2.26) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} From 7ec1e8648c2561263b2781cc8902cc0b67866f05 Mon Sep 17 00:00:00 2001 From: Harald Heigl Date: Sun, 26 Apr 2020 15:01:14 +0200 Subject: [PATCH 061/308] Fixed ipv4 confirmation with nslookup --- getssl | 1 + 1 file changed, 1 insertion(+) diff --git a/getssl b/getssl index 54c95b1..86943ee 100755 --- a/getssl +++ b/getssl @@ -548,6 +548,7 @@ check_config() { # check the config files for all obvious errors found_ip=true elif [[ "$(nslookup "${d}"| grep -c ^Name)" -ge 1 ]]; then debug "found IPv4 record for ${d}" + found_ip=true fi fi From 61fe4647ad2379b2eef6befc1fb4172253e2144c Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 26 Apr 2020 20:21:45 +0100 Subject: [PATCH 062/308] Add tests for #553 --- test/1-simple-http01-dig.bats | 40 ++++++++++++++++++++++++++++++ test/1-simple-http01-nslookup.bats | 40 ++++++++++++++++++++++++++++++ test/1-simple-http01.bats | 4 +-- test/2-simple-dns01-dig.bats | 17 ++++++++++++- test/2-simple-dns01-nslookup.bats | 6 +++++ 5 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 test/1-simple-http01-dig.bats create mode 100644 test/1-simple-http01-nslookup.bats diff --git a/test/1-simple-http01-dig.bats b/test/1-simple-http01-dig.bats new file mode 100644 index 0000000..be01f27 --- /dev/null +++ b/test/1-simple-http01-dig.bats @@ -0,0 +1,40 @@ +#! /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 + if [ -f /usr/bin/host ]; then + mv /usr/bin/host /usr/bin/host.getssl.bak + fi + if [ -f /usr/bin/nslookup ]; then + mv /usr/bin/nslookup /usr/bin/nslookup.getssl.bak + fi +} + + +teardown() { + if [ -f /usr/bin/host.getssl.bak ]; then + mv /usr/bin/host.getssl.bak /usr/bin/host + fi + if [ -f /usr/bin/nslookup.getssl.bak ]; then + mv /usr/bin/nslookup.getssl.bak /usr/bin/nslookup + fi +} + + +@test "Create new certificate using HTTP-01 verification (dig)" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors +} diff --git a/test/1-simple-http01-nslookup.bats b/test/1-simple-http01-nslookup.bats new file mode 100644 index 0000000..78d175a --- /dev/null +++ b/test/1-simple-http01-nslookup.bats @@ -0,0 +1,40 @@ +#! /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 + if [ -f /usr/bin/dig ]; then + mv /usr/bin/dig /usr/bin/dig.getssl.bak + fi + if [ -f /usr/bin/host ]; then + mv /usr/bin/host /usr/bin/host.getssl.bak + fi +} + + +teardown() { + if [ -f /usr/bin/dig.getssl.bak ]; then + mv /usr/bin/dig.getssl.bak /usr/bin/dig + fi + if [ -f /usr/bin/host.getssl.bak ]; then + mv /usr/bin/host.getssl.bak /usr/bin/host + fi +} + + +@test "Create new certificate using HTTP-01 verification (nslookup)" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors +} diff --git a/test/1-simple-http01.bats b/test/1-simple-http01.bats index 6b37f86..a57010b 100644 --- a/test/1-simple-http01.bats +++ b/test/1-simple-http01.bats @@ -11,7 +11,7 @@ setup() { } -@test "Create new certificate using HTTP-01 verification" { +@test "Create new certificate using HTTP-01 verification (any dns tool)" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi @@ -24,7 +24,7 @@ setup() { } -@test "Force renewal of certificate using HTTP-01" { +@test "Force renewal of certificate using HTTP-01 (any dns tool)" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index 6803f15..0a54684 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -5,9 +5,24 @@ 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 + if [ -f /usr/bin/host ]; then + mv /usr/bin/host /usr/bin/host.getssl.bak + fi + if [ -f /usr/bin/nslookup ]; then + mv /usr/bin/nslookup /usr/bin/nslookup.getssl.bak + fi +} + + +teardown() { + if [ -f /usr/bin/host.getssl.bak ]; then + mv /usr/bin/host.getssl.bak /usr/bin/host + fi + if [ -f /usr/bin/nslookup.getssl.bak ]; then + mv /usr/bin/nslookup.getssl.bak /usr/bin/nslookup + fi } diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index 7e675a8..dc6f2f5 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -11,6 +11,9 @@ setup() { if [ -f /usr/bin/dig ]; then mv /usr/bin/dig /usr/bin/dig.getssl.bak fi + if [ -f /usr/bin/host ]; then + mv /usr/bin/host /usr/bin/host.getssl.bak + fi } @@ -18,6 +21,9 @@ teardown() { if [ -f /usr/bin/dig.getssl.bak ]; then mv /usr/bin/dig.getssl.bak /usr/bin/dig fi + if [ -f /usr/bin/host.getssl.bak ]; then + mv /usr/bin/host.getssl.bak /usr/bin/host + fi } From 39ccc6bb0e9790a0264cd181644ed59da4ae3c42 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 29 Apr 2020 19:53:37 +0100 Subject: [PATCH 063/308] Fix ftp/sftp problems if challenge starts with a dash --- getssl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 86943ee..109d96d 100755 --- a/getssl +++ b/getssl @@ -700,7 +700,7 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. user $ftpuser $ftppass cd $ftpdirn lcd $fromdir - put $fromfile + put ./$fromfile _EOF elif [[ "${to:0:5}" == "sftp:" ]] ; then debug "using sftp to copy the file from $from" @@ -718,7 +718,7 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. sshpass -p "$ftppass" sftp $SFTP_OPTS "$ftpuser@$ftphost" <<- _EOF cd $ftpdirn lcd $fromdir - put $fromfile + put ./$fromfile _EOF elif [[ "${to:0:5}" == "davs:" ]] ; then debug "using davs to copy the file from $from" From b5a9a4280ee6d758668877bfc576ac085a46c8af Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 29 Apr 2020 20:56:40 +0100 Subject: [PATCH 064/308] Update revision history --- getssl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/getssl b/getssl index 109d96d..5c044d4 100755 --- a/getssl +++ b/getssl @@ -226,6 +226,8 @@ # 2020-04-20 Check for domain using all DNS utilities (2.25) # 2020-04-22 Fix HAS_HOST and HAS_NSLOOKUP checks - wolfaba # 2020-04-22 Fix domain case conversion for different locales - glynge (2.26) +# 2020-04-26 Fixed ipv4 confirmation with nslookup - Cyber1000 +# 2020-04-29 Fix ftp/sftp problems if challenge starts with a dash # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} From 50a9865e716ec433f878836d6fca30c80cbae0c8 Mon Sep 17 00:00:00 2001 From: Scott Gustafson Date: Sat, 2 May 2020 23:39:50 -0600 Subject: [PATCH 065/308] Fix route53 script for python 3. --- dns_scripts/dns_route53.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dns_scripts/dns_route53.py b/dns_scripts/dns_route53.py index a972dfa..f2011bf 100755 --- a/dns_scripts/dns_route53.py +++ b/dns_scripts/dns_route53.py @@ -31,7 +31,7 @@ for zone in response['HostedZones']: if not zone['Config']['PrivateZone']: zone_list[zone['Name']] = zone['Id'] -for key in sorted(zone_list.iterkeys(), key=len, reverse=True): +for key in sorted(zone_list.keys(), key=len, reverse=True): if ".{z}".format(z=key) in ".{z}.".format(z=fqdn): zone_id = zone_list[key] From 919aed2cdb26b148cf1daeeb7d0a4871b4cb1a09 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 6 May 2020 16:04:11 +0100 Subject: [PATCH 066/308] Fix missing fullchain.ec.crt when creating dual certificates --- getssl | 18 ++++++++++-------- test/3-dual-rsa-ecdsa.bats | 8 ++++++++ test/test_helper.bash | 7 +++++++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/getssl b/getssl index 5c044d4..a92f09b 100755 --- a/getssl +++ b/getssl @@ -1342,6 +1342,7 @@ get_certificate() { # get certificate for csr, if all domains validated. gc_csr=$1 # the csr file gc_certfile=$2 # The filename for the certificate gc_cafile=$3 # The filename for the CA certificate + gc_fullchain=$4 # The filename for the fullchain der=$(openssl req -in "$gc_csr" -outform DER | urlbase64) if [[ $API -eq 1 ]]; then @@ -1388,9 +1389,9 @@ get_certificate() { # get certificate for csr, if all domains validated. done info "Requesting certificate" CertData=$(json_get "$response" "certificate") - send_signed_request "$CertData" "" "" "$FULL_CHAIN" - info "Full certificate saved in $FULL_CHAIN" - awk -v CERT_FILE="$gc_certfile" -v CA_CERT="$gc_cafile" 'BEGIN {outfile=CERT_FILE} split_after==1 {outfile=CA_CERT;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > outfile}' "$FULL_CHAIN" + send_signed_request "$CertData" "" "" "$gc_fullchain" + info "Full certificate saved in $gc_fullchain" + awk -v CERT_FILE="$gc_certfile" -v CA_CERT="$gc_cafile" 'BEGIN {outfile=CERT_FILE} split_after==1 {outfile=CA_CERT;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > outfile}' "$gc_fullchain" info "Certificate saved in $gc_certfile" fi } @@ -1892,7 +1893,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p # get nonce from ACME server if [[ $API -eq 1 ]]; then nonceurl="$CA/directory" - nonce=$($CURL -I $nonceurl | grep "^Replay-Nonce:" | awk '{print $2}' | tr -d '\r\n ') + nonce=$($CURL -I "$nonceurl" | grep "^Replay-Nonce:" | awk '{print $2}' | tr -d '\r\n ') else # APIv2 nonce=$($CURL -I "$URL_newNonce" | grep "^Replay-Nonce:" | awk '{print $2}' | tr -d '\r\n ') fi @@ -2458,8 +2459,7 @@ find_dns_utils check_config # if -i|--install install certs, reload and exit -if [ "0${_CERT_INSTALL}" -eq 1 ] -then +if [ "0${_CERT_INSTALL}" -eq 1 ]; then cert_install reload_service graceful_exit @@ -2724,7 +2724,8 @@ info "Verification completed, obtaining certificate." #obtain the certificate. get_certificate "$DOMAIN_DIR/${DOMAIN}.csr" \ "$CERT_FILE" \ - "$CA_CERT" + "$CA_CERT" \ + "$FULL_CHAIN" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then info "Creating order for EC certificate" if [[ $API -eq 2 ]]; then @@ -2734,7 +2735,8 @@ if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then info "obtaining EC certificate." get_certificate "$DOMAIN_DIR/${DOMAIN}.ec.csr" \ "${CERT_FILE%.*}.ec.crt" \ - "${CA_CERT%.*}.ec.crt" + "${CA_CERT%.*}.ec.crt" \ + "${FULL_CHAIN%.*}.ec.crt" fi # create Archive of new certs and keys. diff --git a/test/3-dual-rsa-ecdsa.bats b/test/3-dual-rsa-ecdsa.bats index d5c58f7..486fa13 100644 --- a/test/3-dual-rsa-ecdsa.bats +++ b/test/3-dual-rsa-ecdsa.bats @@ -21,6 +21,10 @@ setup() { create_certificate assert_success check_output_for_errors + check_certificates + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.ec.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.ec.crt" ] } @@ -43,6 +47,10 @@ setup() { create_certificate assert_success check_output_for_errors + check_certificates + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.ec.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.ec.crt" ] } diff --git a/test/test_helper.bash b/test/test_helper.bash index 0aafa93..1e65189 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -1,6 +1,13 @@ INSTALL_DIR=/root CODE_DIR=/getssl +check_certificates() +{ + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" ] +} + check_output_for_errors() { refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' # less strict tests if running with debug output From 9f19977238bd3618192e457e3bfe825ea498aeba Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 10 May 2020 12:05:32 +0100 Subject: [PATCH 067/308] Update revision history and version --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index a92f09b..76714b7 100755 --- a/getssl +++ b/getssl @@ -228,11 +228,12 @@ # 2020-04-22 Fix domain case conversion for different locales - glynge (2.26) # 2020-04-26 Fixed ipv4 confirmation with nslookup - Cyber1000 # 2020-04-29 Fix ftp/sftp problems if challenge starts with a dash +# 2020-05-06 Fix missing fullchain.ec.crt when creating dual certificates (2.27) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.26" +VERSION="2.27" # defaults ACCOUNT_KEY_LENGTH=4096 From d39f60540a1c6e7b32fdb73b942510e609242516 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 10 May 2020 12:23:04 +0100 Subject: [PATCH 068/308] Change CA to v02, fix shellcheck warning and indentation --- getssl | 123 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 64 insertions(+), 59 deletions(-) diff --git a/getssl b/getssl index a3f5eb9..cbb2559 100755 --- a/getssl +++ b/getssl @@ -2072,72 +2072,77 @@ usage() { # echos out the program usage write_domain_template() { # write out a template file for a domain. if [[ -s "$WORKING_DIR/getssl_default.cfg" ]]; then - export DOMAIN="$DOMAIN" - export EX_SANS="$EX_SANS" - envsubst < $WORKING_DIR/getssl_default.cfg > "$1" + export DOMAIN="$DOMAIN" + export EX_SANS="$EX_SANS" + envsubst < "$WORKING_DIR/getssl_default.cfg" > "$1" else cat > "$1" <<- _EOF_domain_ - # Uncomment and modify any variables you need + # vim: filetype=sh + # + # This file is read second (and per domain if running with the -a option) + # and overwrites any settings from the first file + # + # 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" + #CA="https://acme-staging-v02.api.letsencrypt.org" # This server issues full certificates, however has rate limits - #CA="https://acme-v01.api.letsencrypt.org" - - # Private key types - can be rsa, prime256v1, secp384r1 or secp521r1 - #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="${EX_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. - # You can also user WebDAV over HTTPS as transport mechanism. To do so, start with davs: followed by username, - # password, host, port (explicitly needed even if using default port 443) and path on the server. - #ACL=('/var/www/${DOMAIN}/web/.well-known/acme-challenge' - # 'ssh:server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' - # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' - # 'ftp:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge' - # 'davs:davsuserid:davspassword:{DOMAIN}:443:/web/.well-known/acme-challenge') - - # Specify SSH options, e.g. non standard port in SSH_OPTS - # (Can also use SCP_OPTS and SFTP_OPTS) - # SSH_OPTS=-p 12345 - - # 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/ssl/${DOMAIN}.crt" # this is domain cert - #DOMAIN_KEY_LOCATION="/etc/ssl/${DOMAIN}.key" # this is domain key - #CA_CERT_LOCATION="/etc/ssl/chain.crt" # this is CA cert - #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="" - - # Uncomment the following line to prevent non-interactive renewals of certificates - #PREVENT_NON_INTERACTIVE_RENEWAL="true" - - # 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" - #CHECK_REMOTE_WAIT="2" # wait 2 seconds before checking the remote server - _EOF_domain_ + #CA="https://acme-v02.api.letsencrypt.org" + + # Private key types - can be rsa, prime256v1, secp384r1 or secp521r1 + #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="${EX_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. + # You can also user WebDAV over HTTPS as transport mechanism. To do so, start with davs: followed by username, + # password, host, port (explicitly needed even if using default port 443) and path on the server. + #ACL=('/var/www/${DOMAIN}/web/.well-known/acme-challenge' + # 'ssh:server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' + # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' + # 'ftp:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge' + # 'davs:davsuserid:davspassword:{DOMAIN}:443:/web/.well-known/acme-challenge') + + # Specify SSH options, e.g. non standard port in SSH_OPTS + # (Can also use SCP_OPTS and SFTP_OPTS) + # SSH_OPTS=-p 12345 + + # 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/ssl/${DOMAIN}.crt" # this is domain cert + #DOMAIN_KEY_LOCATION="/etc/ssl/${DOMAIN}.key" # this is domain key + #CA_CERT_LOCATION="/etc/ssl/chain.crt" # this is CA cert + #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="" + + # Uncomment the following line to prevent non-interactive renewals of certificates + #PREVENT_NON_INTERACTIVE_RENEWAL="true" + + # 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" + #CHECK_REMOTE_WAIT="2" # wait 2 seconds before checking the remote server + _EOF_domain_ fi } From 89ca12a72889d1befb70a66a61f6adfa0f161fad Mon Sep 17 00:00:00 2001 From: aws02 user Date: Mon, 11 May 2020 10:53:13 +1000 Subject: [PATCH 069/308] Remove .idea files --- .idea/.gitignore | 2 -- .idea/getssl.iml | 8 -------- .idea/misc.xml | 6 ------ .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ 5 files changed, 30 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/getssl.iml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index e7e9d11..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Default ignored files -/workspace.xml diff --git a/.idea/getssl.iml b/.idea/getssl.iml deleted file mode 100644 index c956989..0000000 --- a/.idea/getssl.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 28a804d..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 5f2e056..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From ee5e1e8cac509b63f76630ebb9cfaf40ec696403 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 13 May 2020 17:12:27 +0100 Subject: [PATCH 070/308] Add --check-config and auto upgrade CA v02 url --- getssl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/getssl b/getssl index a501f78..1a14ac8 100755 --- a/getssl +++ b/getssl @@ -283,6 +283,7 @@ _REVOKE=0 _UPGRADE=0 _UPGRADE_CHECK=1 _USE_DEBUG=0 +_ONLY_CHECK_CONFIG=0 config_errors="false" LANG=C API=1 @@ -292,6 +293,18 @@ ORIGCMD="$0 $*" # Define all functions (in alphabetical order) +auto_upgrade_v2() { # Automatically update clients to v2 + if [[ "${CA}" == *"acme-v01."* ]] || [[ "${CA}" == *"acme-staging."* ]]; then + OLDCA=${CA} + # shellcheck disable=SC2001 + CA=$(echo "${OLDCA}" | sed "s/v01/v02/g") + # shellcheck disable=SC2001 + CA=$(echo "${CA}" | sed "s/staging/staging-v02/g") + info "Upgraded to v2 (changed ${OLDCA} to ${CA})" + fi + debug "Using certificate issuer: ${CA}" +} + cert_archive() { # Archive certificate file by copying files to dated archive dir. debug "creating an archive copy of current new certs" date_time=$(date +%Y_%m_%d_%H_%M) @@ -2245,6 +2258,8 @@ while [[ -n ${1+defined} ]]; do _UPGRADE_CHECK=0 ;; -i | --install) _CERT_INSTALL=1 ;; + --check-config) + _ONLY_CHECK_CONFIG=1 ;; -w) shift; WORKING_DIR="$1" ;; -*) @@ -2462,9 +2477,18 @@ set_server_type # check what dns utils are installed find_dns_utils +# auto upgrade clients to v2 +auto_upgrade_v2 + # check config for typical errors. check_config +# exit if just checking config (used for testing) +if [ "${_ONLY_CHECK_CONFIG}" -eq 1 ]; then + info "Configuration check successful" + graceful_exit +fi + # if -i|--install install certs, reload and exit if [ "0${_CERT_INSTALL}" -eq 1 ]; then cert_install From dfba3304e4260654d665fb724c8dbf9e0fbc8256 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 13 May 2020 17:20:24 +0100 Subject: [PATCH 071/308] Add testing for the auto-update to v02 feature --- test/12-auto-upgrade-v1.bats | 75 +++++++++++++++++++ .../getssl-upgrade-test-pebble.cfg | 8 ++ .../getssl-upgrade-test-v1-prod.cfg | 7 ++ .../getssl-upgrade-test-v1-staging.cfg | 7 ++ .../getssl-upgrade-test-v2-prod.cfg | 7 ++ .../getssl-upgrade-test-v2-staging.cfg | 7 ++ 6 files changed, 111 insertions(+) create mode 100644 test/12-auto-upgrade-v1.bats create mode 100644 test/test-config/getssl-upgrade-test-pebble.cfg create mode 100644 test/test-config/getssl-upgrade-test-v1-prod.cfg create mode 100644 test/test-config/getssl-upgrade-test-v1-staging.cfg create mode 100644 test/test-config/getssl-upgrade-test-v2-prod.cfg create mode 100644 test/test-config/getssl-upgrade-test-v2-staging.cfg diff --git a/test/12-auto-upgrade-v1.bats b/test/12-auto-upgrade-v1.bats new file mode 100644 index 0000000..4165cd3 --- /dev/null +++ b/test/12-auto-upgrade-v1.bats @@ -0,0 +1,75 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +@test "Check that auto upgrade to v2 doesn't change pebble url" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-upgrade-test-pebble.cfg" + setup_environment + mkdir ${INSTALL_DIR}/.getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" + run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + assert_success + assert_line 'Using certificate issuer: https://pebble:14000/dir' +} + + +@test "Check that auto upgrade to v2 doesn't change v2 staging url" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-upgrade-test-v2-staging.cfg" + setup_environment + mkdir ${INSTALL_DIR}/.getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" + run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + assert_success + assert_line 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' +} + + +@test "Check that auto upgrade to v2 doesn't change v2 prod url" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-upgrade-test-v2-prod.cfg" + setup_environment + mkdir ${INSTALL_DIR}/.getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" + run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + assert_success + assert_line 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' +} + + +@test "Check that auto upgrade to v2 changes v1 staging to v2 staging url" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-upgrade-test-v1-staging.cfg" + setup_environment + mkdir ${INSTALL_DIR}/.getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" + run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + assert_success + assert_line 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' +} + + +@test "Check that auto upgrade to v2 changes v1 prod to v2 prod url" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-upgrade-test-v1-prod.cfg" + setup_environment + mkdir ${INSTALL_DIR}/.getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" + run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + assert_success + assert_line 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' +} diff --git a/test/test-config/getssl-upgrade-test-pebble.cfg b/test/test-config/getssl-upgrade-test-pebble.cfg new file mode 100644 index 0000000..f5f8b3b --- /dev/null +++ b/test/test-config/getssl-upgrade-test-pebble.cfg @@ -0,0 +1,8 @@ +# +# Test that auto-upgrade to v2 doesn't change pebble url +# +CA="https://pebble:14000/dir" + + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') diff --git a/test/test-config/getssl-upgrade-test-v1-prod.cfg b/test/test-config/getssl-upgrade-test-v1-prod.cfg new file mode 100644 index 0000000..41f0176 --- /dev/null +++ b/test/test-config/getssl-upgrade-test-v1-prod.cfg @@ -0,0 +1,7 @@ +# +# Test that auto-upgrade to v2 changes v1 prod to v2 prod +# +CA="https://acme-v01.api.letsencrypt.org/directory" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') diff --git a/test/test-config/getssl-upgrade-test-v1-staging.cfg b/test/test-config/getssl-upgrade-test-v1-staging.cfg new file mode 100644 index 0000000..215f246 --- /dev/null +++ b/test/test-config/getssl-upgrade-test-v1-staging.cfg @@ -0,0 +1,7 @@ +# +# Test that auto-upgrade to v2 changes v1 staging to v2 staging +# +CA="https://acme-staging.api.letsencrypt.org/directory" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') diff --git a/test/test-config/getssl-upgrade-test-v2-prod.cfg b/test/test-config/getssl-upgrade-test-v2-prod.cfg new file mode 100644 index 0000000..9b9c009 --- /dev/null +++ b/test/test-config/getssl-upgrade-test-v2-prod.cfg @@ -0,0 +1,7 @@ +# +# Test that auto-upgrade to v2 doesn't change v2 prod url +# +CA="https://acme-v02.api.letsencrypt.org/directory" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') diff --git a/test/test-config/getssl-upgrade-test-v2-staging.cfg b/test/test-config/getssl-upgrade-test-v2-staging.cfg new file mode 100644 index 0000000..98bfd17 --- /dev/null +++ b/test/test-config/getssl-upgrade-test-v2-staging.cfg @@ -0,0 +1,7 @@ +# +# Test that auto-upgrade to v2 doesn't change v2 staging url +# +CA="https://acme-staging-v02.api.letsencrypt.org/directory" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') From aae47d2c260f6025617ed0cd9e38447fdd9f407e Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 14 May 2020 17:05:20 +0100 Subject: [PATCH 072/308] Add --notify-valid --- getssl | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/getssl b/getssl index 1a14ac8..1807249 100755 --- a/getssl +++ b/getssl @@ -277,6 +277,7 @@ _CREATE_CONFIG=0 _FORCE_RENEW=0 _KEEP_VERSIONS="" _MUTE=0 +_NOTIFY_VALID=0 _QUIET=0 _RECREATE_CSR=0 _REVOKE=0 @@ -1496,8 +1497,10 @@ get_signing_params() { # get signing parameters from key } graceful_exit() { # normal exit function. + exit_code=$1 clean_up - exit + # shellcheck disable=SC2086 + exit $exit_code } help_message() { # print out the help message @@ -2230,30 +2233,33 @@ while [[ -n ${1+defined} ]]; do -h | --help) help_message; graceful_exit ;; -d | --debug) - _USE_DEBUG=1 ;; + _USE_DEBUG=1 ;; -c | --create) - _CREATE_CONFIG=1 ;; + _CREATE_CONFIG=1 ;; -f | --force) - _FORCE_RENEW=1 ;; + _FORCE_RENEW=1 ;; + --notify-valid) + # Exit 2 if certificate is valid and doesn't need renewing + _NOTIFY_VALID=2 ;; -a | --all) - _CHECK_ALL=1 ;; + _CHECK_ALL=1 ;; -k | --keep) - shift; _KEEP_VERSIONS="$1";; + shift; _KEEP_VERSIONS="$1";; -q | --quiet) - _QUIET=1 ;; + _QUIET=1 ;; -Q | --mute) - _QUIET=1 - _MUTE=1 ;; + _QUIET=1 + _MUTE=1 ;; -r | --revoke) - _REVOKE=1 - shift - REVOKE_CERT="$1" - shift - REVOKE_KEY="$1" - shift - REVOKE_CA="$1" ;; + _REVOKE=1 + shift + REVOKE_CERT="$1" + shift + REVOKE_KEY="$1" + shift + REVOKE_CA="$1" ;; -u | --upgrade) - _UPGRADE=1 ;; + _UPGRADE=1 ;; -U | --nocheck) _UPGRADE_CHECK=0 ;; -i | --install) @@ -2630,8 +2636,8 @@ if [[ -s "$CERT_FILE" ]]; then debug "upgrading from fake cert to real" else info "${DOMAIN}: certificate is valid for more than $RENEW_ALLOW days (until $enddate)" - # everything is OK, so exit. - graceful_exit + # everything is OK, so exit, if requested with the --notify-valid, exit with code 2 + graceful_exit $_NOTIFY_VALID fi else debug "${DOMAIN}: certificate needs renewal" From 2287057e386996666184b07049d93e1dec9d2aa5 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 14 May 2020 17:05:55 +0100 Subject: [PATCH 073/308] Add test for --notify-valid --- test/13-notify-valid.bats | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 test/13-notify-valid.bats diff --git a/test/13-notify-valid.bats b/test/13-notify-valid.bats new file mode 100644 index 0000000..ac1a50c --- /dev/null +++ b/test/13-notify-valid.bats @@ -0,0 +1,45 @@ +#! /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 certificate to check valid exit code" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check no-renewal needed exits with normal exit code" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + run ${CODE_DIR}/getssl $GETSSL_HOST + assert_success + check_output_for_errors +} + + +@test "Check no-renewal needed returns 2 if requested" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + run ${CODE_DIR}/getssl --notify-valid $GETSSL_HOST + assert [ $status == 2 ] + check_output_for_errors + cleanup_environment +} From db316d0d16b998a470a45bd18f0bb410b793a643 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 23 May 2020 20:58:44 +0100 Subject: [PATCH 074/308] Fix --revoke --- getssl | 93 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/getssl b/getssl index 1807249..710fba4 100755 --- a/getssl +++ b/getssl @@ -1743,6 +1743,45 @@ json_get() { # get values from json fi } +obtain_ca_resource_locations() +{ + # Obtain CA resource locations + ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}" 2>/dev/null) + debug "ca_all_loc from ${CA} gives $ca_all_loc" + # APIv1 + URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') + URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') + URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') + #API v2 + URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') + URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') + URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') + URL_revoke=$(echo "$ca_all_loc" | grep "revokeCert" | awk -F'"' '{print $4}') + + if [[ -z "$URL_new_reg" ]] && [[ -z "$URL_newAccount" ]]; then + ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}/directory" 2>/dev/null) + debug "ca_all_loc from ${CA}/directory gives $ca_all_loc" + # APIv1 + URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') + URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') + URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') + #API v2 + URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') + URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') + URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') + fi + + if [[ -n "$URL_new_reg" ]]; then + API=1 + elif [[ -n "$URL_newAccount" ]]; then + API=2 + else + info "unknown API version" + graceful_exit + fi + debug "Using API v$API" +} + os_esed() { # Use different sed version for different os types (extended regex) if [[ "$os" == "bsd" ]]; then # BSD requires -E flag for extended regex sed -E "${@}" @@ -1807,9 +1846,9 @@ revoke_certificate() { # revoke a certificate # need to set the revoke key as "account_key" since it's used in send_signed_request. get_signing_params "$REVOKE_KEY" TEMP_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t getssl) - debug "revoking from $CA" - rcertdata=$(openssl x509 -in "$REVOKE_CERT" -inform PEM -outform DER | urlbase64) - send_signed_request "$URL_revoke" "{\"resource\": \"revoke-cert\", \"certificate\": \"$rcertdata\"}" + debug "revoking from $URL_revoke" + rcertdata=$(sed '1d;$d' "$REVOKE_CERT" | tr -d "\r\n" | tr '/+' '_-' | tr -d '= ') + send_signed_request "$URL_revoke" "{\"certificate\": \"$rcertdata\",\"reason\": $REVOKE_REASON}" if [[ $code -eq "200" ]]; then info "certificate revoked" else @@ -1959,15 +1998,18 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p while [[ "$code" -eq 500 ]]; do if [[ "$outfile" ]] ; then $CURL -X POST -H "Content-Type: application/jose+json" --data "$body" "$url" > "$outfile" + errcode=$? response=$(cat "$outfile") elif [[ "$needbase64" ]] ; then response=$($CURL -X POST -H "Content-Type: application/jose+json" --data "$body" "$url" | urlbase64) + errcode=$? else response=$($CURL -X POST -H "Content-Type: application/jose+json" --data "$body" "$url") + errcode=$? fi - if [[ "$response" == "" ]]; then - error_exit "ERROR curl \"$url\" returned nothing" + if [[ $errcode -gt 0 || ( "$response" == "" && $url != *"revoke"* ) ]]; then + error_exit "ERROR curl \"$url\" failed with $errcode and returned $response" fi responseHeaders=$(cat "$CURL_HEADER") @@ -2257,7 +2299,9 @@ while [[ -n ${1+defined} ]]; do shift REVOKE_KEY="$1" shift - REVOKE_CA="$1" ;; + CA="$1" + REVOKE_CA="$1" + REVOKE_REASON=0 ;; -u | --upgrade) _UPGRADE=1 ;; -U | --nocheck) @@ -2324,7 +2368,8 @@ if [[ $_REVOKE -eq 1 ]]; then else CA=$REVOKE_CA fi - URL_revoke=$(curl --user-agent "$CURL_USERAGENT" "${CA}/directory" 2>/dev/null | grep "revoke-cert" | awk -F'"' '{print $4}') + + obtain_ca_resource_locations revoke_certificate graceful_exit fi @@ -2508,39 +2553,7 @@ if [[ -e "$DOMAIN_DIR/FORCE_RENEWAL" ]]; then info "${DOMAIN}: forcing renewal (due to FORCE_RENEWAL file)" fi -# Obtain CA resource locations -ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}" 2>/dev/null) -debug "ca_all_loc from ${CA} gives $ca_all_loc" -# APIv1 -URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') -URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') -URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') -#API v2 -URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') -URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') -URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') -if [[ -z "$URL_new_reg" ]] && [[ -z "$URL_newAccount" ]]; then - ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}/directory" 2>/dev/null) - debug "ca_all_loc from ${CA}/directory gives $ca_all_loc" - # APIv1 - URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') - URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') - URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') - #API v2 - URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') - URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') - URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') -fi - -if [[ -n "$URL_new_reg" ]]; then - API=1 -elif [[ -n "$URL_newAccount" ]]; then - API=2 -else - info "unknown API version" - graceful_exit -fi -debug "Using API v$API" +obtain_ca_resource_locations # Check if awk supports json_awk (required for ACMEv2) if [[ $API -eq 2 ]]; then From fc4add8747d46be2398734ffbe616e93d7c2ad88 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 23 May 2020 21:00:04 +0100 Subject: [PATCH 075/308] Test --revoke --- test/14-test-revoke.bats | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 test/14-test-revoke.bats diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats new file mode 100644 index 0000000..ac056c2 --- /dev/null +++ b/test/14-test-revoke.bats @@ -0,0 +1,37 @@ +#! /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 certificate to check revoke" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check we can revoke a certificate" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key + CA="https://pebble:14000/dir" + run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA + assert_success + check_output_for_errors +} From d568e15563ea7353173a940374ccc4470f1e5b32 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 23 May 2020 21:28:32 +0100 Subject: [PATCH 076/308] Update test to test using staging server --- test/14-test-revoke.bats | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats index ac056c2..2e95e0d 100644 --- a/test/14-test-revoke.bats +++ b/test/14-test-revoke.bats @@ -13,9 +13,11 @@ setup() { @test "Create certificate to check revoke" { if [ -n "$STAGING" ]; then - skip "Using staging server, skipping internal test" + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-http01.cfg" fi - CONFIG_FILE="getssl-http01.cfg" + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" setup_environment init_getssl create_certificate @@ -26,11 +28,14 @@ setup() { @test "Check we can revoke a certificate" { if [ -n "$STAGING" ]; then - skip "Using staging server, skipping internal test" + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-http01.cfg" fi + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key - CA="https://pebble:14000/dir" + run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA assert_success check_output_for_errors From 86b365b2c35508cd4421763adc5d96ecffc38418 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 24 May 2020 09:46:13 +0100 Subject: [PATCH 077/308] Update revision history and version number --- getssl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 710fba4..371906f 100755 --- a/getssl +++ b/getssl @@ -229,11 +229,13 @@ # 2020-04-26 Fixed ipv4 confirmation with nslookup - Cyber1000 # 2020-04-29 Fix ftp/sftp problems if challenge starts with a dash # 2020-05-06 Fix missing fullchain.ec.crt when creating dual certificates (2.27) +# 2020-05-14 Add --notify-valid option (exit 2 if certificate is valid) +# 2020-05-23 Fix --revoke (didn't work with ACMEv02) (2.28) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.27" +VERSION="2.28" # defaults ACCOUNT_KEY_LENGTH=4096 From fec8905c1c2ecac816c96a6eafb31a70d6e09ddd Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 6 Jun 2020 14:26:18 +0100 Subject: [PATCH 078/308] Fix missing URL_revoke definition when no CA directory suffix --- getssl | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/getssl b/getssl index 371906f..5668571 100755 --- a/getssl +++ b/getssl @@ -1747,22 +1747,11 @@ json_get() { # get values from json obtain_ca_resource_locations() { - # Obtain CA resource locations - ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}" 2>/dev/null) - debug "ca_all_loc from ${CA} gives $ca_all_loc" - # APIv1 - URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') - URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') - URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') - #API v2 - URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') - URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') - URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') - URL_revoke=$(echo "$ca_all_loc" | grep "revokeCert" | awk -F'"' '{print $4}') - - if [[ -z "$URL_new_reg" ]] && [[ -z "$URL_newAccount" ]]; then - ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}/directory" 2>/dev/null) - debug "ca_all_loc from ${CA}/directory gives $ca_all_loc" + for suffix in "" "/directory" "/dir"; + do + # Obtain CA resource locations + ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}${suffix}" 2>/dev/null) + debug "ca_all_loc from ${CA}${suffix} gives $ca_all_loc" # APIv1 URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') @@ -1771,15 +1760,19 @@ obtain_ca_resource_locations() URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') - fi + URL_revoke=$(echo "$ca_all_loc" | grep "revokeCert" | awk -F'"' '{print $4}') + + if [[ -n "$URL_new_reg" ]] || [[ -n "$URL_newAccount" ]]; then + break + fi + done if [[ -n "$URL_new_reg" ]]; then API=1 elif [[ -n "$URL_newAccount" ]]; then API=2 else - info "unknown API version" - graceful_exit + error_exit "unknown API version" fi debug "Using API v$API" } From 913b7fcbb8ee8e40fd64d3fad8934bdbcbd318ae Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 6 Jun 2020 14:27:09 +0100 Subject: [PATCH 079/308] Add tests for obtain_ca_resource_locations and no CA suffix --- test/15-test-revoke-no-suffix.bats | 42 +++++++++++++++++++ test/test-config/getssl-http01-no-suffix.cfg | 30 +++++++++++++ .../getssl-staging-dns01-no-suffix.cfg | 37 ++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 test/15-test-revoke-no-suffix.bats create mode 100644 test/test-config/getssl-http01-no-suffix.cfg create mode 100644 test/test-config/getssl-staging-dns01-no-suffix.cfg diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats new file mode 100644 index 0000000..ce97ddd --- /dev/null +++ b/test/15-test-revoke-no-suffix.bats @@ -0,0 +1,42 @@ +#! /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 certificate to check revoke" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01-no-suffix.cfg" + else + CONFIG_FILE="getssl-http01-no-suffix.cfg" + fi + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check we can revoke a certificate" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-http01.cfg" + fi + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key + + run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA + assert_success + check_output_for_errors +} diff --git a/test/test-config/getssl-http01-no-suffix.cfg b/test/test-config/getssl-http01-no-suffix.cfg new file mode 100644 index 0000000..a1295dd --- /dev/null +++ b/test/test-config/getssl-http01-no-suffix.cfg @@ -0,0 +1,30 @@ +# 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" +CA="https://pebble:14000" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="" + +# Acme Challenge Location. +ACL=('/var/www/html/.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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" diff --git a/test/test-config/getssl-staging-dns01-no-suffix.cfg b/test/test-config/getssl-staging-dns01-no-suffix.cfg new file mode 100644 index 0000000..32fdda3 --- /dev/null +++ b/test/test-config/getssl-staging-dns01-no-suffix.cfg @@ -0,0 +1,37 @@ +# Test that the script works with external dns provider and staging server +# +CA="https://acme-staging-v02.api.letsencrypt.org" + +VALIDATE_VIA_DNS=true +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" +PUBLIC_DNS_SERVER=ns2.duckdns.org +CHECK_ALL_AUTH_DNS=true +DNS_EXTRA_WAIT=60 + +ACCOUNT_KEY_TYPE="rsa" +PRIVATE_KEY_ALG="rsa" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="" + +# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. +ACL=('/var/www/html/.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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed (using a custom port) +SERVER_TYPE="https" +CHECK_REMOTE="true" From 48298c86da2dadb6c3b12db3bee012200ac2f1ef Mon Sep 17 00:00:00 2001 From: Jaroslav Beran Date: Sat, 13 Jun 2020 12:20:18 +0200 Subject: [PATCH 080/308] .gitattributes added --- .gitattributes | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..217326a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +# Handle line endings automatically for files detected as text +# and leave all files detected as binary untouched. +* text=auto + +# Make all text files lf formatted +* text eol=lf From 59ea8bfe4aae303ece5eb8b29f8750963c339bcc Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 15 Jun 2020 21:52:40 +0100 Subject: [PATCH 081/308] Update nginx config to test both certificates --- .../getssl-dns01-dual-rsa-ecdsa.cfg | 2 +- .../getssl-http01-dual-rsa-ecdsa.cfg | 2 +- test/test-config/nginx-ubuntu-dual-certs | 95 +++++++++++++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 test/test-config/nginx-ubuntu-dual-certs diff --git a/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg b/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg index 8f29088..7b031c8 100644 --- a/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg +++ b/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg @@ -32,7 +32,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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-dual-certs ${NGINX_CONFIG} && /getssl/test/restart-nginx" # Define the server type and confirm correct certificate is installed SERVER_TYPE="https" diff --git a/test/test-config/getssl-http01-dual-rsa-ecdsa.cfg b/test/test-config/getssl-http01-dual-rsa-ecdsa.cfg index f6cfcb7..9e348fc 100644 --- a/test/test-config/getssl-http01-dual-rsa-ecdsa.cfg +++ b/test/test-config/getssl-http01-dual-rsa-ecdsa.cfg @@ -26,7 +26,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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-dual-certs ${NGINX_CONFIG} && /getssl/test/restart-nginx" # Define the server type and confirm correct certificate is installed SERVER_TYPE="https" diff --git a/test/test-config/nginx-ubuntu-dual-certs b/test/test-config/nginx-ubuntu-dual-certs new file mode 100644 index 0000000..6346cde --- /dev/null +++ b/test/test-config/nginx-ubuntu-dual-certs @@ -0,0 +1,95 @@ +## +# 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; + + ssl_certificate /etc/nginx/pki/server.ec.crt; + ssl_certificate_key /etc/nginx/pki/private/server.ec.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; +# } +#} From d24782088d6227d1c9399a3e7885a56622bb504c Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 16 Jun 2020 21:42:51 +0100 Subject: [PATCH 082/308] Add --retry to curl to fix occasional "Bad Gateway" errors --- dns_scripts/dns_add_duckdns | 2 +- dns_scripts/dns_del_duckdns | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dns_scripts/dns_add_duckdns b/dns_scripts/dns_add_duckdns index ef40efe..9f61c8c 100755 --- a/dns_scripts/dns_add_duckdns +++ b/dns_scripts/dns_add_duckdns @@ -11,7 +11,7 @@ fi domain="$1" txtvalue="$2" -response=$(curl --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=${txtvalue}") +response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=${txtvalue}") if [ "$response" != "OK" ]; then echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)" echo "Response: $response" diff --git a/dns_scripts/dns_del_duckdns b/dns_scripts/dns_del_duckdns index b9b9f9f..f20c664 100755 --- a/dns_scripts/dns_del_duckdns +++ b/dns_scripts/dns_del_duckdns @@ -4,7 +4,7 @@ token=${DUCKDNS_TOKEN:-} domain="$1" -response=$(curl --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=&clear=true") +response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=&clear=true") if [ "$response" != "OK" ]; then echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)" echo "$response" From 89036c126b4f317f39051b0f6fc3b11e7d2490af Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 18 Jun 2020 17:19:36 +0100 Subject: [PATCH 083/308] Fix CHECK_REMOTE for DUAL_RSA_ECDSA --- getssl | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/getssl b/getssl index 5668571..4a1a43c 100755 --- a/getssl +++ b/getssl @@ -2561,9 +2561,14 @@ fi # 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 debug "getting certificate for $DOMAIN from remote server" +if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then + CIPHER="-cipher RSA" +else + CIPHER="" +fi # shellcheck disable=SC2086 EX_CERT=$(echo \ - | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null \ + | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${CIPHER} 2>/dev/null \ | openssl x509 2>/dev/null) if [[ -n "$EX_CERT" ]]; then # if obtained a cert if [[ -s "$CERT_FILE" ]]; then # if local exists @@ -2817,16 +2822,30 @@ fi # Check if the certificate is installed correctly if [[ ${CHECK_REMOTE} == "true" ]]; then sleep "$CHECK_REMOTE_WAIT" - # shellcheck disable=SC2086 - CERT_REMOTE=$(echo \ - | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null \ - | openssl x509 -noout -fingerprint 2>/dev/null) - CERT_LOCAL=$(openssl x509 -noout -fingerprint < "$CERT_FILE" 2>/dev/null) - if [[ "$CERT_LOCAL" == "$CERT_REMOTE" ]]; then - info "${DOMAIN} - certificate installed OK on server" + if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then + PARAMS=("-cipher RSA" "-cipher ECDSA") + CERTS=("$CERT_FILE" "${CERT_FILE%.*}.ec.crt") + TYPES=("rsa" "$PRIVATE_KEY_ALG") else - error_exit "${DOMAIN} - certificate obtained but certificate on server is different from the new certificate" + PARAMS=("") + CERTS=("$CERT_FILE") + TYPES=("$PRIVATE_KEY_ALG") fi + + for ((i=0; i<${#PARAMS[@]};++i)); do + debug "Checking ${CERTS[i]}" + # shellcheck disable=SC2086 + CERT_REMOTE=$(echo \ + | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${PARAMS[i]} 2>/dev/null \ + | openssl x509 -noout -fingerprint 2>/dev/null) + CERT_LOCAL=$(openssl x509 -noout -fingerprint < "${CERTS[i]}" 2>/dev/null) + if [[ "$CERT_LOCAL" == "$CERT_REMOTE" ]]; then + info "${DOMAIN} - ${TYPES[i]} certificate installed OK on server" + else + info "${CERTS[i]} didn't match server" + error_exit "${DOMAIN} - ${TYPES[i]} certificate obtained but certificate on server is different from the new certificate" + fi + done fi # end of Check if the certificate is installed correctly From 19369723cac07784e68e20e67a401d186fdf9468 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 18 Jun 2020 17:21:36 +0100 Subject: [PATCH 084/308] Add/fix tests for CHECK_REMOTE and DUAL_RSA_ECDSA --- test/3-dual-rsa-ecdsa.bats | 35 ++++++++++++++++- test/6-dual-rsa-ecdsa-copy-2-locations.bats | 9 ++++- test/Dockerfile-centos6 | 3 ++ .../getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg | 39 +++++++++++++++++++ ...1-dual-rsa-ecdsa-2-locations-old-nginx.cfg | 32 +++++++++++++++ ...tssl-http01-dual-rsa-ecdsa-2-locations.cfg | 2 +- ...getssl-http01-dual-rsa-ecdsa-old-nginx.cfg | 33 ++++++++++++++++ test/test-config/nginx-ubuntu-dual-certs | 2 + test/test_helper.bash | 14 +++++++ 9 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg create mode 100644 test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations-old-nginx.cfg create mode 100644 test/test-config/getssl-http01-dual-rsa-ecdsa-old-nginx.cfg diff --git a/test/3-dual-rsa-ecdsa.bats b/test/3-dual-rsa-ecdsa.bats index 486fa13..87527c2 100644 --- a/test/3-dual-rsa-ecdsa.bats +++ b/test/3-dual-rsa-ecdsa.bats @@ -15,7 +15,14 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - CONFIG_FILE="getssl-http01-dual-rsa-ecdsa.cfg" + + check_nginx + if [ "$OLD_NGINX" = "false" ]; then + CONFIG_FILE="getssl-http01-dual-rsa-ecdsa.cfg" + else + CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-old-nginx.cfg" + fi + setup_environment init_getssl create_certificate @@ -28,6 +35,22 @@ setup() { } +@test "Check renewal test works for dual certificates using HTTP-01" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + check_nginx + run ${CODE_DIR}/getssl -d $GETSSL_HOST + + if [ "$OLD_NGINX" = "false" ]; then + assert_line "certificate on server is same as the local cert" + else + assert_line --partial "certificate is valid for more than 30 days" + fi + assert_success +} + + @test "Force renewal of dual certificates using HTTP-01" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -37,11 +60,19 @@ setup() { check_output_for_errors } + @test "Create dual certificates using DNS-01 verification" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - CONFIG_FILE="getssl-dns01-dual-rsa-ecdsa.cfg" + + check_nginx + if [ "$OLD_NGINX" = "false" ]; then + CONFIG_FILE="getssl-dns01-dual-rsa-ecdsa.cfg" + else + CONFIG_FILE="getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg" + fi + setup_environment init_getssl create_certificate diff --git a/test/6-dual-rsa-ecdsa-copy-2-locations.bats b/test/6-dual-rsa-ecdsa-copy-2-locations.bats index 394e8d6..a8e7653 100644 --- a/test/6-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/6-dual-rsa-ecdsa-copy-2-locations.bats @@ -25,7 +25,14 @@ teardown() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-2-locations.cfg" + + check_nginx + if [ "$OLD_NGINX" = "false" ]; then + CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-2-locations.cfg" + else + CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-2-locations-old-nginx.cfg" + fi + setup_environment mkdir -p /root/a.${GETSSL_HOST} diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index 61c8b6b..5ffc91c 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -1,6 +1,9 @@ FROM centos:centos6 # Note this image uses gawk +# Note if you are running this using WSL2 you need to put the following lines in %userprofile%\.wslconfig +# [wsl2] +# kernelCommandLine = vsyscall=emulate # Update and install required software RUN yum -y update diff --git a/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg b/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg new file mode 100644 index 0000000..062a47c --- /dev/null +++ b/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg @@ -0,0 +1,39 @@ +# 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" + +VALIDATE_VIA_DNS=true +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" +PUBLIC_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT="" + +DUAL_RSA_ECDSA="true" +ACCOUNT_KEY_TYPE="prime256v1" +PRIVATE_KEY_ALG="prime256v1" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="" + +# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. +ACL=('/var/www/html/.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.ec.crt" +DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.ec.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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="false" diff --git a/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations-old-nginx.cfg b/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations-old-nginx.cfg new file mode 100644 index 0000000..50c3970 --- /dev/null +++ b/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations-old-nginx.cfg @@ -0,0 +1,32 @@ +# Test that more than one location can be specified for CERT and KEY locations and that the +# files are copied to both locations when both RSA and ECDSA certificates are created +# +CA="https://pebble:14000/dir" + +DUAL_RSA_ECDSA="true" +ACCOUNT_KEY_TYPE="prime256v1" +PRIVATE_KEY_ALG="prime256v1" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="a.${GETSSL_HOST}" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') + +#Set USE_SINGLE_ACL="true" to 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) +# 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;/root/a.${GETSSL_HOST}/server.key" +CA_CERT_LOCATION="/etc/nginx/pki/chain.crt" +DOMAIN_CHAIN_LOCATION="/etc/nginx/pki/domain-chain.crt;/root/a.${GETSSL_HOST}/domain-chain.crt" # 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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="false" diff --git a/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations.cfg b/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations.cfg index 80533ce..96e4d4d 100644 --- a/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations.cfg +++ b/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations.cfg @@ -25,7 +25,7 @@ DOMAIN_CHAIN_LOCATION="/etc/nginx/pki/domain-chain.crt;/root/a.${GETSSL_HOST}/do 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} && /getssl/test/restart-nginx" +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-dual-certs ${NGINX_CONFIG} && /getssl/test/restart-nginx" # Define the server type and confirm correct certificate is installed SERVER_TYPE="https" diff --git a/test/test-config/getssl-http01-dual-rsa-ecdsa-old-nginx.cfg b/test/test-config/getssl-http01-dual-rsa-ecdsa-old-nginx.cfg new file mode 100644 index 0000000..41581ae --- /dev/null +++ b/test/test-config/getssl-http01-dual-rsa-ecdsa-old-nginx.cfg @@ -0,0 +1,33 @@ +# 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" + +DUAL_RSA_ECDSA="true" +ACCOUNT_KEY_TYPE="prime256v1" +PRIVATE_KEY_ALG="prime256v1" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="" + +# Acme Challenge Location. +ACL=('/var/www/html/.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.ec.crt" +DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.ec.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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="false" diff --git a/test/test-config/nginx-ubuntu-dual-certs b/test/test-config/nginx-ubuntu-dual-certs index 6346cde..ce1fbbf 100644 --- a/test/test-config/nginx-ubuntu-dual-certs +++ b/test/test-config/nginx-ubuntu-dual-certs @@ -42,6 +42,8 @@ server { # Add index.php to the list if you are using PHP index index.html index.htm index.nginx-debian.html; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + server_name _; ssl_certificate /etc/nginx/pki/server.crt; ssl_certificate_key /etc/nginx/pki/private/server.key; diff --git a/test/test_helper.bash b/test/test_helper.bash index 1e65189..fafad5c 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -8,6 +8,20 @@ check_certificates() assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" ] } +# Only nginx > 1.11.0 support dual certificates in a single configuration file +# https://unix.stackexchange.com/questions/285924/how-to-compare-a-programs-version-in-a-shell-script +check_nginx() { + requiredver="1.11.0" + currentver="$(nginx -v)" + if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then + export OLD_NGINX="false" + else + echo "INFO: Running nginx version $currentver which doesn't support dual certificates" >&3 + echo "INFO: not checking that certificate is installed correctly" >&3 + export OLD_NGINX="true" + fi +} + check_output_for_errors() { refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' # less strict tests if running with debug output From 98ee28cd52079d9099e366f09b0ab341fb43119b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 18 Jun 2020 17:22:27 +0100 Subject: [PATCH 085/308] Merge pebble dns and staging dns tests --- test/2-simple-dns01-dig.bats | 7 ++----- test/2-simple-dns01-nslookup.bats | 4 ++-- test/7-staging-dns01-dig.bats | 2 ++ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index 0a54684..6e1eca3 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -27,11 +27,11 @@ teardown() { @test "Create new certificate using DNS-01 verification (dig)" { + CONFIG_FILE="getssl-dns01.cfg" if [ -n "$STAGING" ]; then - skip "Using staging server, skipping internal test" + CONFIG_FILE="getssl-staging-dns01.cfg" fi - CONFIG_FILE="getssl-dns01.cfg" setup_environment init_getssl create_certificate -d @@ -42,9 +42,6 @@ teardown() { @test "Force renewal of certificate using DNS-01 (dig)" { - if [ -n "$STAGING" ]; then - skip "Using staging server, skipping internal test" - fi run ${CODE_DIR}/getssl -d -f $GETSSL_HOST assert_success assert_output --partial "dig" diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index dc6f2f5..39c8bae 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -28,11 +28,11 @@ teardown() { @test "Create new certificate using DNS-01 verification (nslookup)" { + CONFIG_FILE="getssl-dns01.cfg" if [ -n "$STAGING" ]; then - skip "Using staging server, skipping internal test" + CONFIG_FILE="getssl-dns01.cfg" fi - CONFIG_FILE="getssl-dns01.cfg" setup_environment init_getssl create_certificate -d diff --git a/test/7-staging-dns01-dig.bats b/test/7-staging-dns01-dig.bats index 7e21124..3d70ce5 100644 --- a/test/7-staging-dns01-dig.bats +++ b/test/7-staging-dns01-dig.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' @test "Create new certificate using staging server, dig and DuckDNS" { + skip if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi @@ -20,6 +21,7 @@ load '/getssl/test/test_helper.bash' } @test "Force renewal of certificate using staging server, dig and DuckDNS" { + skip if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi From 0f039c0dcf694e53ef60abe7875a2cb826164cb3 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 18 Jun 2020 18:14:27 +0100 Subject: [PATCH 086/308] Update README.md Remove manual ACMEv1 -> ACMEv2 upgrade information --- README.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/README.md b/README.md index 3882b50..12eaf66 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,6 @@ Obtain SSL certificates from the letsencrypt.org ACME server. Suitable for automating the process on remote servers. -## Upgrading from ACME v01 to ACME v02 - -Find the following line in your `getssl.cfg` file: - -```CA="https://acme-v01.api.letsencrypt.org"``` - -and change it to: - -```CA="https://acme-v02.api.letsencrypt.org"``` - ## Features * **Bash** - It runs on virtually all unix machines, including BSD, most @@ -43,7 +33,7 @@ and change it to: debug information is available. * **Reload services** - After a new certificate is obtained then the relevant services (e.g. apache/nginx/postfix) can be reloaded. -* **ACME v1 and V2** - Supports both ACME versions 1 and 2 +* **ACME v1 and V2** - Supports both ACME versions 1 and 2 (note ACMEv1 is deprecated and clients will automatically use v2) ## Installation From 84996161286c36d1503e4eba691bace27e9db27b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 14 Jul 2020 21:40:30 +0100 Subject: [PATCH 087/308] Support centos8 --- test/Dockerfile-centos8 | 20 ++++++++++++++++++++ test/restart-nginx | 2 +- test/test_helper.bash | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 test/Dockerfile-centos8 diff --git a/test/Dockerfile-centos8 b/test/Dockerfile-centos8 new file mode 100644 index 0000000..15c14d6 --- /dev/null +++ b/test/Dockerfile-centos8 @@ -0,0 +1,20 @@ +FROM centos:centos8 + +# Note this image uses drill, does not have dig or nslookup installed + +# Update and install required software +RUN yum -y update +RUN yum -y install epel-release +RUN yum -y install git curl bind-utils wget which 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 +COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf + +# BATS (Bash Automated Testings) +RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN /bats-core/install.sh /usr/local diff --git a/test/restart-nginx b/test/restart-nginx index e62433d..4dc8af0 100755 --- a/test/restart-nginx +++ b/test/restart-nginx @@ -3,7 +3,7 @@ if [ "$GETSSL_OS" = "alpine" ]; then killall -HUP nginx >&3- sleep 5 -elif [ "$GETSSL_OS" == "centos7" ]; then +elif [[ "$GETSSL_OS" == "centos"[78] ]]; then pgrep nginx | head -1 | xargs kill -HUP sleep 5 else diff --git a/test/test_helper.bash b/test/test_helper.bash index fafad5c..9358619 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -72,7 +72,7 @@ if [[ -f /usr/bin/supervisord && -f /etc/supervisord.conf ]]; then if [[ ! $(pgrep supervisord) ]]; then /usr/bin/supervisord -c /etc/supervisord.conf >&3- fi -elif [ "$GETSSL_OS" == "centos7" ]; then +elif [[ "$GETSSL_OS" == "centos"[78] ]]; then if [ -z "$(pgrep nginx)" ]; then nginx >&3- fi From 31958a27f3395e9256ef579dc91e5f1a6c29609e Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 14 Jul 2020 21:40:51 +0100 Subject: [PATCH 088/308] Check error message shown if ACL has a leading space --- test/16-test-bad-acl.bats | 23 +++++++++++++++++ test/test-config/getssl-http01-bad-acl.cfg | 29 ++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 test/16-test-bad-acl.bats create mode 100644 test/test-config/getssl-http01-bad-acl.cfg diff --git a/test/16-test-bad-acl.bats b/test/16-test-bad-acl.bats new file mode 100644 index 0000000..d953951 --- /dev/null +++ b/test/16-test-bad-acl.bats @@ -0,0 +1,23 @@ +#! /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 "Test behaviour if ACL= line has a space" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01-bad-acl.cfg" + setup_environment + init_getssl + create_certificate + assert_failure +} diff --git a/test/test-config/getssl-http01-bad-acl.cfg b/test/test-config/getssl-http01-bad-acl.cfg new file mode 100644 index 0000000..461d3a3 --- /dev/null +++ b/test/test-config/getssl-http01-bad-acl.cfg @@ -0,0 +1,29 @@ +# 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 +SANS="" + +# Acme Challenge Location. +ACL= ('/var/www/html/.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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" From 13f3a8b8def1510f8d5f362952e32cc001101c76 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 14 Jul 2020 21:41:21 +0100 Subject: [PATCH 089/308] Support space delimited SANS --- getssl | 15 ++-- test/15-test-revoke-no-suffix.bats | 4 +- test/17-test-spaces-in-sans.bats | 75 +++++++++++++++++++ ...tp01-spaces-sans-and-ignore-dir-domain.cfg | 29 +++++++ .../test-config/getssl-http01-spaces-sans.cfg | 28 +++++++ 5 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 test/17-test-spaces-in-sans.bats create mode 100644 test/test-config/getssl-http01-spaces-sans-and-ignore-dir-domain.cfg create mode 100644 test/test-config/getssl-http01-spaces-sans.cfg diff --git a/getssl b/getssl index 4a1a43c..a5e72cf 100755 --- a/getssl +++ b/getssl @@ -231,11 +231,14 @@ # 2020-05-06 Fix missing fullchain.ec.crt when creating dual certificates (2.27) # 2020-05-14 Add --notify-valid option (exit 2 if certificate is valid) # 2020-05-23 Fix --revoke (didn't work with ACMEv02) (2.28) +# 2020-06-06 Fix missing URL_revoke definition when no CA directory suffix (#566) +# 2020-06-18 Fix CHECK_REMOTE for DUAL_RSA_ECDSA (#570) +# 2020-07-14 Support space separated SANS (#574) (2.29) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.28" +VERSION="2.29" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -497,7 +500,7 @@ check_config() { # check the config files for all obvious errors # get all domains if [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then - alldomains=${SANS//,/ } + alldomains=${SANS//[, ]/ } else alldomains=$(echo "$DOMAIN,$SANS" | sed "s/,/ /g") fi @@ -784,7 +787,7 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) if [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then alldomains=$(echo "$SANS" | sed -e 's/ //g; s/,$//; y/,/\n/' | sort -u) else - alldomains=$(echo "$DOMAIN,$SANS" | sed -e 's/ //g; s/,$//; y/,/\n/' | sort -u) + alldomains=$(echo "$DOMAIN,$SANS" | sed -e 's/,/ /g; s/ $//; y/ /\n/' | sort -u) fi domains_in_csr=$(openssl req -text -noout -in "$csr_file" \ | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \ @@ -2695,9 +2698,9 @@ fi if [[ -z "$SANS" ]]; then SANLIST="subjectAltName=DNS:${DOMAIN}" elif [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then - SANLIST="subjectAltName=DNS:${SANS//,/,DNS:}" + SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" else - SANLIST="subjectAltName=DNS:${DOMAIN},DNS:${SANS//,/,DNS:}" + SANLIST="subjectAltName=DNS:${DOMAIN},DNS:${SANS//[, ]/,DNS:}" fi debug "created SAN list = $SANLIST" @@ -2757,7 +2760,7 @@ info "Verify each domain" # loop through domains for cert ( from SANS list) if [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then - alldomains=${SANS//,/ } + alldomains=${SANS//[, ]/ } else alldomains=$(echo "$DOMAIN,$SANS" | sed "s/,/ /g") fi diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index ce97ddd..7b19c5a 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -11,7 +11,7 @@ setup() { } -@test "Create certificate to check revoke" { +@test "Create certificate to check revoke (no suffix)" { if [ -n "$STAGING" ]; then CONFIG_FILE="getssl-staging-dns01-no-suffix.cfg" else @@ -26,7 +26,7 @@ setup() { } -@test "Check we can revoke a certificate" { +@test "Check we can revoke a certificate (no suffix)" { if [ -n "$STAGING" ]; then CONFIG_FILE="getssl-staging-dns01.cfg" else diff --git a/test/17-test-spaces-in-sans.bats b/test/17-test-spaces-in-sans.bats new file mode 100644 index 0000000..01e7090 --- /dev/null +++ b/test/17-test-spaces-in-sans.bats @@ -0,0 +1,75 @@ +#! /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 "Test behaviour if SANS line is space separated instead of comma separated" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01-spaces-sans.cfg" + setup_environment + + # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) + for prefix in a b c; do + curl --silent -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 + check_output_for_errors +} + + +@test "Test renewal if SANS line is space separated instead of comma separated" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success + check_output_for_errors + cleanup_environment +} + + +@test "Test behaviour if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01-spaces-sans-and-ignore-dir-domain.cfg" + setup_environment + + # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) + for prefix in a b c; do + curl --silent -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 + check_output_for_errors +} + + +@test "Test renewal if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success + check_output_for_errors + cleanup_environment + + for prefix in a b c; do + curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a + done +} diff --git a/test/test-config/getssl-http01-spaces-sans-and-ignore-dir-domain.cfg b/test/test-config/getssl-http01-spaces-sans-and-ignore-dir-domain.cfg new file mode 100644 index 0000000..1b3cdca --- /dev/null +++ b/test/test-config/getssl-http01-spaces-sans-and-ignore-dir-domain.cfg @@ -0,0 +1,29 @@ +# 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" + +# Ignore directory domain (i.e. the domain passed on the command line), and just use the domains in the SANS list +IGNORE_DIRECTORY_DOMAIN="true" +SANS="a.${GETSSL_HOST} b.${GETSSL_HOST} c.${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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" diff --git a/test/test-config/getssl-http01-spaces-sans.cfg b/test/test-config/getssl-http01-spaces-sans.cfg new file mode 100644 index 0000000..c93b4f7 --- /dev/null +++ b/test/test-config/getssl-http01-spaces-sans.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 +SANS="a.${GETSSL_HOST} b.${GETSSL_HOST} c.${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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" From ed880a39feeb459f83473e13440cb5c14ab3a4ed Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 15 Jul 2020 14:34:49 +0100 Subject: [PATCH 090/308] Add centos8 --- .github/workflows/run-all-tests.yml | 172 +++++++++++++++------------- 1 file changed, 90 insertions(+), 82 deletions(-) diff --git a/.github/workflows/run-all-tests.yml b/.github/workflows/run-all-tests.yml index 08fb41b..7bb05dc 100644 --- a/.github/workflows/run-all-tests.yml +++ b/.github/workflows/run-all-tests.yml @@ -1,82 +1,90 @@ -name: Run all tests -on: - push: - branches: - - master - pull_request: - branches: - - master -jobs: - test-alpine: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on Alpine - run: test/run-test.sh alpine - test-centos6: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on CentOS6 - run: test/run-test.sh centos6 - test-centos7: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on CentOS7 - run: test/run-test.sh centos7 - test-centos7-staging: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on CentOS7 against Staging using DuckDNS - run: test/run-test.sh centos7-staging - test-debian: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on Debian - run: test/run-test.sh debian - test-ubuntu: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on Ubuntu - run: test/run-test.sh ubuntu - test-ubuntu16: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on Ubuntu16 - run: test/run-test.sh ubuntu16 - test-ubuntu18: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on Ubuntu18 - run: test/run-test.sh ubuntu18 - test-ubuntu-staging: - needs: test-centos7-staging - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on Ubuntu against Staging using DuckDNS - run: test/run-test.sh ubuntu-staging +name: Run all tests +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + test-alpine: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Alpine + run: test/run-test.sh alpine + test-centos6: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on CentOS6 + run: test/run-test.sh centos6 + test-centos7: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on CentOS7 + run: test/run-test.sh centos7 + test-centos7-staging: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on CentOS7 against Staging using DuckDNS + run: test/run-test.sh centos7-staging + test-centos8: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on CentOS8 + run: test/run-test.sh centos8 + test-debian: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Debian + run: test/run-test.sh debian + test-ubuntu: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Ubuntu + run: test/run-test.sh ubuntu + test-ubuntu16: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Ubuntu16 + run: test/run-test.sh ubuntu16 + test-ubuntu18: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Ubuntu18 + run: test/run-test.sh ubuntu18 + test-ubuntu-staging: + needs: test-centos7-staging + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Ubuntu against Staging using DuckDNS + run: test/run-test.sh ubuntu-staging From 5c66f2956d85e87078958b5519fb64c512fe6a7a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 16 Jul 2020 11:37:02 +0100 Subject: [PATCH 091/308] Test space delimited SANS using DNS-01 authentication --- test/17-test-spaces-in-sans-dns01.bats | 75 +++++++++++++++++++ ...ats => 17-test-spaces-in-sans-http01.bats} | 8 +- test/9-multiple-domains-dns01.bats | 4 +- ... getssl-dns01-ignore-directory-domain.cfg} | 0 ....cfg => getssl-dns01-multiple-domains.cfg} | 0 ...ns01-spaces-sans-and-ignore-dir-domain.cfg | 35 +++++++++ test/test-config/getssl-dns01-spaces-sans.cfg | 34 +++++++++ 7 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 test/17-test-spaces-in-sans-dns01.bats rename test/{17-test-spaces-in-sans.bats => 17-test-spaces-in-sans-http01.bats} (94%) rename test/test-config/{getssl-ignore-directory-domain.cfg => getssl-dns01-ignore-directory-domain.cfg} (100%) rename test/test-config/{getssl-multiple-domains-dns01.cfg => getssl-dns01-multiple-domains.cfg} (100%) create mode 100644 test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg create mode 100644 test/test-config/getssl-dns01-spaces-sans.cfg diff --git a/test/17-test-spaces-in-sans-dns01.bats b/test/17-test-spaces-in-sans-dns01.bats new file mode 100644 index 0000000..c54de7b --- /dev/null +++ b/test/17-test-spaces-in-sans-dns01.bats @@ -0,0 +1,75 @@ +#! /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 "Test behaviour if SANS line is space separated instead of comma separated (dns01)" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-dns01-spaces-sans.cfg" + setup_environment + + # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) + for prefix in a b c; do + curl --silent -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 + check_output_for_errors +} + + +@test "Test renewal if SANS line is space separated instead of comma separated (dns01)" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success + check_output_for_errors + cleanup_environment +} + + +@test "Test behaviour if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN (dns01)" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg" + setup_environment + + # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) + for prefix in a b c; do + curl --silent -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 + check_output_for_errors +} + + +@test "Test renewal if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN (dns01)" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success + check_output_for_errors + cleanup_environment + + for prefix in a b c; do + curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a + done +} diff --git a/test/17-test-spaces-in-sans.bats b/test/17-test-spaces-in-sans-http01.bats similarity index 94% rename from test/17-test-spaces-in-sans.bats rename to test/17-test-spaces-in-sans-http01.bats index 01e7090..2d2d667 100644 --- a/test/17-test-spaces-in-sans.bats +++ b/test/17-test-spaces-in-sans-http01.bats @@ -11,7 +11,7 @@ setup() { } -@test "Test behaviour if SANS line is space separated instead of comma separated" { +@test "Test behaviour if SANS line is space separated instead of comma separated (http01)" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi @@ -30,7 +30,7 @@ setup() { } -@test "Test renewal if SANS line is space separated instead of comma separated" { +@test "Test renewal if SANS line is space separated instead of comma separated (http01)" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi @@ -41,7 +41,7 @@ setup() { } -@test "Test behaviour if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN" { +@test "Test behaviour if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN (http01)" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi @@ -60,7 +60,7 @@ setup() { } -@test "Test renewal if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN" { +@test "Test renewal if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN (http01)" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi diff --git a/test/9-multiple-domains-dns01.bats b/test/9-multiple-domains-dns01.bats index c1de91c..65eab09 100644 --- a/test/9-multiple-domains-dns01.bats +++ b/test/9-multiple-domains-dns01.bats @@ -16,7 +16,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - CONFIG_FILE="getssl-multiple-domains-dns01.cfg" + CONFIG_FILE="getssl-dns01-multiple-domains.cfg" setup_environment # Add top level domain from SANS to DNS @@ -47,7 +47,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - CONFIG_FILE="getssl-ignore-directory-domain.cfg" + CONFIG_FILE="getssl-dns01-ignore-directory-domain.cfg" setup_environment # Add top level domain from SANS to DNS diff --git a/test/test-config/getssl-ignore-directory-domain.cfg b/test/test-config/getssl-dns01-ignore-directory-domain.cfg similarity index 100% rename from test/test-config/getssl-ignore-directory-domain.cfg rename to test/test-config/getssl-dns01-ignore-directory-domain.cfg diff --git a/test/test-config/getssl-multiple-domains-dns01.cfg b/test/test-config/getssl-dns01-multiple-domains.cfg similarity index 100% rename from test/test-config/getssl-multiple-domains-dns01.cfg rename to test/test-config/getssl-dns01-multiple-domains.cfg diff --git a/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg b/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg new file mode 100644 index 0000000..453d046 --- /dev/null +++ b/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg @@ -0,0 +1,35 @@ +# 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" + +VALIDATE_VIA_DNS=true +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" +PUBLIC_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT="" + +# Ignore directory domain (i.e. the domain passed on the command line), and just use the domains in the SANS list +IGNORE_DIRECTORY_DOMAIN="true" +SANS="a.${GETSSL_HOST} b.${GETSSL_HOST} c.${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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" diff --git a/test/test-config/getssl-dns01-spaces-sans.cfg b/test/test-config/getssl-dns01-spaces-sans.cfg new file mode 100644 index 0000000..2b7e02b --- /dev/null +++ b/test/test-config/getssl-dns01-spaces-sans.cfg @@ -0,0 +1,34 @@ +# 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" + +VALIDATE_VIA_DNS=true +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" +PUBLIC_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT="" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="a.${GETSSL_HOST} b.${GETSSL_HOST} c.${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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" From e6336b9c8b2605895e824a6e6fee25dbb8a86c10 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 4 Aug 2020 21:23:13 +0100 Subject: [PATCH 092/308] Add some debug statements to CHECK_REMOTE --- getssl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/getssl b/getssl index a5e72cf..56fc765 100755 --- a/getssl +++ b/getssl @@ -2842,6 +2842,8 @@ if [[ ${CHECK_REMOTE} == "true" ]]; then | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${PARAMS[i]} 2>/dev/null \ | openssl x509 -noout -fingerprint 2>/dev/null) CERT_LOCAL=$(openssl x509 -noout -fingerprint < "${CERTS[i]}" 2>/dev/null) + debug CERT_LOCAL="${CERT_LOCAL}" + debug CERT_REMOTE="${CERT_REMOTE}" if [[ "$CERT_LOCAL" == "$CERT_REMOTE" ]]; then info "${DOMAIN} - ${TYPES[i]} certificate installed OK on server" else From 1bed21bff574fe552bdf94b40741c5e8be9d02bc Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 4 Aug 2020 21:23:45 +0100 Subject: [PATCH 093/308] Fix bug detecting the nginx version --- test/test_helper.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_helper.bash b/test/test_helper.bash index 9358619..d498f93 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -12,7 +12,7 @@ check_certificates() # https://unix.stackexchange.com/questions/285924/how-to-compare-a-programs-version-in-a-shell-script check_nginx() { requiredver="1.11.0" - currentver="$(nginx -v)" + currentver=$(nginx -v 2>&1) if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then export OLD_NGINX="false" else From 73a7939f4fe8b19c8cabc91750b158869c516f61 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 4 Aug 2020 21:24:22 +0100 Subject: [PATCH 094/308] Fix DOMAIN_CERT and DOMAIN_KEY --- test/test-config/getssl-http01-dual-rsa-ecdsa-old-nginx.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-config/getssl-http01-dual-rsa-ecdsa-old-nginx.cfg b/test/test-config/getssl-http01-dual-rsa-ecdsa-old-nginx.cfg index 41581ae..9cf155f 100644 --- a/test/test-config/getssl-http01-dual-rsa-ecdsa-old-nginx.cfg +++ b/test/test-config/getssl-http01-dual-rsa-ecdsa-old-nginx.cfg @@ -19,8 +19,8 @@ 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.ec.crt" -DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.ec.key" +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 From d188e9ec7d07d817c8c25183516040be3e39385b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 5 Aug 2020 20:48:14 +0100 Subject: [PATCH 095/308] Use -sigalgs instead of -cipher to check certificate installed --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 56fc765..385c3bf 100755 --- a/getssl +++ b/getssl @@ -2826,7 +2826,7 @@ fi if [[ ${CHECK_REMOTE} == "true" ]]; then sleep "$CHECK_REMOTE_WAIT" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - PARAMS=("-cipher RSA" "-cipher ECDSA") + PARAMS=("-sigalgs RSA-PSS+SHA256:RSA-PSS+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA512") CERTS=("$CERT_FILE" "${CERT_FILE%.*}.ec.crt") TYPES=("rsa" "$PRIVATE_KEY_ALG") else From ac4f848dac14f53c6e576d35254f5ac0083d4e6a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 5 Aug 2020 20:49:14 +0100 Subject: [PATCH 096/308] Include tls1.3 in the tests --- test/test-config/nginx-ubuntu-dual-certs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-config/nginx-ubuntu-dual-certs b/test/test-config/nginx-ubuntu-dual-certs index ce1fbbf..1eceecd 100644 --- a/test/test-config/nginx-ubuntu-dual-certs +++ b/test/test-config/nginx-ubuntu-dual-certs @@ -42,7 +42,7 @@ server { # Add index.php to the list if you are using PHP index index.html index.htm index.nginx-debian.html; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; server_name _; ssl_certificate /etc/nginx/pki/server.crt; From 68f04db61ffc8b5cc667aaa5d01ad147c088c401 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 6 Aug 2020 14:49:20 +0100 Subject: [PATCH 097/308] Add ECDSA+SHA384 to -sigalgs --- getssl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 385c3bf..b22c83b 100755 --- a/getssl +++ b/getssl @@ -234,6 +234,7 @@ # 2020-06-06 Fix missing URL_revoke definition when no CA directory suffix (#566) # 2020-06-18 Fix CHECK_REMOTE for DUAL_RSA_ECDSA (#570) # 2020-07-14 Support space separated SANS (#574) (2.29) +# 2020-08-06 Use -sigalgs instead of -cipher when checking remote for tls1.3 (#570) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} @@ -2565,7 +2566,7 @@ fi if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then debug "getting certificate for $DOMAIN from remote server" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - CIPHER="-cipher RSA" + CIPHER="-sigalgs RSA-PSS+SHA256" else CIPHER="" fi @@ -2826,7 +2827,7 @@ fi if [[ ${CHECK_REMOTE} == "true" ]]; then sleep "$CHECK_REMOTE_WAIT" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - PARAMS=("-sigalgs RSA-PSS+SHA256:RSA-PSS+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA512") + PARAMS=("-sigalgs RSA-PSS+SHA256" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") CERTS=("$CERT_FILE" "${CERT_FILE%.*}.ec.crt") TYPES=("rsa" "$PRIVATE_KEY_ALG") else From 0b4a8e505ad3c1af058b65890149a98098d5056c Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 20 Aug 2020 18:55:04 +0100 Subject: [PATCH 098/308] Add test for certificate created but not installed --- test/6-dual-rsa-ecdsa-copy-2-locations.bats | 24 ++++++++++++++ ...dual-rsa-ecdsa-2-locations-wrong-nginx.cfg | 32 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations-wrong-nginx.cfg diff --git a/test/6-dual-rsa-ecdsa-copy-2-locations.bats b/test/6-dual-rsa-ecdsa-copy-2-locations.bats index a8e7653..593d770 100644 --- a/test/6-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/6-dual-rsa-ecdsa-copy-2-locations.bats @@ -40,6 +40,8 @@ teardown() { create_certificate assert_success check_output_for_errors + assert_line --partial "rsa certificate installed OK on server" + assert_line --partial "prime256v1 certificate installed OK on server" # Check that the RSA chain and key have been copied to both locations assert [ -e "/etc/nginx/pki/domain-chain.crt" ] @@ -53,3 +55,25 @@ teardown() { assert [ -e "/etc/nginx/pki/private/server.ec.key" ] assert [ -e "/root/a.${GETSSL_HOST}/server.ec.key" ] } + + +@test "Create dual certificates and copy to two locations but not returned by server" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + check_nginx + if [ "$OLD_NGINX" = "false" ]; then + CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-2-locations-wrong-nginx.cfg" + else + skip "Skipping as old nginx servers cannot return both certificates" + fi + + setup_environment + mkdir -p /root/a.${GETSSL_HOST} + + init_getssl + create_certificate + assert_failure + assert_line --partial "prime256v1 certificate obtained but not installed on server" +} diff --git a/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations-wrong-nginx.cfg b/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations-wrong-nginx.cfg new file mode 100644 index 0000000..80533ce --- /dev/null +++ b/test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations-wrong-nginx.cfg @@ -0,0 +1,32 @@ +# Test that more than one location can be specified for CERT and KEY locations and that the +# files are copied to both locations when both RSA and ECDSA certificates are created +# +CA="https://pebble:14000/dir" + +DUAL_RSA_ECDSA="true" +ACCOUNT_KEY_TYPE="prime256v1" +PRIVATE_KEY_ALG="prime256v1" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="a.${GETSSL_HOST}" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') + +#Set USE_SINGLE_ACL="true" to 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) +# 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;/root/a.${GETSSL_HOST}/server.key" +CA_CERT_LOCATION="/etc/nginx/pki/chain.crt" +DOMAIN_CHAIN_LOCATION="/etc/nginx/pki/domain-chain.crt;/root/a.${GETSSL_HOST}/domain-chain.crt" # 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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" From e9912e790db735633eee65b94bcea078fbc561d5 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 20 Aug 2020 18:58:25 +0100 Subject: [PATCH 099/308] Update sigalgs, different error if certificate not installed vs different --- getssl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index b22c83b..6e7fb80 100755 --- a/getssl +++ b/getssl @@ -2565,11 +2565,11 @@ fi # 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 debug "getting certificate for $DOMAIN from remote server" -if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - CIPHER="-sigalgs RSA-PSS+SHA256" -else + if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then + CIPHER="-sigalgs RSA-PSS+SHA256:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512" + else CIPHER="" -fi + fi # shellcheck disable=SC2086 EX_CERT=$(echo \ | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${CIPHER} 2>/dev/null \ @@ -2827,7 +2827,7 @@ fi if [[ ${CHECK_REMOTE} == "true" ]]; then sleep "$CHECK_REMOTE_WAIT" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - PARAMS=("-sigalgs RSA-PSS+SHA256" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") + PARAMS=("-sigalgs RSA-PSS+SHA256:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") CERTS=("$CERT_FILE" "${CERT_FILE%.*}.ec.crt") TYPES=("rsa" "$PRIVATE_KEY_ALG") else @@ -2847,6 +2847,9 @@ if [[ ${CHECK_REMOTE} == "true" ]]; then debug CERT_REMOTE="${CERT_REMOTE}" if [[ "$CERT_LOCAL" == "$CERT_REMOTE" ]]; then info "${DOMAIN} - ${TYPES[i]} certificate installed OK on server" + elif [[ "$CERT_REMOTE" == "" ]]; then + info "${CERTS[i]} not returned by server" + error_exit "${DOMAIN} - ${TYPES[i]} certificate obtained but not installed on server" else info "${CERTS[i]} didn't match server" error_exit "${DOMAIN} - ${TYPES[i]} certificate obtained but certificate on server is different from the new certificate" From 82fa60a81f072777168de2fd0d526879b8bc9999 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 24 Aug 2020 18:34:58 +0100 Subject: [PATCH 100/308] Fix tests for old nginx --- test/6-dual-rsa-ecdsa-copy-2-locations.bats | 6 ++++-- test/test_helper.bash | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/6-dual-rsa-ecdsa-copy-2-locations.bats b/test/6-dual-rsa-ecdsa-copy-2-locations.bats index 593d770..6f75f25 100644 --- a/test/6-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/6-dual-rsa-ecdsa-copy-2-locations.bats @@ -40,8 +40,10 @@ teardown() { create_certificate assert_success check_output_for_errors - assert_line --partial "rsa certificate installed OK on server" - assert_line --partial "prime256v1 certificate installed OK on server" + if [ "$OLD_NGINX" = "false" ]; then + assert_line --partial "rsa certificate installed OK on server" + assert_line --partial "prime256v1 certificate installed OK on server" + fi # Check that the RSA chain and key have been copied to both locations assert [ -e "/etc/nginx/pki/domain-chain.crt" ] diff --git a/test/test_helper.bash b/test/test_helper.bash index d498f93..db79ea4 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -12,7 +12,7 @@ check_certificates() # https://unix.stackexchange.com/questions/285924/how-to-compare-a-programs-version-in-a-shell-script check_nginx() { requiredver="1.11.0" - currentver=$(nginx -v 2>&1) + currentver=$(nginx -v 2>&1 | awk -F"/" '{print $2}') if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then export OLD_NGINX="false" else From 68b05d7c6e051d35bd585379f60e04c7bf0c4f35 Mon Sep 17 00:00:00 2001 From: Paul Slootman Date: Mon, 31 Aug 2020 13:06:42 +0200 Subject: [PATCH 101/308] Fix slow fork bomb when directory containing getssl isn't writeable (#440) getssl updets itself by: - checking for a new version - if so: - download the new one into a tmp location - rename the current one to name with version appended - rename the tmp file to the current location - run the new version If the renaming fails, the old version gets run, which again downloads, etc. Now exit if the rename (install command) fails. --- getssl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index a5e72cf..734f176 100755 --- a/getssl +++ b/getssl @@ -234,6 +234,7 @@ # 2020-06-06 Fix missing URL_revoke definition when no CA directory suffix (#566) # 2020-06-18 Fix CHECK_REMOTE for DUAL_RSA_ECDSA (#570) # 2020-07-14 Support space separated SANS (#574) (2.29) +# 2020-08-31 Fix slow fork bomb when directory containing getssl isn't writeable (#440) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} @@ -608,8 +609,12 @@ check_getssl_upgrade() { # check if a more recent version of code is available a # use a default of 0 for cases where the latest code has not been obtained. if [[ "${latestvdec:-0}" -gt "$localvdec" ]]; then if [[ ${_UPGRADE} -eq 1 ]]; then - install "$0" "${0}.v${VERSION}" - install -m 700 "$TEMP_UPGRADE_FILE" "$0" + if ! install "$0" "${0}.v${VERSION}"; then + error_exit "problem renaming old version while updating, check permissions" + fi + if ! install -m 700 "$TEMP_UPGRADE_FILE" "$0"; then + error_exit "problem installing new version while updating, check permissions" + fi if [[ ${_MUTE} -eq 0 ]]; then echo "Updated getssl from v${VERSION} to v${latestversion}" echo "these update notification can be turned off using the -Q option" From 47b3962c139d799f9c1b19a0d5a4eb4ecde2b665 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 2 Sep 2020 08:54:39 +0100 Subject: [PATCH 102/308] Support older versions of openssl which don't support RSA-PSS --- getssl | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 6e7fb80..5e4285d 100755 --- a/getssl +++ b/getssl @@ -2566,7 +2566,13 @@ fi if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then debug "getting certificate for $DOMAIN from remote server" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - CIPHER="-sigalgs RSA-PSS+SHA256:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512" + # shellcheck disable=SC2086 + # check if openssl supports RSA-PSS + if [[ $(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS 2>/dev/null) ]]; then + CIPHER="-sigalgs RSA+SHA256:RSA+SHA384:RSA+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA512" + else + CIPHER="-sigalgs RSA+SHA256:RSA+SHA384:RSA+SHA512" + fi else CIPHER="" fi @@ -2827,7 +2833,14 @@ fi if [[ ${CHECK_REMOTE} == "true" ]]; then sleep "$CHECK_REMOTE_WAIT" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then - PARAMS=("-sigalgs RSA-PSS+SHA256:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") + # shellcheck disable=SC2086 + # check if openssl supports RSA-PSS + if [[ $(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS 2>/dev/null) ]]; then + PARAMS=("-sigalgs RSA-PSS+SHA256:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") + else + PARAMS=("-sigalgs RSA+SHA256:RSA+SHA384:RSA+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") + fi + CERTS=("$CERT_FILE" "${CERT_FILE%.*}.ec.crt") TYPES=("rsa" "$PRIVATE_KEY_ALG") else From 693c37d4db4225508675e5a7f2fa5fc81f906675 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 2 Sep 2020 08:55:26 +0100 Subject: [PATCH 103/308] Fix some test fragility --- test/14-test-revoke.bats | 2 +- test/15-test-revoke-no-suffix.bats | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats index 2e95e0d..e624552 100644 --- a/test/14-test-revoke.bats +++ b/test/14-test-revoke.bats @@ -38,5 +38,5 @@ setup() { run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA assert_success - check_output_for_errors + check_output_for_errors "debug" } diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index 7b19c5a..26f5f3f 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -38,5 +38,5 @@ setup() { run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA assert_success - check_output_for_errors + check_output_for_errors "debug" } From 50310a722ad707bc974613c45645572c22c9dc55 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 2 Sep 2020 08:56:46 +0100 Subject: [PATCH 104/308] Fix bug when SANS is separated by commas and spaces --- getssl | 4 +++ test/17-test-spaces-in-sans-dns01.bats | 19 +++++++++++ test/17-test-spaces-in-sans-http01.bats | 19 +++++++++++ .../getssl-dns01-spaces-and-commas-sans.cfg | 34 +++++++++++++++++++ .../getssl-http01-spaces-and-commas-sans.cfg | 28 +++++++++++++++ 5 files changed, 104 insertions(+) create mode 100644 test/test-config/getssl-dns01-spaces-and-commas-sans.cfg create mode 100644 test/test-config/getssl-http01-spaces-and-commas-sans.cfg diff --git a/getssl b/getssl index 6e7fb80..c317d3d 100755 --- a/getssl +++ b/getssl @@ -2521,6 +2521,10 @@ if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then . "$DOMAIN_DIR/getssl.cfg" fi +# Ensure SANS is comma separated by replacing any number of commas or spaces with a single comma +# shellcheck disable=SC2001 +SANS=$(echo "$SANS" | sed 's/[, ]\+/,/g') + # from SERVER_TYPE set REMOTE_PORT and REMOTE_EXTRA set_server_type diff --git a/test/17-test-spaces-in-sans-dns01.bats b/test/17-test-spaces-in-sans-dns01.bats index c54de7b..75dce4b 100644 --- a/test/17-test-spaces-in-sans-dns01.bats +++ b/test/17-test-spaces-in-sans-dns01.bats @@ -73,3 +73,22 @@ setup() { curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a done } + + +@test "Test behaviour if SANS line is comma and space separated (dns01)" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-dns01-spaces-and-commas-sans.cfg" + setup_environment + + # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) + for prefix in a b c; do + curl --silent -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 + check_output_for_errors +} diff --git a/test/17-test-spaces-in-sans-http01.bats b/test/17-test-spaces-in-sans-http01.bats index 2d2d667..f3ba482 100644 --- a/test/17-test-spaces-in-sans-http01.bats +++ b/test/17-test-spaces-in-sans-http01.bats @@ -73,3 +73,22 @@ setup() { curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a done } + + +@test "Test behaviour if SANS line is comma and space separated (http01)" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01-spaces-and-commas-sans.cfg" + setup_environment + + # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) + for prefix in a b c; do + curl --silent -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 + check_output_for_errors +} diff --git a/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg b/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg new file mode 100644 index 0000000..fe38df9 --- /dev/null +++ b/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg @@ -0,0 +1,34 @@ +# 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" + +VALIDATE_VIA_DNS=true +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" +PUBLIC_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT="" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="a.${GETSSL_HOST}, b.${GETSSL_HOST}, c.${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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" diff --git a/test/test-config/getssl-http01-spaces-and-commas-sans.cfg b/test/test-config/getssl-http01-spaces-and-commas-sans.cfg new file mode 100644 index 0000000..c4f02c7 --- /dev/null +++ b/test/test-config/getssl-http01-spaces-and-commas-sans.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 +SANS="a.${GETSSL_HOST}, b.${GETSSL_HOST}, c.${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} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" From d95b3e61b79c79369ab4c43c9c1c4a64ae9db5b7 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 2 Sep 2020 15:25:59 +0100 Subject: [PATCH 105/308] Fix openssl RSA-PSS check --- getssl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 5e4285d..2737f1a 100755 --- a/getssl +++ b/getssl @@ -2568,7 +2568,7 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then # shellcheck disable=SC2086 # check if openssl supports RSA-PSS - if [[ $(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS 2>/dev/null) ]]; then + if [[ $(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS+SHA256 2>/dev/null) ]]; then CIPHER="-sigalgs RSA+SHA256:RSA+SHA384:RSA+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA512" else CIPHER="-sigalgs RSA+SHA256:RSA+SHA384:RSA+SHA512" @@ -2835,7 +2835,7 @@ if [[ ${CHECK_REMOTE} == "true" ]]; then if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then # shellcheck disable=SC2086 # check if openssl supports RSA-PSS - if [[ $(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS 2>/dev/null) ]]; then + if [[ $(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS+SHA256 2>/dev/null) ]]; then PARAMS=("-sigalgs RSA-PSS+SHA256:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") else PARAMS=("-sigalgs RSA+SHA256:RSA+SHA384:RSA+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") From 07bf481a591ac722f7e28017379d689ac04a550b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 3 Sep 2020 20:41:51 +0100 Subject: [PATCH 106/308] Increase DNS_EXTRA_WAIT to allow dns changes extra time to propagate --- test/test-config/getssl-staging-dns01-no-suffix.cfg | 2 +- test/test-config/getssl-staging-dns01.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-config/getssl-staging-dns01-no-suffix.cfg b/test/test-config/getssl-staging-dns01-no-suffix.cfg index 32fdda3..47d2cec 100644 --- a/test/test-config/getssl-staging-dns01-no-suffix.cfg +++ b/test/test-config/getssl-staging-dns01-no-suffix.cfg @@ -7,7 +7,7 @@ DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" PUBLIC_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true -DNS_EXTRA_WAIT=60 +DNS_EXTRA_WAIT=120 ACCOUNT_KEY_TYPE="rsa" PRIVATE_KEY_ALG="rsa" diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 8c12ee1..348cabf 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -7,7 +7,7 @@ DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" PUBLIC_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true -DNS_EXTRA_WAIT=60 +DNS_EXTRA_WAIT=120 ACCOUNT_KEY_TYPE="rsa" PRIVATE_KEY_ALG="rsa" From 65befd7db5c44ed89ab246bd262d7631272e36c1 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 6 Sep 2020 21:24:38 +0100 Subject: [PATCH 107/308] Update revision history and version number --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index b1b7e16..35a6a73 100755 --- a/getssl +++ b/getssl @@ -237,11 +237,12 @@ # 2020-08-06 Use -sigalgs instead of -cipher when checking remote for tls1.3 (#570) # 2020-08-31 Fix slow fork bomb when directory containing getssl isn't writeable (#440) # 2020-09-01 Use RSA-PSS when checking remote for DUAL_RSA_ECDSA (#570) +# 2020-09-02 Fix issue when SANS is space and comma separated (#579) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.29" +VERSION="2.30" # defaults ACCOUNT_KEY_LENGTH=4096 From c1346a1be8c078b62464dc4b5f0b913dfd7dd240 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 10 Sep 2020 09:45:27 +0100 Subject: [PATCH 108/308] Merge staging server tests into normal tests --- test/10-mixed-case-staging.bats | 22 --------------- test/10-mixed-case.bats | 6 ++-- test/2-simple-dns01-nslookup.bats | 2 +- test/7-staging-dns01-dig.bats | 32 --------------------- test/7-staging-dns01-nslookup.bats | 45 ------------------------------ 5 files changed, 5 insertions(+), 102 deletions(-) delete mode 100644 test/10-mixed-case-staging.bats delete mode 100644 test/7-staging-dns01-dig.bats delete mode 100644 test/7-staging-dns01-nslookup.bats diff --git a/test/10-mixed-case-staging.bats b/test/10-mixed-case-staging.bats deleted file mode 100644 index ea622f7..0000000 --- a/test/10-mixed-case-staging.bats +++ /dev/null @@ -1,22 +0,0 @@ -#! /usr/bin/env bats - -load '/bats-support/load.bash' -load '/bats-assert/load.bash' -load '/getssl/test/test_helper.bash' - - -@test "Check can create certificate if domain is not lowercase using staging server and DuckDNS" { - if [ -z "$STAGING" ]; then - skip "Running internal tests, skipping external test" - fi - - CONFIG_FILE="getssl-staging-dns01.cfg" - GETSSL_CMD_HOST=$(echo $GETSSL_HOST | tr a-z A-Z) - - setup_environment - init_getssl - create_certificate - - assert_success - check_output_for_errors -} diff --git a/test/10-mixed-case.bats b/test/10-mixed-case.bats index b1d8f07..12b787c 100644 --- a/test/10-mixed-case.bats +++ b/test/10-mixed-case.bats @@ -28,9 +28,11 @@ setup() { @test "Check that DNS-01 verification works if the domain is not lowercase" { if [ -n "$STAGING" ]; then - skip "Using staging server, skipping internal test" + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01.cfg" fi - CONFIG_FILE="getssl-dns01.cfg" + GETSSL_CMD_HOST=$(echo $GETSSL_HOST | tr a-z A-Z) setup_environment diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index 39c8bae..d13b318 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -30,7 +30,7 @@ teardown() { @test "Create new certificate using DNS-01 verification (nslookup)" { CONFIG_FILE="getssl-dns01.cfg" if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-dns01.cfg" + CONFIG_FILE="getssl-staging-dns01.cfg" fi setup_environment diff --git a/test/7-staging-dns01-dig.bats b/test/7-staging-dns01-dig.bats deleted file mode 100644 index 3d70ce5..0000000 --- a/test/7-staging-dns01-dig.bats +++ /dev/null @@ -1,32 +0,0 @@ -#! /usr/bin/env bats - -load '/bats-support/load.bash' -load '/bats-assert/load.bash' -load '/getssl/test/test_helper.bash' - - - -@test "Create new certificate using staging server, dig and DuckDNS" { - skip - if [ -z "$STAGING" ]; then - skip "Running internal tests, skipping external test" - fi - CONFIG_FILE="getssl-staging-dns01.cfg" - - setup_environment - init_getssl - create_certificate - assert_success - check_output_for_errors -} - -@test "Force renewal of certificate using staging server, dig and DuckDNS" { - skip - if [ -z "$STAGING" ]; then - skip "Running internal tests, skipping external test" - fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST - assert_success - check_output_for_errors - cleanup_environment -} diff --git a/test/7-staging-dns01-nslookup.bats b/test/7-staging-dns01-nslookup.bats deleted file mode 100644 index bd8d9da..0000000 --- a/test/7-staging-dns01-nslookup.bats +++ /dev/null @@ -1,45 +0,0 @@ -#! /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 - if [ -f /usr/bin/dig ]; then - mv /usr/bin/dig /usr/bin/dig.getssl.bak - fi -} - - -teardown() { - if [ -f /usr/bin/dig.getssl.bak ]; then - mv /usr/bin/dig.getssl.bak /usr/bin/dig - fi -} - - -@test "Create new certificate using staging server, nslookup and DuckDNS" { - if [ -z "$STAGING" ]; then - skip "Running internal tests, skipping external test" - fi - CONFIG_FILE="getssl-staging-dns01.cfg" - - setup_environment - init_getssl - create_certificate - assert_success - check_output_for_errors "debug" -} - - -@test "Force renewal of certificate using staging server, nslookup and DuckDNS" { - if [ -z "$STAGING" ]; then - skip "Running internal tests, skipping external test" - fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST - assert_success - check_output_for_errors "debug" - cleanup_environment -} From fb1823e356c999b8397d248c572996eab29a2e1c Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 10 Sep 2020 09:46:57 +0100 Subject: [PATCH 109/308] Retry DNS_ADD_COMMAND if dns isn't updated after waiting 10 times --- getssl | 27 +++++++++++++-- test/18-staging-retry-dns-add.bats | 20 +++++++++++ test/dns_fail_add_duckdns | 19 +++++++++++ .../getssl-staging-dns01-fail-dns-add.cfg | 33 +++++++++++++++++++ 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 test/18-staging-retry-dns-add.bats create mode 100644 test/dns_fail_add_duckdns create mode 100644 test/test-config/getssl-staging-dns01-fail-dns-add.cfg diff --git a/getssl b/getssl index 35a6a73..7ae6ae5 100755 --- a/getssl +++ b/getssl @@ -258,8 +258,10 @@ CSR_SUBJECT="/" CURL_USERAGENT="${PROGNAME}/${VERSION}" DEACTIVATE_AUTH="false" DEFAULT_REVOKE_CA="https://acme-v02.api.letsencrypt.org" -DNS_EXTRA_WAIT=60 -DNS_WAIT=10 +DNS_EXTRA_WAIT=60 # How long to wait after the DNS has updated before telling the ACME server to check. +DNS_WAIT_RETRY_ADD="false" # Try the dns_add_command again if the DNS record hasn't updated +DNS_WAIT=10 # How long to wait before checking the DNS record again +DNS_WAIT_COUNT=100 # How many times to wait for the DNS record to update DOMAIN_KEY_LENGTH=4096 DUAL_RSA_ECDSA="false" GETSSL_IGNORE_CP_PRESERVE="false" @@ -454,6 +456,7 @@ check_challenge_completion() { # checks with the ACME server if our challenge is # if ACME response is that their check gave an invalid response, error exit if [[ "$status" == "invalid" ]] ; then err_detail=$(echo "$response" | grep "detail") + #! FIXME need to check for "DNS problem: SERVFAIL looking up CAA ..." and retry error_exit "$domain:Verify error:$err_detail" fi @@ -1187,13 +1190,29 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then if [[ "$check_result" == *"$auth_key"* ]]; then check_dns="success" else - if [[ $ntries -lt 100 ]]; then + if [[ $ntries -lt $DNS_WAIT_COUNT ]]; then ntries=$(( ntries + 1 )) + + if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 == 0 )) ]]; then + # shellcheck disable=SC2018,SC2019 + lower_d=$(echo "$d" | tr A-Z a-z) + debug "Retrying adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" + if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then + error_exit "DNS_ADD_COMMAND failed for domain $d" + fi + + fi info "checking DNS at ${ns} for ${d}. Attempt $ntries/100 gave wrong result, "\ "waiting $DNS_WAIT secs before checking again" sleep $DNS_WAIT else debug "dns check failed - removing existing value" + # shellcheck disable=SC2018,SC2019 + lower_d=$(echo "$d" | tr A-Z a-z) + eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" + # remove $dnsfile after each loop. + rm -f "$dnsfile" + error_exit "checking _acme-challenge.${d} gave $check_result not $auth_key" fi fi @@ -1235,6 +1254,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ "$os" == "cygwin" ]]; then gad_d="$orig_gad_d" + # shellcheck disable=SC2086 all_auth_dns_servers=$(nslookup -type=soa "${d}" ${PUBLIC_DNS_SERVER} 2>/dev/null \ | grep "primary name server" \ | awk '{print $NF}') @@ -1314,6 +1334,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ "$HAS_NSLOOKUP" == "true" ]]; then gad_d="$orig_gad_d" debug Using "nslookup -debug -type=soa -type=ns $gad_d $gad_s" to find primary name server + # shellcheck disable=SC2086 res=$(nslookup -debug -type=soa -type=ns "$gad_d" ${gad_s}) if [[ "$(echo "$res" | grep -c "Non-authoritative")" -gt 0 ]]; then diff --git a/test/18-staging-retry-dns-add.bats b/test/18-staging-retry-dns-add.bats new file mode 100644 index 0000000..8b636d6 --- /dev/null +++ b/test/18-staging-retry-dns-add.bats @@ -0,0 +1,20 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + + +@test "Check retry add dns command if dns isn't updated (DuckDNS)" { + if [ -z "$STAGING" ]; then + skip "Running internal tests, skipping external test" + fi + CONFIG_FILE="getssl-staging-dns01-fail-dns-add.cfg" + + setup_environment + init_getssl + create_certificate -d + assert_failure + assert_line --partial "Retrying adding dns via command" +} diff --git a/test/dns_fail_add_duckdns b/test/dns_fail_add_duckdns new file mode 100644 index 0000000..03df89f --- /dev/null +++ b/test/dns_fail_add_duckdns @@ -0,0 +1,19 @@ +#!/bin/bash + +# Special test script which will always fail to update dns + +token=${DUCKDNS_TOKEN:-} + +if [ -z "$token" ]; then + echo "DUCKDNS_TOKEN not set" + exit 1 +fi + +domain="$1" + +response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=FAIL") +if [ "$response" != "OK" ]; then + echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)" + echo "Response: $response" + exit 1 +fi diff --git a/test/test-config/getssl-staging-dns01-fail-dns-add.cfg b/test/test-config/getssl-staging-dns01-fail-dns-add.cfg new file mode 100644 index 0000000..2985d32 --- /dev/null +++ b/test/test-config/getssl-staging-dns01-fail-dns-add.cfg @@ -0,0 +1,33 @@ +# Special config to test that the retry dns_add_command logic works +# +CA="https://acme-staging-v02.api.letsencrypt.org/directory" + +# Generic staging config +VALIDATE_VIA_DNS=true +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" +PUBLIC_DNS_SERVER=ns2.duckdns.org +CHECK_ALL_AUTH_DNS=true + +# Test that the retry works (dns_add_command will always fail) +DNS_WAIT_RETRY_ADD="true" +DNS_ADD_COMMAND="/getssl/test/dns_fail_add_duckdns" + +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_EXTRA_WAIT=0 + +# Standard config +ACCOUNT_KEY_TYPE="rsa" +PRIVATE_KEY_ALG="rsa" +SANS="" +ACL=('/var/www/html/.well-known/acme-challenge') +USE_SINGLE_ACL="false" +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 +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx" +SERVER_TYPE="https" +CHECK_REMOTE="true" From 8c3210e4d998ed0842583e6e782a8548e66b4f7f Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 13 Sep 2020 15:31:22 +0100 Subject: [PATCH 110/308] Add tests for multiple ACL --- test/1-simple-http01-two-acl.bats | 26 +++++++++++++++++++ test/test-config/getssl-http01-two-acl.cfg | 29 ++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 test/1-simple-http01-two-acl.bats create mode 100644 test/test-config/getssl-http01-two-acl.cfg diff --git a/test/1-simple-http01-two-acl.bats b/test/1-simple-http01-two-acl.bats new file mode 100644 index 0000000..0169bd0 --- /dev/null +++ b/test/1-simple-http01-two-acl.bats @@ -0,0 +1,26 @@ +#! /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 "Check that can install challenge token to multiple locations when using HTTP-01 verification" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01-two-acl.cfg" + setup_environment + init_getssl + create_certificate -d + assert_success + assert_output --partial "to /var/www/html/.well-known/acme-challenge" + assert_output --partial "to /var/webroot/html/.well-known/acme-challenge" + check_output_for_errors "debug" +} diff --git a/test/test-config/getssl-http01-two-acl.cfg b/test/test-config/getssl-http01-two-acl.cfg new file mode 100644 index 0000000..dcf28fd --- /dev/null +++ b/test/test-config/getssl-http01-two-acl.cfg @@ -0,0 +1,29 @@ +# 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 +SANS="" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge;/var/webroot/html/.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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" From f644f97ab685ea541785f56916837fde15cfecd8 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 15 Sep 2020 08:42:32 +0100 Subject: [PATCH 111/308] Remove ACL from cfg for dns tests --- .../getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg | 6 ------ test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg | 6 ------ .../test-config/getssl-dns01-ignore-directory-domain.cfg | 9 --------- test/test-config/getssl-dns01-multiple-domains.cfg | 9 --------- test/test-config/getssl-dns01-spaces-and-commas-sans.cfg | 6 ------ .../getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg | 6 ------ test/test-config/getssl-dns01-spaces-sans.cfg | 6 ------ test/test-config/getssl-dns01.cfg | 6 ------ 8 files changed, 54 deletions(-) diff --git a/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg b/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg index 062a47c..235e1da 100644 --- a/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg +++ b/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg @@ -17,12 +17,6 @@ PRIVATE_KEY_ALG="prime256v1" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="" -# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. -ACL=('/var/www/html/.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.ec.crt" diff --git a/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg b/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg index 7b031c8..6bbcc44 100644 --- a/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg +++ b/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg @@ -17,12 +17,6 @@ PRIVATE_KEY_ALG="prime256v1" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="" -# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. -ACL=('/var/www/html/.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" diff --git a/test/test-config/getssl-dns01-ignore-directory-domain.cfg b/test/test-config/getssl-dns01-ignore-directory-domain.cfg index 9777891..4bbd766 100644 --- a/test/test-config/getssl-dns01-ignore-directory-domain.cfg +++ b/test/test-config/getssl-dns01-ignore-directory-domain.cfg @@ -14,15 +14,6 @@ DNS_EXTRA_WAIT="" IGNORE_DIRECTORY_DOMAIN="true" SANS="getssl.test,$GETSSL_HOST" -# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. -ACL=( - '/var/www/html/.well-known/acme-challenge' - '/var/www/html/.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" diff --git a/test/test-config/getssl-dns01-multiple-domains.cfg b/test/test-config/getssl-dns01-multiple-domains.cfg index 8754677..f0fae04 100644 --- a/test/test-config/getssl-dns01-multiple-domains.cfg +++ b/test/test-config/getssl-dns01-multiple-domains.cfg @@ -13,15 +13,6 @@ DNS_EXTRA_WAIT="" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="getssl.test" -# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. -ACL=( - '/var/www/html/.well-known/acme-challenge' - '/var/www/html/.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" diff --git a/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg b/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg index fe38df9..2660a9d 100644 --- a/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg +++ b/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg @@ -13,12 +13,6 @@ DNS_EXTRA_WAIT="" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="a.${GETSSL_HOST}, b.${GETSSL_HOST}, c.${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" diff --git a/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg b/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg index 453d046..6b87010 100644 --- a/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg +++ b/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg @@ -14,12 +14,6 @@ DNS_EXTRA_WAIT="" IGNORE_DIRECTORY_DOMAIN="true" SANS="a.${GETSSL_HOST} b.${GETSSL_HOST} c.${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" diff --git a/test/test-config/getssl-dns01-spaces-sans.cfg b/test/test-config/getssl-dns01-spaces-sans.cfg index 2b7e02b..8438228 100644 --- a/test/test-config/getssl-dns01-spaces-sans.cfg +++ b/test/test-config/getssl-dns01-spaces-sans.cfg @@ -13,12 +13,6 @@ DNS_EXTRA_WAIT="" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="a.${GETSSL_HOST} b.${GETSSL_HOST} c.${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" diff --git a/test/test-config/getssl-dns01.cfg b/test/test-config/getssl-dns01.cfg index 0b816b1..883f29e 100644 --- a/test/test-config/getssl-dns01.cfg +++ b/test/test-config/getssl-dns01.cfg @@ -13,12 +13,6 @@ DNS_EXTRA_WAIT="" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="" -# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. -ACL=('/var/www/html/.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" From 2d6d4719332478f767fd8bf80bebe8fc6666bd7b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 15 Sep 2020 09:42:43 +0100 Subject: [PATCH 112/308] make executable --- test/dns_fail_add_duckdns | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 test/dns_fail_add_duckdns diff --git a/test/dns_fail_add_duckdns b/test/dns_fail_add_duckdns old mode 100644 new mode 100755 From 90a418801d5b3669e10ef627886d893e9a749bd9 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 15 Sep 2020 15:04:49 +0100 Subject: [PATCH 113/308] Add retry logic for "Bad Gateway" duckdns error --- dns_scripts/dns_add_duckdns | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dns_scripts/dns_add_duckdns b/dns_scripts/dns_add_duckdns index 9f61c8c..9d1776a 100755 --- a/dns_scripts/dns_add_duckdns +++ b/dns_scripts/dns_add_duckdns @@ -10,8 +10,17 @@ fi domain="$1" txtvalue="$2" +i=1 response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=${txtvalue}") + +while [[ "${response}" == *"502 Bad Gateway"* ]] && [ $i -le 5 ]; do + echo "Retrying Bad Gateway response (attempt $i of 5)" + sleep 5 + i=$((i+1)) + response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=${txtvalue}") +done + if [ "$response" != "OK" ]; then echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)" echo "Response: $response" From ad097a5b29e068debc14f8439abe78441638e0b6 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 15 Sep 2020 15:37:41 +0100 Subject: [PATCH 114/308] Add bad gateway retry logic to duckdns del command --- dns_scripts/dns_del_duckdns | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dns_scripts/dns_del_duckdns b/dns_scripts/dns_del_duckdns index f20c664..bdb653c 100755 --- a/dns_scripts/dns_del_duckdns +++ b/dns_scripts/dns_del_duckdns @@ -3,8 +3,17 @@ # need to add your Token for duckdns below token=${DUCKDNS_TOKEN:-} domain="$1" +i=1 response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=&clear=true") + +while [[ "${response}" == *"502 Bad Gateway"* ]] && [ $i -le 5 ]; do + echo "Retrying Bad Gateway response (attempt $i of 5)" + sleep 5 + i=$((i+1)) + response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=&clear=true") +done + if [ "$response" != "OK" ]; then echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)" echo "$response" From 75d06beb5adca32c2172e14763c3494b337b24c4 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 17 Sep 2020 13:50:50 +0100 Subject: [PATCH 115/308] Fix get_auth_dns to return multiple nameservers (broken in v2.21) --- getssl | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/getssl b/getssl index 7ae6ae5..c92733f 100755 --- a/getssl +++ b/getssl @@ -1222,7 +1222,7 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then done if [[ "$DNS_EXTRA_WAIT" -gt 0 && "$PREVIOUSLY_VALIDATED" != "true" ]]; then - info "sleeping $DNS_EXTRA_WAIT seconds before asking the ACME-server to check the dns" + info "sleeping $DNS_EXTRA_WAIT seconds before asking the ACME server to check the dns" sleep "$DNS_EXTRA_WAIT" fi @@ -1267,20 +1267,22 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ -n "$HAS_DIG_OR_DRILL" ]]; then gad_d="$orig_gad_d" - debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d @$gad_s" to find primary nameserver # Use SOA +trace to find the name server if [[ -z "$gad_s" ]]; then - res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" 2>/dev/null | grep "IN\WNS\W" | tail -1) + debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d" to find primary nameserver + res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" 2>/dev/null | grep "IN\WNS\W") else - res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" "@$gad_s" 2>/dev/null | grep "IN\WNS\W" | tail -1) + debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d @$gad_s" to find primary nameserver + res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" "@$gad_s" 2>/dev/null | grep "IN\WNS\W") fi # fallback to existing code if [[ -z "$res" ]]; then - debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d @$gad_s" if [[ -z "$gad_s" ]]; then #checking for CNAMEs (need grep as dig 9.11 sometimes returns everything not just CNAME entries) + debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d" res=$($HAS_DIG_OR_DRILL CNAME "$gad_d"| grep "^$gad_d" | grep CNAME) else + debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d @$gad_s" res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" "@$gad_s"| grep "^$gad_d" | grep CNAME) fi if [[ -n "$res" ]]; then # domain is a CNAME so get main domain @@ -1294,11 +1296,12 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n # dig NS www.getssl.text # > www.getssl.test. IN CNAME getssl.test # > getssl.test. IN NS ns1.duckdns.org - debug Using "$HAS_DIG_OR_DRILL NS $gad_d @$gad_s" to find primary nameserver if [[ -z "$gad_s" ]]; then - res=$($HAS_DIG_OR_DRILL NS "$gad_d"| grep -E "IN\W(NS|SOA)\W" | tail -1) + debug Using "$HAS_DIG_OR_DRILL NS $gad_d" to find primary nameserver + res=$($HAS_DIG_OR_DRILL NS "$gad_d"| grep -E "IN\W(NS|SOA)\W") else - res=$($HAS_DIG_OR_DRILL NS "$gad_d" "@$gad_s"| grep -E "IN\W(NS|SOA)\W" | tail -1) + debug Using "$HAS_DIG_OR_DRILL NS $gad_d @$gad_s" to find primary nameserver + res=$($HAS_DIG_OR_DRILL NS "$gad_d" "@$gad_s"| grep -E "IN\W(NS|SOA)\W") fi fi if [[ -n "$res" ]]; then @@ -2194,6 +2197,7 @@ write_domain_template() { # write out a template file for a domain. # where "/path/to/your/website/folder/" is the path, on your web server, to the web root for your domain. # You can also user WebDAV over HTTPS as transport mechanism. To do so, start with davs: followed by username, # password, host, port (explicitly needed even if using default port 443) and path on the server. + # Multiple locations can be defined for a file by separating the locations with a semi-colon. #ACL=('/var/www/${DOMAIN}/web/.well-known/acme-challenge' # 'ssh:server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' From 36c92d150e954390fd4f8603cce1997a98bcbdf8 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 23 Sep 2020 22:34:40 +0100 Subject: [PATCH 116/308] Fixes and changes to test get_auth_dns --- getssl | 98 +++++++++++------ test/19-test-get_auth_dns-dig.bats | 166 +++++++++++++++++++++++++++++ 2 files changed, 231 insertions(+), 33 deletions(-) create mode 100644 test/19-test-get_auth_dns-dig.bats diff --git a/getssl b/getssl index c92733f..05b2f2f 100755 --- a/getssl +++ b/getssl @@ -292,6 +292,9 @@ _NOTIFY_VALID=0 _QUIET=0 _RECREATE_CSR=0 _REVOKE=0 +_RUNNING_TEST=0 +_TEST_SKIP_CNAME_CALL=0 +_TEST_SKIP_SOA_CALL=0 _UPGRADE=0 _UPGRADE_CHECK=1 _USE_DEBUG=0 @@ -942,8 +945,19 @@ date_renew() { # calculates the renewal time in epoch debug() { # write out debug info if the debug flag has been set if [[ ${_USE_DEBUG} -eq 1 ]]; then - echo " " - echo "$@" + # If running tests then output in TAP format (for debugging tests) + if [[ -n "$_RUNNING_TEST" ]]; then + echo "#" "$@" >&3 + else + echo " " + echo "$@" + fi + fi +} + +test_output() { # write out debug output for testing + if [[ ${_RUNNING_TEST} -eq 1 ]]; then + echo "#" "$@" fi } @@ -1251,6 +1265,9 @@ fi get_auth_dns() { # get the authoritative dns server for a domain (sets primary_ns ) orig_gad_d="$1" # domain name gad_s="$PUBLIC_DNS_SERVER" # start with PUBLIC_DNS_SERVER + if [[ -n "$gad_s" ]]; then + gad_s="@$gad_s" + fi if [[ "$os" == "cygwin" ]]; then gad_d="$orig_gad_d" @@ -1268,49 +1285,62 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ -n "$HAS_DIG_OR_DRILL" ]]; then gad_d="$orig_gad_d" # Use SOA +trace to find the name server - if [[ -z "$gad_s" ]]; then - debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d" to find primary nameserver - res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" 2>/dev/null | grep "IN\WNS\W") - else - debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d @$gad_s" to find primary nameserver - res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" "@$gad_s" 2>/dev/null | grep "IN\WNS\W") + if [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then + debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d $gad_s" to find primary nameserver + test_output "Using $HAS_DIG_OR_DRILL SOA" + res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" "$gad_s" 2>/dev/null | grep "IN\WNS\W") fi - # fallback to existing code + # Check if domain is a CNAME if [[ -z "$res" ]]; then - if [[ -z "$gad_s" ]]; then #checking for CNAMEs (need grep as dig 9.11 sometimes returns everything not just CNAME entries) - debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d" - res=$($HAS_DIG_OR_DRILL CNAME "$gad_d"| grep "^$gad_d" | grep CNAME) + test_output "Using $HAS_DIG_OR_DRILL CNAME" + + # Two options here; either dig CNAME will return the CNAME and the NS or just the CNAME + debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d $gad_s" + res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" "$gad_s"| grep "^$gad_d") + cname=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') + + if [[ $_TEST_SKIP_CNAME_CALL == 0 ]]; then + debug Checking if CNAME result contains NS records + res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" "$gad_s"| grep -E "IN\W(NS|SOA)\W") else - debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d @$gad_s" - res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" "@$gad_s"| grep "^$gad_d" | grep CNAME) - fi - if [[ -n "$res" ]]; then # domain is a CNAME so get main domain - gad_d=$(echo "$res"| awk '{print $5}' |sed 's/\.$//g') - debug Domain is a CNAME, actual domain is "$gad_d" + res="" fi - # If gad_d is an A record then this returns the SOA for the root domain, e.g. without the www - # dig NS ubuntu.getssl.text - # > getssl.test. IN SOA ns1.duckdns.org - # If gad_d is a CNAME record then this returns the NS for the domain pointed to by $gad_d - # dig NS www.getssl.text - # > www.getssl.test. IN CNAME getssl.test - # > getssl.test. IN NS ns1.duckdns.org - if [[ -z "$gad_s" ]]; then - debug Using "$HAS_DIG_OR_DRILL NS $gad_d" to find primary nameserver - res=$($HAS_DIG_OR_DRILL NS "$gad_d"| grep -E "IN\W(NS|SOA)\W") - else - debug Using "$HAS_DIG_OR_DRILL NS $gad_d @$gad_s" to find primary nameserver - res=$($HAS_DIG_OR_DRILL NS "$gad_d" "@$gad_s"| grep -E "IN\W(NS|SOA)\W") + + if [[ -n "$cname" ]]; then # domain is a CNAME so get main domain + debug Domain is a CNAME, actual domain is "$cname" fi fi + + # Query for NS records + if [[ -z "$res" ]]; then + test_output "Using $HAS_DIG_OR_DRILL NS" + debug Using "$HAS_DIG_OR_DRILL NS $gad_d $gad_s" to find primary nameserver + res=$($HAS_DIG_OR_DRILL NS "$gad_d" $gad_s | grep -E "IN\W(NS|SOA)\W") + fi + if [[ -n "$res" ]]; then - all_auth_dns_servers=$(echo "$res" | awk '$4 ~ "NS" {print $5}' | sed 's/\.$//g'|tr '\n' ' ') + # Convert dig output into an array of nameservers + IFS=$'\n' read -r -d '' -a ns_servers < <(echo "$res" | awk '$4 ~ "(NS|SOA)" {print $5}' | sed 's/\.$//g') + + # Nameservers from SOA +trace includes root and all intermediate servers, so just use all the ones with the same domain as the last name server + # i.e. if we have root, google, duckdns1, duckdns2 then return all the duckdns servers + ns_domain=${ns_servers[${#ns_servers[@]} -1 ]#*.} + all_auth_dns_servers="" + for i in "${ns_servers[@]}"; do + if [[ $i =~ $ns_domain ]]; then + all_auth_dns_servers="$all_auth_dns_servers $i" + fi + done + if [[ $CHECK_ALL_AUTH_DNS == "true" ]]; then primary_ns="$all_auth_dns_servers" else - primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') + primary_ns=$(echo "$all_auth_dns_servers" | awk '{print " " $1}') fi + + debug set primary_ns = "$primary_ns" + test_output set primary_ns ="$primary_ns" return fi fi @@ -2343,6 +2373,8 @@ while [[ -n ${1+defined} ]]; do _ONLY_CHECK_CONFIG=1 ;; -w) shift; WORKING_DIR="$1" ;; + --source) + return ;; -*) usage error_exit "Unknown option $1" ;; diff --git a/test/19-test-get_auth_dns-dig.bats b/test/19-test-get_auth_dns-dig.bats new file mode 100644 index 0000000..a726442 --- /dev/null +++ b/test/19-test-get_auth_dns-dig.bats @@ -0,0 +1,166 @@ +#! /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() { + . /getssl/getssl --source + find_dns_utils + _RUNNING_TEST=1 + _USE_DEBUG=0 + echo " " >&3 + echo " " >&3 + + if [ -f /usr/bin/host ]; then + mv /usr/bin/host /usr/bin/host.getssl.bak + fi + if [ -f /usr/bin/nslookup ]; then + mv /usr/bin/nslookup /usr/bin/nslookup.getssl.bak + fi +} + + +teardown() { + if [ -f /usr/bin/host.getssl.bak ]; then + mv /usr/bin/host.getssl.bak /usr/bin/host + fi + if [ -f /usr/bin/nslookup.getssl.bak ]; then + mv /usr/bin/nslookup.getssl.bak /usr/bin/nslookup + fi +} + + + @test "Check get_auth_dns using dig NS" { + # Test that get_auth_dns() handles scenario where NS query returns Authority section + # + # ************** EXAMPLE DIG OUTPUT ************** + # + # ;; ANSWER SECTION: + # ubuntu-getssl.duckdns.org. 60 IN A 54.89.252.137 + # + # ;; AUTHORITY SECTION: + # duckdns.org. 600 IN NS ns2.duckdns.org. + # duckdns.org. 600 IN NS ns3.duckdns.org. + # duckdns.org. 600 IN NS ns1.duckdns.org. + # + # ;; ADDITIONAL SECTION: + # ns2.duckdns.org. 600 IN A 54.191.117.119 + # ns3.duckdns.org. 600 IN A 52.26.169.94 + # ns1.duckdns.org. 600 IN A 54.187.92.222 + + # Disable CNAME check + _TEST_SKIP_CNAME_CALL=1 + + PUBLIC_DNS_SERVER=ns1.duckdns.org + CHECK_ALL_AUTH_DNS=false + + run get_auth_dns ubuntu-getssl.duckdns.org + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + # Assert that we had to use dig NS + assert_line --partial 'Using dig NS' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=true + run get_auth_dns ubuntu-getssl.duckdns.org + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' +} + + +@test "Check get_auth_dns using dig SOA" { + # Test that get_auth_dns() handles scenario where SOA query returns Authority section + # + # ************** EXAMPLE DIG OUTPUT ************** + # + # ;; AUTHORITY SECTION: + # duckdns.org. 600 IN SOA ns3.duckdns.org. hostmaster.duckdns.org. 2019170803 6000 120 2419200 600 + + # DuckDNS server returns nothing for SOA, so use public dns instead + PUBLIC_DNS_SERVER=1.0.0.1 + CHECK_ALL_AUTH_DNS=false + + run get_auth_dns ubuntu-getssl.duckdns.org + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + + # Assert that we had to use dig NS + assert_line --partial 'Using dig SOA' + refute_line --partial 'Using dig NS' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=true + run get_auth_dns ubuntu-getssl.duckdns.org + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' +} + + +@test "Check get_auth_dns using dig CNAME (public dns)" { + # Test that get_auth_dns() handles scenario where CNAME query returns just a CNAME record + # + # ************** EXAMPLE DIG OUTPUT ************** + # + # ;; ANSWER SECTION: + # www.duckdns.org. 600 IN CNAME DuckDNSAppELB-570522007.us-west-2.elb.amazonaws.com. + + # Disable SOA check + _TEST_SKIP_SOA_CALL=1 + + PUBLIC_DNS_SERVER=1.0.0.1 + CHECK_ALL_AUTH_DNS=false + + run get_auth_dns www.duckdns.org + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' + + # Assert that we found a CNAME and use dig NS + assert_line --partial 'Using dig CNAME' + assert_line --partial 'Using dig NS' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=false + run get_auth_dns www.duckdns.org + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' +} + + +@test "Check get_auth_dns using dig CNAME (duckdns)" { + # Test that get_auth_dns() handles scenario where CNAME query returns authority section containing NS records + # + # ************** EXAMPLE DIG OUTPUT ************** + # + # ;; ANSWER SECTION: + # www.duckdns.org. 600 IN CNAME DuckDNSAppELB-570522007.us-west-2.elb.amazonaws.com. + # + # ;; AUTHORITY SECTION: + # duckdns.org. 600 IN NS ns1.duckdns.org. + # duckdns.org. 600 IN NS ns2.duckdns.org. + # duckdns.org. 600 IN NS ns3.duckdns.org. + # + # ;; ADDITIONAL SECTION: + # ns1.duckdns.org. 600 IN A 54.187.92.222 + # ns2.duckdns.org. 600 IN A 54.191.117.119 + # ns3.duckdns.org. 600 IN A 52.26.169.94 + + PUBLIC_DNS_SERVER=ns1.duckdns.org + CHECK_ALL_AUTH_DNS=false + + run get_auth_dns www.duckdns.org + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + + # Assert that we found a CNAME but didn't use dig NS + assert_line --partial 'Using dig CNAME' + refute_line --partial 'Using dig NS' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=true + run get_auth_dns www.duckdns.org + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' +} From 6e25567397a77f6101adfd6093015f97b6f76e71 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 30 Sep 2020 10:15:08 +0100 Subject: [PATCH 117/308] Fix dns check for upper case domain names --- getssl | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/getssl b/getssl index 05b2f2f..5fbabca 100755 --- a/getssl +++ b/getssl @@ -946,7 +946,7 @@ date_renew() { # calculates the renewal time in epoch debug() { # write out debug info if the debug flag has been set if [[ ${_USE_DEBUG} -eq 1 ]]; then # If running tests then output in TAP format (for debugging tests) - if [[ -n "$_RUNNING_TEST" ]]; then + if [[ ${_RUNNING_TEST} -eq 1 ]]; then echo "#" "$@" >&3 else echo " " @@ -1141,8 +1141,7 @@ for d in $alldomains; do command="rm -f ${t_loc:(( ${#sshhost} + 5))}/${token:?}" debug "running following command to remove token" debug "ssh $SSH_OPTS $sshhost ${command}" - # shellcheck disable=SC2029 - # shellcheck disable=SC2086 + # shellcheck disable=SC2029 disable=SC2086 ssh $SSH_OPTS "$sshhost" "${command}" 1>/dev/null 2>&1 rm -f "${TEMP_DIR:?}/${token:?}" elif [[ "${t_loc:0:4}" == "ftp:" ]] ; then @@ -1177,6 +1176,10 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then # shellcheck source=/dev/null . "$dnsfile" + # Always use lowercase domain name when querying DNS servers + # shellcheck disable=SC2018,SC2019 + lower_d=$(echo "$d" | tr A-Z a-z) + # check for token at public dns server, waiting for a valid response. for ns in $primary_ns; do debug "checking dns at $ns" @@ -1184,18 +1187,18 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then check_dns="fail" while [[ "$check_dns" == "fail" ]]; do if [[ "$os" == "cygwin" ]]; then - check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" \ + check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ | grep ^_acme -A2\ | grep '"'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - debug "$DNS_CHECK_FUNC" TXT "_acme-challenge.${d}" "@${ns}" - check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${d}" "@${ns}" \ + debug "$DNS_CHECK_FUNC" TXT "_acme-challenge.${lower_d}" "@${ns}" + check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${lower_d}" "@${ns}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then - check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${d}" "${ns}" \ + check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${lower_d}" "${ns}" \ | grep 'descriptive text'|awk -F'"' '{ print $2}') else - check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" \ + check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ | grep 'text ='|awk -F'"' '{ print $2}') fi debug "expecting $auth_key" @@ -1208,26 +1211,22 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then ntries=$(( ntries + 1 )) if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 == 0 )) ]]; then - # shellcheck disable=SC2018,SC2019 - lower_d=$(echo "$d" | tr A-Z a-z) debug "Retrying adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then error_exit "DNS_ADD_COMMAND failed for domain $d" fi fi - info "checking DNS at ${ns} for ${d}. Attempt $ntries/100 gave wrong result, "\ + info "checking DNS at ${ns} for ${lower_d}. Attempt $ntries/${DNS_WAIT_COUNT} gave wrong result, "\ "waiting $DNS_WAIT secs before checking again" sleep $DNS_WAIT else debug "dns check failed - removing existing value" - # shellcheck disable=SC2018,SC2019 - lower_d=$(echo "$d" | tr A-Z a-z) eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" # remove $dnsfile after each loop. rm -f "$dnsfile" - error_exit "checking _acme-challenge.${d} gave $check_result not $auth_key" + error_exit "checking _acme-challenge.${lower_d} gave $check_result not $auth_key" fi fi done From cfd6562e9b9df4e341da7f61ca94620d0c918306 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 30 Sep 2020 10:18:49 +0100 Subject: [PATCH 118/308] Fix the dns test config files --- .../test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg | 4 ++-- test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg | 4 ++-- test/test-config/getssl-dns01-ignore-directory-domain.cfg | 4 ++-- test/test-config/getssl-dns01-multiple-domains.cfg | 4 ++-- test/test-config/getssl-dns01-spaces-and-commas-sans.cfg | 4 ++-- .../getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg | 4 ++-- test/test-config/getssl-dns01-spaces-sans.cfg | 4 ++-- test/test-config/getssl-dns01.cfg | 8 ++++++-- test/test-config/getssl-staging-dns01-fail-dns-add.cfg | 2 +- test/test-config/getssl-staging-dns01-no-suffix.cfg | 2 +- test/test-config/getssl-staging-dns01.cfg | 2 +- 11 files changed, 23 insertions(+), 19 deletions(-) diff --git a/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg b/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg index 235e1da..15b4108 100644 --- a/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg +++ b/test/test-config/getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg @@ -7,8 +7,8 @@ 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" -PUBLIC_DNS_SERVER=10.30.50.3 -DNS_EXTRA_WAIT="" +AUTH_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT=0 DUAL_RSA_ECDSA="true" ACCOUNT_KEY_TYPE="prime256v1" diff --git a/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg b/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg index 6bbcc44..4059dd4 100644 --- a/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg +++ b/test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg @@ -7,8 +7,8 @@ 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" -PUBLIC_DNS_SERVER=10.30.50.3 -DNS_EXTRA_WAIT="" +AUTH_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT=0 DUAL_RSA_ECDSA="true" ACCOUNT_KEY_TYPE="prime256v1" diff --git a/test/test-config/getssl-dns01-ignore-directory-domain.cfg b/test/test-config/getssl-dns01-ignore-directory-domain.cfg index 4bbd766..e55fbe0 100644 --- a/test/test-config/getssl-dns01-ignore-directory-domain.cfg +++ b/test/test-config/getssl-dns01-ignore-directory-domain.cfg @@ -7,8 +7,8 @@ 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" -PUBLIC_DNS_SERVER=10.30.50.3 -DNS_EXTRA_WAIT="" +AUTH_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT=0 # Ignore directory domain (i.e. the domain passed on the command line), and just use the domains in the SANS list IGNORE_DIRECTORY_DOMAIN="true" diff --git a/test/test-config/getssl-dns01-multiple-domains.cfg b/test/test-config/getssl-dns01-multiple-domains.cfg index f0fae04..82497ad 100644 --- a/test/test-config/getssl-dns01-multiple-domains.cfg +++ b/test/test-config/getssl-dns01-multiple-domains.cfg @@ -7,8 +7,8 @@ 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" -PUBLIC_DNS_SERVER=10.30.50.3 -DNS_EXTRA_WAIT="" +AUTH_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT=0 # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="getssl.test" diff --git a/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg b/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg index 2660a9d..204d0bf 100644 --- a/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg +++ b/test/test-config/getssl-dns01-spaces-and-commas-sans.cfg @@ -7,8 +7,8 @@ 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" -PUBLIC_DNS_SERVER=10.30.50.3 -DNS_EXTRA_WAIT="" +AUTH_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT=0 # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="a.${GETSSL_HOST}, b.${GETSSL_HOST}, c.${GETSSL_HOST}" diff --git a/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg b/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg index 6b87010..75e7304 100644 --- a/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg +++ b/test/test-config/getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg @@ -7,8 +7,8 @@ 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" -PUBLIC_DNS_SERVER=10.30.50.3 -DNS_EXTRA_WAIT="" +AUTH_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT=0 # Ignore directory domain (i.e. the domain passed on the command line), and just use the domains in the SANS list IGNORE_DIRECTORY_DOMAIN="true" diff --git a/test/test-config/getssl-dns01-spaces-sans.cfg b/test/test-config/getssl-dns01-spaces-sans.cfg index 8438228..e954fa0 100644 --- a/test/test-config/getssl-dns01-spaces-sans.cfg +++ b/test/test-config/getssl-dns01-spaces-sans.cfg @@ -7,8 +7,8 @@ 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" -PUBLIC_DNS_SERVER=10.30.50.3 -DNS_EXTRA_WAIT="" +AUTH_DNS_SERVER=10.30.50.3 +DNS_EXTRA_WAIT=0 # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="a.${GETSSL_HOST} b.${GETSSL_HOST} c.${GETSSL_HOST}" diff --git a/test/test-config/getssl-dns01.cfg b/test/test-config/getssl-dns01.cfg index 883f29e..e995c80 100644 --- a/test/test-config/getssl-dns01.cfg +++ b/test/test-config/getssl-dns01.cfg @@ -7,8 +7,12 @@ 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" -PUBLIC_DNS_SERVER=10.30.50.3 -DNS_EXTRA_WAIT="" +AUTH_DNS_SERVER=10.30.50.3 + +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_EXTRA_WAIT=0 # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="" diff --git a/test/test-config/getssl-staging-dns01-fail-dns-add.cfg b/test/test-config/getssl-staging-dns01-fail-dns-add.cfg index 2985d32..125cfef 100644 --- a/test/test-config/getssl-staging-dns01-fail-dns-add.cfg +++ b/test/test-config/getssl-staging-dns01-fail-dns-add.cfg @@ -5,7 +5,7 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" # Generic staging config VALIDATE_VIA_DNS=true DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=ns2.duckdns.org +AUTH_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true # Test that the retry works (dns_add_command will always fail) diff --git a/test/test-config/getssl-staging-dns01-no-suffix.cfg b/test/test-config/getssl-staging-dns01-no-suffix.cfg index 47d2cec..6b764f3 100644 --- a/test/test-config/getssl-staging-dns01-no-suffix.cfg +++ b/test/test-config/getssl-staging-dns01-no-suffix.cfg @@ -5,7 +5,7 @@ CA="https://acme-staging-v02.api.letsencrypt.org" VALIDATE_VIA_DNS=true DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=ns2.duckdns.org +AUTH_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true DNS_EXTRA_WAIT=120 diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 348cabf..655f1c6 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -5,7 +5,7 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" VALIDATE_VIA_DNS=true DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=ns2.duckdns.org +AUTH_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true DNS_EXTRA_WAIT=120 From b0debe01b0e8c7518ef1d11d3c9d36e4de39e86b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 1 Oct 2020 08:58:58 +0100 Subject: [PATCH 119/308] Use different args for drill in SOA check --- getssl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/getssl b/getssl index 5fbabca..92c01a3 100755 --- a/getssl +++ b/getssl @@ -1285,9 +1285,15 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n gad_d="$orig_gad_d" # Use SOA +trace to find the name server if [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then - debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d $gad_s" to find primary nameserver - test_output "Using $HAS_DIG_OR_DRILL SOA" - res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" "$gad_s" 2>/dev/null | grep "IN\WNS\W") + if [[ "$HAS_DIG_OR_DRILL" == "dig" ]]; then + debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d $gad_s" to find primary nameserver + test_output "Using $HAS_DIG_OR_DRILL SOA" + res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" "$gad_s" 2>/dev/null | grep "IN\WNS\W") + else + debug Using "$HAS_DIG_OR_DRILL -T $gad_d $gad_s" to find primary nameserver + test_output "Using $HAS_DIG_OR_DRILL SOA" + res=$($HAS_DIG_OR_DRILL -T SOA "$gad_d" "$gad_s" 2>/dev/null | grep "IN\WNS\W") + fi fi # Check if domain is a CNAME From 55ea0642c7bca86365b687e5d585379d79ec0d84 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 2 Oct 2020 15:09:23 +0100 Subject: [PATCH 120/308] Add unit test for get_auth_dns using drill --- ...dig.bats => u1-test-get_auth_dns-dig.bats} | 28 ++- test/u2-test-get_auth_dns-drill.bats | 201 ++++++++++++++++++ 2 files changed, 214 insertions(+), 15 deletions(-) rename test/{19-test-get_auth_dns-dig.bats => u1-test-get_auth_dns-dig.bats} (91%) create mode 100644 test/u2-test-get_auth_dns-drill.bats diff --git a/test/19-test-get_auth_dns-dig.bats b/test/u1-test-get_auth_dns-dig.bats similarity index 91% rename from test/19-test-get_auth_dns-dig.bats rename to test/u1-test-get_auth_dns-dig.bats index a726442..356c5c5 100644 --- a/test/19-test-get_auth_dns-dig.bats +++ b/test/u1-test-get_auth_dns-dig.bats @@ -7,29 +7,27 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + for app in drill host nslookup + do + if [ -f /usr/bin/${app} ]; then + mv /usr/bin/${app} /usr/bin/${app}.getssl.bak + fi + done + . /getssl/getssl --source find_dns_utils _RUNNING_TEST=1 _USE_DEBUG=0 - echo " " >&3 - echo " " >&3 - - if [ -f /usr/bin/host ]; then - mv /usr/bin/host /usr/bin/host.getssl.bak - fi - if [ -f /usr/bin/nslookup ]; then - mv /usr/bin/nslookup /usr/bin/nslookup.getssl.bak - fi } teardown() { - if [ -f /usr/bin/host.getssl.bak ]; then - mv /usr/bin/host.getssl.bak /usr/bin/host - fi - if [ -f /usr/bin/nslookup.getssl.bak ]; then - mv /usr/bin/nslookup.getssl.bak /usr/bin/nslookup - fi + for app in drill host nslookup + do + if [ -f /usr/bin/${app}.getssl.bak ]; then + mv /usr/bin/${app}.getssl.bak /usr/bin/${app} + fi + done } diff --git a/test/u2-test-get_auth_dns-drill.bats b/test/u2-test-get_auth_dns-drill.bats new file mode 100644 index 0000000..a0d977c --- /dev/null +++ b/test/u2-test-get_auth_dns-drill.bats @@ -0,0 +1,201 @@ +#! /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() { + for app in dig host nslookup + do + if [ -f /usr/bin/${app} ]; then + mv /usr/bin/${app} /usr/bin/${app}.getssl.bak + fi + done + + . /getssl/getssl --source + find_dns_utils + _RUNNING_TEST=1 + _USE_DEBUG=0 +} + + +teardown() { + for app in dig host nslookup + do + if [ -f /usr/bin/${app}.getssl.bak ]; then + mv /usr/bin/${app}.getssl.bak /usr/bin/${app} + fi + done +} + + +teardown() { + if [ -f /usr/bin/host.getssl.bak ]; then + mv /usr/bin/host.getssl.bak /usr/bin/host + fi + if [ -f /usr/bin/nslookup.getssl.bak ]; then + mv /usr/bin/nslookup.getssl.bak /usr/bin/nslookup + fi + if [ -f /usr/bin/dig.getssl.bak ]; then + mv /usr/bin/dig.getssl.bak /usr/bin/dig + fi +} + + +@test "Check get_auth_dns using drill NS" { + if [ ! -f /usr/bin/drill ]; then + # Can't find drill package for centos8 + skip "Drill not installed on this system" + fi + + # Test that get_auth_dns() handles scenario where NS query returns Authority section + # + # ************** EXAMPLE DRILL OUTPUT ************** + # + # ;; ANSWER SECTION: + # ubuntu-getssl.duckdns.org. 60 IN A 54.89.252.137 + # + # ;; AUTHORITY SECTION: + # duckdns.org. 600 IN NS ns2.duckdns.org. + # duckdns.org. 600 IN NS ns3.duckdns.org. + # duckdns.org. 600 IN NS ns1.duckdns.org. + # + # ;; ADDITIONAL SECTION: + # ns2.duckdns.org. 600 IN A 54.191.117.119 + # ns3.duckdns.org. 600 IN A 52.26.169.94 + # ns1.duckdns.org. 600 IN A 54.187.92.222 + + # Disable SOA and CNAME check + _TEST_SKIP_CNAME_CALL=1 + _TEST_SKIP_SOA_CALL=1 + + PUBLIC_DNS_SERVER=ns1.duckdns.org + CHECK_ALL_AUTH_DNS=false + + run get_auth_dns ubuntu-getssl.duckdns.org + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + # Assert that we had to use drill NS + assert_line --partial 'Using drill NS' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=true + run get_auth_dns ubuntu-getssl.duckdns.org + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' +} + + +@test "Check get_auth_dns using drill SOA" { + if [ ! -f /usr/bin/drill ]; then + # Can't find drill package for centos8 + skip "Drill not installed on this system" + fi + + # Test that get_auth_dns() handles scenario where SOA query returns Authority section + # + # ************** EXAMPLE DRILL OUTPUT ************** + # + # ;; AUTHORITY SECTION: + # duckdns.org. 600 IN SOA ns3.duckdns.org. hostmaster.duckdns.org. 2019170803 6000 120 2419200 600 + + # DuckDNS server returns nothing for SOA, so use public dns instead + PUBLIC_DNS_SERVER=1.0.0.1 + CHECK_ALL_AUTH_DNS=false + + run get_auth_dns ubuntu-getssl.duckdns.org + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + + # Assert that we had to use drill NS + assert_line --partial 'Using drill SOA' + refute_line --partial 'Using drill NS' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=true + run get_auth_dns ubuntu-getssl.duckdns.org + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' +} + + +@test "Check get_auth_dns using drill CNAME (public dns)" { + if [ ! -f /usr/bin/drill ]; then + # Can't find drill package for centos8 + skip "Drill not installed on this system" + fi + + # Test that get_auth_dns() handles scenario where CNAME query returns just a CNAME record + # + # ************** EXAMPLE drill OUTPUT ************** + # + # ;; ANSWER SECTION: + # www.duckdns.org. 600 IN CNAME DuckDNSAppELB-570522007.us-west-2.elb.amazonaws.com. + + # Disable SOA check + _TEST_SKIP_SOA_CALL=1 + + PUBLIC_DNS_SERVER=1.0.0.1 + CHECK_ALL_AUTH_DNS=false + + run get_auth_dns www.duckdns.org + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' + + # Assert that we found a CNAME and use drill NS + assert_line --partial 'Using drill CNAME' + assert_line --partial 'Using drill NS' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=false + run get_auth_dns www.duckdns.org + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' +} + + +@test "Check get_auth_dns using drill CNAME (duckdns)" { + if [ ! -f /usr/bin/drill ]; then + # Can't find drill package for centos8 + skip "Drill not installed on this system" + fi + + # Test that get_auth_dns() handles scenario where CNAME query returns authority section containing NS records + # + # ************** EXAMPLE drill OUTPUT ************** + # + # ;; ANSWER SECTION: + # www.duckdns.org. 600 IN CNAME DuckDNSAppELB-570522007.us-west-2.elb.amazonaws.com. + # + # ;; AUTHORITY SECTION: + # duckdns.org. 600 IN NS ns1.duckdns.org. + # duckdns.org. 600 IN NS ns2.duckdns.org. + # duckdns.org. 600 IN NS ns3.duckdns.org. + # + # ;; ADDITIONAL SECTION: + # ns1.duckdns.org. 600 IN A 54.187.92.222 + # ns2.duckdns.org. 600 IN A 54.191.117.119 + # ns3.duckdns.org. 600 IN A 52.26.169.94 + + # Disable SOA check + _TEST_SKIP_SOA_CALL=1 + + PUBLIC_DNS_SERVER=ns1.duckdns.org + CHECK_ALL_AUTH_DNS=false + + run get_auth_dns www.duckdns.org + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + + # Assert that we found a CNAME but didn't use drill NS + assert_line --partial 'Using drill CNAME' + refute_line --partial 'Using drill NS' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=true + run get_auth_dns www.duckdns.org + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' +} From 0f422225f47bdcc194266548b06cfc92815e1bbd Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 2 Oct 2020 15:09:50 +0100 Subject: [PATCH 121/308] Update all docker images to include drill (for unit tests) --- test/Dockerfile-alpine | 2 +- test/Dockerfile-centos6 | 2 +- test/Dockerfile-centos7 | 4 +--- test/Dockerfile-centos7-staging | 2 +- test/Dockerfile-debian | 2 +- test/Dockerfile-ubuntu | 2 +- test/Dockerfile-ubuntu-staging | 3 +-- test/Dockerfile-ubuntu16 | 5 +---- test/Dockerfile-ubuntu18 | 2 +- 9 files changed, 9 insertions(+), 15 deletions(-) diff --git a/test/Dockerfile-alpine b/test/Dockerfile-alpine index caad22a..e0f3a6c 100644 --- a/test/Dockerfile-alpine +++ b/test/Dockerfile-alpine @@ -2,7 +2,7 @@ FROM alpine:latest # Note this image uses busybox awk instead of gawk -RUN apk --no-cache add supervisor openssl git curl bind-tools wget nginx bash +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash WORKDIR /root diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index 5ffc91c..862e680 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -8,7 +8,7 @@ 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 +RUN yum -y install git curl dnsutils ldns wget nginx WORKDIR /root RUN mkdir /etc/nginx/pki diff --git a/test/Dockerfile-centos7 b/test/Dockerfile-centos7 index 02fbcb7..afbcf23 100644 --- a/test/Dockerfile-centos7 +++ b/test/Dockerfile-centos7 @@ -1,11 +1,9 @@ FROM centos:centos7 -# Note this image uses drill, does not have dig or nslookup installed - # Update and install required software RUN yum -y update RUN yum -y install epel-release -RUN yum -y install git curl ldns wget which nginx +RUN yum -y install git curl ldns bind-utils wget which nginx WORKDIR /root RUN mkdir /etc/nginx/pki diff --git a/test/Dockerfile-centos7-staging b/test/Dockerfile-centos7-staging index 899bf9b..a539cac 100644 --- a/test/Dockerfile-centos7-staging +++ b/test/Dockerfile-centos7-staging @@ -5,7 +5,7 @@ FROM centos:centos7 # Update and install required software RUN yum -y update RUN yum -y install epel-release -RUN yum -y install git curl bind-utils wget which nginx +RUN yum -y install git curl bind-utils ldns wget which nginx ENV staging "true" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb diff --git a/test/Dockerfile-debian b/test/Dockerfile-debian index b5da5dd..d066813 100644 --- a/test/Dockerfile-debian +++ b/test/Dockerfile-debian @@ -4,7 +4,7 @@ FROM debian:latest # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils wget nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light WORKDIR /root RUN mkdir /etc/nginx/pki diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index 66d7a35..2ef9e25 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -7,7 +7,7 @@ ENV DEBIAN_FRONTEND noninteractive # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils wget nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light RUN apt-get install -y vim dos2unix # for debugging # TODO test with drill, dig, host diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-staging index 58762d0..05f0471 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-staging @@ -11,9 +11,8 @@ ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils wget nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light RUN apt-get install -y vim dos2unix # for debugging -# TODO test with drill, dig, host WORKDIR /root diff --git a/test/Dockerfile-ubuntu16 b/test/Dockerfile-ubuntu16 index 030d03a..ba6164c 100644 --- a/test/Dockerfile-ubuntu16 +++ b/test/Dockerfile-ubuntu16 @@ -5,16 +5,13 @@ FROM ubuntu:xenial # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils wget nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light 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 -# Prevent "Can't load /root/.rnd into RNG" error from openssl -# RUN touch /root/.rnd - # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core RUN git clone https://github.com/bats-core/bats-support /bats-support diff --git a/test/Dockerfile-ubuntu18 b/test/Dockerfile-ubuntu18 index 1d68cd3..1735646 100644 --- a/test/Dockerfile-ubuntu18 +++ b/test/Dockerfile-ubuntu18 @@ -5,7 +5,7 @@ FROM ubuntu:bionic # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils wget gawk nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget gawk nginx-light WORKDIR /root RUN mkdir /etc/nginx/pki From 44f0ce1a536243c32253bf2cd697beae1544b5e0 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 2 Oct 2020 15:16:23 +0100 Subject: [PATCH 122/308] Update revision history --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 92c01a3..e6500e8 100755 --- a/getssl +++ b/getssl @@ -237,7 +237,8 @@ # 2020-08-06 Use -sigalgs instead of -cipher when checking remote for tls1.3 (#570) # 2020-08-31 Fix slow fork bomb when directory containing getssl isn't writeable (#440) # 2020-09-01 Use RSA-PSS when checking remote for DUAL_RSA_ECDSA (#570) -# 2020-09-02 Fix issue when SANS is space and comma separated (#579) +# 2020-09-02 Fix issue when SANS is space and comma separated (#579) (2.30) +# 2020-10-02 Various fixes to get_auth_dns and changes to support unit tests (#308) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} From cb5941307afc25e81bf0518a354548c88eec0ba9 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 3 Oct 2020 19:27:28 +0100 Subject: [PATCH 123/308] Change staging tests to use all auth dns servers --- test/test-config/getssl-staging-dns01-fail-dns-add.cfg | 2 +- test/test-config/getssl-staging-dns01-no-suffix.cfg | 2 +- test/test-config/getssl-staging-dns01.cfg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test-config/getssl-staging-dns01-fail-dns-add.cfg b/test/test-config/getssl-staging-dns01-fail-dns-add.cfg index 125cfef..2985d32 100644 --- a/test/test-config/getssl-staging-dns01-fail-dns-add.cfg +++ b/test/test-config/getssl-staging-dns01-fail-dns-add.cfg @@ -5,7 +5,7 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" # Generic staging config VALIDATE_VIA_DNS=true DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -AUTH_DNS_SERVER=ns2.duckdns.org +PUBLIC_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true # Test that the retry works (dns_add_command will always fail) diff --git a/test/test-config/getssl-staging-dns01-no-suffix.cfg b/test/test-config/getssl-staging-dns01-no-suffix.cfg index 6b764f3..47d2cec 100644 --- a/test/test-config/getssl-staging-dns01-no-suffix.cfg +++ b/test/test-config/getssl-staging-dns01-no-suffix.cfg @@ -5,7 +5,7 @@ CA="https://acme-staging-v02.api.letsencrypt.org" VALIDATE_VIA_DNS=true DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -AUTH_DNS_SERVER=ns2.duckdns.org +PUBLIC_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true DNS_EXTRA_WAIT=120 diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 655f1c6..348cabf 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -5,7 +5,7 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" VALIDATE_VIA_DNS=true DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -AUTH_DNS_SERVER=ns2.duckdns.org +PUBLIC_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true DNS_EXTRA_WAIT=120 From 96d987c07bec39f5a941527975bc05461b350bb3 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 4 Oct 2020 20:01:17 +0100 Subject: [PATCH 124/308] Add CHECK_PUBLIC_DNS_SERVER --- getssl | 21 ++++++++++++++++++++- test/u1-test-get_auth_dns-dig.bats | 18 ++++++++++++++++-- test/u2-test-get_auth_dns-drill.bats | 16 +++++++++++++++- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/getssl b/getssl index e6500e8..a6fa355 100755 --- a/getssl +++ b/getssl @@ -239,6 +239,7 @@ # 2020-09-01 Use RSA-PSS when checking remote for DUAL_RSA_ECDSA (#570) # 2020-09-02 Fix issue when SANS is space and comma separated (#579) (2.30) # 2020-10-02 Various fixes to get_auth_dns and changes to support unit tests (#308) +# 2020-10-04 Add CHECK_PUBLIC_DNS_SERVER to check the DNS challenge has been updated there # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} @@ -272,6 +273,7 @@ ORIG_UMASK=$(umask) PREVIOUSLY_VALIDATED="true" PRIVATE_KEY_ALG="rsa" PUBLIC_DNS_SERVER="" +CHECK_PUBLIC_DNS_SERVER="true" RELOAD_CMD="" RENEW_ALLOW="30" REUSE_PRIVATE_KEY="true" @@ -1278,7 +1280,11 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ -z "$all_auth_dns_servers" ]]; then error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" fi - primary_ns="$all_auth_dns_servers" + if [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then + primary_ns="$all_auth_dns_servers $PUBLIC_DNS_SERVER" + else + primary_ns="$all_auth_dns_servers" + fi return fi @@ -1345,6 +1351,10 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n primary_ns=$(echo "$all_auth_dns_servers" | awk '{print " " $1}') fi + if [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then + primary_ns="$primary_ns $PUBLIC_DNS_SERVER" + fi + debug set primary_ns = "$primary_ns" test_output set primary_ns ="$primary_ns" return @@ -1366,6 +1376,11 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n else primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') fi + + if [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then + primary_ns="$primary_ns $PUBLIC_DNS_SERVER" + fi + return fi fi @@ -1416,6 +1431,10 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n else primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') fi + + if [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then + primary_ns="$primary_ns $PUBLIC_DNS_SERVER" + fi return fi fi diff --git a/test/u1-test-get_auth_dns-dig.bats b/test/u1-test-get_auth_dns-dig.bats index 356c5c5..d13cc56 100644 --- a/test/u1-test-get_auth_dns-dig.bats +++ b/test/u1-test-get_auth_dns-dig.bats @@ -31,7 +31,7 @@ teardown() { } - @test "Check get_auth_dns using dig NS" { +@test "Check get_auth_dns using dig NS" { # Test that get_auth_dns() handles scenario where NS query returns Authority section # # ************** EXAMPLE DIG OUTPUT ************** @@ -53,6 +53,7 @@ teardown() { _TEST_SKIP_CNAME_CALL=1 PUBLIC_DNS_SERVER=ns1.duckdns.org + CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=false run get_auth_dns ubuntu-getssl.duckdns.org @@ -79,6 +80,7 @@ teardown() { # DuckDNS server returns nothing for SOA, so use public dns instead PUBLIC_DNS_SERVER=1.0.0.1 + CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=false run get_auth_dns ubuntu-getssl.duckdns.org @@ -94,6 +96,11 @@ teardown() { CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' + + # Check that we also check the public DNS server if requested + CHECK_PUBLIC_DNS_SERVER=true + run get_auth_dns ubuntu-getssl.duckdns.org + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org 1\.0\.0\.1' } @@ -109,6 +116,7 @@ teardown() { _TEST_SKIP_SOA_CALL=1 PUBLIC_DNS_SERVER=1.0.0.1 + CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=false run get_auth_dns www.duckdns.org @@ -121,9 +129,14 @@ teardown() { assert_line --partial 'Using dig NS' # Check all Authoritive DNS servers are returned if requested - CHECK_ALL_AUTH_DNS=false + CHECK_ALL_AUTH_DNS=true run get_auth_dns www.duckdns.org assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' + + # Check that we also check the public DNS server if requested + CHECK_PUBLIC_DNS_SERVER=true + run get_auth_dns www.duckdns.org + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com 1\.0\.0\.1' } @@ -146,6 +159,7 @@ teardown() { # ns3.duckdns.org. 600 IN A 52.26.169.94 PUBLIC_DNS_SERVER=ns1.duckdns.org + CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=false run get_auth_dns www.duckdns.org diff --git a/test/u2-test-get_auth_dns-drill.bats b/test/u2-test-get_auth_dns-drill.bats index a0d977c..1db1011 100644 --- a/test/u2-test-get_auth_dns-drill.bats +++ b/test/u2-test-get_auth_dns-drill.bats @@ -72,6 +72,7 @@ teardown() { _TEST_SKIP_SOA_CALL=1 PUBLIC_DNS_SERVER=ns1.duckdns.org + CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=false run get_auth_dns ubuntu-getssl.duckdns.org @@ -103,6 +104,7 @@ teardown() { # DuckDNS server returns nothing for SOA, so use public dns instead PUBLIC_DNS_SERVER=1.0.0.1 + CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=false run get_auth_dns ubuntu-getssl.duckdns.org @@ -118,6 +120,11 @@ teardown() { CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' + + # Check that we also check the public DNS server if requested + CHECK_PUBLIC_DNS_SERVER=true + run get_auth_dns ubuntu-getssl.duckdns.org + assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org 1\.0\.0\.1' } @@ -138,6 +145,7 @@ teardown() { _TEST_SKIP_SOA_CALL=1 PUBLIC_DNS_SERVER=1.0.0.1 + CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=false run get_auth_dns www.duckdns.org @@ -150,9 +158,14 @@ teardown() { assert_line --partial 'Using drill NS' # Check all Authoritive DNS servers are returned if requested - CHECK_ALL_AUTH_DNS=false + CHECK_ALL_AUTH_DNS=true run get_auth_dns www.duckdns.org assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' + + # Check that we also check the public DNS server if requested + CHECK_PUBLIC_DNS_SERVER=true + run get_auth_dns www.duckdns.org + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com 1\.0\.0\.1' } @@ -183,6 +196,7 @@ teardown() { _TEST_SKIP_SOA_CALL=1 PUBLIC_DNS_SERVER=ns1.duckdns.org + CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=false run get_auth_dns www.duckdns.org From d195235a7ed78a83f6f93257b9aa8971ba93d8bf Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 4 Oct 2020 20:12:41 +0100 Subject: [PATCH 125/308] Document the settings used for DNS verification --- getssl | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/getssl b/getssl index a6fa355..f99c53e 100755 --- a/getssl +++ b/getssl @@ -252,7 +252,6 @@ ACCOUNT_KEY_TYPE="rsa" CA="https://acme-staging-v02.api.letsencrypt.org/directory" CA_CERT_LOCATION="" CHALLENGE_CHECK_TYPE="http" -CHECK_ALL_AUTH_DNS="false" CHECK_REMOTE="true" CHECK_REMOTE_WAIT=0 CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" @@ -260,10 +259,6 @@ CSR_SUBJECT="/" CURL_USERAGENT="${PROGNAME}/${VERSION}" DEACTIVATE_AUTH="false" DEFAULT_REVOKE_CA="https://acme-v02.api.letsencrypt.org" -DNS_EXTRA_WAIT=60 # How long to wait after the DNS has updated before telling the ACME server to check. -DNS_WAIT_RETRY_ADD="false" # Try the dns_add_command again if the DNS record hasn't updated -DNS_WAIT=10 # How long to wait before checking the DNS record again -DNS_WAIT_COUNT=100 # How many times to wait for the DNS record to update DOMAIN_KEY_LENGTH=4096 DUAL_RSA_ECDSA="false" GETSSL_IGNORE_CP_PRESERVE="false" @@ -272,8 +267,6 @@ IGNORE_DIRECTORY_DOMAIN="false" ORIG_UMASK=$(umask) PREVIOUSLY_VALIDATED="true" PRIVATE_KEY_ALG="rsa" -PUBLIC_DNS_SERVER="" -CHECK_PUBLIC_DNS_SERVER="true" RELOAD_CMD="" RENEW_ALLOW="30" REUSE_PRIVATE_KEY="true" @@ -284,8 +277,22 @@ OCSP_MUST_STAPLE="false" TEMP_UPGRADE_FILE="" TOKEN_USER_ID="" USE_SINGLE_ACL="false" -VALIDATE_VIA_DNS="" WORKING_DIR_CANDIDATES=("/etc/getssl/" "${PROGDIR}/conf" "${PROGDIR}/.getssl" "${HOME}/.getssl") + +# Variables used when validating using a DNS entry +VALIDATE_VIA_DNS="" # Set this to "true" to enable DNS validation +AUTH_DNS_SERVER="" # Use this DNS server to check the challenge token has been set +PUBLIC_DNS_SERVER="" # Use this DNS server to find the authoritative DNS servers for the domain +CHECK_ALL_AUTH_DNS="false" # Check the challenge token has been set on all authoritative DNS servers +CHECK_PUBLIC_DNS_SERVER="true" # Check the public DNS server as well as the authoritative DNS servers +DNS_ADD_COMMAND="" # Use this command/script to add the challenge token to the DNS entries for the domain +DNS_DEL_COMMAND="" # Use this command/script to remove the challenge token from the DNS entries for the domain +DNS_WAIT_COUNT=100 # How many times to wait for the DNS record to update +DNS_WAIT=10 # How long to wait before checking the DNS record again +DNS_EXTRA_WAIT=60 # How long to wait after the DNS entries are visible to us before telling the ACME server to check. +DNS_WAIT_RETRY_ADD="false" # Try the dns_add_command again if the DNS record hasn't updated + +# Private variables _CHECK_ALL=0 _CREATE_CONFIG=0 _FORCE_RENEW=0 From 7be325dbadd4993b9b68dd1b38328a42082d9b79 Mon Sep 17 00:00:00 2001 From: Mesar Hameed Date: Tue, 13 Oct 2020 00:19:47 +0100 Subject: [PATCH 126/308] bugfix: strip comments in drill/dig output when checking txt in dns. The dns query is often being reprinted as a comment as part of the drill/dig output this caused multiple hits for the grep, making the comparison invalid. Make sure we strip out comments before we look for the challenge text in the txt record. --- getssl | 1 + 1 file changed, 1 insertion(+) diff --git a/getssl b/getssl index f99c53e..e6541aa 100755 --- a/getssl +++ b/getssl @@ -1203,6 +1203,7 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then debug "$DNS_CHECK_FUNC" TXT "_acme-challenge.${lower_d}" "@${ns}" check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${lower_d}" "@${ns}" \ + | grep -i "^_acme-challenge.${lower_d}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${lower_d}" "${ns}" \ From f2bcce5ab2acf39d0b1a37261e11a46706f1d0b6 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 25 Oct 2020 14:46:30 +0000 Subject: [PATCH 127/308] Add more info to debug statemetns when running tests --- getssl | 60 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/getssl b/getssl index f99c53e..9fd63ea 100755 --- a/getssl +++ b/getssl @@ -629,10 +629,10 @@ check_getssl_upgrade() { # check if a more recent version of code is available a if [[ "${latestvdec:-0}" -gt "$localvdec" ]]; then if [[ ${_UPGRADE} -eq 1 ]]; then if ! install "$0" "${0}.v${VERSION}"; then - error_exit "problem renaming old version while updating, check permissions" + error_exit "problem renaming old version while updating, check permissions" fi if ! install -m 700 "$TEMP_UPGRADE_FILE" "$0"; then - error_exit "problem installing new version while updating, check permissions" + error_exit "problem installing new version while updating, check permissions" fi if [[ ${_MUTE} -eq 0 ]]; then echo "Updated getssl from v${VERSION} to v${latestversion}" @@ -819,7 +819,7 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) for d in $alldomains; do if [[ "$(echo "${domains_in_csr}"| grep "^${d}$")" != "${d}" ]]; then info "existing csr at $csr_file does not contain ${d} - re-create-csr"\ - ".... $(echo "${domains_in_csr}"| grep "^${d}$")" + ".... $(echo "${domains_in_csr}"| grep "^${d}$")" _RECREATE_CSR=1 fi done @@ -889,6 +889,7 @@ create_order() { OrderLink=$(echo "$responseHeaders" | grep -i location | awk '{print $2}'| tr -d '\r\n ') debug "Order link $OrderLink" FinalizeLink=$(json_get "$response" "finalize") + debug "Finalize link $FinalizeLink" if [[ $API -eq 1 ]]; then dn=0 @@ -915,6 +916,7 @@ create_order() { d=$(echo "$d" | tr "[:upper:]" "[:lower:]") if [ "$d" == "$authdomain" ]; then debug "Saving authorization response for $authdomain for domain alldomains[$dn]" + debug "Response = ${response//['\t\r\n']}" AuthLinkResponse[$dn]=$response AuthLinkResponseHeader[$dn]=$responseHeaders fi @@ -957,7 +959,7 @@ debug() { # write out debug info if the debug flag has been set if [[ ${_USE_DEBUG} -eq 1 ]]; then # If running tests then output in TAP format (for debugging tests) if [[ ${_RUNNING_TEST} -eq 1 ]]; then - echo "#" "$@" >&3 + echo "# $(date "+%b %d %T") ${FUNCNAME[1]}:${BASH_LINENO[1]}" "$@" >&3 else echo " " echo "$@" @@ -1047,7 +1049,7 @@ for d in $alldomains; do uri=$(json_get "$response" "uri" "dns-01") debug uri "$uri" else # APIv2 - debug "authlink response = $response" + debug "authlink response = ${response//['\t\r\n']}" # get the token and uri from the dns-01 component token=$(json_get "$response" "challenges" "type" "dns-01" "token") uri=$(json_get "$response" "challenges" "type" "dns-01" "url") @@ -1058,10 +1060,11 @@ for d in $alldomains; do debug keyauthorization "$keyauthorization" #create signed authorization key from token. - auth_key=$(printf '%s' "$keyauthorization" | openssl dgst -sha256 -binary \ - | openssl base64 -e \ - | tr -d '\n\r' \ - | sed -e 's:=*$::g' -e 'y:+/:-_:') + auth_key=$(printf '%s' "$keyauthorization" \ + | openssl dgst -sha256 -binary \ + | openssl base64 -e \ + | tr -d '\n\r' \ + | sed -e 's:=*$::g' -e 'y:+/:-_:') debug auth_key "$auth_key" # shellcheck disable=SC2018,SC2019 @@ -1102,7 +1105,7 @@ for d in $alldomains; do uri=$(json_get "$response" "uri" "http-01") debug uri "$uri" else # APIv2 - debug "authlink response = $response" + debug "authlink response = ${response//['\t\r\n']}" # get the token from the http-01 component token=$(json_get "$response" "challenges" "type" "http-01" "token") # get the uri from the http component @@ -1198,18 +1201,18 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then while [[ "$check_dns" == "fail" ]]; do if [[ "$os" == "cygwin" ]]; then check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ - | grep ^_acme -A2\ - | grep '"'|awk -F'"' '{ print $2}') + | grep ^_acme -A2\ + | grep '"'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then debug "$DNS_CHECK_FUNC" TXT "_acme-challenge.${lower_d}" "@${ns}" check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${lower_d}" "@${ns}" \ - | grep 'IN\WTXT'|awk -F'"' '{ print $2}') + | grep 'IN\WTXT'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${lower_d}" "${ns}" \ - | grep 'descriptive text'|awk -F'"' '{ print $2}') + | grep 'descriptive text'|awk -F'"' '{ print $2}') else check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ - | grep 'text ='|awk -F'"' '{ print $2}') + | grep 'text ='|awk -F'"' '{ print $2}') fi debug "expecting $auth_key" debug "${ns} gave ... $check_result" @@ -1515,7 +1518,7 @@ get_cr() { # get curl response debug url "$url" response=$(curl --user-agent "$CURL_USERAGENT" --silent "$url") ret=$? - debug response "$response" + debug response "${response//[$'\t\r\n']}" code=$(json_get "$response" status) debug code "$code" debug "get_cr return code $ret" @@ -1566,8 +1569,8 @@ get_signing_params() { # get signing parameters from key crv="$(openssl ec -in "$skey" -noout -text 2>/dev/null | awk '$2 ~ "CURVE:" {print $3}')" if [[ -z "$crv" ]]; then gsp_keytype="$(openssl ec -in "$skey" -noout -text 2>/dev/null \ - | grep "^ASN1 OID:" \ - | awk '{print $3}')" + | grep "^ASN1 OID:" \ + | awk '{print $3}')" case "$gsp_keytype" in prime256v1) crv="P-256" ;; secp384r1) crv="P-384" ;; @@ -1582,8 +1585,8 @@ get_signing_params() { # get signing parameters from key *) error_exit "invalid curve algorithm type $crv";; esac pubtext="$(openssl ec -in "$skey" -noout -text 2>/dev/null \ - | awk '/^pub:/{p=1;next}/^ASN1 OID:/{p=0}p' \ - | tr -d ": \n\r")" + | awk '/^pub:/{p=1;next}/^ASN1 OID:/{p=0}p' \ + | tr -d ": \n\r")" mid=$(( (${#pubtext} -2) / 2 + 2 )) x64=$(echo "$pubtext" | cut -b 3-$mid | hex2bin | urlbase64) y64=$(echo "$pubtext" | cut -b $((mid+1))-${#pubtext} | hex2bin | urlbase64) @@ -1634,6 +1637,11 @@ hex2bin() { # Remove spaces, add leading zero, escape as hex string ensuring no info() { # write out info as long as the quiet flag has not been set. if [[ ${_QUIET} -eq 0 ]]; then + # If running tests then output in TAP format as well (for debugging tests) + if [[ ${_RUNNING_TEST} -eq 1 ]]; then + echo "# $(date "+%b %d %T") ${FUNCNAME[1]}:${BASH_LINENO[1]}" "$@" >&3 + fi + echo "$@" fi } @@ -2111,7 +2119,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p fi debug responseHeaders "$responseHeaders" - debug response "$response" + debug response "${response//[$'\t\r\n']}" code=$(awk ' $1 ~ "^HTTP" {print $2}' "$CURL_HEADER" | tail -1) debug code "$code" if [[ "$code" == 4* && $response != *"error:badNonce"* && "$code" != 409 ]]; then @@ -2223,9 +2231,9 @@ usage() { # echos out the program usage write_domain_template() { # write out a template file for a domain. if [[ -s "$WORKING_DIR/getssl_default.cfg" ]]; then - export DOMAIN="$DOMAIN" - export EX_SANS="$EX_SANS" - envsubst < "$WORKING_DIR/getssl_default.cfg" > "$1" + export DOMAIN="$DOMAIN" + export EX_SANS="$EX_SANS" + envsubst < "$WORKING_DIR/getssl_default.cfg" > "$1" else cat > "$1" <<- _EOF_domain_ # vim: filetype=sh @@ -2786,10 +2794,10 @@ fi # if not reusing private key, then remove the old keys if [[ "$REUSE_PRIVATE_KEY" != "true" ]]; then if [[ -s "$DOMAIN_DIR/${DOMAIN}.key" ]]; then - rm -f "$DOMAIN_DIR/${DOMAIN}.key" + rm -f "$DOMAIN_DIR/${DOMAIN}.key" fi if [[ -s "$DOMAIN_DIR/${DOMAIN}.ec.key" ]]; then - rm -f "$DOMAIN_DIR/${DOMAIN}.ec.key" + rm -f "$DOMAIN_DIR/${DOMAIN}.ec.key" fi fi # create new domain keys if they don't already exist From 8871da0b2c65ec7160137253eccce9349312968d Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 25 Oct 2020 14:48:27 +0000 Subject: [PATCH 128/308] Add tests for changing SANS (bug not fixed) --- test/19-test-add-to-sans.bats | 61 +++++++++++++++++++ .../getssl-dns01-add-to-sans-1.cfg | 37 +++++++++++ .../getssl-dns01-add-to-sans-2.cfg | 37 +++++++++++ 3 files changed, 135 insertions(+) create mode 100644 test/19-test-add-to-sans.bats create mode 100644 test/test-config/getssl-dns01-add-to-sans-1.cfg create mode 100644 test/test-config/getssl-dns01-add-to-sans-2.cfg diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats new file mode 100644 index 0000000..8d6f560 --- /dev/null +++ b/test/19-test-add-to-sans.bats @@ -0,0 +1,61 @@ +#! /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 + curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a +} + +teardown() { + curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a +} + + + +@test "Create certificate to check can add to SANS" { + skip "FIXME: Certificate is not recreated when SANS is updated" + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01-add-to-sans-1.cfg" + fi + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + setup_environment + + + init_getssl + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check we can add a new domain to SANS" { + skip "FIXME: Certificate is not recreated when SANS is updated" + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01-add-to-sans-2.cfg" + fi + # . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + # CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + # KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key + # cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + + create_certificate + assert_success + check_output_for_errors + + # As the SANS list changed, a new certificate is needed + assert_line --partial "certificate installed OK on server" + refute_line --partial 'certificate is valid for more than' +} diff --git a/test/test-config/getssl-dns01-add-to-sans-1.cfg b/test/test-config/getssl-dns01-add-to-sans-1.cfg new file mode 100644 index 0000000..ddb514a --- /dev/null +++ b/test/test-config/getssl-dns01-add-to-sans-1.cfg @@ -0,0 +1,37 @@ +# 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" + +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 + +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_EXTRA_WAIT=0 + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="a.${GETSSL_HOST}" + +# 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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" +IGNORE_DIRECTORY_DOMAIN="true" + +#_USE_DEBUG=1 +#_RUNNING_TEST=1 diff --git a/test/test-config/getssl-dns01-add-to-sans-2.cfg b/test/test-config/getssl-dns01-add-to-sans-2.cfg new file mode 100644 index 0000000..9196905 --- /dev/null +++ b/test/test-config/getssl-dns01-add-to-sans-2.cfg @@ -0,0 +1,37 @@ +# 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" + +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 + +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_EXTRA_WAIT=0 + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="b.${GETSSL_HOST}, a.${GETSSL_HOST}" + +# 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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="false" +IGNORE_DIRECTORY_DOMAIN="true" + +#_USE_DEBUG=1 +#_RUNNING_TEST=1 From f44346f835a706cd2043c708d46639668e12f41b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 25 Oct 2020 16:09:40 +0000 Subject: [PATCH 129/308] Reduce number of DNS lookup attempts and retry DNS_ADD --- test/test-config/getssl-staging-dns01-no-suffix.cfg | 11 +++++------ test/test-config/getssl-staging-dns01.cfg | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/test/test-config/getssl-staging-dns01-no-suffix.cfg b/test/test-config/getssl-staging-dns01-no-suffix.cfg index 47d2cec..b4f5202 100644 --- a/test/test-config/getssl-staging-dns01-no-suffix.cfg +++ b/test/test-config/getssl-staging-dns01-no-suffix.cfg @@ -9,18 +9,17 @@ PUBLIC_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true DNS_EXTRA_WAIT=120 +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_WAIT_RETRY_ADD="true" + ACCOUNT_KEY_TYPE="rsa" PRIVATE_KEY_ALG="rsa" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="" -# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. -ACL=('/var/www/html/.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" diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 348cabf..030eaa1 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -9,18 +9,17 @@ PUBLIC_DNS_SERVER=ns2.duckdns.org CHECK_ALL_AUTH_DNS=true DNS_EXTRA_WAIT=120 +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_WAIT_RETRY_ADD="true" + ACCOUNT_KEY_TYPE="rsa" PRIVATE_KEY_ALG="rsa" # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="" -# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. -ACL=('/var/www/html/.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" From 9e4372c5b6a7c0621e1876b773616f42775f786c Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 25 Oct 2020 16:34:38 +0000 Subject: [PATCH 130/308] Don't check all the auth servers as one DuckDNS server isn't updating --- test/test-config/getssl-staging-dns01.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 030eaa1..d7eb7a4 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -6,7 +6,7 @@ VALIDATE_VIA_DNS=true DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" PUBLIC_DNS_SERVER=ns2.duckdns.org -CHECK_ALL_AUTH_DNS=true +CHECK_ALL_AUTH_DNS="false" DNS_EXTRA_WAIT=120 # Speed up the test by reducing the number or retries and the wait between retries. From c6b75847a486d89454608bd8519429ed8bee6198 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 25 Oct 2020 21:24:53 +0000 Subject: [PATCH 131/308] When retrying DNS_ADD, delete first --- getssl | 9 +++++---- test/test-config/getssl-staging-dns01.cfg | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index cdd18e0..2fc8275 100755 --- a/getssl +++ b/getssl @@ -916,7 +916,7 @@ create_order() { d=$(echo "$d" | tr "[:upper:]" "[:lower:]") if [ "$d" == "$authdomain" ]; then debug "Saving authorization response for $authdomain for domain alldomains[$dn]" - debug "Response = ${response//['\t\r\n']}" + debug "Response = ${response//[$'\t\r\n']}" AuthLinkResponse[$dn]=$response AuthLinkResponseHeader[$dn]=$responseHeaders fi @@ -1049,7 +1049,7 @@ for d in $alldomains; do uri=$(json_get "$response" "uri" "dns-01") debug uri "$uri" else # APIv2 - debug "authlink response = ${response//['\t\r\n']}" + debug "authlink response = ${response//[$'\t\r\n']}" # get the token and uri from the dns-01 component token=$(json_get "$response" "challenges" "type" "dns-01" "token") uri=$(json_get "$response" "challenges" "type" "dns-01" "url") @@ -1105,7 +1105,7 @@ for d in $alldomains; do uri=$(json_get "$response" "uri" "http-01") debug uri "$uri" else # APIv2 - debug "authlink response = ${response//['\t\r\n']}" + debug "authlink response = ${response//[$'\t\r\n']}" # get the token from the http-01 component token=$(json_get "$response" "challenges" "type" "http-01" "token") # get the uri from the http component @@ -1224,8 +1224,9 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then if [[ $ntries -lt $DNS_WAIT_COUNT ]]; then ntries=$(( ntries + 1 )) - if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 == 0 )) ]]; then + if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 )) == 0 ]]; then debug "Retrying adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" + eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then error_exit "DNS_ADD_COMMAND failed for domain $d" fi diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index d7eb7a4..910c7fe 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -5,7 +5,7 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" VALIDATE_VIA_DNS=true DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=ns2.duckdns.org +PUBLIC_DNS_SERVER=1.1.1.1 CHECK_ALL_AUTH_DNS="false" DNS_EXTRA_WAIT=120 From e045239a356219a2de71bf51e2a0727b4223614e Mon Sep 17 00:00:00 2001 From: Wade Fitzpatrick Date: Fri, 30 Oct 2020 17:00:56 +1000 Subject: [PATCH 132/308] Allow scoped Cloudflare API Tokens --- dns_scripts/Cloudflare-README.md | 52 +++++++++++ dns_scripts/dns_add_cloudflare | 148 ++++++++++++++++-------------- dns_scripts/dns_del_cloudflare | 150 ++++++++++++++++--------------- 3 files changed, 211 insertions(+), 139 deletions(-) create mode 100644 dns_scripts/Cloudflare-README.md diff --git a/dns_scripts/Cloudflare-README.md b/dns_scripts/Cloudflare-README.md new file mode 100644 index 0000000..f831cfb --- /dev/null +++ b/dns_scripts/Cloudflare-README.md @@ -0,0 +1,52 @@ +## Using Cloudflare DNS for LetsEncrypt domain validation + +### Enabling the scripts + +Set the following options in `getssl.cfg` (either global or domain-specific): + +``` +VALIDATE_VIA_DNS="true" +DNS_ADD_COMMAND="/usr/share/getssl/dns_scripts/dns_add_cloudflare" +DNS_DEL_COMMAND="/usr/share/getssl/dns_scripts/dns_del_cloudflare" +``` + +### Authentication + +There are 2 methods of authenticating with Cloudflare: + +1. API Keys - Account level, all-purpose tokens +2. API Tokens - Scoped and permissioned access to resources + +Both are configured from your profile in the [Cloudflare dashboard][1] + +[1]: https://dash.cloudflare.com/profile/api-tokens + +#### API Keys + +The **Zone ID** for the domain will be searched for programmatically. + +Set the following options in `getssl.cfg`: + +``` +export CF_EMAIL="..." # Cloudflare account email address +export CF_KEY="..." # Global API Key +``` + +#### API Tokens + +Cloudflare provides a template for creating an API Token with access to edit +zone records. Tokens must be created with at least '**DNS:Edit** permissions +for the domain to add/delete records. + +The API requires higher privileges to be able to list zones, therefore this +method also requires the **Zone ID** from the Overview tab in the Cloudflare +Dashboard. + +Set the following options in the domain-specific `getssl.cfg` + +``` +export CF_API_TOKEN="..." +export CF_ZONE_ID="..." +``` + +__Note__: API Keys will be used instead if also configured diff --git a/dns_scripts/dns_add_cloudflare b/dns_scripts/dns_add_cloudflare index ea323c1..b1a6a16 100755 --- a/dns_scripts/dns_add_cloudflare +++ b/dns_scripts/dns_add_cloudflare @@ -1,9 +1,11 @@ #!/usr/bin/env bash -# need to add your email address and API key to cloudflare below or set as env variables +# either configure here or export environment variables in getssl.cfg email=${CF_EMAIL:-''} key=${CF_KEY:-''} +api_token=${CF_API_TOKEN:-''} +zone_id=${CF_ZONE_ID:-''} -# This script adds a token to cloudflare DNS for the ACME challenge +# This script adds a TXT record to cloudflare DNS for the ACME challenge # usage dns_add_cloudflare "domain name" "token" # return codes are; # 0 - success @@ -14,7 +16,11 @@ key=${CF_KEY:-''} fulldomain="${1}" token="${2}" API='https://api.cloudflare.com/client/v4/zones' -curl_params=( -H "X-Auth-Email: $email" -H "X-Auth-Key: $key" -H 'Content-Type: application/json' ) +if [[ -z "$api_token" ]]; then + curl_params=( -H "X-Auth-Email: $email" -H "X-Auth-Key: $key" -H 'Content-Type: application/json' ) +else + curl_params=( -H "Authorization: Bearer $api_token" -H 'Content-Type: application/json' ) +fi # check initial parameters @@ -28,84 +34,88 @@ if [[ -z "$token" ]]; then exit 1 fi -if [[ -z "$email" ]]; then - echo "CF_EMAIL (email) parameter not set" - exit 1 -fi +if [[ -z "$api_token" ]]; then + if [[ -z "$email" ]]; then + echo "CF_EMAIL (email) parameter not set" + exit 1 + fi -if [[ -z "$key" ]]; then - echo "CF_KEY (key) parameter not set" - exit 1 + if [[ -z "$key" ]]; then + echo "CF_KEY (key) parameter not set" + exit 1 + fi fi -# get a list of all domain names from cloudflare -# If you have a lot, you may need add "&page=1&per_page=1000" and/or "&status=active" -resp=$(curl --silent "${curl_params[@]}" -X GET "$API") -re='"result":\[(([^][]*\[[^][]*])*[^][]*)]' # find result section -if [[ "${resp// }" =~ $re ]]; then - resp="${BASH_REMATCH[1]}" -fi - -# iterate through all sections to obtain a list of domains -while [[ "$resp" ]]; do - re='[^}{]*\{(([^}{]*\{[^}{]*})*[^}{]*)}(.*)' - if [[ "$resp" =~ $re ]]; then - first="${BASH_REMATCH[1]}" - resp="${BASH_REMATCH[3]}" +if [[ -z "$zone_id" ]]; then + # get a list of all domain names from cloudflare + # If you have a lot, you may need add "&page=1&per_page=1000" and/or "&status=active" + resp=$(curl --silent "${curl_params[@]}" -X GET "$API") + re='"result":\[(([^][]*\[[^][]*])*[^][]*)]' # find result section + if [[ "${resp// }" =~ $re ]]; then + resp="${BASH_REMATCH[1]}" fi - # remove subsections - leave only domain level - while [[ "$first" =~ (.*)[\[\{][^]\{\}[]*[\]\}](.*) ]]; do - first="${BASH_REMATCH[1]}${BASH_REMATCH[2]}" - done - re='"name":"([^"]*)"' - if [[ "$first" =~ $re ]]; then - domains=( "${domains[@]}" "${BASH_REMATCH[1]}" ) - else - echo "Error getting domain name" - exit 2 - fi - re='"id":"([^"]*)"' - if [[ "$first" =~ $re ]]; then - ids=( "${ids[@]}" "${BASH_REMATCH[1]}" ) - else - echo "Error getting domain id" - exit 2 - fi -done -# split required domain name into an array -dnarray=(${fulldomain//./ }) -# get number of parts in required domain name -NumParts=${#dnarray[@]} -# build a test domain name, starting with the largest, and reduce it -# until a match is found, set domain = first ( longest) match. -domain="" -i=1 -while [ $i -lt "$NumParts" ]; do - testdomain="${dnarray[i-1]}" - for ((j=i; j Date: Wed, 18 Nov 2020 21:33:39 +0000 Subject: [PATCH 133/308] Wildcard support in ACMEv2 Fixes #347 and #400 --- getssl | 273 +++++++++++++++++++++++++++------------------------------ 1 file changed, 128 insertions(+), 145 deletions(-) diff --git a/getssl b/getssl index 2fc8275..f62174e 100755 --- a/getssl +++ b/getssl @@ -469,7 +469,7 @@ check_challenge_completion() { # checks with the ACME server if our challenge is # if ACME response is that their check gave an invalid response, error exit if [[ "$status" == "invalid" ]] ; then err_detail=$(echo "$response" | grep "detail") - #! FIXME need to check for "DNS problem: SERVFAIL looking up CAA ..." and retry + # TODO need to check for "DNS problem: SERVFAIL looking up CAA ..." and retry error_exit "$domain:Verify error:$err_detail" fi @@ -491,6 +491,84 @@ check_challenge_completion() { # checks with the ACME server if our challenge is fi } +check_challenge_completion_dns() { # perform validation via DNS challenge + token=$1 + uri=$2 + keyauthorization=$3 + d=$4 + primary_ns=$5 + auth_key=$6 + + # Always use lowercase domain name when querying DNS servers + # shellcheck disable=SC2018,SC2019 + lower_d=$(echo "${d##\*.}" | tr A-Z a-z) + + # check for token at public dns server, waiting for a valid response. + for ns in $primary_ns; do + debug "checking dns at $ns" + ntries=0 + check_dns="fail" + while [[ "$check_dns" == "fail" ]]; do + if [[ "$os" == "cygwin" ]]; then + check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ + | grep ^_acme -A2\ + | grep '"'|awk -F'"' '{ print $2}') + elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then + debug "$DNS_CHECK_FUNC" TXT "_acme-challenge.${lower_d}" "@${ns}" + check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${lower_d}" "@${ns}" \ + | grep -i "^_acme-challenge.${lower_d}" \ + | grep 'IN\WTXT'|awk -F'"' '{ print $2}') + elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then + check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${lower_d}" "${ns}" \ + | grep 'descriptive text'|awk -F'"' '{ print $2}') + else + check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ + | grep 'text ='|awk -F'"' '{ print $2}') + fi + debug "expecting $auth_key" + debug "${ns} gave ... $check_result" + + if [[ "$check_result" == *"$auth_key"* ]]; then + check_dns="success" + else + if [[ $ntries -lt $DNS_WAIT_COUNT ]]; then + ntries=$(( ntries + 1 )) + + if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 )) == 0 ]]; then + debug "Retrying adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" + eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" + if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then + error_exit "DNS_ADD_COMMAND failed for domain $d" + fi + + fi + info "checking DNS at ${ns} for ${lower_d}. Attempt $ntries/${DNS_WAIT_COUNT} gave wrong result, "\ + "waiting $DNS_WAIT secs before checking again" + sleep $DNS_WAIT + else + debug "dns check failed - removing existing value" + eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" + + error_exit "checking _acme-challenge.${lower_d} gave $check_result not $auth_key" + fi + fi + done + done + + if [[ "$DNS_EXTRA_WAIT" -gt 0 && "$PREVIOUSLY_VALIDATED" != "true" ]]; then + info "sleeping $DNS_EXTRA_WAIT seconds before asking the ACME server to check the dns" + sleep "$DNS_EXTRA_WAIT" + fi + + check_challenge_completion "$uri" "$d" "$keyauthorization" + + debug "remove DNS entry" + # shellcheck disable=SC2018,SC2019 + lower_d=$(echo "${d##\*.}" | tr A-Z a-z) + eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" +} +# end of ... perform validation if via DNS challenge + check_config() { # check the config files for all obvious errors debug "checking config" @@ -518,13 +596,13 @@ check_config() { # check the config files for all obvious errors config_errors=true fi - # get all domains + # get all domains into an array if [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then - alldomains=${SANS//[, ]/ } + read -r -a alldomains <<< "${SANS//[, ]/ }" else - alldomains=$(echo "$DOMAIN,$SANS" | sed "s/,/ /g") + read -r -a alldomains <<< "$(echo "$DOMAIN,$SANS" | sed "s/,/ /g")" fi - if [[ -z "$alldomains" ]]; then + if [[ -z "${alldomains[*]}" ]]; then info "${DOMAIN}: no domains specified" config_errors=true fi @@ -542,11 +620,14 @@ check_config() { # check the config files for all obvious errors dn=0 tmplist=$(mktemp 2>/dev/null || mktemp -t getssl) - for d in $alldomains; do # loop over domains (dn is domain number) + for d in "${alldomains[@]}"; do # loop over domains (dn is domain number) debug "checking domain $d" if [[ "$(grep "^${d}$" "$tmplist")" = "$d" ]]; then info "${DOMAIN}: $d appears to be duplicated in domain, SAN list" config_errors=true + elif [[ "$d" != "${d##\*.}" ]] && [[ "$VALIDATE_VIA_DNS" != "true" ]]; then + info "${DOMAIN}: cannot use http-01 validation for wildcard domains" + config_errors=true else echo "$d" >> "$tmplist" fi @@ -682,7 +763,7 @@ clean_up() { # Perform pre-exit housekeeping # shellcheck source=/dev/null . "$dnsfile" debug "attempting to clean up DNS entry for $d" - eval "$DNS_DEL_COMMAND" "$d" "$auth_key" + eval "$DNS_DEL_COMMAND" "${d##\*.}" "$auth_key" done shopt -u nullglob fi @@ -809,14 +890,14 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) debug "domain csr exists at - $csr_file" # check all domains in config are in csr if [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then - alldomains=$(echo "$SANS" | sed -e 's/ //g; s/,$//; y/,/\n/' | sort -u) + read -r -a alldomains <<< "$(echo "$SANS" | sed -e 's/ //g; s/,$//; y/,/\n/' | sort -u)" else - alldomains=$(echo "$DOMAIN,$SANS" | sed -e 's/,/ /g; s/ $//; y/ /\n/' | sort -u) + read -r -a alldomains <<< "$(echo "$DOMAIN,$SANS" | sed -e 's/,/ /g; s/ $//; y/ /\n/' | sort -u)" fi domains_in_csr=$(openssl req -text -noout -in "$csr_file" \ | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \ | sort -u) - for d in $alldomains; do + for d in "${alldomains[@]}"; do if [[ "$(echo "${domains_in_csr}"| grep "^${d}$")" != "${d}" ]]; then info "existing csr at $csr_file does not contain ${d} - re-create-csr"\ ".... $(echo "${domains_in_csr}"| grep "^${d}$")" @@ -824,7 +905,7 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) fi done # check all domains in csr are in config - if [[ "$alldomains" != "$domains_in_csr" ]]; then + if [[ "${alldomains[*]}" != "$domains_in_csr" ]]; then info "existing csr at $csr_file does not have the same domains as the config - re-create-csr" _RECREATE_CSR=1 fi @@ -877,7 +958,7 @@ create_key() { # create a domain key (if it doesn't already exist) create_order() { dstring="[" - for d in $alldomains; do + for d in "${alldomains[@]}"; do dstring="${dstring}{\"type\":\"dns\",\"value\":\"$d\"}," done dstring="${dstring::${#dstring}-1}]" @@ -893,9 +974,9 @@ create_order() { if [[ $API -eq 1 ]]; then dn=0 - for d in $alldomains; do + for d in "${alldomains[@]}"; do # get authorizations link - AuthLink[$dn]=$(json_get "$response" "identifiers" "value" "$d" "authorizations" "x") + AuthLink[$dn]=$(json_get "$response" "identifiers" "value" "${d##\*.}" "authorizations" "x") debug "authorizations link for $d - ${AuthLink[$dn]}" ((dn++)) done @@ -909,12 +990,14 @@ create_order() { send_signed_request "$l" "" # Get domain from response authdomain=$(json_get "$response" "identifier" "value") - # find array position (This is O(n2) but that doubt we'll see performance issues) + wildcard=$(json_get "$response" "wildcard") + debug wildcard="$wildcard" + # find array position (This is O(n2) but doubt that we'll see performance issues) dn=0 - for d in $alldomains; do + for d in "${alldomains[@]}"; do # Convert domain to lowercase as response from server will be in lowercase - d=$(echo "$d" | tr "[:upper:]" "[:lower:]") - if [ "$d" == "$authdomain" ]; then + lower_d=$(echo "$d" | tr "[:upper:]" "[:lower:]") + if [[ ( "$lower_d" == "$authdomain" && -z "$wildcard" ) || ( "$lower_d" == "*.${authdomain}" && -n "$wildcard" ) ]]; then debug "Saving authorization response for $authdomain for domain alldomains[$dn]" debug "Response = ${response//[$'\t\r\n']}" AuthLinkResponse[$dn]=$response @@ -1004,7 +1087,7 @@ find_dns_utils() { fulfill_challenges() { dn=0 -for d in $alldomains; do +for d in "${alldomains[@]}"; do # $d is domain in current loop, which is number $dn for ACL info "Verifying $d" if [[ "$USE_SINGLE_ACL" == "true" ]]; then @@ -1015,7 +1098,7 @@ for d in $alldomains; do # request a challenge token from ACME server if [[ $API -eq 1 ]]; then - request="{\"resource\":\"new-authz\",\"identifier\":{\"type\":\"dns\",\"value\":\"$d\"}}" + request="{\"resource\":\"new-authz\",\"identifier\":{\"type\":\"dns\",\"value\":\"${d##\*.}\"}}" send_signed_request "$URL_new_authz" "$request" debug "completed send_signed_request" @@ -1068,7 +1151,7 @@ for d in $alldomains; do debug auth_key "$auth_key" # shellcheck disable=SC2018,SC2019 - lower_d=$(echo "$d" | tr A-Z a-z) + lower_d=$(echo "${d##\*.}" | tr A-Z a-z) debug "adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then error_exit "DNS_ADD_COMMAND failed for domain $d" @@ -1082,21 +1165,7 @@ for d in $alldomains; do fi debug primary_ns "$primary_ns" - # make a directory to hold pending dns-challenges - if [[ ! -d "$TEMP_DIR/dns_verify" ]]; then - mkdir "$TEMP_DIR/dns_verify" - fi - - # generate a file with the current variables for the dns-challenge - cat > "$TEMP_DIR/dns_verify/$d" <<- _EOF_ - token="${token}" - uri="${uri}" - keyauthorization="${keyauthorization}" - d="${d}" - primary_ns="${primary_ns}" - auth_key="${auth_key}" - _EOF_ - + check_challenge_completion_dns "${token}" "${uri}" "${keyauthorization}" "${d}" "${primary_ns}" "${auth_key}" else # set up the correct http token for verification if [[ $API -eq 1 ]]; then # get the token from the http component @@ -1179,101 +1248,7 @@ for d in $alldomains; do ((dn++)) fi done # end of ... loop through domains for cert ( from SANS list) - -# perform validation if via DNS challenge -if [[ $VALIDATE_VIA_DNS == "true" ]]; then - # loop through dns-variable files to check if dns has been changed - for dnsfile in "$TEMP_DIR"/dns_verify/*; do - if [[ -e "$dnsfile" ]]; then - debug "loading DNSfile: $dnsfile" - # shellcheck source=/dev/null - . "$dnsfile" - - # Always use lowercase domain name when querying DNS servers - # shellcheck disable=SC2018,SC2019 - lower_d=$(echo "$d" | tr A-Z a-z) - - # check for token at public dns server, waiting for a valid response. - for ns in $primary_ns; do - debug "checking dns at $ns" - ntries=0 - check_dns="fail" - while [[ "$check_dns" == "fail" ]]; do - if [[ "$os" == "cygwin" ]]; then - check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ - | grep ^_acme -A2\ - | grep '"'|awk -F'"' '{ print $2}') - elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - debug "$DNS_CHECK_FUNC" TXT "_acme-challenge.${lower_d}" "@${ns}" - check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${lower_d}" "@${ns}" \ - | grep -i "^_acme-challenge.${lower_d}" \ - | grep 'IN\WTXT'|awk -F'"' '{ print $2}') - elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then - check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${lower_d}" "${ns}" \ - | grep 'descriptive text'|awk -F'"' '{ print $2}') - else - check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ - | grep 'text ='|awk -F'"' '{ print $2}') - fi - debug "expecting $auth_key" - debug "${ns} gave ... $check_result" - - if [[ "$check_result" == *"$auth_key"* ]]; then - check_dns="success" - else - if [[ $ntries -lt $DNS_WAIT_COUNT ]]; then - ntries=$(( ntries + 1 )) - - if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 )) == 0 ]]; then - debug "Retrying adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" - eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" - if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then - error_exit "DNS_ADD_COMMAND failed for domain $d" - fi - - fi - info "checking DNS at ${ns} for ${lower_d}. Attempt $ntries/${DNS_WAIT_COUNT} gave wrong result, "\ - "waiting $DNS_WAIT secs before checking again" - sleep $DNS_WAIT - else - debug "dns check failed - removing existing value" - eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" - # remove $dnsfile after each loop. - rm -f "$dnsfile" - - error_exit "checking _acme-challenge.${lower_d} gave $check_result not $auth_key" - fi - fi - done - done - fi - done - - if [[ "$DNS_EXTRA_WAIT" -gt 0 && "$PREVIOUSLY_VALIDATED" != "true" ]]; then - info "sleeping $DNS_EXTRA_WAIT seconds before asking the ACME server to check the dns" - sleep "$DNS_EXTRA_WAIT" - fi - - # loop through dns-variable files to let the ACME server check the challenges - for dnsfile in "$TEMP_DIR"/dns_verify/*; do - if [[ -e "$dnsfile" ]]; then - debug "loading DNSfile: $dnsfile" - # shellcheck source=/dev/null - . "$dnsfile" - - check_challenge_completion "$uri" "$d" "$keyauthorization" - - debug "remove DNS entry" - # shellcheck disable=SC2018,SC2019 - lower_d=$(echo "$d" | tr A-Z a-z) - eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" - # remove $dnsfile after each loop. - rm -f "$dnsfile" - fi - done -fi -# end of ... perform validation if via DNS challenge -#end of varify each domain. +#end of verify each domain. } get_auth_dns() { # get the authoritative dns server for a domain (sets primary_ns ) @@ -2557,7 +2532,7 @@ if [[ ${_CHECK_ALL} -eq 1 ]]; then fi # check if $dir is a directory with a getssl.cfg in it if [[ -f "$dir/getssl.cfg" ]]; then - cmd="$cmd -w $WORKING_DIR $(basename "$dir")" + cmd="$cmd -w $WORKING_DIR \"$(basename "$dir")\"" debug "CMD: $cmd" eval "$cmd" fi @@ -2590,15 +2565,20 @@ if [[ ${_CREATE_CONFIG} -eq 1 ]]; then info "creating domain config file in $DOMAIN_DIR/getssl.cfg" # if domain has an existing cert, copy from domain and use to create defaults. EX_CERT=$(echo \ - | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:443" 2>/dev/null \ + | openssl s_client -servername "${DOMAIN##\*.}" -connect "${DOMAIN##\*.}:443" 2>/dev/null \ | openssl x509 2>/dev/null) - EX_SANS="www.${DOMAIN}" + EX_SANS="www.${DOMAIN##\*.}" if [[ -n "${EX_CERT}" ]]; then + # Putting this inside the EX_SANS line below doesn't work on Centos7 + escaped_d=${DOMAIN/\*/\\\*} EX_SANS=$(echo "$EX_CERT" \ | openssl x509 -noout -text 2>/dev/null| grep "Subject Alternative Name" -A2 \ - | grep -Eo "DNS:[a-zA-Z 0-9.-]*" | sed "s@DNS:$DOMAIN@@g" | grep -v '^$' | cut -c 5-) + | grep -Eo "DNS:[a-zA-Z 0-9.-\*]*" | sed "s@DNS:${escaped_d}@@g" | grep -v '^$' | cut -c 5-) EX_SANS=${EX_SANS//$'\n'/','} fi + if [[ -n "${EX_SANS}" ]]; then + info "Adding SANS=$EX_SANS from certificate installed on ${DOMAIN##\*.} to new configuration file" + fi write_domain_template "$DOMAIN_DIR/getssl.cfg" fi TEMP_DIR="$DOMAIN_DIR/tmp" @@ -2674,11 +2654,12 @@ fi # 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 - debug "getting certificate for $DOMAIN from remote server" + real_d=${DOMAIN##\*.} + debug "getting certificate for $DOMAIN from remote server ($real_d)" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then # shellcheck disable=SC2086 # check if openssl supports RSA-PSS - if [[ $(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS+SHA256 2>/dev/null) ]]; then + if [[ $(echo | openssl s_client -servername "${real_d}" -connect "${real_d}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS+SHA256 2>/dev/null) ]]; then CIPHER="-sigalgs RSA+SHA256:RSA+SHA384:RSA+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA512" else CIPHER="-sigalgs RSA+SHA256:RSA+SHA384:RSA+SHA512" @@ -2688,7 +2669,7 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then fi # shellcheck disable=SC2086 EX_CERT=$(echo \ - | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${CIPHER} 2>/dev/null \ + | openssl s_client -servername "${real_d}" -connect "${real_d}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${CIPHER} 2>/dev/null \ | openssl x509 2>/dev/null) if [[ -n "$EX_CERT" ]]; then # if obtained a cert if [[ -s "$CERT_FILE" ]]; then # if local exists @@ -2877,9 +2858,9 @@ info "Verify each domain" # loop through domains for cert ( from SANS list) if [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then - alldomains=${SANS//[, ]/ } + read -r -a alldomains <<< "${SANS//[, ]/ }" else - alldomains=$(echo "$DOMAIN,$SANS" | sed "s/,/ /g") + read -r -a alldomains <<< "$(echo "$DOMAIN,$SANS" | sed "s/,/ /g")" fi if [[ $API -eq 2 ]]; then @@ -2941,11 +2922,12 @@ fi # Check if the certificate is installed correctly if [[ ${CHECK_REMOTE} == "true" ]]; then + real_d=${DOMAIN##\*.} sleep "$CHECK_REMOTE_WAIT" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then # shellcheck disable=SC2086 # check if openssl supports RSA-PSS - if [[ $(echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS+SHA256 2>/dev/null) ]]; then + if [[ $(echo | openssl s_client -servername "${real_d}" -connect "${real_d}:${REMOTE_PORT}" ${REMOTE_EXTRA} -sigalgs RSA-PSS+SHA256 2>/dev/null) ]]; then PARAMS=("-sigalgs RSA-PSS+SHA256:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") else PARAMS=("-sigalgs RSA+SHA256:RSA+SHA384:RSA+SHA512" "-sigalgs ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512") @@ -2962,20 +2944,21 @@ if [[ ${CHECK_REMOTE} == "true" ]]; then for ((i=0; i<${#PARAMS[@]};++i)); do debug "Checking ${CERTS[i]}" # shellcheck disable=SC2086 + debug openssl s_client -servername "${real_d}" -connect "${real_d}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${PARAMS[i]} CERT_REMOTE=$(echo \ - | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${PARAMS[i]} 2>/dev/null \ + | openssl s_client -servername "${real_d}" -connect "${real_d}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${PARAMS[i]} 2>/dev/null \ | openssl x509 -noout -fingerprint 2>/dev/null) CERT_LOCAL=$(openssl x509 -noout -fingerprint < "${CERTS[i]}" 2>/dev/null) debug CERT_LOCAL="${CERT_LOCAL}" debug CERT_REMOTE="${CERT_REMOTE}" if [[ "$CERT_LOCAL" == "$CERT_REMOTE" ]]; then - info "${DOMAIN} - ${TYPES[i]} certificate installed OK on server" + info "${real_d} - ${TYPES[i]} certificate installed OK on server" elif [[ "$CERT_REMOTE" == "" ]]; then info "${CERTS[i]} not returned by server" - error_exit "${DOMAIN} - ${TYPES[i]} certificate obtained but not installed on server" + error_exit "${real_d} - ${TYPES[i]} certificate obtained but not installed on server" else info "${CERTS[i]} didn't match server" - error_exit "${DOMAIN} - ${TYPES[i]} certificate obtained but certificate on server is different from the new certificate" + error_exit "${real_d} - ${TYPES[i]} certificate obtained but certificate on server is different from the new certificate" fi done fi From d359059971c8868a8835f924b8beef16aa09094f Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 18 Nov 2020 21:35:55 +0000 Subject: [PATCH 134/308] Tests for wildcard changes --- test/10-mixed-case.bats | 4 +- test/14-test-revoke.bats | 4 +- test/15-test-revoke-no-suffix.bats | 4 +- test/17-test-spaces-in-sans-dns01.bats | 4 +- test/17-test-spaces-in-sans-http01.bats | 4 +- test/19-test-add-to-sans.bats | 15 ++- test/2-simple-dns01-dig.bats | 4 +- test/2-simple-dns01-nslookup.bats | 4 +- test/20-wildcard-simple.bats | 68 ++++++++++ test/21-wildcard-dual-rsa.bats | 82 ++++++++++++ ...dcard-dual-rsa-ecdsa-copy-2-locations.bats | 65 ++++++++++ test/23-wildcard-check-globbing.bats | 46 +++++++ test/24-wildcard-sans.bats | 69 ++++++++++ test/25-wildcard-all.bats | 42 ++++++ test/26-wildcard-revoke.bats | 49 +++++++ test/27-wildcard-existing-cert.bats | 45 +++++++ test/28-wildcard-error-http01-validation.bats | 31 +++++ test/README-Testing.md | 2 +- test/run-test.cmd | 1 + test/run-test.sh | 1 + ...etssl-dns01-dual-rsa-ecdsa-2-locations.cfg | 37 ++++++ test/test-config/getssl-dns01-secp384.cfg | 36 ++++++ test/test-config/getssl-dns01.cfg | 7 + test/test-config/getssl-staging-dns01.cfg | 6 +- test/test_helper.bash | 122 +++++++++--------- 25 files changed, 678 insertions(+), 74 deletions(-) create mode 100644 test/20-wildcard-simple.bats create mode 100644 test/21-wildcard-dual-rsa.bats create mode 100644 test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats create mode 100644 test/23-wildcard-check-globbing.bats create mode 100644 test/24-wildcard-sans.bats create mode 100644 test/25-wildcard-all.bats create mode 100644 test/26-wildcard-revoke.bats create mode 100644 test/27-wildcard-existing-cert.bats create mode 100644 test/28-wildcard-error-http01-validation.bats create mode 100644 test/test-config/getssl-dns01-dual-rsa-ecdsa-2-locations.cfg create mode 100644 test/test-config/getssl-dns01-secp384.cfg diff --git a/test/10-mixed-case.bats b/test/10-mixed-case.bats index 12b787c..f144058 100644 --- a/test/10-mixed-case.bats +++ b/test/10-mixed-case.bats @@ -7,7 +7,9 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi } @test "Check that HTTP-01 verification works if the domain is not lowercase" { diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats index e624552..5bdb72b 100644 --- a/test/14-test-revoke.bats +++ b/test/14-test-revoke.bats @@ -7,7 +7,9 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi } diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index 26f5f3f..5e8d797 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -7,7 +7,9 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi } diff --git a/test/17-test-spaces-in-sans-dns01.bats b/test/17-test-spaces-in-sans-dns01.bats index 75dce4b..9f3b3dc 100644 --- a/test/17-test-spaces-in-sans-dns01.bats +++ b/test/17-test-spaces-in-sans-dns01.bats @@ -7,7 +7,9 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi } diff --git a/test/17-test-spaces-in-sans-http01.bats b/test/17-test-spaces-in-sans-http01.bats index f3ba482..fab530f 100644 --- a/test/17-test-spaces-in-sans-http01.bats +++ b/test/17-test-spaces-in-sans-http01.bats @@ -7,7 +7,9 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi } diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats index 8d6f560..8ba9f20 100644 --- a/test/19-test-add-to-sans.bats +++ b/test/19-test-add-to-sans.bats @@ -7,18 +7,21 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt - curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a - curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + fi } teardown() { - curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a - curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + if [ -z "$STAGING" ]; then + curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + fi } - @test "Create certificate to check can add to SANS" { skip "FIXME: Certificate is not recreated when SANS is updated" if [ -n "$STAGING" ]; then diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index 6e1eca3..6f701b3 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -6,7 +6,9 @@ load '/getssl/test/test_helper.bash' setup() { - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi if [ -f /usr/bin/host ]; then mv /usr/bin/host /usr/bin/host.getssl.bak fi diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index d13b318..c883485 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -7,7 +7,9 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi if [ -f /usr/bin/dig ]; then mv /usr/bin/dig /usr/bin/dig.getssl.bak fi diff --git a/test/20-wildcard-simple.bats b/test/20-wildcard-simple.bats new file mode 100644 index 0000000..e9b0f98 --- /dev/null +++ b/test/20-wildcard-simple.bats @@ -0,0 +1,68 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Create wildcard certificate" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check CHECK_REMOTE works for wildcard certificates" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + run ${CODE_DIR}/getssl "*.$GETSSL_HOST" + assert_success + assert_line --partial "certificate is valid for more than" + check_output_for_errors +} + + +@test "Force renewal of wildcard certificate" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + run ${CODE_DIR}/getssl -f "*.$GETSSL_HOST" + assert_success + refute_line --partial "certificate is valid for more than" + check_output_for_errors +} + + +@test "Check renewal of near-expiration wildcard certificate" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + echo "RENEW_ALLOW=2000" >> "${INSTALL_DIR}/.getssl/*.${GETSSL_HOST}/getssl.cfg" + + run ${CODE_DIR}/getssl "*.$GETSSL_HOST" + assert_success + refute_line --partial "certificate is valid for more than" + check_output_for_errors + cleanup_environment +} diff --git a/test/21-wildcard-dual-rsa.bats b/test/21-wildcard-dual-rsa.bats new file mode 100644 index 0000000..7f0943f --- /dev/null +++ b/test/21-wildcard-dual-rsa.bats @@ -0,0 +1,82 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Create secp384r1 wildcard certificate" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +ACCOUNT_KEY_TYPE="secp384r1" +PRIVATE_KEY_ALG="secp384r1" +EOF + + create_certificate + assert_success + check_output_for_errors + run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" + assert_line --partial "Public Key Algorithm: id-ecPublicKey" + cleanup_environment +} + + +@test "Create dual certificates using DNS-01 verification" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +DUAL_RSA_ECDSA="true" +ACCOUNT_KEY_TYPE="prime256v1" +PRIVATE_KEY_ALG="prime256v1" +EOF + + check_nginx + if [ "$OLD_NGINX" = "false" ]; then + echo 'RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-dual-certs ${NGINX_CONFIG} && /getssl/test/restart-nginx"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + else + echo 'CHECK_REMOTE="false"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + fi + + create_certificate + assert_success + check_output_for_errors + check_certificates + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.ec.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.ec.crt" ] + + run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" + assert_line --partial "Public Key Algorithm: rsaEncryption" + + run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.ec.crt" + assert_line --partial "Public Key Algorithm: id-ecPublicKey" + + cleanup_environment +} diff --git a/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats new file mode 100644 index 0000000..238142e --- /dev/null +++ b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats @@ -0,0 +1,65 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +# These are run for every test, not once per file +setup() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Create dual certificates (one wildcard) and copy RSA and ECDSA chain and key to two locations" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + + setup_environment + init_getssl + + cat <<- 'EOF' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +DUAL_RSA_ECDSA="true" +ACCOUNT_KEY_TYPE="prime256v1" +PRIVATE_KEY_ALG="prime256v1" +DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key;/root/a.${GETSSL_HOST}/server.key" +DOMAIN_CHAIN_LOCATION="/etc/nginx/pki/domain-chain.crt;/root/a.${GETSSL_HOST}/domain-chain.crt" # this is the domain cert and CA cert +EOF + + check_nginx + if [ "$OLD_NGINX" = "false" ]; then + echo 'RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-dual-certs ${NGINX_CONFIG} && /getssl/test/restart-nginx"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + else + echo 'CHECK_REMOTE="false"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + fi + + create_certificate + assert_success + check_output_for_errors + + if [ "$OLD_NGINX" = "false" ]; then + assert_line --partial "rsa certificate installed OK on server" + assert_line --partial "prime256v1 certificate installed OK on server" + fi + + # Check that the RSA chain and key have been copied to both locations + assert [ -e "/etc/nginx/pki/domain-chain.crt" ] + assert [ -e "/root/a.${GETSSL_HOST}/domain-chain.crt" ] + assert [ -e "/etc/nginx/pki/private/server.key" ] + assert [ -e "/root/a.${GETSSL_HOST}/server.key" ] + + # Check that the ECDSA chain and key have been copied to both locations + assert [ -e "/etc/nginx/pki/domain-chain.ec.crt" ] + assert [ -e "/root/a.${GETSSL_HOST}/domain-chain.ec.crt" ] + assert [ -e "/etc/nginx/pki/private/server.ec.key" ] + assert [ -e "/root/a.${GETSSL_HOST}/server.ec.key" ] + + cleanup_environment +} diff --git a/test/23-wildcard-check-globbing.bats b/test/23-wildcard-check-globbing.bats new file mode 100644 index 0000000..1c812b1 --- /dev/null +++ b/test/23-wildcard-check-globbing.bats @@ -0,0 +1,46 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Check for globbing for wildcard domains" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + setup_environment + + init_getssl + + # Create a directory in /root which looks like a domain so that if glob expansion is performed a certificate for the wrong domain will be created + mkdir -p "${INSTALL_DIR}/a.${GETSSL_HOST}" + + create_certificate + assert_success + check_output_for_errors +} + + +@test "Force renewal of wildcard certificate" { + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + fi + + run ${CODE_DIR}/getssl -f "*.$GETSSL_HOST" + assert_success + refute_line --partial "certificate is valid for more than" + check_output_for_errors +} diff --git a/test/24-wildcard-sans.bats b/test/24-wildcard-sans.bats new file mode 100644 index 0000000..6e463c8 --- /dev/null +++ b/test/24-wildcard-sans.bats @@ -0,0 +1,69 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + curl --silent -X POST -d '{"host":"wild-'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + fi +} + + +teardown() { + if [ -z "$STAGING" ]; then + curl --silent -X POST -d '{"host":"wild-'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + fi +} + + +@test "Check can create certificate for wildcard domain as arg and non-wildcard in SANS" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + # Staging server generates an error if try to create a certificate for *.domain and a.domain + # so create for *.wild-domain and a.domain instead + GETSSL_CMD_HOST="*.wild-${GETSSL_HOST}" + setup_environment + init_getssl + + echo 'SANS="${GETSSL_HOST}"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + + create_certificate + assert_success + check_output_for_errors + run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" + # verify certificate is for wildcard domain with non-wildcard domain in the Subject Alternative Name list + assert_output --regexp "Subject: CN[ ]?=[ ]?\*.wild-${GETSSL_HOST}" + assert_output --partial "DNS:${GETSSL_HOST}" +} + + +@test "Check can create certificate for non-wildcard domain as arg and wildcard in SANS" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + GETSSL_CMD_HOST="${GETSSL_HOST}" + setup_environment + init_getssl + + echo 'SANS="*.wild-${GETSSL_HOST}"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + + create_certificate + assert_success + check_output_for_errors + run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" + # verify certificate is for non-wildcard domain with wildcard domain in the Subject Alternative Name list + assert_output --regexp "Subject: CN[ ]?=[ ]?${GETSSL_HOST}" + assert_output --partial "DNS:*.wild-${GETSSL_HOST}" +} diff --git a/test/25-wildcard-all.bats b/test/25-wildcard-all.bats new file mode 100644 index 0000000..8e428ab --- /dev/null +++ b/test/25-wildcard-all.bats @@ -0,0 +1,42 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Check can create certificate for wildcard domain using --all" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + setup_environment + # Create .getssl directory and .getssl/*.{host} directory + init_getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/*.${GETSSL_HOST}/getssl.cfg" + + # create another domain in the .getssl directory + run ${CODE_DIR}/getssl -c "a.${GETSSL_HOST}" + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/a.${GETSSL_HOST}/getssl.cfg" + + # Create a directory in /root which looks like a domain so that if glob expansion is performed the wildcard certificate won't be created + mkdir -p "${INSTALL_DIR}/a.${GETSSL_HOST}" + + run ${CODE_DIR}/getssl --all + + assert_success + assert_line --partial "Certificate saved in /root/.getssl/*.${GETSSL_HOST}/*.${GETSSL_HOST}" + assert_line --partial "Certificate saved in /root/.getssl/a.${GETSSL_HOST}/a.${GETSSL_HOST}" + check_output_for_errors +} diff --git a/test/26-wildcard-revoke.bats b/test/26-wildcard-revoke.bats new file mode 100644 index 0000000..1416ef4 --- /dev/null +++ b/test/26-wildcard-revoke.bats @@ -0,0 +1,49 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Create certificate to check wildcard revoke" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check we can revoke a wildcard certificate" { + if [ -n "$STAGING" ]; then + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key + + run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA + assert_line "certificate revoked" + assert_success + check_output_for_errors "debug" +} diff --git a/test/27-wildcard-existing-cert.bats b/test/27-wildcard-existing-cert.bats new file mode 100644 index 0000000..76f2aa7 --- /dev/null +++ b/test/27-wildcard-existing-cert.bats @@ -0,0 +1,45 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Check that new creating a new configuration files uses details from existing certificate" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + else + CONFIG_FILE="getssl-dns01.cfg" + fi + + # Create and install certificate for wildcard + another domain + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + setup_environment + init_getssl + + echo 'SANS="a.${GETSSL_HOST}"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + + create_certificate + assert_success + check_output_for_errors + + # Delete configuration + rm -r ${INSTALL_DIR}/.getssl + + # Create configuration + run ${CODE_DIR}/getssl -c "${GETSSL_CMD_HOST}" + + # Assert that the newly created configuration contains the additional domain in SANS + # if this fails then error in tests will be "grep failed" - this means SANS did not hold the expected value + # eg SANS="a.centos7.getssl.test" + grep -q "SANS=\"a.${GETSSL_HOST}\"" ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg + assert_success +} diff --git a/test/28-wildcard-error-http01-validation.bats b/test/28-wildcard-error-http01-validation.bats new file mode 100644 index 0000000..dbb64b7 --- /dev/null +++ b/test/28-wildcard-error-http01-validation.bats @@ -0,0 +1,31 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Check that trying to create a wildcard certificate using http-01 validation shows an error message" { + if [ -n "$STAGING" ]; then + skip "Internal test, no need to test on staging server" + else + CONFIG_FILE="getssl-http01.cfg" + fi + + # Try and create a wildcard certificate using http-01 validation + GETSSL_CMD_HOST="*.${GETSSL_HOST}" + setup_environment + init_getssl + + create_certificate + assert_failure + assert_line --partial "cannot use http-01 validation for wildcard domains" +} diff --git a/test/README-Testing.md b/test/README-Testing.md index 3cd4b2c..d713914 100644 --- a/test/README-Testing.md +++ b/test/README-Testing.md @@ -8,7 +8,7 @@ For continuous integration testing we have the following: 1. Uses `docker-compose` to start `pebble` (letsencrypt test server) and `challtestsrv` (minimal dns client for pebble) 2. Then runs the `bats` test scripts (all the files with a ".bats" extension) for each OS (alpine, centos6, debian, ubuntu) -3. Runs the `bats` test script against the staging server (using nn ubuntu docker image and duckdns.org) +3. Runs the `bats` test script against the staging server (using ubuntu docker image and duckdns.org) ## To run all the tests on a single OS diff --git a/test/run-test.cmd b/test/run-test.cmd index 43c4e40..23235c9 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -49,6 +49,7 @@ docker run -it ^ --network-alias i.%OS%.getssl.test ^ --network-alias j.%OS%.getssl.test ^ --network-alias k.%OS%.getssl.test ^ + --network-alias wild-%ALIAS% ^ --name getssl-%OS% ^ getssl-%OS% ^ %COMMAND% diff --git a/test/run-test.sh b/test/run-test.sh index d99d5a3..8a2a9f2 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -42,6 +42,7 @@ docker run \ --network-alias "i.$OS.getssl.test" \ --network-alias "j.$OS.getssl.test" \ --network-alias "k.$OS.getssl.test" \ + --network-alias "wild-$OS.getssl.test" \ --name "getssl-$OS" \ "getssl-$OS" \ $COMMAND diff --git a/test/test-config/getssl-dns01-dual-rsa-ecdsa-2-locations.cfg b/test/test-config/getssl-dns01-dual-rsa-ecdsa-2-locations.cfg new file mode 100644 index 0000000..829e73c --- /dev/null +++ b/test/test-config/getssl-dns01-dual-rsa-ecdsa-2-locations.cfg @@ -0,0 +1,37 @@ +# Test that more than one location can be specified for CERT and KEY locations and that the +# files are copied to both locations when both RSA and ECDSA certificates are created +# +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 + +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_EXTRA_WAIT=0 + +DUAL_RSA_ECDSA="true" +ACCOUNT_KEY_TYPE="prime256v1" +PRIVATE_KEY_ALG="prime256v1" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="" +# SANS="a.${GETSSL_HOST}" + +# 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;/root/a.${GETSSL_HOST}/server.key" +CA_CERT_LOCATION="/etc/nginx/pki/chain.crt" +DOMAIN_CHAIN_LOCATION="/etc/nginx/pki/domain-chain.crt;/root/a.${GETSSL_HOST}/domain-chain.crt" # 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-dual-certs ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" diff --git a/test/test-config/getssl-dns01-secp384.cfg b/test/test-config/getssl-dns01-secp384.cfg new file mode 100644 index 0000000..2cc360c --- /dev/null +++ b/test/test-config/getssl-dns01-secp384.cfg @@ -0,0 +1,36 @@ +# 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" + +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 + +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_EXTRA_WAIT=0 + +ACCOUNT_KEY_TYPE="secp384r1" +PRIVATE_KEY_ALG="secp384r1" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="" + +# 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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" diff --git a/test/test-config/getssl-dns01.cfg b/test/test-config/getssl-dns01.cfg index e995c80..c67f995 100644 --- a/test/test-config/getssl-dns01.cfg +++ b/test/test-config/getssl-dns01.cfg @@ -31,3 +31,10 @@ RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /get # Define the server type and confirm correct certificate is installed SERVER_TYPE="https" CHECK_REMOTE="true" + +#_USE_DEBUG=1 +#_RUNNING_TEST=1 + +if [[ -s "$DOMAIN_DIR/getssl_test_specific.cfg" ]]; then + . $DOMAIN_DIR/getssl_test_specific.cfg +fi diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 910c7fe..905c44d 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -31,6 +31,10 @@ 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} && /getssl/test/restart-nginx" -# Define the server type and confirm correct certificate is installed (using a custom port) +# Define the server type and confirm correct certificate is installed SERVER_TYPE="https" CHECK_REMOTE="true" + +if [[ -s "$DOMAIN_DIR/getssl_test_specific.cfg" ]]; then + . $DOMAIN_DIR/getssl_test_specific.cfg +fi diff --git a/test/test_helper.bash b/test/test_helper.bash index db79ea4..c5d5320 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -3,99 +3,103 @@ CODE_DIR=/getssl check_certificates() { - assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.crt" ] - assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" ] - assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" ] } # Only nginx > 1.11.0 support dual certificates in a single configuration file # https://unix.stackexchange.com/questions/285924/how-to-compare-a-programs-version-in-a-shell-script check_nginx() { - requiredver="1.11.0" - currentver=$(nginx -v 2>&1 | awk -F"/" '{print $2}') - if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then - export OLD_NGINX="false" - else - echo "INFO: Running nginx version $currentver which doesn't support dual certificates" >&3 - echo "INFO: not checking that certificate is installed correctly" >&3 - export OLD_NGINX="true" - fi + requiredver="1.11.0" + currentver=$(nginx -v 2>&1 | awk -F"/" '{print $2}') + if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then + export OLD_NGINX="false" + else + echo "INFO: Running nginx version $currentver which doesn't support dual certificates" >&3 + echo "INFO: not checking that certificate is installed correctly" >&3 + export OLD_NGINX="true" + fi } check_output_for_errors() { - refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - # less strict tests if running with debug output - if [ -n "$1" ]; then - # don't fail for :error:badNonce - refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - # don't check for "Warnings:" as there might be a warning message if nslookup doesn't support -debug (alpine/ubuntu) - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' - else - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' - fi - refute_line --partial 'command not found' + refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' + # less strict tests if running with debug output + if [ -n "$1" ]; then + # don't fail for :error:badNonce + refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' + # don't check for "Warnings:" as there might be a warning message if nslookup doesn't support -debug (alpine/ubuntu) + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' + else + refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' + fi + refute_line --partial 'command not found' } cleanup_environment() { + if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"'"$GETSSL_HOST"'"}' http://10.30.50.3:8055/clear-a + fi } create_certificate() { - # Create certificate - cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" - # shellcheck disable=SC2086 - run ${CODE_DIR}/getssl $1 "$GETSSL_CMD_HOST" + # Create certificate + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + # shellcheck disable=SC2086 + run ${CODE_DIR}/getssl $1 "$GETSSL_CMD_HOST" } init_getssl() { - # Run initialisation (create account key, etc) - run ${CODE_DIR}/getssl -c "$GETSSL_CMD_HOST" - assert_success - [ -d "$INSTALL_DIR/.getssl" ] + # Run initialisation (create account key, etc) + run ${CODE_DIR}/getssl -c "$GETSSL_CMD_HOST" + assert_success + [ -d "$INSTALL_DIR/.getssl" ] } setup_environment() { - # One-off test setup - if [[ -d ${INSTALL_DIR}/.getssl ]]; then - rm -r ${INSTALL_DIR}/.getssl - fi + # One-off test setup + if [[ -d ${INSTALL_DIR}/.getssl ]]; then + rm -r ${INSTALL_DIR}/.getssl + fi + if [ -z "$STAGING" ]; then curl --silent -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}" - /getssl/test/restart-nginx + fi + cp ${CODE_DIR}/test/test-config/nginx-ubuntu-no-ssl "${NGINX_CONFIG}" + /getssl/test/restart-nginx } # start nginx in background on alpine via supervisord # shellcheck disable=SC2153 # Ignore GETSSL_OS looks like typo of GETSSL_IP if [[ -f /usr/bin/supervisord && -f /etc/supervisord.conf ]]; then - if [[ ! $(pgrep supervisord) ]]; then - /usr/bin/supervisord -c /etc/supervisord.conf >&3- - fi + if [[ ! $(pgrep supervisord) ]]; then + /usr/bin/supervisord -c /etc/supervisord.conf >&3- + fi elif [[ "$GETSSL_OS" == "centos"[78] ]]; then - if [ -z "$(pgrep nginx)" ]; then - nginx >&3- - fi + if [ -z "$(pgrep nginx)" ]; then + nginx >&3- + fi fi # Find NGINX configuration directory for HTTP-01 testing (need to add SSL to config) if [[ -f /etc/nginx/conf.d/default.conf ]]; then - export NGINX_CONFIG=/etc/nginx/conf.d/default.conf + export NGINX_CONFIG=/etc/nginx/conf.d/default.conf elif [[ -f /etc/nginx/sites-enabled/default ]]; then - export NGINX_CONFIG=/etc/nginx/sites-enabled/default + export NGINX_CONFIG=/etc/nginx/sites-enabled/default else - echo "Can't find NGINX directory" - exit 1 + echo "Can't find NGINX directory" + exit 1 fi # Find IP address if [[ -n "$(command -v ip)" ]]; then - GETSSL_IP=$(ip address | awk '/10.30.50/ { print $2 }' | awk -F/ '{ print $1 }') + GETSSL_IP=$(ip address | awk '/10.30.50/ { print $2 }' | awk -F/ '{ print $1 }') elif [[ -n "$(command -v hostname)" ]]; then - GETSSL_IP=$(hostname -I | sed -e 's/[[:space:]]*$//') + GETSSL_IP=$(hostname -I | sed -e 's/[[:space:]]*$//') else - echo "Cannot find IP address" - exit 1 + echo "Cannot find IP address" + exit 1 fi export GETSSL_IP @@ -103,11 +107,11 @@ export GETSSL_IP GETSSL_CMD_HOST=$GETSSL_HOST export GETSSL_CMD_HOST -if [ ! -f ${INSTALL_DIR}/pebble.minica.pem ]; then - wget --quiet --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 +if [ -z "$STAGING" ] && [ ! -f ${INSTALL_DIR}/pebble.minica.pem ]; then + wget --quiet --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 From 36f9b1912b96ea1b2ca2ec22d7e2c81ddb248bfc Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 18 Nov 2020 21:36:19 +0000 Subject: [PATCH 135/308] Hardcode bats release to avoid test fragility --- test/Dockerfile-alpine | 2 +- test/Dockerfile-centos6 | 2 +- test/Dockerfile-centos7 | 2 +- test/Dockerfile-centos7-staging | 2 +- test/Dockerfile-centos8 | 2 +- test/Dockerfile-debian | 2 +- test/Dockerfile-ubuntu | 3 +-- test/Dockerfile-ubuntu-staging | 2 +- test/Dockerfile-ubuntu16 | 2 +- test/Dockerfile-ubuntu18 | 2 +- 10 files changed, 10 insertions(+), 11 deletions(-) diff --git a/test/Dockerfile-alpine b/test/Dockerfile-alpine index e0f3a6c..b609938 100644 --- a/test/Dockerfile-alpine +++ b/test/Dockerfile-alpine @@ -12,7 +12,7 @@ RUN mkdir /etc/nginx/pki RUN mkdir /etc/nginx/pki/private # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index 862e680..d578f4b 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -16,7 +16,7 @@ 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/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-centos7 b/test/Dockerfile-centos7 index afbcf23..e86f521 100644 --- a/test/Dockerfile-centos7 +++ b/test/Dockerfile-centos7 @@ -12,7 +12,7 @@ COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-centos7-staging b/test/Dockerfile-centos7-staging index a539cac..0b2ff08 100644 --- a/test/Dockerfile-centos7-staging +++ b/test/Dockerfile-centos7-staging @@ -17,7 +17,7 @@ COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-centos8 b/test/Dockerfile-centos8 index 15c14d6..4ccb817 100644 --- a/test/Dockerfile-centos8 +++ b/test/Dockerfile-centos8 @@ -14,7 +14,7 @@ COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-debian b/test/Dockerfile-debian index d066813..b39f915 100644 --- a/test/Dockerfile-debian +++ b/test/Dockerfile-debian @@ -11,7 +11,7 @@ RUN mkdir /etc/nginx/pki RUN mkdir /etc/nginx/pki/private # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index 2ef9e25..3849e55 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -9,7 +9,6 @@ ENV DEBIAN_FRONTEND noninteractive RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light RUN apt-get install -y vim dos2unix # for debugging -# TODO test with drill, dig, host WORKDIR /root @@ -17,7 +16,7 @@ WORKDIR /root RUN touch /root/.rnd # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-staging index 05f0471..1ee3f83 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-staging @@ -20,7 +20,7 @@ WORKDIR /root RUN touch /root/.rnd # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-ubuntu16 b/test/Dockerfile-ubuntu16 index ba6164c..41be837 100644 --- a/test/Dockerfile-ubuntu16 +++ b/test/Dockerfile-ubuntu16 @@ -13,7 +13,7 @@ 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 /bats-core +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-ubuntu18 b/test/Dockerfile-ubuntu18 index 1735646..5e4c574 100644 --- a/test/Dockerfile-ubuntu18 +++ b/test/Dockerfile-ubuntu18 @@ -16,7 +16,7 @@ COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default RUN touch /root/.rnd # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local From ccab4baeb6763c7a8db6375de4d9593c05b1f14c Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 18 Nov 2020 21:47:12 +0000 Subject: [PATCH 136/308] Update revision history --- getssl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/getssl b/getssl index f62174e..be7f2bc 100755 --- a/getssl +++ b/getssl @@ -240,6 +240,8 @@ # 2020-09-02 Fix issue when SANS is space and comma separated (#579) (2.30) # 2020-10-02 Various fixes to get_auth_dns and changes to support unit tests (#308) # 2020-10-04 Add CHECK_PUBLIC_DNS_SERVER to check the DNS challenge has been updated there +# 2020-10-13 Bugfix: strip comments in drill/dig output (mhameed) +# 2020-11-18 Wildcard support (#347)(#400) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} @@ -2945,6 +2947,7 @@ if [[ ${CHECK_REMOTE} == "true" ]]; then debug "Checking ${CERTS[i]}" # shellcheck disable=SC2086 debug openssl s_client -servername "${real_d}" -connect "${real_d}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${PARAMS[i]} + # shellcheck disable=SC2086 CERT_REMOTE=$(echo \ | openssl s_client -servername "${real_d}" -connect "${real_d}:${REMOTE_PORT}" ${REMOTE_EXTRA} ${PARAMS[i]} 2>/dev/null \ | openssl x509 -noout -fingerprint 2>/dev/null) From 5677a13fd59f6cc4e1c749a33a405365b2c5cee1 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 19 Nov 2020 14:55:25 +0000 Subject: [PATCH 137/308] Don't check certificate is installed when testing against staging server --- test/24-wildcard-sans.bats | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/24-wildcard-sans.bats b/test/24-wildcard-sans.bats index 6e463c8..da5fea9 100644 --- a/test/24-wildcard-sans.bats +++ b/test/24-wildcard-sans.bats @@ -35,6 +35,9 @@ teardown() { init_getssl echo 'SANS="${GETSSL_HOST}"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + if [ -n "$STAGING" ]; then + echo 'CHECK_REMOTE="false"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + fi create_certificate assert_success From 60bda5a3d466aef8665825c835bbcedab7848c47 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Mon, 23 Nov 2020 22:50:00 +0800 Subject: [PATCH 138/308] Improve README.md code block readability by correct syntax highlight --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 12eaf66..7803ef8 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ command line). Within the **working directory** is a config file `getssl.cfg` which is a simple bash file containing variables, an example of which is: -```getssl +```sh # Uncomment and modify any variables you need # The staging server is best for testing (hence set as default) CA="https://acme-staging-v02.api.letsencrypt.org" @@ -200,7 +200,7 @@ then, within the **working directory** there will be a folder for each certificate (based on its domain name). Within that folder will be a config file (again called `getssl.cfg`). An example of which is: -```getssl +```sh # 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 @@ -270,7 +270,7 @@ Multiple locations can be defined for a file by separating the locations with a A typical config file for `example.com` and `www.example.com` on the same server would be: -```getssl +```sh # uncomment and modify any variables you need # The staging server is best for testing CA="https://acme-staging-v02.api.letsencrypt.org" From 9a3dc5c553992b3772810122305d214ef8dac75a Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Tue, 24 Nov 2020 22:56:55 +0800 Subject: [PATCH 139/308] Remove deprecated Travis CI config Looks like getssl was not using Travis CI for a while: https://travis-ci.org/github/srvrco/getssl And the GitHub Actions was introduced for a while: https://github.com/srvrco/getssl/commits/master/.github/workflows Remove Travis CI config in the repository will help contributor reduce the confusion about which CI platform is currently using. --- .travis.yml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 867a6d2..0000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: bash - -# Use container-based infrastructure for quicker build start-up -sudo: false - -addons: - apt: - sources: - - debian-sid # Grab shellcheck from the Debian repo (o_O) - packages: - - shellcheck - -script: - - bash -c 'shopt -s globstar; shellcheck getssl' - -matrix: - fast_finish: true From f361492fae1461adb083b910dc1d766da10294a8 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Wed, 25 Nov 2020 03:43:45 +0800 Subject: [PATCH 140/308] Add "Table of Contents" in README.md --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 7803ef8..14878a5 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,19 @@ Obtain SSL certificates from the letsencrypt.org ACME server. Suitable for automating the process on remote servers. +## Table of Contents + +- [Features](#features) +- [Installation](#installation) +- [Overview](#overview) +- [Getting started](#getting-started) +- [Automating updates](#automating-updates) +- [Structure](#structure) +- [Server-Types](#server-types) +- [Revoke a certificate](#revoke-a-certificate) +- [Elliptic curve keys](#elliptic-curve-keys) +- [Issues / problems / help](#issues--problems--help) + ## Features * **Bash** - It runs on virtually all unix machines, including BSD, most From 970004eda76b9bdaa137bac21d7b50274bc729d5 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Wed, 25 Nov 2020 03:45:07 +0800 Subject: [PATCH 141/308] Correct Makefile indentation in .editorconfig --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 91d16ec..5abccad 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,6 @@ end_of_line = lf insert_final_newline = true indent_style = space indent_size = 2 + +[Makefile] +indent_style = tab From 7ed9a01314862fd1026e9a75b3ff1d49a5b0fcab Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Wed, 25 Nov 2020 03:52:14 +0800 Subject: [PATCH 142/308] Follow EditorConfig, use consistent space indent in Nginx test configs --- test/test-config/nginx-ubuntu-dual-certs | 104 +++++++++++------------ test/test-config/nginx-ubuntu-no-ssl | 36 ++++---- test/test-config/nginx-ubuntu-ssl | 104 +++++++++++------------ 3 files changed, 122 insertions(+), 122 deletions(-) diff --git a/test/test-config/nginx-ubuntu-dual-certs b/test/test-config/nginx-ubuntu-dual-certs index 1eceecd..b8f4bcc 100644 --- a/test/test-config/nginx-ubuntu-dual-certs +++ b/test/test-config/nginx-ubuntu-dual-certs @@ -14,66 +14,66 @@ # Default server configuration # server { - listen 80 default_server; - listen 5002 default_server; - listen [::]:5002 default_server; + listen 80 default_server; + listen 5002 default_server; + listen [::]:5002 default_server; - # SSL configuration - # + # SSL configuration + # listen 443 ssl default_server; - 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; + 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; + root /var/www/html; - # Add index.php to the list if you are using PHP - index index.html index.htm index.nginx-debian.html; + # Add index.php to the list if you are using PHP + index index.html index.htm index.nginx-debian.html; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - server_name _; + server_name _; ssl_certificate /etc/nginx/pki/server.crt; ssl_certificate_key /etc/nginx/pki/private/server.key; ssl_certificate /etc/nginx/pki/server.ec.crt; ssl_certificate_key /etc/nginx/pki/private/server.ec.key; - location / { - # First attempt to serve request as file, then - # as directory, then fall back to displaying a 404. - try_files $uri $uri/ =404; - } + 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; - #} + # 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; - #} + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} } @@ -83,15 +83,15 @@ server { # to sites-enabled/ to enable it. # #server { -# listen 80; -# listen [::]:80; +# listen 80; +# listen [::]:80; # -# server_name example.com; +# server_name example.com; # -# root /var/www/example.com; -# index index.html; +# root /var/www/example.com; +# index index.html; # -# location / { -# try_files $uri $uri/ =404; -# } +# location / { +# try_files $uri $uri/ =404; +# } #} diff --git a/test/test-config/nginx-ubuntu-no-ssl b/test/test-config/nginx-ubuntu-no-ssl index e7b046e..8dc55ff 100644 --- a/test/test-config/nginx-ubuntu-no-ssl +++ b/test/test-config/nginx-ubuntu-no-ssl @@ -1,30 +1,30 @@ # Default server configuration # server { - listen 80 default_server; - listen 5002 default_server; - listen [::]:5002 default_server; + listen 80 default_server; + listen 5002 default_server; + listen [::]:5002 default_server; - # SSL configuration - # - listen 443 default_server; - listen [::]:443 default_server; + # SSL configuration + # + listen 443 default_server; + listen [::]:443 default_server; - listen 5001 default_server; - listen [::]:5001 default_server; + listen 5001 default_server; + listen [::]:5001 default_server; - root /var/www/html; + root /var/www/html; - # Add index.php to the list if you are using PHP - index index.html index.htm index.nginx-debian.html; + # Add index.php to the list if you are using PHP + index index.html index.htm index.nginx-debian.html; - server_name _; + 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; - } + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } } diff --git a/test/test-config/nginx-ubuntu-ssl b/test/test-config/nginx-ubuntu-ssl index 9f79407..882b36a 100644 --- a/test/test-config/nginx-ubuntu-ssl +++ b/test/test-config/nginx-ubuntu-ssl @@ -14,61 +14,61 @@ # Default server configuration # server { - listen 80 default_server; - listen 5002 default_server; - listen [::]:5002 default_server; + listen 80 default_server; + listen 5002 default_server; + listen [::]:5002 default_server; - # SSL configuration - # + # SSL configuration + # listen 443 ssl default_server; - 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; + 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; + root /var/www/html; - # Add index.php to the list if you are using PHP - index index.html index.htm index.nginx-debian.html; + # Add index.php to the list if you are using PHP + index index.html index.htm index.nginx-debian.html; - server_name _; + 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; - } + 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; - #} + # 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; - #} + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} } @@ -78,15 +78,15 @@ server { # to sites-enabled/ to enable it. # #server { -# listen 80; -# listen [::]:80; +# listen 80; +# listen [::]:80; # -# server_name example.com; +# server_name example.com; # -# root /var/www/example.com; -# index index.html; +# root /var/www/example.com; +# index index.html; # -# location / { -# try_files $uri $uri/ =404; -# } +# location / { +# try_files $uri $uri/ =404; +# } #} From 1c617c1bf68389d84bbb192c986ae1eee1b5d821 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Wed, 25 Nov 2020 04:02:02 +0800 Subject: [PATCH 143/308] Make markdownlint happy about README.md ``` README.md:1 MD041/first-line-heading/first-line-h1 First line in file should be a top level heading [Context: "![Run all tests](https://githu..."] README.md:2 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Above] [Context: "# getssl"] ``` --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7803ef8..e5441d9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -![Run all tests](https://github.com/srvrco/getssl/workflows/Run%20all%20tests/badge.svg) ![shellcheck](https://github.com/srvrco/getssl/workflows/shellcheck/badge.svg) # getssl +![Run all tests](https://github.com/srvrco/getssl/workflows/Run%20all%20tests/badge.svg) ![shellcheck](https://github.com/srvrco/getssl/workflows/shellcheck/badge.svg) + Obtain SSL certificates from the letsencrypt.org ACME server. Suitable for automating the process on remote servers. From 9fec3b445c291e91d3b8d2ddd72be5e85ffc4a6c Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Wed, 25 Nov 2020 03:55:33 +0800 Subject: [PATCH 144/308] Fix indentation to two spaces in other_scripts/cpanel_cert_upload --- other_scripts/cpanel_cert_upload | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/other_scripts/cpanel_cert_upload b/other_scripts/cpanel_cert_upload index a76181b..757504f 100755 --- a/other_scripts/cpanel_cert_upload +++ b/other_scripts/cpanel_cert_upload @@ -14,12 +14,12 @@ rawurlencode() { local pos c o for (( pos=0 ; pos Date: Fri, 27 Nov 2020 14:01:41 +0800 Subject: [PATCH 145/308] Reduce git clone depth in the Dockerfile for test This change will drop the history of the repository when cloning, which will save bandwidth and disk space, speed up the clone and checkout process during the test and Docker build process. --- test/Dockerfile-alpine | 6 +++--- test/Dockerfile-centos6 | 6 +++--- test/Dockerfile-centos7 | 6 +++--- test/Dockerfile-centos7-staging | 6 +++--- test/Dockerfile-centos8 | 6 +++--- test/Dockerfile-debian | 6 +++--- test/Dockerfile-ubuntu | 6 +++--- test/Dockerfile-ubuntu-staging | 6 +++--- test/Dockerfile-ubuntu16 | 6 +++--- test/Dockerfile-ubuntu18 | 6 +++--- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/test/Dockerfile-alpine b/test/Dockerfile-alpine index b609938..7728c8c 100644 --- a/test/Dockerfile-alpine +++ b/test/Dockerfile-alpine @@ -12,9 +12,9 @@ RUN mkdir /etc/nginx/pki RUN mkdir /etc/nginx/pki/private # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Use supervisord to run nginx in the background diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index d578f4b..6db7a74 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -16,9 +16,9 @@ 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 --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local EXPOSE 80 443 diff --git a/test/Dockerfile-centos7 b/test/Dockerfile-centos7 index e86f521..620a9c6 100644 --- a/test/Dockerfile-centos7 +++ b/test/Dockerfile-centos7 @@ -12,7 +12,7 @@ COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-centos7-staging b/test/Dockerfile-centos7-staging index 0b2ff08..9fdb29d 100644 --- a/test/Dockerfile-centos7-staging +++ b/test/Dockerfile-centos7-staging @@ -17,9 +17,9 @@ COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local EXPOSE 80 443 diff --git a/test/Dockerfile-centos8 b/test/Dockerfile-centos8 index 4ccb817..9c144d3 100644 --- a/test/Dockerfile-centos8 +++ b/test/Dockerfile-centos8 @@ -14,7 +14,7 @@ COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local diff --git a/test/Dockerfile-debian b/test/Dockerfile-debian index b39f915..2cf919d 100644 --- a/test/Dockerfile-debian +++ b/test/Dockerfile-debian @@ -11,9 +11,9 @@ RUN mkdir /etc/nginx/pki RUN mkdir /etc/nginx/pki/private # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index 3849e55..21169ea 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -16,9 +16,9 @@ WORKDIR /root RUN touch /root/.rnd # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-staging index 1ee3f83..15d5a59 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-staging @@ -20,9 +20,9 @@ WORKDIR /root RUN touch /root/.rnd # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing diff --git a/test/Dockerfile-ubuntu16 b/test/Dockerfile-ubuntu16 index 41be837..038fd79 100644 --- a/test/Dockerfile-ubuntu16 +++ b/test/Dockerfile-ubuntu16 @@ -13,9 +13,9 @@ 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 /bats-core --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing diff --git a/test/Dockerfile-ubuntu18 b/test/Dockerfile-ubuntu18 index 5e4c574..01d33d0 100644 --- a/test/Dockerfile-ubuntu18 +++ b/test/Dockerfile-ubuntu18 @@ -16,9 +16,9 @@ COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default RUN touch /root/.rnd # BATS (Bash Automated Testings) -RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 -RUN git clone https://github.com/bats-core/bats-support /bats-support -RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local EXPOSE 80 443 From 6a6851e185f0336c95aeb4b5d46b567fbc187e32 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Thu, 26 Nov 2020 12:04:48 +0800 Subject: [PATCH 146/308] Reduce Docker image layer by merging mkdir operation --- test/Dockerfile-alpine | 3 +-- test/Dockerfile-centos6 | 3 +-- test/Dockerfile-centos7 | 3 +-- test/Dockerfile-centos7-staging | 3 +-- test/Dockerfile-centos8 | 3 +-- test/Dockerfile-debian | 3 +-- test/Dockerfile-ubuntu16 | 3 +-- test/Dockerfile-ubuntu18 | 3 +-- 8 files changed, 8 insertions(+), 16 deletions(-) diff --git a/test/Dockerfile-alpine b/test/Dockerfile-alpine index 7728c8c..5b1dbf3 100644 --- a/test/Dockerfile-alpine +++ b/test/Dockerfile-alpine @@ -8,8 +8,7 @@ WORKDIR /root # Create nginx directories in standard places RUN mkdir /run/nginx -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /etc/nginx/pki/private # BATS (Bash Automated Testings) RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index 6db7a74..108add0 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -11,8 +11,7 @@ RUN yum -y install epel-release RUN yum -y install git curl dnsutils ldns wget nginx WORKDIR /root -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf # BATS (Bash Automated Testings) diff --git a/test/Dockerfile-centos7 b/test/Dockerfile-centos7 index 620a9c6..382a703 100644 --- a/test/Dockerfile-centos7 +++ b/test/Dockerfile-centos7 @@ -6,8 +6,7 @@ RUN yum -y install epel-release RUN yum -y install git curl ldns bind-utils wget which nginx WORKDIR /root -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf diff --git a/test/Dockerfile-centos7-staging b/test/Dockerfile-centos7-staging index 9fdb29d..abb697c 100644 --- a/test/Dockerfile-centos7-staging +++ b/test/Dockerfile-centos7-staging @@ -11,8 +11,7 @@ ENV staging "true" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb WORKDIR /root -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf diff --git a/test/Dockerfile-centos8 b/test/Dockerfile-centos8 index 9c144d3..2b20d8f 100644 --- a/test/Dockerfile-centos8 +++ b/test/Dockerfile-centos8 @@ -8,8 +8,7 @@ RUN yum -y install epel-release RUN yum -y install git curl bind-utils wget which nginx WORKDIR /root -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf diff --git a/test/Dockerfile-debian b/test/Dockerfile-debian index 2cf919d..6da08d5 100644 --- a/test/Dockerfile-debian +++ b/test/Dockerfile-debian @@ -7,8 +7,7 @@ RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light WORKDIR /root -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /etc/nginx/pki/private # BATS (Bash Automated Testings) RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 diff --git a/test/Dockerfile-ubuntu16 b/test/Dockerfile-ubuntu16 index 038fd79..6b13f68 100644 --- a/test/Dockerfile-ubuntu16 +++ b/test/Dockerfile-ubuntu16 @@ -8,8 +8,7 @@ RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light WORKDIR /root -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default # BATS (Bash Automated Testings) diff --git a/test/Dockerfile-ubuntu18 b/test/Dockerfile-ubuntu18 index 01d33d0..0979cab 100644 --- a/test/Dockerfile-ubuntu18 +++ b/test/Dockerfile-ubuntu18 @@ -8,8 +8,7 @@ RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget gawk nginx-light WORKDIR /root -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default # Prevent "Can't load /root/.rnd into RNG" error from openssl From fb7b3ee145203257ee59c6a81fb1a9995f29084c Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Thu, 26 Nov 2020 20:08:44 +0800 Subject: [PATCH 147/308] Use JSON notation for Dockerfile CMD arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reference: - https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#cmd > The `CMD` instruction should be used to run the software contained in your image, along with any arguments. `CMD` should almost always be used in the form of `CMD ["executable", "param1", "param2"…]` --- test/Dockerfile-alpine | 2 +- test/Dockerfile-centos6 | 2 +- test/Dockerfile-centos7-staging | 2 +- test/Dockerfile-debian | 2 +- test/Dockerfile-ubuntu | 2 +- test/Dockerfile-ubuntu-staging | 2 +- test/Dockerfile-ubuntu16 | 2 +- test/Dockerfile-ubuntu18 | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/Dockerfile-alpine b/test/Dockerfile-alpine index 5b1dbf3..399e10f 100644 --- a/test/Dockerfile-alpine +++ b/test/Dockerfile-alpine @@ -18,4 +18,4 @@ RUN /bats-core/install.sh /usr/local # Use supervisord to run nginx in the background COPY ./test/test-config/alpine-supervisord.conf /etc/supervisord.conf -CMD tail -f /dev/null +CMD [ "tail", "-f", "/dev/null" ] diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index 108add0..66cc468 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -23,4 +23,4 @@ RUN /bats-core/install.sh /usr/local EXPOSE 80 443 # Run eternal loop - for testing -CMD tail -f /dev/null +CMD [ "tail", "-f", "/dev/null" ] diff --git a/test/Dockerfile-centos7-staging b/test/Dockerfile-centos7-staging index abb697c..f3d985b 100644 --- a/test/Dockerfile-centos7-staging +++ b/test/Dockerfile-centos7-staging @@ -24,4 +24,4 @@ RUN /bats-core/install.sh /usr/local EXPOSE 80 443 # Run eternal loop - for testing -CMD tail -f /dev/null +CMD [ "tail", "-f", "/dev/null" ] diff --git a/test/Dockerfile-debian b/test/Dockerfile-debian index 6da08d5..640f069 100644 --- a/test/Dockerfile-debian +++ b/test/Dockerfile-debian @@ -16,4 +16,4 @@ RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing -CMD tail -f /dev/null +CMD [ "tail", "-f", "/dev/null" ] diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index 21169ea..953c3bf 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -22,4 +22,4 @@ RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing -CMD tail -f /dev/null +CMD [ "tail", "-f", "/dev/null" ] diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-staging index 15d5a59..8fc3455 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-staging @@ -26,4 +26,4 @@ RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing -CMD tail -f /dev/null +CMD [ "tail", "-f", "/dev/null" ] diff --git a/test/Dockerfile-ubuntu16 b/test/Dockerfile-ubuntu16 index 6b13f68..bb521ff 100644 --- a/test/Dockerfile-ubuntu16 +++ b/test/Dockerfile-ubuntu16 @@ -18,4 +18,4 @@ RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local # Run eternal loop - for testing -CMD tail -f /dev/null +CMD [ "tail", "-f", "/dev/null" ] diff --git a/test/Dockerfile-ubuntu18 b/test/Dockerfile-ubuntu18 index 0979cab..98b71af 100644 --- a/test/Dockerfile-ubuntu18 +++ b/test/Dockerfile-ubuntu18 @@ -23,4 +23,4 @@ RUN /bats-core/install.sh /usr/local EXPOSE 80 443 # Run eternal loop - for testing -CMD tail -f /dev/null +CMD [ "tail", "-f", "/dev/null" ] From 9d43cf81f144771be537a10e93a91880e0ad991a Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Thu, 26 Nov 2020 23:21:16 +0800 Subject: [PATCH 148/308] Remove useless comment in nginx test configs --- test/test-config/nginx-centos7.conf | 8 --- test/test-config/nginx-ubuntu-dual-certs | 69 ------------------------ test/test-config/nginx-ubuntu-no-ssl | 9 ---- test/test-config/nginx-ubuntu-ssl | 69 ------------------------ 4 files changed, 155 deletions(-) diff --git a/test/test-config/nginx-centos7.conf b/test/test-config/nginx-centos7.conf index 2327039..f487519 100644 --- a/test/test-config/nginx-centos7.conf +++ b/test/test-config/nginx-centos7.conf @@ -1,13 +1,8 @@ -# For more information on configuration, see: -# * Official English Documentation: http://nginx.org/en/docs/ -# * Official Russian Documentation: http://nginx.org/ru/docs/ - user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; -# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { @@ -30,8 +25,5 @@ http { include /etc/nginx/mime.types; default_type application/octet-stream; - # Load modular configuration files from the /etc/nginx/conf.d directory. - # See http://nginx.org/en/docs/ngx_core_module.html#include - # for more information. include /etc/nginx/conf.d/*.conf; } diff --git a/test/test-config/nginx-ubuntu-dual-certs b/test/test-config/nginx-ubuntu-dual-certs index b8f4bcc..f6a4c80 100644 --- a/test/test-config/nginx-ubuntu-dual-certs +++ b/test/test-config/nginx-ubuntu-dual-certs @@ -1,45 +1,16 @@ -## -# 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; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; @@ -52,46 +23,6 @@ server { ssl_certificate_key /etc/nginx/pki/private/server.ec.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-no-ssl b/test/test-config/nginx-ubuntu-no-ssl index 8dc55ff..aa32d05 100644 --- a/test/test-config/nginx-ubuntu-no-ssl +++ b/test/test-config/nginx-ubuntu-no-ssl @@ -1,12 +1,8 @@ -# 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; @@ -15,16 +11,11 @@ server { 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; } } diff --git a/test/test-config/nginx-ubuntu-ssl b/test/test-config/nginx-ubuntu-ssl index 882b36a..e87a497 100644 --- a/test/test-config/nginx-ubuntu-ssl +++ b/test/test-config/nginx-ubuntu-ssl @@ -1,45 +1,16 @@ -## -# 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 _; @@ -47,46 +18,6 @@ server { 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; -# } -#} From 8333a1e8175d8cd20a207a6222a3ff2441bc3125 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 28 Nov 2020 11:26:13 +0000 Subject: [PATCH 149/308] Update version to 2.31 Fix bug with nslookup server param --- getssl | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/getssl b/getssl index be7f2bc..1fb58fb 100755 --- a/getssl +++ b/getssl @@ -241,12 +241,12 @@ # 2020-10-02 Various fixes to get_auth_dns and changes to support unit tests (#308) # 2020-10-04 Add CHECK_PUBLIC_DNS_SERVER to check the DNS challenge has been updated there # 2020-10-13 Bugfix: strip comments in drill/dig output (mhameed) -# 2020-11-18 Wildcard support (#347)(#400) +# 2020-11-18 Wildcard support (#347)(#400)(2.31) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.30" +VERSION="2.31" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -1255,13 +1255,11 @@ done # end of ... loop through domains for cert ( from SANS list) get_auth_dns() { # get the authoritative dns server for a domain (sets primary_ns ) orig_gad_d="$1" # domain name - gad_s="$PUBLIC_DNS_SERVER" # start with PUBLIC_DNS_SERVER - if [[ -n "$gad_s" ]]; then - gad_s="@$gad_s" - fi + orig_gad_s="$PUBLIC_DNS_SERVER" # start with PUBLIC_DNS_SERVER + gad_d="$orig_gad_d" + gad_s="$orig_gad_s" if [[ "$os" == "cygwin" ]]; then - gad_d="$orig_gad_d" # shellcheck disable=SC2086 all_auth_dns_servers=$(nslookup -type=soa "${d}" ${PUBLIC_DNS_SERVER} 2>/dev/null \ | grep "primary name server" \ @@ -1278,7 +1276,10 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n fi if [[ -n "$HAS_DIG_OR_DRILL" ]]; then - gad_d="$orig_gad_d" + if [[ -n "$gad_s" ]]; then + gad_s="@$gad_s" + fi + # Use SOA +trace to find the name server if [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then if [[ "$HAS_DIG_OR_DRILL" == "dig" ]]; then @@ -1350,6 +1351,9 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n fi fi + # Remove leading '@' if we tried using dig/drill + gad_s="$orig_gad_s" + if [[ "$HAS_HOST" == "true" ]]; then gad_d="$orig_gad_d" debug Using "host -t NS" to find primary name server for "$gad_d" From e5d44d31178cfb3faf64a9eb62811883c2ca0a30 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 28 Nov 2020 11:26:57 +0000 Subject: [PATCH 150/308] Tweaks to try and make staging tests more robust --- test/test-config/getssl-staging-dns01.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 905c44d..19413cd 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -6,12 +6,12 @@ VALIDATE_VIA_DNS=true DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" PUBLIC_DNS_SERVER=1.1.1.1 -CHECK_ALL_AUTH_DNS="false" +CHECK_ALL_AUTH_DNS="true" +CHECK_PUBLIC_DNS_SERVER="true" DNS_EXTRA_WAIT=120 -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 +# Speed up the test by reducing the number or retries and retrying DNS_ADD after 10 failures +DNS_WAIT_COUNT=20 DNS_WAIT_RETRY_ADD="true" ACCOUNT_KEY_TYPE="rsa" From c8415df61de275c65f5ae1dd6f2074e62cf659bb Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 8 Dec 2020 21:41:47 +0000 Subject: [PATCH 151/308] mktemp not working correctly on Alpine Linux (added XXXXXX to template) Fixes #612 --- getssl | 11 +++++--- test/29-check-mktemp-failure.bats | 47 +++++++++++++++++++++++++++++++ test/u3-mktemp-template.bats | 11 ++++++++ 3 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 test/29-check-mktemp-failure.bats create mode 100644 test/u3-mktemp-template.bats diff --git a/getssl b/getssl index 1fb58fb..f509060 100755 --- a/getssl +++ b/getssl @@ -621,7 +621,7 @@ check_config() { # check the config files for all obvious errors fi dn=0 - tmplist=$(mktemp 2>/dev/null || mktemp -t getssl) + tmplist=$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX) || error_exit "mktemp failed" for d in "${alldomains[@]}"; do # loop over domains (dn is domain number) debug "checking domain $d" if [[ "$(grep "^${d}$" "$tmplist")" = "$d" ]]; then @@ -695,7 +695,10 @@ check_config() { # check the config files for all obvious errors } check_getssl_upgrade() { # check if a more recent version of code is available available - TEMP_UPGRADE_FILE="$(mktemp 2>/dev/null || mktemp -t getssl)" + TEMP_UPGRADE_FILE="$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX)" + if [ "$TEMP_UPGRADE_FILE" == "" ]; then + error_exit "mktemp failed" + fi curl --user-agent "$CURL_USERAGENT" --silent "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" errcode=$? if [[ $errcode -eq 60 ]]; then @@ -918,7 +921,7 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) if [[ ! -s "$csr_file" ]] || [[ "$_RECREATE_CSR" == "1" ]]; then info "creating domain csr - $csr_file" # create a temporary config file, for portability. - tmp_conf=$(mktemp 2>/dev/null || mktemp -t getssl) + tmp_conf=$(mktemp 2>/dev/null || mktemp -t getssl) || error_exit "mktemp failed" cat "$SSLCONF" > "$tmp_conf" printf "[SAN]\n%s" "$SANLIST" >> "$tmp_conf" # add OCSP Must-Staple to the domain csr @@ -1928,7 +1931,7 @@ revoke_certificate() { # revoke a certificate ACCOUNT_KEY="$REVOKE_KEY" # need to set the revoke key as "account_key" since it's used in send_signed_request. get_signing_params "$REVOKE_KEY" - TEMP_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t getssl) + TEMP_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t getssl) || error_exit "mktemp failed" debug "revoking from $URL_revoke" rcertdata=$(sed '1d;$d' "$REVOKE_CERT" | tr -d "\r\n" | tr '/+' '_-' | tr -d '= ') send_signed_request "$URL_revoke" "{\"certificate\": \"$rcertdata\",\"reason\": $REVOKE_REASON}" diff --git a/test/29-check-mktemp-failure.bats b/test/29-check-mktemp-failure.bats new file mode 100644 index 0000000..782dc64 --- /dev/null +++ b/test/29-check-mktemp-failure.bats @@ -0,0 +1,47 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Check that getssl -c fails with an error message if mktemp fails" { + if [ -n "$STAGING" ]; then + skip "Internal test, no need to test on staging server" + else + CONFIG_FILE="getssl-http01.cfg" + fi + + # set TMPDIR to an invalid directory and check for failure + export TMPDIR=/getssl.invalid.directory + setup_environment + run ${CODE_DIR}/getssl -c "$GETSSL_CMD_HOST" + assert_failure + assert_line --partial "mktemp failed" +} + + +@test "Check that getssl fails with an error message if mktemp fails" { + if [ -n "$STAGING" ]; then + skip "Internal test, no need to test on staging server" + else + CONFIG_FILE="getssl-http01.cfg" + fi + + setup_environment + init_getssl + + # set TMPDIR to an invalid directory and check for failure + export TMPDIR=/getssl.invalid.directory + create_certificate + assert_failure + assert_line --partial "mktemp failed" +} diff --git a/test/u3-mktemp-template.bats b/test/u3-mktemp-template.bats new file mode 100644 index 0000000..2cb8040 --- /dev/null +++ b/test/u3-mktemp-template.bats @@ -0,0 +1,11 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +@test "Check mktemp -t getssl.XXXXXX works on all platforms" { + run mktemp -t getssl.XXXXXX + assert_success +} From 9350bce17f453a5c0ba05cba4e9c430f4ca1d513 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 10 Dec 2020 18:39:29 +0000 Subject: [PATCH 152/308] Add dns scripts for Dynu.com --- dns_scripts/dns_add_dynu | 68 ++++++++++++++++++++++++++++++++++++++++ dns_scripts/dns_del_dynu | 63 +++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 dns_scripts/dns_add_dynu create mode 100644 dns_scripts/dns_del_dynu diff --git a/dns_scripts/dns_add_dynu b/dns_scripts/dns_add_dynu new file mode 100644 index 0000000..7a08ce8 --- /dev/null +++ b/dns_scripts/dns_add_dynu @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# Need to add your API key below or set as env variable +apikey=${DYNU_API_KEY:-''} + +# This script adds a token to dynu.com DNS for the ACME challenge +# usage dns_add_dynu "domain name" "token" +# return codes are; +# 0 - success +# 1 - error in input +# 2 - error within internal processing +# 3 - error in result ( domain not found in dynu.com etc) + +fulldomain="${1}" +token="${2}" + +API='https://api.dynu.com/v2/dns' + +# Check initial parameters +if [[ -z "$fulldomain" ]]; then + echo "DNS script requires full domain name as first parameter" + exit 1 +fi +if [[ -z "$token" ]]; then + echo "DNS script requires challenge token as second parameter" + exit 1 +fi + +curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) + +# Get domain id +resp=$(curl --silent "${curl_params[@]}" -X GET "$API") + +# Match domain id +re="\"id\":([^,]*),\"name\":\"getssl-testing.freeddns.org\"" +if [[ "$resp" =~ $re ]]; then + domain_id="${BASH_REMATCH[1]}" +fi + +if [[ -z "$domain_id" ]]; then + echo 'Domain name not found on your Dynu account' + exit 3 +fi + +# Check for existing _acme-challenge TXT record +resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") +re="\"id\":([^,]*)" +if [[ "$resp" =~ $re ]]; then + record_id="${BASH_REMATCH[1]}" +fi + +if [[ -z "$record_id" ]]; then + # Add new TXT challenge record + resp=$(curl --silent \ + "${curl_params[@]}" \ + -X POST "${API}/${domain_id}/record" \ + --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"textData\":\"$token\"}") +else + resp=$(curl --silent \ + "${curl_params[@]}" \ + -X POST "${API}/${domain_id}/record/${record_id}" \ + --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"textData\":\"$token\"}") +fi + +# If adding record failed (exception:) then print error message +if [[ "${resp// }" == *'"exception"'* ]]; then + echo "Error: DNS challenge not added: unknown error - ${resp}" + exit 3 +fi diff --git a/dns_scripts/dns_del_dynu b/dns_scripts/dns_del_dynu new file mode 100644 index 0000000..310bb61 --- /dev/null +++ b/dns_scripts/dns_del_dynu @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Need to add your API key below or set as env variable +apikey=${DYNU_API_KEY:-''} + +# This script deletes the _acme-challenge TXT record from the dynu.com DNS entry for the domain +# usage dns_del_dynu "domain name" +# return codes are; +# 0 - success +# 1 - error in input +# 2 - error within internal processing +# 3 - error in result ( domain not found in dynu.com etc) + +fulldomain="${1}" + +API='https://api.dynu.com/v2/dns' + +# Check initial parameters +if [[ -z "$fulldomain" ]]; then + echo "DNS script requires full domain name as first parameter" + exit 1 +fi +if [[ -z "$apikey" ]]; then + echo "DNS script requires an apikey to be set" + exit 1 +fi + +curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) + +# Get domain id +resp=$(curl --silent "${curl_params[@]}" -X GET "$API") + +# Match domain id +re="\"id\":([^,]*),\"name\":\"getssl-testing.freeddns.org\"" +if [[ "$resp" =~ $re ]]; then + domain_id="${BASH_REMATCH[1]}" +fi + +if [[ -z "$domain_id" ]]; then + echo 'Domain name not found on your Dynu account' + exit 3 +fi + +# Find existing _acme-challenge TXT record +resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") +re="\"id\":([^,]*)" +if [[ "$resp" =~ $re ]]; then + record_id="${BASH_REMATCH[1]}" +fi + +if [[ -z "$record_id" ]]; then + echo "No _acme-challenge TXT record found for $fulldomain" + exit 3 +fi + +resp=$(curl --silent \ + "${curl_params[@]}" \ + -X DELETE "${API}/${domain_id}/record/${record_id}") + +# If adding record failed (exception:) then print error message +if [[ "${resp// }" == *'"exception"'* ]]; then + echo "Error: DNS challenge not added: unknown error - ${resp}" + exit 3 +fi From fa9a8c7f4532934d5c0fc9efd85d8bb88e4e0088 Mon Sep 17 00:00:00 2001 From: Veit Wahlich Date: Thu, 17 Dec 2020 15:12:57 +0100 Subject: [PATCH 153/308] Fix delimiter issues with ${alldomains[]} in create_csr() - use \n as delimiter for read to array - use \n as delimiter for comparing SANs --- getssl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/getssl b/getssl index f509060..31885d6 100755 --- a/getssl +++ b/getssl @@ -895,9 +895,9 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) debug "domain csr exists at - $csr_file" # check all domains in config are in csr if [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then - read -r -a alldomains <<< "$(echo "$SANS" | sed -e 's/ //g; s/,$//; y/,/\n/' | sort -u)" + read -d '\n' -r -a alldomains <<< "$(echo "$SANS" | sed -e 's/ //g; s/,$//; y/,/\n/' | sort -u)" else - read -r -a alldomains <<< "$(echo "$DOMAIN,$SANS" | sed -e 's/,/ /g; s/ $//; y/ /\n/' | sort -u)" + read -d '\n' -r -a alldomains <<< "$(echo "$DOMAIN,$SANS" | sed -e 's/,/ /g; s/ $//; y/ /\n/' | sort -u)" fi domains_in_csr=$(openssl req -text -noout -in "$csr_file" \ | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \ @@ -910,7 +910,7 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) fi done # check all domains in csr are in config - if [[ "${alldomains[*]}" != "$domains_in_csr" ]]; then + if [[ "$(IFS=$'\n'; echo -n "${alldomains[*]}")" != "$domains_in_csr" ]]; then info "existing csr at $csr_file does not have the same domains as the config - re-create-csr" _RECREATE_CSR=1 fi From d35f7baf9139edeacdc35e732ed28ae04ccd1a82 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 17 Dec 2020 21:58:47 +0000 Subject: [PATCH 154/308] Some fixes to get_auth_dns --- getssl | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/getssl b/getssl index f509060..8c85771 100755 --- a/getssl +++ b/getssl @@ -520,12 +520,24 @@ check_challenge_completion_dns() { # perform validation via DNS challenge check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${lower_d}" "@${ns}" \ | grep -i "^_acme-challenge.${lower_d}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') + debug "check_result=$check_result" + if [[ -z "$check_result" ]]; then + debug "$DNS_CHECK_FUNC" ANY "_acme-challenge.${lower_d}" "@${ns}" + check_result=$($DNS_CHECK_FUNC ANY "_acme-challenge.${lower_d}" "@${ns}" \ + | grep -i "^_acme-challenge.${lower_d}" \ + | grep 'IN\WTXT'|awk -F'"' '{ print $2}') + debug "check_result=$check_result" + fi elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${lower_d}" "${ns}" \ | grep 'descriptive text'|awk -F'"' '{ print $2}') else check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ | grep 'text ='|awk -F'"' '{ print $2}') + if [[ -z "$check_result" ]]; then + check_result=$(nslookup -type=any "_acme-challenge.${lower_d}" "${ns}" \ + | grep 'text ='|awk -F'"' '{ print $2}') + fi fi debug "expecting $auth_key" debug "${ns} gave ... $check_result" @@ -538,6 +550,7 @@ check_challenge_completion_dns() { # perform validation via DNS challenge if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 )) == 0 ]]; then debug "Retrying adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" + test_output "Retrying adding dns via command: $DNS_ADD_COMMAND" eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then error_exit "DNS_ADD_COMMAND failed for domain $d" @@ -1165,10 +1178,12 @@ for d in "${alldomains[@]}"; do # find a primary / authoritative DNS server for the domain if [[ -z "$AUTH_DNS_SERVER" ]]; then get_auth_dns "$d" + elif [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then + primary_ns="$AUTH_DNS_SERVER $PUBLIC_DNS_SERVER" else primary_ns="$AUTH_DNS_SERVER" fi - debug primary_ns "$primary_ns" + debug set primary_ns = "$primary_ns" check_challenge_completion_dns "${token}" "${uri}" "${keyauthorization}" "${d}" "${primary_ns}" "${auth_key}" else # set up the correct http token for verification @@ -1270,11 +1285,11 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ -z "$all_auth_dns_servers" ]]; then error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" fi + primary_ns="$all_auth_dns_servers" if [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then - primary_ns="$all_auth_dns_servers $PUBLIC_DNS_SERVER" - else - primary_ns="$all_auth_dns_servers" + primary_ns="$primary_ns $PUBLIC_DNS_SERVER" fi + return fi @@ -1348,8 +1363,8 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n primary_ns="$primary_ns $PUBLIC_DNS_SERVER" fi - debug set primary_ns = "$primary_ns" test_output set primary_ns ="$primary_ns" + return fi fi @@ -1428,9 +1443,6 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') fi - if [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then - primary_ns="$primary_ns $PUBLIC_DNS_SERVER" - fi return fi fi From 1199739fc97bf8b845933d17e42dbd002812e884 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 17 Dec 2020 22:00:04 +0000 Subject: [PATCH 155/308] Move DNS used for staging tests to Dynu --- dns_scripts/dns_add_dynu | 14 +++++--- dns_scripts/dns_del_dynu | 22 ++++++++---- test/15-test-revoke-no-suffix.bats | 6 +++- test/18-staging-retry-dns-add.bats | 16 +++++++-- test/Dockerfile-centos7-staging | 1 + test/Dockerfile-ubuntu-staging | 1 + test/dns_add_fail | 6 ++++ test/dns_fail_add_duckdns | 19 ---------- test/run-test.cmd | 2 +- test/run-test.sh | 3 +- .../getssl-staging-dns01-fail-dns-add.cfg | 33 ----------------- .../getssl-staging-dns01-no-suffix.cfg | 36 ------------------- test/test-config/getssl-staging-dns01.cfg | 11 ++++-- 13 files changed, 62 insertions(+), 108 deletions(-) create mode 100644 test/dns_add_fail delete mode 100755 test/dns_fail_add_duckdns delete mode 100644 test/test-config/getssl-staging-dns01-fail-dns-add.cfg delete mode 100644 test/test-config/getssl-staging-dns01-no-suffix.cfg diff --git a/dns_scripts/dns_add_dynu b/dns_scripts/dns_add_dynu index 7a08ce8..e20470d 100644 --- a/dns_scripts/dns_add_dynu +++ b/dns_scripts/dns_add_dynu @@ -28,10 +28,11 @@ fi curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) # Get domain id -resp=$(curl --silent "${curl_params[@]}" -X GET "$API") +# curl -X GET https://api.dynu.com/v2/dns/getroot/ubuntu-getssl.freeddns.org +resp=$(curl --silent "${curl_params[@]}" -X GET "$API/getroot/${fulldomain}") # Match domain id -re="\"id\":([^,]*),\"name\":\"getssl-testing.freeddns.org\"" +re="\"id\":([^,]*),\"domainName\":\"${fulldomain}\"" if [[ "$resp" =~ $re ]]; then domain_id="${BASH_REMATCH[1]}" fi @@ -42,6 +43,7 @@ if [[ -z "$domain_id" ]]; then fi # Check for existing _acme-challenge TXT record +# curl -X GET "https://api.dynu.com/v2/dns/record/_acme-challenge.ubuntu-getssl.freeddns.org?recordType=TXT" resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") re="\"id\":([^,]*)" if [[ "$resp" =~ $re ]]; then @@ -53,16 +55,18 @@ if [[ -z "$record_id" ]]; then resp=$(curl --silent \ "${curl_params[@]}" \ -X POST "${API}/${domain_id}/record" \ - --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"textData\":\"$token\"}") + --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"state\":\"true\",\"textData\":\"$token\"}") else + # Update existing record + # curl -X POST https://api.dynu.com/v2/dns/9329328/record/7082063 -d "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"state\":\"true\",\"textData\":\"Test2\"}" resp=$(curl --silent \ "${curl_params[@]}" \ -X POST "${API}/${domain_id}/record/${record_id}" \ - --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"textData\":\"$token\"}") + --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"state\":\"true\",\"textData\":\"$token\"}") fi # If adding record failed (exception:) then print error message -if [[ "${resp// }" == *'"exception"'* ]]; then +if [[ "$resp" != *"\"statusCode\":200"* ]]; then echo "Error: DNS challenge not added: unknown error - ${resp}" exit 3 fi diff --git a/dns_scripts/dns_del_dynu b/dns_scripts/dns_del_dynu index 310bb61..1d8d588 100644 --- a/dns_scripts/dns_del_dynu +++ b/dns_scripts/dns_del_dynu @@ -10,6 +10,12 @@ apikey=${DYNU_API_KEY:-''} # 2 - error within internal processing # 3 - error in result ( domain not found in dynu.com etc) +# After deleting the TXT record from Dynu.com it takes over 30 minutes to add a new TXT record! +# This doesn't happen when updating the TXT record, just for delete then add +# As this is used for testing, changed the delete to a no-op. + +exit 0 + fulldomain="${1}" API='https://api.dynu.com/v2/dns' @@ -20,17 +26,18 @@ if [[ -z "$fulldomain" ]]; then exit 1 fi if [[ -z "$apikey" ]]; then - echo "DNS script requires an apikey to be set" + echo "DNS script requires apikey environment variable to be set" exit 1 fi curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) # Get domain id -resp=$(curl --silent "${curl_params[@]}" -X GET "$API") +# curl -X GET https://api.dynu.com/v2/dns/getroot/ubuntu-getssl.freeddns.org +resp=$(curl --silent "${curl_params[@]}" -X GET "$API/getroot/${fulldomain}") # Match domain id -re="\"id\":([^,]*),\"name\":\"getssl-testing.freeddns.org\"" +re="\"id\":([^,]*),\"domainName\":\"${fulldomain}\"" if [[ "$resp" =~ $re ]]; then domain_id="${BASH_REMATCH[1]}" fi @@ -40,7 +47,8 @@ if [[ -z "$domain_id" ]]; then exit 3 fi -# Find existing _acme-challenge TXT record +# Check for existing _acme-challenge TXT record +# curl -X GET "https://api.dynu.com/v2/dns/record/_acme-challenge.ubuntu-getssl.freeddns.org?recordType=TXT" resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") re="\"id\":([^,]*)" if [[ "$resp" =~ $re ]]; then @@ -48,8 +56,8 @@ if [[ "$resp" =~ $re ]]; then fi if [[ -z "$record_id" ]]; then - echo "No _acme-challenge TXT record found for $fulldomain" - exit 3 + echo "No _acme-challenge.${fulldomain} TXT record found" + exit 0 fi resp=$(curl --silent \ @@ -57,7 +65,7 @@ resp=$(curl --silent \ -X DELETE "${API}/${domain_id}/record/${record_id}") # If adding record failed (exception:) then print error message -if [[ "${resp// }" == *'"exception"'* ]]; then +if [[ "$resp" != *"\"statusCode\":200"* ]]; then echo "Error: DNS challenge not added: unknown error - ${resp}" exit 3 fi diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index 5e8d797..96e174b 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -15,10 +15,12 @@ setup() { @test "Create certificate to check revoke (no suffix)" { if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01-no-suffix.cfg" + CONFIG_FILE="getssl-staging-dns01.cfg" else CONFIG_FILE="getssl-http01-no-suffix.cfg" fi + echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" setup_environment init_getssl @@ -34,6 +36,8 @@ setup() { else CONFIG_FILE="getssl-http01.cfg" fi + echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key diff --git a/test/18-staging-retry-dns-add.bats b/test/18-staging-retry-dns-add.bats index 8b636d6..bca7c05 100644 --- a/test/18-staging-retry-dns-add.bats +++ b/test/18-staging-retry-dns-add.bats @@ -6,14 +6,26 @@ load '/getssl/test/test_helper.bash' -@test "Check retry add dns command if dns isn't updated (DuckDNS)" { +@test "Check retry add dns command if dns isn't updated" { if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi - CONFIG_FILE="getssl-staging-dns01-fail-dns-add.cfg" + + CONFIG_FILE="getssl-staging-dns01.cfg" setup_environment init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +DNS_ADD_COMMAND="/getssl/test/dns_add_fail" + +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_EXTRA_WAIT=0 +CHECK_ALL_AUTH_DNS="false" +CHECK_PUBLIC_DNS_SERVER="false" +EOF create_certificate -d assert_failure assert_line --partial "Retrying adding dns via command" diff --git a/test/Dockerfile-centos7-staging b/test/Dockerfile-centos7-staging index 0b2ff08..ad49896 100644 --- a/test/Dockerfile-centos7-staging +++ b/test/Dockerfile-centos7-staging @@ -9,6 +9,7 @@ RUN yum -y install git curl bind-utils ldns wget which nginx ENV staging "true" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb +ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 WORKDIR /root RUN mkdir /etc/nginx/pki diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-staging index 1ee3f83..3032c85 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-staging @@ -8,6 +8,7 @@ ENV DEBIAN_FRONTEND noninteractive # Ensure tests in this image use the staging server ENV staging "true" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb +ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 # Update and install required software RUN apt-get update --fix-missing diff --git a/test/dns_add_fail b/test/dns_add_fail new file mode 100644 index 0000000..44ab42b --- /dev/null +++ b/test/dns_add_fail @@ -0,0 +1,6 @@ +#!/bin/bash + +# Special test script which will always fail to update dns + +echo "This is a test script to check retry works if DNS isn't updated" +exit 0 diff --git a/test/dns_fail_add_duckdns b/test/dns_fail_add_duckdns deleted file mode 100755 index 03df89f..0000000 --- a/test/dns_fail_add_duckdns +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# Special test script which will always fail to update dns - -token=${DUCKDNS_TOKEN:-} - -if [ -z "$token" ]; then - echo "DUCKDNS_TOKEN not set" - exit 1 -fi - -domain="$1" - -response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=FAIL") -if [ "$response" != "OK" ]; then - echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)" - echo "Response: $response" - exit 1 -fi diff --git a/test/run-test.cmd b/test/run-test.cmd index 23235c9..0462617 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -23,7 +23,7 @@ set COMMAND=bats /getssl/test GOTO CheckAlias :staging -set ALIAS=%OS:-staging=%-getssl.duckdns.org +set ALIAS=%OS:-staging=%-getssl.freeddns.org set STAGING=--env STAGING=true :Run diff --git a/test/run-test.sh b/test/run-test.sh index 8a2a9f2..760c600 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -15,7 +15,8 @@ else fi if [[ "$OS" == *"staging"* ]]; then - ALIAS="${OS%-staging}-getssl.duckdns.org" + #ALIAS="${OS%-staging}-getssl.duckdns.org" + ALIAS="${OS%-staging}-getssl.freeddns.org" STAGING="--env STAGING=true" else ALIAS="$OS.getssl.test" diff --git a/test/test-config/getssl-staging-dns01-fail-dns-add.cfg b/test/test-config/getssl-staging-dns01-fail-dns-add.cfg deleted file mode 100644 index 2985d32..0000000 --- a/test/test-config/getssl-staging-dns01-fail-dns-add.cfg +++ /dev/null @@ -1,33 +0,0 @@ -# Special config to test that the retry dns_add_command logic works -# -CA="https://acme-staging-v02.api.letsencrypt.org/directory" - -# Generic staging config -VALIDATE_VIA_DNS=true -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=ns2.duckdns.org -CHECK_ALL_AUTH_DNS=true - -# Test that the retry works (dns_add_command will always fail) -DNS_WAIT_RETRY_ADD="true" -DNS_ADD_COMMAND="/getssl/test/dns_fail_add_duckdns" - -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 -DNS_EXTRA_WAIT=0 - -# Standard config -ACCOUNT_KEY_TYPE="rsa" -PRIVATE_KEY_ALG="rsa" -SANS="" -ACL=('/var/www/html/.well-known/acme-challenge') -USE_SINGLE_ACL="false" -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 -RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx" -SERVER_TYPE="https" -CHECK_REMOTE="true" diff --git a/test/test-config/getssl-staging-dns01-no-suffix.cfg b/test/test-config/getssl-staging-dns01-no-suffix.cfg deleted file mode 100644 index b4f5202..0000000 --- a/test/test-config/getssl-staging-dns01-no-suffix.cfg +++ /dev/null @@ -1,36 +0,0 @@ -# Test that the script works with external dns provider and staging server -# -CA="https://acme-staging-v02.api.letsencrypt.org" - -VALIDATE_VIA_DNS=true -DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=ns2.duckdns.org -CHECK_ALL_AUTH_DNS=true -DNS_EXTRA_WAIT=120 - -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 -DNS_WAIT_RETRY_ADD="true" - -ACCOUNT_KEY_TYPE="rsa" -PRIVATE_KEY_ALG="rsa" - -# Additional domains - this could be multiple domains / subdomains in a comma separated list -SANS="" - -# 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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" - -# Define the server type and confirm correct certificate is installed (using a custom port) -SERVER_TYPE="https" -CHECK_REMOTE="true" diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 19413cd..64a7388 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -3,15 +3,17 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" VALIDATE_VIA_DNS=true -DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=1.1.1.1 +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_dynu" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_dynu" +PUBLIC_DNS_SERVER="8.8.8.8 resolver1.infoserve.de" +AUTH_DNS_SERVER=ns1.dynu.com CHECK_ALL_AUTH_DNS="true" CHECK_PUBLIC_DNS_SERVER="true" DNS_EXTRA_WAIT=120 # Speed up the test by reducing the number or retries and retrying DNS_ADD after 10 failures DNS_WAIT_COUNT=20 +DNS_WAIT=30 DNS_WAIT_RETRY_ADD="true" ACCOUNT_KEY_TYPE="rsa" @@ -38,3 +40,6 @@ CHECK_REMOTE="true" if [[ -s "$DOMAIN_DIR/getssl_test_specific.cfg" ]]; then . $DOMAIN_DIR/getssl_test_specific.cfg fi + +#_RUNNING_TEST=1 +#_USE_DEBUG=1 From 27265df6671568a0873df4f666cc77ac1a8dba66 Mon Sep 17 00:00:00 2001 From: atisne Date: Fri, 18 Dec 2020 10:28:58 +0100 Subject: [PATCH 156/308] Wrong SANS when domain contains a minus character A regexp to extract 'Subject Alternative Name' doesn't work when the domain use a minus character. For grep regexp, to lose its special meaning inside brackets, the minus character must be placed in the first or last position in the list. https://www.gnu.org/software/grep/manual/grep.html#Character-Classes-and-Bracket-Expressions --- getssl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/getssl b/getssl index f509060..0caa2a4 100755 --- a/getssl +++ b/getssl @@ -2578,11 +2578,10 @@ if [[ ${_CREATE_CONFIG} -eq 1 ]]; then | openssl x509 2>/dev/null) EX_SANS="www.${DOMAIN##\*.}" if [[ -n "${EX_CERT}" ]]; then - # Putting this inside the EX_SANS line below doesn't work on Centos7 escaped_d=${DOMAIN/\*/\\\*} EX_SANS=$(echo "$EX_CERT" \ | openssl x509 -noout -text 2>/dev/null| grep "Subject Alternative Name" -A2 \ - | grep -Eo "DNS:[a-zA-Z 0-9.-\*]*" | sed "s@DNS:${escaped_d}@@g" | grep -v '^$' | cut -c 5-) + | grep -Eo "DNS:[a-zA-Z 0-9.\*-]*" | sed "s@DNS:${escaped_d}@@g" | grep -v '^$' | cut -c 5-) EX_SANS=${EX_SANS//$'\n'/','} fi if [[ -n "${EX_SANS}" ]]; then From c90ca25ede458182fb4b7c7ee37cbda57cdac8cc Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 18 Dec 2020 21:11:10 +0000 Subject: [PATCH 157/308] Add unit test for create_csr --- getssl | 2 ++ test/u4-create-csr-and-ifs.bats | 54 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 test/u4-create-csr-and-ifs.bats diff --git a/getssl b/getssl index 31885d6..cf82e0c 100755 --- a/getssl +++ b/getssl @@ -913,6 +913,8 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) if [[ "$(IFS=$'\n'; echo -n "${alldomains[*]}")" != "$domains_in_csr" ]]; then info "existing csr at $csr_file does not have the same domains as the config - re-create-csr" _RECREATE_CSR=1 + else + test_output "Existing csr at $csr_file contains same domains as the config" fi fi # end of ... check if domain csr exists - if not then create it diff --git a/test/u4-create-csr-and-ifs.bats b/test/u4-create-csr-and-ifs.bats new file mode 100644 index 0000000..c30277c --- /dev/null +++ b/test/u4-create-csr-and-ifs.bats @@ -0,0 +1,54 @@ +#! /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() { + . /getssl/getssl --source + find_dns_utils + _RUNNING_TEST=1 + _USE_DEBUG=0 +} + + +@test "Check create_csr works for multiple domains" { + # Create a key + csr_key=$(mktemp -t getssl.XXXXXX.key) || error_exit "mktemp failed" + csr_file=$(mktemp -t getssl.XXXXXX.csr) || error_exit "mktemp failed" + SANS="a.getssl.test,b.getssl.test" + SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" + create_key "$ACCOUNT_KEY_TYPE" "$csr_key" "$ACCOUNT_KEY_LENGTH" + + # Create an initial csr + run create_csr $csr_file $csr_key + assert_success + + # Check that calling create_csr with the same SANSLIST doesn't re-create the csr + run create_csr $csr_file $csr_key + assert_success + refute_line --partial "does not have the same domains" + + # Check that calling create_csr with a different SANSLIST does re-create the csr + SANS="a.getssl.test,b.getssl.test,c.getssl.test" + SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" + run create_csr $csr_file $csr_key + assert_success + assert_line --partial "does not contain" + + # Check that calling create_csr with the same SANSLIST, but in a different order does not re-create the csr + SANS="c.getssl.test,a.getssl.test,b.getssl.test" + SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" + run create_csr $csr_file $csr_key + assert_success + refute_line --partial "does not contain" + + # Check that removing a domain from the SANSLIST causes the csr to be re-created + SANS="c.getssl.test,a.getssl.test" + SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" + run create_csr $csr_file $csr_key + assert_success + assert_line --partial "does not have the same domains as the config" +} From 92673dae6ea8aeb31f95eb6fff33fd263f3ddcd1 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 10 Dec 2020 18:39:29 +0000 Subject: [PATCH 158/308] Add dns scripts for Dynu.com --- dns_scripts/dns_add_dynu | 68 ++++++++++++++++++++++++++++++++++++++++ dns_scripts/dns_del_dynu | 63 +++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 dns_scripts/dns_add_dynu create mode 100644 dns_scripts/dns_del_dynu diff --git a/dns_scripts/dns_add_dynu b/dns_scripts/dns_add_dynu new file mode 100644 index 0000000..7a08ce8 --- /dev/null +++ b/dns_scripts/dns_add_dynu @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# Need to add your API key below or set as env variable +apikey=${DYNU_API_KEY:-''} + +# This script adds a token to dynu.com DNS for the ACME challenge +# usage dns_add_dynu "domain name" "token" +# return codes are; +# 0 - success +# 1 - error in input +# 2 - error within internal processing +# 3 - error in result ( domain not found in dynu.com etc) + +fulldomain="${1}" +token="${2}" + +API='https://api.dynu.com/v2/dns' + +# Check initial parameters +if [[ -z "$fulldomain" ]]; then + echo "DNS script requires full domain name as first parameter" + exit 1 +fi +if [[ -z "$token" ]]; then + echo "DNS script requires challenge token as second parameter" + exit 1 +fi + +curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) + +# Get domain id +resp=$(curl --silent "${curl_params[@]}" -X GET "$API") + +# Match domain id +re="\"id\":([^,]*),\"name\":\"getssl-testing.freeddns.org\"" +if [[ "$resp" =~ $re ]]; then + domain_id="${BASH_REMATCH[1]}" +fi + +if [[ -z "$domain_id" ]]; then + echo 'Domain name not found on your Dynu account' + exit 3 +fi + +# Check for existing _acme-challenge TXT record +resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") +re="\"id\":([^,]*)" +if [[ "$resp" =~ $re ]]; then + record_id="${BASH_REMATCH[1]}" +fi + +if [[ -z "$record_id" ]]; then + # Add new TXT challenge record + resp=$(curl --silent \ + "${curl_params[@]}" \ + -X POST "${API}/${domain_id}/record" \ + --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"textData\":\"$token\"}") +else + resp=$(curl --silent \ + "${curl_params[@]}" \ + -X POST "${API}/${domain_id}/record/${record_id}" \ + --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"textData\":\"$token\"}") +fi + +# If adding record failed (exception:) then print error message +if [[ "${resp// }" == *'"exception"'* ]]; then + echo "Error: DNS challenge not added: unknown error - ${resp}" + exit 3 +fi diff --git a/dns_scripts/dns_del_dynu b/dns_scripts/dns_del_dynu new file mode 100644 index 0000000..310bb61 --- /dev/null +++ b/dns_scripts/dns_del_dynu @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Need to add your API key below or set as env variable +apikey=${DYNU_API_KEY:-''} + +# This script deletes the _acme-challenge TXT record from the dynu.com DNS entry for the domain +# usage dns_del_dynu "domain name" +# return codes are; +# 0 - success +# 1 - error in input +# 2 - error within internal processing +# 3 - error in result ( domain not found in dynu.com etc) + +fulldomain="${1}" + +API='https://api.dynu.com/v2/dns' + +# Check initial parameters +if [[ -z "$fulldomain" ]]; then + echo "DNS script requires full domain name as first parameter" + exit 1 +fi +if [[ -z "$apikey" ]]; then + echo "DNS script requires an apikey to be set" + exit 1 +fi + +curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) + +# Get domain id +resp=$(curl --silent "${curl_params[@]}" -X GET "$API") + +# Match domain id +re="\"id\":([^,]*),\"name\":\"getssl-testing.freeddns.org\"" +if [[ "$resp" =~ $re ]]; then + domain_id="${BASH_REMATCH[1]}" +fi + +if [[ -z "$domain_id" ]]; then + echo 'Domain name not found on your Dynu account' + exit 3 +fi + +# Find existing _acme-challenge TXT record +resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") +re="\"id\":([^,]*)" +if [[ "$resp" =~ $re ]]; then + record_id="${BASH_REMATCH[1]}" +fi + +if [[ -z "$record_id" ]]; then + echo "No _acme-challenge TXT record found for $fulldomain" + exit 3 +fi + +resp=$(curl --silent \ + "${curl_params[@]}" \ + -X DELETE "${API}/${domain_id}/record/${record_id}") + +# If adding record failed (exception:) then print error message +if [[ "${resp// }" == *'"exception"'* ]]; then + echo "Error: DNS challenge not added: unknown error - ${resp}" + exit 3 +fi From 2e558854c3a9ef18c8df5460880641a92997011a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 17 Dec 2020 21:58:47 +0000 Subject: [PATCH 159/308] Some fixes to get_auth_dns --- getssl | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/getssl b/getssl index 0caa2a4..84ef2cc 100755 --- a/getssl +++ b/getssl @@ -520,12 +520,24 @@ check_challenge_completion_dns() { # perform validation via DNS challenge check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${lower_d}" "@${ns}" \ | grep -i "^_acme-challenge.${lower_d}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') + debug "check_result=$check_result" + if [[ -z "$check_result" ]]; then + debug "$DNS_CHECK_FUNC" ANY "_acme-challenge.${lower_d}" "@${ns}" + check_result=$($DNS_CHECK_FUNC ANY "_acme-challenge.${lower_d}" "@${ns}" \ + | grep -i "^_acme-challenge.${lower_d}" \ + | grep 'IN\WTXT'|awk -F'"' '{ print $2}') + debug "check_result=$check_result" + fi elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${lower_d}" "${ns}" \ | grep 'descriptive text'|awk -F'"' '{ print $2}') else check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ | grep 'text ='|awk -F'"' '{ print $2}') + if [[ -z "$check_result" ]]; then + check_result=$(nslookup -type=any "_acme-challenge.${lower_d}" "${ns}" \ + | grep 'text ='|awk -F'"' '{ print $2}') + fi fi debug "expecting $auth_key" debug "${ns} gave ... $check_result" @@ -538,6 +550,7 @@ check_challenge_completion_dns() { # perform validation via DNS challenge if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 )) == 0 ]]; then debug "Retrying adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" + test_output "Retrying adding dns via command: $DNS_ADD_COMMAND" eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then error_exit "DNS_ADD_COMMAND failed for domain $d" @@ -1165,10 +1178,12 @@ for d in "${alldomains[@]}"; do # find a primary / authoritative DNS server for the domain if [[ -z "$AUTH_DNS_SERVER" ]]; then get_auth_dns "$d" + elif [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then + primary_ns="$AUTH_DNS_SERVER $PUBLIC_DNS_SERVER" else primary_ns="$AUTH_DNS_SERVER" fi - debug primary_ns "$primary_ns" + debug set primary_ns = "$primary_ns" check_challenge_completion_dns "${token}" "${uri}" "${keyauthorization}" "${d}" "${primary_ns}" "${auth_key}" else # set up the correct http token for verification @@ -1270,11 +1285,11 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ -z "$all_auth_dns_servers" ]]; then error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" fi + primary_ns="$all_auth_dns_servers" if [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then - primary_ns="$all_auth_dns_servers $PUBLIC_DNS_SERVER" - else - primary_ns="$all_auth_dns_servers" + primary_ns="$primary_ns $PUBLIC_DNS_SERVER" fi + return fi @@ -1348,8 +1363,8 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n primary_ns="$primary_ns $PUBLIC_DNS_SERVER" fi - debug set primary_ns = "$primary_ns" test_output set primary_ns ="$primary_ns" + return fi fi @@ -1428,9 +1443,6 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n primary_ns=$(echo "$all_auth_dns_servers" | awk '{print $1}') fi - if [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then - primary_ns="$primary_ns $PUBLIC_DNS_SERVER" - fi return fi fi From 5732867d2dfda26576aa1eb17da7d4355d7f2b13 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 17 Dec 2020 22:00:04 +0000 Subject: [PATCH 160/308] Move DNS used for staging tests to Dynu --- dns_scripts/dns_add_dynu | 14 +++++--- dns_scripts/dns_del_dynu | 22 ++++++++---- test/15-test-revoke-no-suffix.bats | 6 +++- test/18-staging-retry-dns-add.bats | 16 +++++++-- test/Dockerfile-centos7-staging | 1 + test/Dockerfile-ubuntu-staging | 1 + test/dns_add_fail | 6 ++++ test/dns_fail_add_duckdns | 19 ---------- test/run-test.cmd | 2 +- test/run-test.sh | 3 +- .../getssl-staging-dns01-fail-dns-add.cfg | 33 ----------------- .../getssl-staging-dns01-no-suffix.cfg | 36 ------------------- test/test-config/getssl-staging-dns01.cfg | 11 ++++-- 13 files changed, 62 insertions(+), 108 deletions(-) create mode 100644 test/dns_add_fail delete mode 100755 test/dns_fail_add_duckdns delete mode 100644 test/test-config/getssl-staging-dns01-fail-dns-add.cfg delete mode 100644 test/test-config/getssl-staging-dns01-no-suffix.cfg diff --git a/dns_scripts/dns_add_dynu b/dns_scripts/dns_add_dynu index 7a08ce8..e20470d 100644 --- a/dns_scripts/dns_add_dynu +++ b/dns_scripts/dns_add_dynu @@ -28,10 +28,11 @@ fi curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) # Get domain id -resp=$(curl --silent "${curl_params[@]}" -X GET "$API") +# curl -X GET https://api.dynu.com/v2/dns/getroot/ubuntu-getssl.freeddns.org +resp=$(curl --silent "${curl_params[@]}" -X GET "$API/getroot/${fulldomain}") # Match domain id -re="\"id\":([^,]*),\"name\":\"getssl-testing.freeddns.org\"" +re="\"id\":([^,]*),\"domainName\":\"${fulldomain}\"" if [[ "$resp" =~ $re ]]; then domain_id="${BASH_REMATCH[1]}" fi @@ -42,6 +43,7 @@ if [[ -z "$domain_id" ]]; then fi # Check for existing _acme-challenge TXT record +# curl -X GET "https://api.dynu.com/v2/dns/record/_acme-challenge.ubuntu-getssl.freeddns.org?recordType=TXT" resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") re="\"id\":([^,]*)" if [[ "$resp" =~ $re ]]; then @@ -53,16 +55,18 @@ if [[ -z "$record_id" ]]; then resp=$(curl --silent \ "${curl_params[@]}" \ -X POST "${API}/${domain_id}/record" \ - --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"textData\":\"$token\"}") + --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"state\":\"true\",\"textData\":\"$token\"}") else + # Update existing record + # curl -X POST https://api.dynu.com/v2/dns/9329328/record/7082063 -d "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"state\":\"true\",\"textData\":\"Test2\"}" resp=$(curl --silent \ "${curl_params[@]}" \ -X POST "${API}/${domain_id}/record/${record_id}" \ - --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"textData\":\"$token\"}") + --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"state\":\"true\",\"textData\":\"$token\"}") fi # If adding record failed (exception:) then print error message -if [[ "${resp// }" == *'"exception"'* ]]; then +if [[ "$resp" != *"\"statusCode\":200"* ]]; then echo "Error: DNS challenge not added: unknown error - ${resp}" exit 3 fi diff --git a/dns_scripts/dns_del_dynu b/dns_scripts/dns_del_dynu index 310bb61..1d8d588 100644 --- a/dns_scripts/dns_del_dynu +++ b/dns_scripts/dns_del_dynu @@ -10,6 +10,12 @@ apikey=${DYNU_API_KEY:-''} # 2 - error within internal processing # 3 - error in result ( domain not found in dynu.com etc) +# After deleting the TXT record from Dynu.com it takes over 30 minutes to add a new TXT record! +# This doesn't happen when updating the TXT record, just for delete then add +# As this is used for testing, changed the delete to a no-op. + +exit 0 + fulldomain="${1}" API='https://api.dynu.com/v2/dns' @@ -20,17 +26,18 @@ if [[ -z "$fulldomain" ]]; then exit 1 fi if [[ -z "$apikey" ]]; then - echo "DNS script requires an apikey to be set" + echo "DNS script requires apikey environment variable to be set" exit 1 fi curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) # Get domain id -resp=$(curl --silent "${curl_params[@]}" -X GET "$API") +# curl -X GET https://api.dynu.com/v2/dns/getroot/ubuntu-getssl.freeddns.org +resp=$(curl --silent "${curl_params[@]}" -X GET "$API/getroot/${fulldomain}") # Match domain id -re="\"id\":([^,]*),\"name\":\"getssl-testing.freeddns.org\"" +re="\"id\":([^,]*),\"domainName\":\"${fulldomain}\"" if [[ "$resp" =~ $re ]]; then domain_id="${BASH_REMATCH[1]}" fi @@ -40,7 +47,8 @@ if [[ -z "$domain_id" ]]; then exit 3 fi -# Find existing _acme-challenge TXT record +# Check for existing _acme-challenge TXT record +# curl -X GET "https://api.dynu.com/v2/dns/record/_acme-challenge.ubuntu-getssl.freeddns.org?recordType=TXT" resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") re="\"id\":([^,]*)" if [[ "$resp" =~ $re ]]; then @@ -48,8 +56,8 @@ if [[ "$resp" =~ $re ]]; then fi if [[ -z "$record_id" ]]; then - echo "No _acme-challenge TXT record found for $fulldomain" - exit 3 + echo "No _acme-challenge.${fulldomain} TXT record found" + exit 0 fi resp=$(curl --silent \ @@ -57,7 +65,7 @@ resp=$(curl --silent \ -X DELETE "${API}/${domain_id}/record/${record_id}") # If adding record failed (exception:) then print error message -if [[ "${resp// }" == *'"exception"'* ]]; then +if [[ "$resp" != *"\"statusCode\":200"* ]]; then echo "Error: DNS challenge not added: unknown error - ${resp}" exit 3 fi diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index 5e8d797..96e174b 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -15,10 +15,12 @@ setup() { @test "Create certificate to check revoke (no suffix)" { if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01-no-suffix.cfg" + CONFIG_FILE="getssl-staging-dns01.cfg" else CONFIG_FILE="getssl-http01-no-suffix.cfg" fi + echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" setup_environment init_getssl @@ -34,6 +36,8 @@ setup() { else CONFIG_FILE="getssl-http01.cfg" fi + echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key diff --git a/test/18-staging-retry-dns-add.bats b/test/18-staging-retry-dns-add.bats index 8b636d6..bca7c05 100644 --- a/test/18-staging-retry-dns-add.bats +++ b/test/18-staging-retry-dns-add.bats @@ -6,14 +6,26 @@ load '/getssl/test/test_helper.bash' -@test "Check retry add dns command if dns isn't updated (DuckDNS)" { +@test "Check retry add dns command if dns isn't updated" { if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi - CONFIG_FILE="getssl-staging-dns01-fail-dns-add.cfg" + + CONFIG_FILE="getssl-staging-dns01.cfg" setup_environment init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +DNS_ADD_COMMAND="/getssl/test/dns_add_fail" + +# Speed up the test by reducing the number or retries and the wait between retries. +DNS_WAIT=2 +DNS_WAIT_COUNT=11 +DNS_EXTRA_WAIT=0 +CHECK_ALL_AUTH_DNS="false" +CHECK_PUBLIC_DNS_SERVER="false" +EOF create_certificate -d assert_failure assert_line --partial "Retrying adding dns via command" diff --git a/test/Dockerfile-centos7-staging b/test/Dockerfile-centos7-staging index 0b2ff08..ad49896 100644 --- a/test/Dockerfile-centos7-staging +++ b/test/Dockerfile-centos7-staging @@ -9,6 +9,7 @@ RUN yum -y install git curl bind-utils ldns wget which nginx ENV staging "true" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb +ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 WORKDIR /root RUN mkdir /etc/nginx/pki diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-staging index 1ee3f83..3032c85 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-staging @@ -8,6 +8,7 @@ ENV DEBIAN_FRONTEND noninteractive # Ensure tests in this image use the staging server ENV staging "true" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb +ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 # Update and install required software RUN apt-get update --fix-missing diff --git a/test/dns_add_fail b/test/dns_add_fail new file mode 100644 index 0000000..44ab42b --- /dev/null +++ b/test/dns_add_fail @@ -0,0 +1,6 @@ +#!/bin/bash + +# Special test script which will always fail to update dns + +echo "This is a test script to check retry works if DNS isn't updated" +exit 0 diff --git a/test/dns_fail_add_duckdns b/test/dns_fail_add_duckdns deleted file mode 100755 index 03df89f..0000000 --- a/test/dns_fail_add_duckdns +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# Special test script which will always fail to update dns - -token=${DUCKDNS_TOKEN:-} - -if [ -z "$token" ]; then - echo "DUCKDNS_TOKEN not set" - exit 1 -fi - -domain="$1" - -response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=FAIL") -if [ "$response" != "OK" ]; then - echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)" - echo "Response: $response" - exit 1 -fi diff --git a/test/run-test.cmd b/test/run-test.cmd index 23235c9..0462617 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -23,7 +23,7 @@ set COMMAND=bats /getssl/test GOTO CheckAlias :staging -set ALIAS=%OS:-staging=%-getssl.duckdns.org +set ALIAS=%OS:-staging=%-getssl.freeddns.org set STAGING=--env STAGING=true :Run diff --git a/test/run-test.sh b/test/run-test.sh index 8a2a9f2..760c600 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -15,7 +15,8 @@ else fi if [[ "$OS" == *"staging"* ]]; then - ALIAS="${OS%-staging}-getssl.duckdns.org" + #ALIAS="${OS%-staging}-getssl.duckdns.org" + ALIAS="${OS%-staging}-getssl.freeddns.org" STAGING="--env STAGING=true" else ALIAS="$OS.getssl.test" diff --git a/test/test-config/getssl-staging-dns01-fail-dns-add.cfg b/test/test-config/getssl-staging-dns01-fail-dns-add.cfg deleted file mode 100644 index 2985d32..0000000 --- a/test/test-config/getssl-staging-dns01-fail-dns-add.cfg +++ /dev/null @@ -1,33 +0,0 @@ -# Special config to test that the retry dns_add_command logic works -# -CA="https://acme-staging-v02.api.letsencrypt.org/directory" - -# Generic staging config -VALIDATE_VIA_DNS=true -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=ns2.duckdns.org -CHECK_ALL_AUTH_DNS=true - -# Test that the retry works (dns_add_command will always fail) -DNS_WAIT_RETRY_ADD="true" -DNS_ADD_COMMAND="/getssl/test/dns_fail_add_duckdns" - -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 -DNS_EXTRA_WAIT=0 - -# Standard config -ACCOUNT_KEY_TYPE="rsa" -PRIVATE_KEY_ALG="rsa" -SANS="" -ACL=('/var/www/html/.well-known/acme-challenge') -USE_SINGLE_ACL="false" -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 -RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx" -SERVER_TYPE="https" -CHECK_REMOTE="true" diff --git a/test/test-config/getssl-staging-dns01-no-suffix.cfg b/test/test-config/getssl-staging-dns01-no-suffix.cfg deleted file mode 100644 index b4f5202..0000000 --- a/test/test-config/getssl-staging-dns01-no-suffix.cfg +++ /dev/null @@ -1,36 +0,0 @@ -# Test that the script works with external dns provider and staging server -# -CA="https://acme-staging-v02.api.letsencrypt.org" - -VALIDATE_VIA_DNS=true -DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=ns2.duckdns.org -CHECK_ALL_AUTH_DNS=true -DNS_EXTRA_WAIT=120 - -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 -DNS_WAIT_RETRY_ADD="true" - -ACCOUNT_KEY_TYPE="rsa" -PRIVATE_KEY_ALG="rsa" - -# Additional domains - this could be multiple domains / subdomains in a comma separated list -SANS="" - -# 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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" - -# Define the server type and confirm correct certificate is installed (using a custom port) -SERVER_TYPE="https" -CHECK_REMOTE="true" diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 19413cd..64a7388 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -3,15 +3,17 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" VALIDATE_VIA_DNS=true -DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns" -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns" -PUBLIC_DNS_SERVER=1.1.1.1 +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_dynu" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_dynu" +PUBLIC_DNS_SERVER="8.8.8.8 resolver1.infoserve.de" +AUTH_DNS_SERVER=ns1.dynu.com CHECK_ALL_AUTH_DNS="true" CHECK_PUBLIC_DNS_SERVER="true" DNS_EXTRA_WAIT=120 # Speed up the test by reducing the number or retries and retrying DNS_ADD after 10 failures DNS_WAIT_COUNT=20 +DNS_WAIT=30 DNS_WAIT_RETRY_ADD="true" ACCOUNT_KEY_TYPE="rsa" @@ -38,3 +40,6 @@ CHECK_REMOTE="true" if [[ -s "$DOMAIN_DIR/getssl_test_specific.cfg" ]]; then . $DOMAIN_DIR/getssl_test_specific.cfg fi + +#_RUNNING_TEST=1 +#_USE_DEBUG=1 From 5969d5b3fa4d4cc3f7bfbae44d0fc7ed932e6e7b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 18 Dec 2020 21:36:44 +0000 Subject: [PATCH 161/308] Fix mktemp template format for alpine --- test/u4-create-csr-and-ifs.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/u4-create-csr-and-ifs.bats b/test/u4-create-csr-and-ifs.bats index c30277c..344a536 100644 --- a/test/u4-create-csr-and-ifs.bats +++ b/test/u4-create-csr-and-ifs.bats @@ -16,8 +16,8 @@ setup() { @test "Check create_csr works for multiple domains" { # Create a key - csr_key=$(mktemp -t getssl.XXXXXX.key) || error_exit "mktemp failed" - csr_file=$(mktemp -t getssl.XXXXXX.csr) || error_exit "mktemp failed" + csr_key=$(mktemp -t getssl.key.XXXXXX) || error_exit "mktemp failed" + csr_file=$(mktemp -t getssl.csr.XXXXXX) || error_exit "mktemp failed" SANS="a.getssl.test,b.getssl.test" SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" create_key "$ACCOUNT_KEY_TYPE" "$csr_key" "$ACCOUNT_KEY_LENGTH" From 26dadf3c7fb3d58b06df0564bcf8f02ac260a041 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 22 Dec 2020 12:48:06 +0000 Subject: [PATCH 162/308] Split tests into pebble/staging --- ...run-all-tests.yml => run-tests-pebble.yml} | 27 +------------------ .../workflows/run-tests-staging-duckdns.yml | 25 +++++++++++++++++ .github/workflows/run-tests-staging-dynu.yml | 25 +++++++++++++++++ 3 files changed, 51 insertions(+), 26 deletions(-) rename .github/workflows/{run-all-tests.yml => run-tests-pebble.yml} (67%) create mode 100644 .github/workflows/run-tests-staging-duckdns.yml create mode 100644 .github/workflows/run-tests-staging-dynu.yml diff --git a/.github/workflows/run-all-tests.yml b/.github/workflows/run-tests-pebble.yml similarity index 67% rename from .github/workflows/run-all-tests.yml rename to .github/workflows/run-tests-pebble.yml index 7bb05dc..0e26962 100644 --- a/.github/workflows/run-all-tests.yml +++ b/.github/workflows/run-tests-pebble.yml @@ -1,4 +1,4 @@ -name: Run all tests +name: Run all tests on pebble on: push: branches: @@ -15,14 +15,6 @@ jobs: run: docker-compose up -d --build - name: Run test suite on Alpine run: test/run-test.sh alpine - test-centos6: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on CentOS6 - run: test/run-test.sh centos6 test-centos7: runs-on: ubuntu-latest steps: @@ -31,14 +23,6 @@ jobs: run: docker-compose up -d --build - name: Run test suite on CentOS7 run: test/run-test.sh centos7 - test-centos7-staging: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on CentOS7 against Staging using DuckDNS - run: test/run-test.sh centos7-staging test-centos8: runs-on: ubuntu-latest steps: @@ -79,12 +63,3 @@ jobs: run: docker-compose up -d --build - name: Run test suite on Ubuntu18 run: test/run-test.sh ubuntu18 - test-ubuntu-staging: - needs: test-centos7-staging - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Build the docker-compose stack - run: docker-compose up -d --build - - name: Run test suite on Ubuntu against Staging using DuckDNS - run: test/run-test.sh ubuntu-staging diff --git a/.github/workflows/run-tests-staging-duckdns.yml b/.github/workflows/run-tests-staging-duckdns.yml new file mode 100644 index 0000000..54da950 --- /dev/null +++ b/.github/workflows/run-tests-staging-duckdns.yml @@ -0,0 +1,25 @@ +name: Run all tests using DuckDNS +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + test-centos7-duckdns: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on CentOS7 against Staging using DuckDNS + run: test/run-test.sh centos7-duckdns + test-ubuntu-duckdns: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Ubuntu against Staging using DuckDNS + run: test/run-test.sh ubuntu-duckdns diff --git a/.github/workflows/run-tests-staging-dynu.yml b/.github/workflows/run-tests-staging-dynu.yml new file mode 100644 index 0000000..c523278 --- /dev/null +++ b/.github/workflows/run-tests-staging-dynu.yml @@ -0,0 +1,25 @@ +name: Run all tests using Dynu +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + test-centos7-dynu: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on CentOS7 against Staging using Dynu + run: test/run-test.sh centos7-dynu + test-ubuntu-dynu: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Ubuntu against Staging using Dynu + run: test/run-test.sh ubuntu-dynu From 5d6988f0eca3175f3ef3cdbd72fb41e1b15b8b4a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 22 Dec 2020 12:48:57 +0000 Subject: [PATCH 163/308] Test using both Dynu.com and Duckdns.org --- ...os7-staging => Dockerfile-centos7-duckdns} | 2 +- test/Dockerfile-centos7-dynu | 29 ++++++++++++++++++ ...untu-staging => Dockerfile-ubuntu-duckdns} | 2 +- test/Dockerfile-ubuntu-dynu | 30 +++++++++++++++++++ test/run-test.cmd | 18 +++++++---- test/run-test.sh | 14 +++++---- test/test-config/getssl-staging-dns01.cfg | 10 +++++-- test/u1-test-get_auth_dns-dig.bats | 14 ++++----- test/u2-test-get_auth_dns-drill.bats | 14 ++++----- 9 files changed, 104 insertions(+), 29 deletions(-) rename test/{Dockerfile-centos7-staging => Dockerfile-centos7-duckdns} (94%) create mode 100644 test/Dockerfile-centos7-dynu rename test/{Dockerfile-ubuntu-staging => Dockerfile-ubuntu-duckdns} (94%) create mode 100644 test/Dockerfile-ubuntu-dynu diff --git a/test/Dockerfile-centos7-staging b/test/Dockerfile-centos7-duckdns similarity index 94% rename from test/Dockerfile-centos7-staging rename to test/Dockerfile-centos7-duckdns index ad49896..719c9de 100644 --- a/test/Dockerfile-centos7-staging +++ b/test/Dockerfile-centos7-duckdns @@ -8,8 +8,8 @@ RUN yum -y install epel-release RUN yum -y install git curl bind-utils ldns wget which nginx ENV staging "true" +ENV dynamic_dns "dynu" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb -ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 WORKDIR /root RUN mkdir /etc/nginx/pki diff --git a/test/Dockerfile-centos7-dynu b/test/Dockerfile-centos7-dynu new file mode 100644 index 0000000..01d41a7 --- /dev/null +++ b/test/Dockerfile-centos7-dynu @@ -0,0 +1,29 @@ +FROM centos:centos7 + +# Note this image uses gawk + +# Update and install required software +RUN yum -y update +RUN yum -y install epel-release +RUN yum -y install git curl bind-utils ldns wget which nginx + +ENV staging "true" +ENV dynamic_dns "duckdns" +ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 + +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 +COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf + +# BATS (Bash Automated Testings) +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN /bats-core/install.sh /usr/local + +EXPOSE 80 443 + +# Run eternal loop - for testing +CMD tail -f /dev/null diff --git a/test/Dockerfile-ubuntu-staging b/test/Dockerfile-ubuntu-duckdns similarity index 94% rename from test/Dockerfile-ubuntu-staging rename to test/Dockerfile-ubuntu-duckdns index 3032c85..f4cf9e3 100644 --- a/test/Dockerfile-ubuntu-staging +++ b/test/Dockerfile-ubuntu-duckdns @@ -7,8 +7,8 @@ ENV DEBIAN_FRONTEND noninteractive # Ensure tests in this image use the staging server ENV staging "true" +ENV dynamic_dns "duckdns" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb -ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 # Update and install required software RUN apt-get update --fix-missing diff --git a/test/Dockerfile-ubuntu-dynu b/test/Dockerfile-ubuntu-dynu new file mode 100644 index 0000000..2ea8c31 --- /dev/null +++ b/test/Dockerfile-ubuntu-dynu @@ -0,0 +1,30 @@ +FROM ubuntu:latest + +# Note this image uses mawk1.3 + +# Set noninteractive otherwise tzdata hangs +ENV DEBIAN_FRONTEND noninteractive + +# Ensure tests in this image use the staging server +ENV staging "true" +ENV dynamic_dns "dynu" +ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 + +# Update and install required software +RUN apt-get update --fix-missing +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light +RUN apt-get install -y vim dos2unix # for debugging + +WORKDIR /root + +# Prevent "Can't load /root/.rnd into RNG" error from openssl +RUN touch /root/.rnd + +# BATS (Bash Automated Testings) +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN /bats-core/install.sh /usr/local + +# Run eternal loop - for testing +CMD tail -f /dev/null diff --git a/test/run-test.cmd b/test/run-test.cmd index 0462617..af5fb30 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -8,7 +8,8 @@ set COMMAND=%2 %3 :CheckAlias REM check if OS *contains* staging -IF NOT x%OS:staging=%==x%OS% GOTO staging +IF NOT x%OS:duck=%==x%OS% GOTO duckdns +IF NOT x%OS:dynu=%==x%OS% GOTO dynu set ALIAS=%OS%.getssl.test set STAGING= GOTO Run @@ -22,9 +23,16 @@ REM set COMMAND=/getssl/test/run-bats.sh set COMMAND=bats /getssl/test GOTO CheckAlias -:staging -set ALIAS=%OS:-staging=%-getssl.freeddns.org -set STAGING=--env STAGING=true +:duckdns +set ALIAS=%OS:-duckdns=%-getssl.duckdns.org +set STAGING=--env STAGING=true --env dynamic_dns=duckdns +set GETSSL_OS=%OS:-duckdns=% +GOTO Run + +:dynu +set ALIAS=%OS:-dynu=%-getssl.freeddns.org +set STAGING=--env STAGING=true --env dynamic_dns=dynu +set GETSSL_OS=%OS:-dynu=% :Run for %%I in (.) do set CurrDirName=%%~nxI @@ -33,7 +41,7 @@ docker build --rm -f "test\Dockerfile-%OS%" -t getssl-%OS% . @echo on docker run -it ^ --env GETSSL_HOST=%ALIAS% %STAGING% ^ - --env GETSSL_OS=%OS:-staging=% ^ + --env GETSSL_OS=%GETSSL_OS% ^ -v %cd%:/getssl ^ --rm ^ --network %CurrDirName%_acmenet ^ diff --git a/test/run-test.sh b/test/run-test.sh index 760c600..0503c2d 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -14,10 +14,14 @@ else COMMAND="bats /getssl/test" fi -if [[ "$OS" == *"staging"* ]]; then - #ALIAS="${OS%-staging}-getssl.duckdns.org" - ALIAS="${OS%-staging}-getssl.freeddns.org" - STAGING="--env STAGING=true" +if [[ "$OS" == *"duckdns"* ]]; then + ALIAS="${OS%-duckdns}-getssl.duckdns.org" + STAGING="--env STAGING=true --env dynamic_dns=duckdns" + GETSSL_OS="${OS%-duckdns}" +elif [[ "$OS" == *"dynu"* ]]; then + ALIAS="${OS%-dynu}-getssl.freeddns.org" + STAGING="--env STAGING=true --env dynamic_dns=dynu" + GETSSL_OS="${OS%-dynu}" else ALIAS="$OS.getssl.test" STAGING="" @@ -27,7 +31,7 @@ docker build --rm -f "test/Dockerfile-$OS" -t "getssl-$OS" . # shellcheck disable=SC2086 docker run \ --env GETSSL_HOST=$ALIAS $STAGING \ - --env GETSSL_OS=${OS%-staging} \ + --env GETSSL_OS=$GETSSL_OS \ -v "$(pwd)":/getssl \ --rm \ --network ${PWD##*/}_acmenet \ diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg index 64a7388..8859686 100644 --- a/test/test-config/getssl-staging-dns01.cfg +++ b/test/test-config/getssl-staging-dns01.cfg @@ -3,10 +3,14 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" VALIDATE_VIA_DNS=true -DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_dynu" -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_dynu" +DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_${dynamic_dns}" +DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_${dynamic_dns}" PUBLIC_DNS_SERVER="8.8.8.8 resolver1.infoserve.de" -AUTH_DNS_SERVER=ns1.dynu.com +if [[ "${dynamic_dns}" == "dynu" ]]; then + AUTH_DNS_SERVER=ns1.dynu.com +else + AUTH_DNS_SERVER=ns1.duckdns.org +fi CHECK_ALL_AUTH_DNS="true" CHECK_PUBLIC_DNS_SERVER="true" DNS_EXTRA_WAIT=120 diff --git a/test/u1-test-get_auth_dns-dig.bats b/test/u1-test-get_auth_dns-dig.bats index d13cc56..6e64e68 100644 --- a/test/u1-test-get_auth_dns-dig.bats +++ b/test/u1-test-get_auth_dns-dig.bats @@ -59,14 +59,14 @@ teardown() { run get_auth_dns ubuntu-getssl.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we had to use dig NS assert_line --partial 'Using dig NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' } @@ -86,7 +86,7 @@ teardown() { run get_auth_dns ubuntu-getssl.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we had to use dig NS assert_line --partial 'Using dig SOA' @@ -95,12 +95,12 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' # Check that we also check the public DNS server if requested CHECK_PUBLIC_DNS_SERVER=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org 1\.0\.0\.1' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org 1\.0\.0\.1' } @@ -165,7 +165,7 @@ teardown() { run get_auth_dns www.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we found a CNAME but didn't use dig NS assert_line --partial 'Using dig CNAME' @@ -174,5 +174,5 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns www.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' } diff --git a/test/u2-test-get_auth_dns-drill.bats b/test/u2-test-get_auth_dns-drill.bats index 1db1011..c5feadf 100644 --- a/test/u2-test-get_auth_dns-drill.bats +++ b/test/u2-test-get_auth_dns-drill.bats @@ -78,14 +78,14 @@ teardown() { run get_auth_dns ubuntu-getssl.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we had to use drill NS assert_line --partial 'Using drill NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' } @@ -110,7 +110,7 @@ teardown() { run get_auth_dns ubuntu-getssl.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we had to use drill NS assert_line --partial 'Using drill SOA' @@ -119,12 +119,12 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' # Check that we also check the public DNS server if requested CHECK_PUBLIC_DNS_SERVER=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org 1\.0\.0\.1' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org 1\.0\.0\.1' } @@ -202,7 +202,7 @@ teardown() { run get_auth_dns www.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we found a CNAME but didn't use drill NS assert_line --partial 'Using drill CNAME' @@ -211,5 +211,5 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns www.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org ns[1-3]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' } From f33f796c932b6031e3db518054d3a37b7b6bb08f Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 22 Dec 2020 14:43:54 +0000 Subject: [PATCH 164/308] Ensure GETSSL_OS variable is set --- test/run-test.cmd | 1 + test/run-test.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/test/run-test.cmd b/test/run-test.cmd index af5fb30..47b2a79 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -12,6 +12,7 @@ IF NOT x%OS:duck=%==x%OS% GOTO duckdns IF NOT x%OS:dynu=%==x%OS% GOTO dynu set ALIAS=%OS%.getssl.test set STAGING= +set GETSSL_OS=%OS% GOTO Run :NoOS diff --git a/test/run-test.sh b/test/run-test.sh index 0503c2d..715dae3 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -25,6 +25,7 @@ elif [[ "$OS" == *"dynu"* ]]; then else ALIAS="$OS.getssl.test" STAGING="" + GETSSL_OS=$OS fi docker build --rm -f "test/Dockerfile-$OS" -t "getssl-$OS" . From b931b79d622af7728f0727268df08467f2e68cf0 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 22 Dec 2020 14:49:12 +0000 Subject: [PATCH 165/308] Fix execute permission on dns scripts --- dns_scripts/dns_add_dynu | 0 dns_scripts/dns_del_dynu | 0 test/dns_add_fail | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 dns_scripts/dns_add_dynu mode change 100644 => 100755 dns_scripts/dns_del_dynu mode change 100644 => 100755 test/dns_add_fail diff --git a/dns_scripts/dns_add_dynu b/dns_scripts/dns_add_dynu old mode 100644 new mode 100755 diff --git a/dns_scripts/dns_del_dynu b/dns_scripts/dns_del_dynu old mode 100644 new mode 100755 diff --git a/test/dns_add_fail b/test/dns_add_fail old mode 100644 new mode 100755 From 1d1159f946ccc47ef037ca86dfdeb2ca0290aa16 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 22 Dec 2020 18:57:33 +0000 Subject: [PATCH 166/308] Add timing information to tests --- getssl | 2 +- test/run-test.cmd | 2 +- test/run-test.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/getssl b/getssl index 924c835..2257349 100755 --- a/getssl +++ b/getssl @@ -507,7 +507,7 @@ check_challenge_completion_dns() { # perform validation via DNS challenge # check for token at public dns server, waiting for a valid response. for ns in $primary_ns; do - debug "checking dns at $ns" + info "checking dns at $ns" ntries=0 check_dns="fail" while [[ "$check_dns" == "fail" ]]; do diff --git a/test/run-test.cmd b/test/run-test.cmd index 47b2a79..ed6ad6e 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -21,7 +21,7 @@ GOTO CheckCommand :NoCmd REM set COMMAND=/getssl/test/run-bats.sh -set COMMAND=bats /getssl/test +set COMMAND=bats /getssl/test --timing GOTO CheckAlias :duckdns diff --git a/test/run-test.sh b/test/run-test.sh index 715dae3..18443cd 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -11,7 +11,7 @@ if [ $# -gt 1 ]; then shift COMMAND=$* else - COMMAND="bats /getssl/test" + COMMAND="bats /getssl/test --timing" fi if [[ "$OS" == *"duckdns"* ]]; then From aef203287c5c06a51f5b3d791f9731c3eff469b5 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 22 Dec 2020 20:46:06 +0000 Subject: [PATCH 167/308] Check that dig doesn't return an error before setting HAS_DIG_OR_DRILL --- getssl | 2 +- test/30-handle-dig-failure.bats | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 test/30-handle-dig-failure.bats diff --git a/getssl b/getssl index 2257349..b714129 100755 --- a/getssl +++ b/getssl @@ -1094,7 +1094,7 @@ find_dns_utils() { if [[ -n "$(command -v drill 2>/dev/null)" ]]; then debug "HAS DIG_OR_DRILL=drill" HAS_DIG_OR_DRILL="drill" - elif [[ -n "$(command -v dig 2>/dev/null)" ]]; then + elif [[ -n "$(command -v dig 2>/dev/null)" ]] && dig >/dev/null 2>&1; then debug "HAS DIG_OR_DRILL=dig" HAS_DIG_OR_DRILL="dig" fi diff --git a/test/30-handle-dig-failure.bats b/test/30-handle-dig-failure.bats new file mode 100644 index 0000000..7ebd2c3 --- /dev/null +++ b/test/30-handle-dig-failure.bats @@ -0,0 +1,44 @@ +#! /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 + if [ -f /usr/bin/drill ]; then + mv /usr/bin/drill /usr/bin/drill.getssl.bak + fi + if [ -f /usr/bin/dig ]; then + chmod +x /usr/bin/dig + fi +} + + +teardown() { + if [ -f /usr/bin/drill.getssl.bak ]; then + mv /usr/bin/drill.getssl.bak /usr/bin/drill + fi + if [ -f /usr/bin/dig ]; then + chmod -x /usr/bin/dig + fi +} + + +@test "Test that if dig exists but errors HAS_DIG is not set" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + if [ ! -f /usr/bin/dig ]; then + skip "dig not installed, skipping dig test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate -d + assert_success + refute_line --partial "HAS DIG_OR_DRILL=dig" + check_output_for_errors "debug" +} From 836b3d8ebcafd14b6020394e949e58c33e1bb993 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 22 Dec 2020 20:55:14 +0000 Subject: [PATCH 168/308] Update revision history and version --- getssl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index b714129..eefe4fa 100755 --- a/getssl +++ b/getssl @@ -242,11 +242,16 @@ # 2020-10-04 Add CHECK_PUBLIC_DNS_SERVER to check the DNS challenge has been updated there # 2020-10-13 Bugfix: strip comments in drill/dig output (mhameed) # 2020-11-18 Wildcard support (#347)(#400)(2.31) +# 2020-12-08 Fix mktemp template on alpine (#612) +# 2020-12-17 Fix delimiter issues with ${alldomains[]} in create_csr (#614)(vietw) +# 2020-12-18 Wrong SANS when domain contains a minus character (atisne) +# 2020-12-22 Fixes to get_auth_dns +# 2020-12-22 Check that dig doesn't return an error (#611)(2.32) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.31" +VERSION="2.32" # defaults ACCOUNT_KEY_LENGTH=4096 From bd11be65ccb942c356232c6b78534885f2e682d7 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 23 Dec 2020 10:08:41 +0000 Subject: [PATCH 169/308] Fix typo --- test/30-handle-dig-failure.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/30-handle-dig-failure.bats b/test/30-handle-dig-failure.bats index 7ebd2c3..1102745 100644 --- a/test/30-handle-dig-failure.bats +++ b/test/30-handle-dig-failure.bats @@ -12,7 +12,7 @@ setup() { mv /usr/bin/drill /usr/bin/drill.getssl.bak fi if [ -f /usr/bin/dig ]; then - chmod +x /usr/bin/dig + chmod -x /usr/bin/dig fi } @@ -22,7 +22,7 @@ teardown() { mv /usr/bin/drill.getssl.bak /usr/bin/drill fi if [ -f /usr/bin/dig ]; then - chmod -x /usr/bin/dig + chmod +x /usr/bin/dig fi } From 35a3e0226f9e5fb39428a472f82beed1d2d1b917 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 28 Dec 2020 15:21:43 +0000 Subject: [PATCH 170/308] Remove duplicate teardown() function --- test/u2-test-get_auth_dns-drill.bats | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/test/u2-test-get_auth_dns-drill.bats b/test/u2-test-get_auth_dns-drill.bats index c5feadf..33b2277 100644 --- a/test/u2-test-get_auth_dns-drill.bats +++ b/test/u2-test-get_auth_dns-drill.bats @@ -31,19 +31,6 @@ teardown() { } -teardown() { - if [ -f /usr/bin/host.getssl.bak ]; then - mv /usr/bin/host.getssl.bak /usr/bin/host - fi - if [ -f /usr/bin/nslookup.getssl.bak ]; then - mv /usr/bin/nslookup.getssl.bak /usr/bin/nslookup - fi - if [ -f /usr/bin/dig.getssl.bak ]; then - mv /usr/bin/dig.getssl.bak /usr/bin/dig - fi -} - - @test "Check get_auth_dns using drill NS" { if [ ! -f /usr/bin/drill ]; then # Can't find drill package for centos8 From dd3d72a806bfd710beadb101b24618dafc99fa4d Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 28 Dec 2020 15:25:25 +0000 Subject: [PATCH 171/308] Add tests for issue #617 --- .../u5-test-get_auth_dns-no-root-servers.bats | 89 +++++++++++++++++ .../u6-test-get_auth_dns-no-root-servers.bats | 99 +++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 test/u5-test-get_auth_dns-no-root-servers.bats create mode 100644 test/u6-test-get_auth_dns-no-root-servers.bats diff --git a/test/u5-test-get_auth_dns-no-root-servers.bats b/test/u5-test-get_auth_dns-no-root-servers.bats new file mode 100644 index 0000000..40d79a4 --- /dev/null +++ b/test/u5-test-get_auth_dns-no-root-servers.bats @@ -0,0 +1,89 @@ +#! /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() { + for app in drill host nslookup + do + if [ -f /usr/bin/${app} ]; then + mv /usr/bin/${app} /usr/bin/${app}.getssl.bak + fi + done + + . /getssl/getssl --source + find_dns_utils + _RUNNING_TEST=1 + _USE_DEBUG=0 +} + + +teardown() { + for app in drill host nslookup + do + if [ -f /usr/bin/${app}.getssl.bak ]; then + mv /usr/bin/${app}.getssl.bak /usr/bin/${app} + fi + done +} + + +@test "Check get_auth_dns doesn't include root servers (dig NS)" { + # Test that get_auth_dns() handles scenario where NS query returns root servers + # Issue #617 + # + # Log output was: + # Verifying example.com + # checking DNS at h.root-servers.net for example.com. Attempt 1/100 gave wrong result, waiting 10 secs before checking again + # ... (retried until max attempts then failed) + + # Disable SOA and CNAME check + _TEST_SKIP_CNAME_CALL=1 + _TEST_SKIP_SOA_CALL=1 + + PUBLIC_DNS_SERVER=8.8.8.8 + CHECK_PUBLIC_DNS_SERVER=false + CHECK_ALL_AUTH_DNS=true + + run get_auth_dns example.com + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ' + # Assert that we had to use dig NS + assert_line --partial 'Using dig NS' + + # Check we didn't include any root servers + refute_line --partial 'IN\WNS\W\.root-servers\.net\.' +} + + +@test "Check get_auth_dns doesn't include root servers (dig SOA)" { + # Test that get_auth_dns() handles scenario where NS query returns root servers + # Issue #617 + # + # Log output was: + # Verifying example.com + # checking DNS at h.root-servers.net for example.com. Attempt 1/100 gave wrong result, waiting 10 secs before checking again + # ... (retried until max attempts then failed) + + # Disable CNAME check, ensure SOA check is enabled + _TEST_SKIP_CNAME_CALL=1 + _TEST_SKIP_SOA_CALL=0 + + PUBLIC_DNS_SERVER=8.8.8.8 + CHECK_PUBLIC_DNS_SERVER=false + CHECK_ALL_AUTH_DNS=true + + run get_auth_dns example.com + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ' + # Assert that we had to use dig SOA + assert_line --partial 'Using dig SOA' + + # Check we didn't include any root servers + refute_line --partial 'IN\WNS\W\.root-servers\.net\.' +} diff --git a/test/u6-test-get_auth_dns-no-root-servers.bats b/test/u6-test-get_auth_dns-no-root-servers.bats new file mode 100644 index 0000000..84012c3 --- /dev/null +++ b/test/u6-test-get_auth_dns-no-root-servers.bats @@ -0,0 +1,99 @@ +#! /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() { + for app in dig host nslookup + do + if [ -f /usr/bin/${app} ]; then + mv /usr/bin/${app} /usr/bin/${app}.getssl.bak + fi + done + + . /getssl/getssl --source + find_dns_utils + _RUNNING_TEST=1 + _USE_DEBUG=0 +} + + +teardown() { + for app in dig host nslookup + do + if [ -f /usr/bin/${app}.getssl.bak ]; then + mv /usr/bin/${app}.getssl.bak /usr/bin/${app} + fi + done +} + + +@test "Check get_auth_dns doesn't include root servers (drill NS)" { + if [ ! -f /usr/bin/drill ]; then + # Can't find drill package for centos8 + skip "Drill not installed on this system" + fi + + # Test that get_auth_dns() handles scenario where NS query returns root servers + # Issue #617 + # + # Log output was: + # Verifying example.com + # checking DNS at h.root-servers.net for example.com. Attempt 1/100 gave wrong result, waiting 10 secs before checking again + # ... (retried until max attempts then failed) + + # Disable CNAME check, ensure SOA check is enabled + _TEST_SKIP_CNAME_CALL=1 + _TEST_SKIP_SOA_CALL=1 + + PUBLIC_DNS_SERVER=8.8.8.8 + CHECK_PUBLIC_DNS_SERVER=false + CHECK_ALL_AUTH_DNS=true + + run get_auth_dns example.com + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ' + # Assert that we had to use drill NS + assert_line --partial 'Using drill NS' + + # Check we didn't include any root servers + refute_line --partial 'IN\WNS\W\.root-servers\.net\.' +} + + +@test "Check get_auth_dns doesn't include root servers (drill SOA)" { + if [ ! -f /usr/bin/drill ]; then + # Can't find drill package for centos8 + skip "Drill not installed on this system" + fi + + # Test that get_auth_dns() handles scenario where NS query returns root servers + # Issue #617 + # + # Log output was: + # Verifying example.com + # checking DNS at h.root-servers.net for example.com. Attempt 1/100 gave wrong result, waiting 10 secs before checking again + # ... (retried until max attempts then failed) + + # Disable SOA and CNAME check + _TEST_SKIP_CNAME_CALL=1 + _TEST_SKIP_SOA_CALL=0 + + PUBLIC_DNS_SERVER=8.8.8.8 + CHECK_PUBLIC_DNS_SERVER=false + CHECK_ALL_AUTH_DNS=true + + run get_auth_dns example.com + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns = ' + # Assert that we had to use drill SOA + assert_line --partial 'Using drill SOA' + + # Check we didn't include any root servers + refute_line --partial 'IN\WNS\W\.root-servers\.net\.' +} From 630554073e5a54caa5b8a8a538c84361cc0302f7 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 28 Dec 2020 16:15:38 +0000 Subject: [PATCH 172/308] Remove spaces around server when calling dig or drill --- getssl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index eefe4fa..afa5fba 100755 --- a/getssl +++ b/getssl @@ -1310,11 +1310,11 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ "$HAS_DIG_OR_DRILL" == "dig" ]]; then debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d $gad_s" to find primary nameserver test_output "Using $HAS_DIG_OR_DRILL SOA" - res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" "$gad_s" 2>/dev/null | grep "IN\WNS\W") + res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W") else debug Using "$HAS_DIG_OR_DRILL -T $gad_d $gad_s" to find primary nameserver test_output "Using $HAS_DIG_OR_DRILL SOA" - res=$($HAS_DIG_OR_DRILL -T SOA "$gad_d" "$gad_s" 2>/dev/null | grep "IN\WNS\W") + res=$($HAS_DIG_OR_DRILL -T SOA "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W") fi fi @@ -1324,12 +1324,12 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n # Two options here; either dig CNAME will return the CNAME and the NS or just the CNAME debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d $gad_s" - res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" "$gad_s"| grep "^$gad_d") + res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" $gad_s| grep "^$gad_d") cname=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') if [[ $_TEST_SKIP_CNAME_CALL == 0 ]]; then debug Checking if CNAME result contains NS records - res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" "$gad_s"| grep -E "IN\W(NS|SOA)\W") + res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" $gad_s| grep -E "IN\W(NS|SOA)\W") else res="" fi @@ -1385,7 +1385,8 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ -z "$gad_s" ]]; then res=$(host -t NS "$gad_d"| grep "name server") else - res=$(host -t NS "$gad_d" "$gad_s"| grep "name server") + # shellcheck disable=SC2086 + res=$(host -t NS "$gad_d" $gad_s| grep "name server") fi if [[ -n "$res" ]]; then all_auth_dns_servers=$(echo "$res" | awk '{print $4}' | sed 's/\.$//g'|tr '\n' ' ') From f8f3e5b901eb0d622795fad0b88be43946b9b952 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 29 Dec 2020 21:36:44 +0000 Subject: [PATCH 173/308] Updated tests to reproduce bug in #617 --- .../u5-test-get_auth_dns-no-root-servers.bats | 15 ++- .../u6-test-get_auth_dns-no-root-servers.bats | 99 ------------------- 2 files changed, 11 insertions(+), 103 deletions(-) delete mode 100644 test/u6-test-get_auth_dns-no-root-servers.bats diff --git a/test/u5-test-get_auth_dns-no-root-servers.bats b/test/u5-test-get_auth_dns-no-root-servers.bats index 40d79a4..b88fd41 100644 --- a/test/u5-test-get_auth_dns-no-root-servers.bats +++ b/test/u5-test-get_auth_dns-no-root-servers.bats @@ -7,6 +7,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + cp /etc/resolv.conf /etc/resolv.conf.getssl + cat <<- EOF > /etc/resolv.conf +nameserver 8.8.8.8 +options ndots:0 +EOF + for app in drill host nslookup do if [ -f /usr/bin/${app} ]; then @@ -22,6 +28,7 @@ setup() { teardown() { + cat /etc/resolv.conf.getssl > /etc/resolv.conf for app in drill host nslookup do if [ -f /usr/bin/${app}.getssl.bak ]; then @@ -44,7 +51,7 @@ teardown() { _TEST_SKIP_CNAME_CALL=1 _TEST_SKIP_SOA_CALL=1 - PUBLIC_DNS_SERVER=8.8.8.8 + PUBLIC_DNS_SERVER= CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=true @@ -56,7 +63,7 @@ teardown() { assert_line --partial 'Using dig NS' # Check we didn't include any root servers - refute_line --partial 'IN\WNS\W\.root-servers\.net\.' + refute_line --partial 'root-servers.net' } @@ -73,7 +80,7 @@ teardown() { _TEST_SKIP_CNAME_CALL=1 _TEST_SKIP_SOA_CALL=0 - PUBLIC_DNS_SERVER=8.8.8.8 + PUBLIC_DNS_SERVER= CHECK_PUBLIC_DNS_SERVER=false CHECK_ALL_AUTH_DNS=true @@ -85,5 +92,5 @@ teardown() { assert_line --partial 'Using dig SOA' # Check we didn't include any root servers - refute_line --partial 'IN\WNS\W\.root-servers\.net\.' + refute_line --partial 'root-servers.net' } diff --git a/test/u6-test-get_auth_dns-no-root-servers.bats b/test/u6-test-get_auth_dns-no-root-servers.bats deleted file mode 100644 index 84012c3..0000000 --- a/test/u6-test-get_auth_dns-no-root-servers.bats +++ /dev/null @@ -1,99 +0,0 @@ -#! /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() { - for app in dig host nslookup - do - if [ -f /usr/bin/${app} ]; then - mv /usr/bin/${app} /usr/bin/${app}.getssl.bak - fi - done - - . /getssl/getssl --source - find_dns_utils - _RUNNING_TEST=1 - _USE_DEBUG=0 -} - - -teardown() { - for app in dig host nslookup - do - if [ -f /usr/bin/${app}.getssl.bak ]; then - mv /usr/bin/${app}.getssl.bak /usr/bin/${app} - fi - done -} - - -@test "Check get_auth_dns doesn't include root servers (drill NS)" { - if [ ! -f /usr/bin/drill ]; then - # Can't find drill package for centos8 - skip "Drill not installed on this system" - fi - - # Test that get_auth_dns() handles scenario where NS query returns root servers - # Issue #617 - # - # Log output was: - # Verifying example.com - # checking DNS at h.root-servers.net for example.com. Attempt 1/100 gave wrong result, waiting 10 secs before checking again - # ... (retried until max attempts then failed) - - # Disable CNAME check, ensure SOA check is enabled - _TEST_SKIP_CNAME_CALL=1 - _TEST_SKIP_SOA_CALL=1 - - PUBLIC_DNS_SERVER=8.8.8.8 - CHECK_PUBLIC_DNS_SERVER=false - CHECK_ALL_AUTH_DNS=true - - run get_auth_dns example.com - - # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ' - # Assert that we had to use drill NS - assert_line --partial 'Using drill NS' - - # Check we didn't include any root servers - refute_line --partial 'IN\WNS\W\.root-servers\.net\.' -} - - -@test "Check get_auth_dns doesn't include root servers (drill SOA)" { - if [ ! -f /usr/bin/drill ]; then - # Can't find drill package for centos8 - skip "Drill not installed on this system" - fi - - # Test that get_auth_dns() handles scenario where NS query returns root servers - # Issue #617 - # - # Log output was: - # Verifying example.com - # checking DNS at h.root-servers.net for example.com. Attempt 1/100 gave wrong result, waiting 10 secs before checking again - # ... (retried until max attempts then failed) - - # Disable SOA and CNAME check - _TEST_SKIP_CNAME_CALL=1 - _TEST_SKIP_SOA_CALL=0 - - PUBLIC_DNS_SERVER=8.8.8.8 - CHECK_PUBLIC_DNS_SERVER=false - CHECK_ALL_AUTH_DNS=true - - run get_auth_dns example.com - - # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ' - # Assert that we had to use drill SOA - assert_line --partial 'Using drill SOA' - - # Check we didn't include any root servers - refute_line --partial 'IN\WNS\W\.root-servers\.net\.' -} From a1d4eb00ccb8102faf8c4ae3095c49a060913c4f Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 29 Dec 2020 21:39:50 +0000 Subject: [PATCH 174/308] Update version and revision history --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index afa5fba..a20a9bd 100755 --- a/getssl +++ b/getssl @@ -247,11 +247,12 @@ # 2020-12-18 Wrong SANS when domain contains a minus character (atisne) # 2020-12-22 Fixes to get_auth_dns # 2020-12-22 Check that dig doesn't return an error (#611)(2.32) +# 2020-12-29 Fix dig SOA lookup (#617)(2.33) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.32" +VERSION="2.33" # defaults ACCOUNT_KEY_LENGTH=4096 From 140456f602bc0af525611a35fd18df3260a01c6a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 30 Dec 2020 20:55:19 +0000 Subject: [PATCH 175/308] Run tests on older versions of bash --- .github/workflows/run-tests-pebble.yml | 24 ++++++++++++++++++++++++ test/Dockerfile-bash4-0 | 22 ++++++++++++++++++++++ test/Dockerfile-bash4-2 | 22 ++++++++++++++++++++++ test/Dockerfile-bash5-0 | 22 ++++++++++++++++++++++ test/run-test.cmd | 7 +++++++ test/run-test.sh | 26 ++++++++++++++------------ 6 files changed, 111 insertions(+), 12 deletions(-) create mode 100644 test/Dockerfile-bash4-0 create mode 100644 test/Dockerfile-bash4-2 create mode 100644 test/Dockerfile-bash5-0 diff --git a/.github/workflows/run-tests-pebble.yml b/.github/workflows/run-tests-pebble.yml index 0e26962..058bb35 100644 --- a/.github/workflows/run-tests-pebble.yml +++ b/.github/workflows/run-tests-pebble.yml @@ -15,6 +15,30 @@ jobs: run: docker-compose up -d --build - name: Run test suite on Alpine run: test/run-test.sh alpine + test-bash-4-0: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Alpine using Bash 4.0 + run: test/run-test.sh bash4-0 + test-bash-4-2: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Alpine using Bash 4.2 + run: test/run-test.sh bash4-2 + test-bash-5-0: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on Alpine using Bash 5 + run: test/run-test.sh bash5-0 test-centos7: runs-on: ubuntu-latest steps: diff --git a/test/Dockerfile-bash4-0 b/test/Dockerfile-bash4-0 new file mode 100644 index 0000000..e75b74a --- /dev/null +++ b/test/Dockerfile-bash4-0 @@ -0,0 +1,22 @@ +FROM bash:4.0 + +# https://hub.docker.com/_/bash + +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash + +WORKDIR /root + +# Create nginx directories in standard places +RUN mkdir /run/nginx +RUN mkdir /etc/nginx/pki +RUN mkdir /etc/nginx/pki/private + +# BATS (Bash Automated Testings) +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN /bats-core/install.sh /usr/local + +# Use supervisord to run nginx in the background +COPY ./test/test-config/alpine-supervisord.conf /etc/supervisord.conf +CMD tail -f /dev/null diff --git a/test/Dockerfile-bash4-2 b/test/Dockerfile-bash4-2 new file mode 100644 index 0000000..720884c --- /dev/null +++ b/test/Dockerfile-bash4-2 @@ -0,0 +1,22 @@ +FROM bash:4.2 + +# https://hub.docker.com/_/bash + +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash + +WORKDIR /root + +# Create nginx directories in standard places +RUN mkdir /run/nginx +RUN mkdir /etc/nginx/pki +RUN mkdir /etc/nginx/pki/private + +# BATS (Bash Automated Testings) +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN /bats-core/install.sh /usr/local + +# Use supervisord to run nginx in the background +COPY ./test/test-config/alpine-supervisord.conf /etc/supervisord.conf +CMD tail -f /dev/null diff --git a/test/Dockerfile-bash5-0 b/test/Dockerfile-bash5-0 new file mode 100644 index 0000000..ba0295a --- /dev/null +++ b/test/Dockerfile-bash5-0 @@ -0,0 +1,22 @@ +FROM bash:5.0 + +# https://hub.docker.com/_/bash + +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash + +WORKDIR /root + +# Create nginx directories in standard places +RUN mkdir /run/nginx +RUN mkdir /etc/nginx/pki +RUN mkdir /etc/nginx/pki/private + +# BATS (Bash Automated Testings) +RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone https://github.com/bats-core/bats-support /bats-support +RUN git clone https://github.com/bats-core/bats-assert /bats-assert +RUN /bats-core/install.sh /usr/local + +# Use supervisord to run nginx in the background +COPY ./test/test-config/alpine-supervisord.conf /etc/supervisord.conf +CMD tail -f /dev/null diff --git a/test/run-test.cmd b/test/run-test.cmd index ed6ad6e..d33c005 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -10,6 +10,7 @@ set COMMAND=%2 %3 REM check if OS *contains* staging IF NOT x%OS:duck=%==x%OS% GOTO duckdns IF NOT x%OS:dynu=%==x%OS% GOTO dynu +IF NOT x%OS:bash=%==x%OS% GOTO bash set ALIAS=%OS%.getssl.test set STAGING= set GETSSL_OS=%OS% @@ -34,6 +35,12 @@ GOTO Run set ALIAS=%OS:-dynu=%-getssl.freeddns.org set STAGING=--env STAGING=true --env dynamic_dns=dynu set GETSSL_OS=%OS:-dynu=% +GOTO Run + +:bash +set ALIAS=%OS%.getssl.test +set STAGING= +set GETSSL_OS=alpine :Run for %%I in (.) do set CurrDirName=%%~nxI diff --git a/test/run-test.sh b/test/run-test.sh index 18443cd..4aa9d9f 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -1,27 +1,29 @@ #! /usr/bin/env bash if [ $# -eq 0 ]; then - echo "Usage: $(basename "$0") []" - echo "e.g. $(basename "$0") alpine bats /getssl/test" - exit 1 + echo "Usage: $(basename "$0") []" + echo "e.g. $(basename "$0") alpine bats /getssl/test" + exit 1 fi OS=$1 if [ $# -gt 1 ]; then - shift - COMMAND=$* + shift + COMMAND=$* else - COMMAND="bats /getssl/test --timing" + COMMAND="bats /getssl/test --timing" fi if [[ "$OS" == *"duckdns"* ]]; then - ALIAS="${OS%-duckdns}-getssl.duckdns.org" - STAGING="--env STAGING=true --env dynamic_dns=duckdns" - GETSSL_OS="${OS%-duckdns}" + ALIAS="${OS%-duckdns}-getssl.duckdns.org" + STAGING="--env STAGING=true --env dynamic_dns=duckdns" + GETSSL_OS="${OS%-duckdns}" elif [[ "$OS" == *"dynu"* ]]; then - ALIAS="${OS%-dynu}-getssl.freeddns.org" - STAGING="--env STAGING=true --env dynamic_dns=dynu" - GETSSL_OS="${OS%-dynu}" + ALIAS="${OS%-dynu}-getssl.freeddns.org" + STAGING="--env STAGING=true --env dynamic_dns=dynu" + GETSSL_OS="${OS%-dynu}" +elif [[ "$OS" == "bash"* ]]; then + GETSSL_OS="alpine" else ALIAS="$OS.getssl.test" STAGING="" From 4b2d4e4109a821d99c59cff1b6d734dfc5b58f75 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 30 Dec 2020 20:56:01 +0000 Subject: [PATCH 176/308] Use vault.centos6 --- test/Dockerfile-centos6 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index d578f4b..6874cb2 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -5,8 +5,14 @@ FROM centos:centos6 # [wsl2] # kernelCommandLine = vsyscall=emulate +# Centos 6 is EOL and is no longer available from the usual mirrors, so switch +# to https://vault.centos.org +RUN sed -i 's/enabled=1/enabled=0/g' /etc/yum/pluginconf.d/fastestmirror.conf && \ + sed -i 's/^mirrorlist/#mirrorlist/g' /etc/yum.repos.d/*.repo && \ + sed -i 's;^#baseurl=http://mirror;baseurl=https://vault;g' /etc/yum.repos.d/*.repo + # Update and install required software -RUN yum -y update +#RUN yum -y update RUN yum -y install epel-release RUN yum -y install git curl dnsutils ldns wget nginx From a02306294abaf66109c55a06f67a6ae004497c2d Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 30 Dec 2020 20:59:58 +0000 Subject: [PATCH 177/308] Add centos6 tests back --- .github/workflows/run-tests-pebble.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/run-tests-pebble.yml b/.github/workflows/run-tests-pebble.yml index 058bb35..29af06d 100644 --- a/.github/workflows/run-tests-pebble.yml +++ b/.github/workflows/run-tests-pebble.yml @@ -39,6 +39,14 @@ jobs: run: docker-compose up -d --build - name: Run test suite on Alpine using Bash 5 run: test/run-test.sh bash5-0 + test-centos76 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on CentOS6 + run: test/run-test.sh centos6 test-centos7: runs-on: ubuntu-latest steps: From 12f2921c3bf08e451ddea848d8c6f7ce69ea1897 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 30 Dec 2020 22:01:20 +0000 Subject: [PATCH 178/308] Fix typo --- .github/workflows/run-tests-pebble.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests-pebble.yml b/.github/workflows/run-tests-pebble.yml index 29af06d..5dc53a4 100644 --- a/.github/workflows/run-tests-pebble.yml +++ b/.github/workflows/run-tests-pebble.yml @@ -39,7 +39,7 @@ jobs: run: docker-compose up -d --build - name: Run test suite on Alpine using Bash 5 run: test/run-test.sh bash5-0 - test-centos76 + test-centos6: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 From 1b24a5820f243d2f837e0da93aeb311ad0ea3eb2 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 31 Dec 2020 10:32:16 +0000 Subject: [PATCH 179/308] Set env variables when running bash containers --- test/run-test.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/run-test.sh b/test/run-test.sh index 4aa9d9f..ef7e403 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -14,6 +14,10 @@ else COMMAND="bats /getssl/test --timing" fi +ALIAS="$OS.getssl.test" +STAGING="" +GETSSL_OS=$OS + if [[ "$OS" == *"duckdns"* ]]; then ALIAS="${OS%-duckdns}-getssl.duckdns.org" STAGING="--env STAGING=true --env dynamic_dns=duckdns" @@ -24,10 +28,6 @@ elif [[ "$OS" == *"dynu"* ]]; then GETSSL_OS="${OS%-dynu}" elif [[ "$OS" == "bash"* ]]; then GETSSL_OS="alpine" -else - ALIAS="$OS.getssl.test" - STAGING="" - GETSSL_OS=$OS fi docker build --rm -f "test/Dockerfile-$OS" -t "getssl-$OS" . From 0c48343c7a35e299595c6af70c7191a5cc402262 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 1 Jan 2021 18:39:08 +0000 Subject: [PATCH 180/308] Check for posix mode and show a sensible error --- getssl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/getssl b/getssl index a20a9bd..be34b3b 100755 --- a/getssl +++ b/getssl @@ -250,6 +250,10 @@ # 2020-12-29 Fix dig SOA lookup (#617)(2.33) # ---------------------------------------------------------------------------------------- +case :$SHELLOPTS: in + *:posix:*) echo -e "${0##*/}: Running with POSIX mode enabled is not supported" >&2; exit 1;; +esac + PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" VERSION="2.33" From 6ce5114b6bfbc0dfbf529101d6767c4a00630a39 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 5 Jan 2021 18:41:29 +0000 Subject: [PATCH 181/308] Show error message if starting new getssl after upgrade fails --- getssl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index be34b3b..5d74222 100755 --- a/getssl +++ b/getssl @@ -771,7 +771,9 @@ check_getssl_upgrade() { # check if a more recent version of code is available a getssl_versions=("${getssl_versions[@]:1}") done fi - eval "$ORIGCMD" + if ! eval "$ORIGCMD"; then + error_exit "Running upgraded getssl failed" + fi graceful_exit else info "" From a749cb460687fc197cee52fc579e8c8683874133 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 5 Jan 2021 18:42:52 +0000 Subject: [PATCH 182/308] Add tests for --upgrade and posix error --- test/31-test-posix-error.bats | 25 ++++++++++ test/32-test-upgrade.bats | 78 ++++++++++++++++++++++++++++++ test/test-config/getssl-http01.cfg | 7 +++ 3 files changed, 110 insertions(+) create mode 100644 test/31-test-posix-error.bats create mode 100644 test/32-test-upgrade.bats diff --git a/test/31-test-posix-error.bats b/test/31-test-posix-error.bats new file mode 100644 index 0000000..e9950fd --- /dev/null +++ b/test/31-test-posix-error.bats @@ -0,0 +1,25 @@ +#! /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 "Test that running in POSIX mode shows an error" { + # v2.31 uses read to create an array in the get_auth_dns function which causes a parse error in posix mode + # Could be re-written to not use this functionality if it causes for required. + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + run bash --posix "${CODE_DIR}/getssl" + assert_failure + assert_line "getssl: Running with POSIX mode enabled is not supported" + check_output_for_errors +} diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats new file mode 100644 index 0000000..5b66dee --- /dev/null +++ b/test/32-test-upgrade.bats @@ -0,0 +1,78 @@ +#! /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 + CURRENT_VERSION=$(awk -F '"' '$1 == "VERSION=" {print $2}' ${CODE_DIR}/getssl) + PREVIOUS_VERSION=$(echo ${CURRENT_VERSION} | awk -F. '{ print $1 "." --$2}') + run git clone https://github.com/srvrco/getssl.git "$INSTALL_DIR/upgrade-getssl" +} + + +teardown() { + rm -r "$INSTALL_DIR/upgrade-getssl" +} + + +@test "Test that we are told that a newer version is available" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + cd "$INSTALL_DIR/upgrade-getssl" + git checkout tags/v${PREVIOUS_VERSION} + + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config ${GETSSL_CMD_HOST} + assert_success + #assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" + assert_line "A more recent version (v${CURRENT_VERSION}) of getssl is available, please update" + check_output_for_errors +} + + +@test "Test that we can upgrade to the newer version" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + cd "$INSTALL_DIR/upgrade-getssl" + git checkout tags/v${PREVIOUS_VERSION} + + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config --upgrade ${GETSSL_CMD_HOST} + assert_success + assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" + check_output_for_errors +} + + +@test "Test that we can upgrade to the newer version when invoking as \"bash ./getssl\"" { + # Note that `bash getssl` will fail if the CWD isn't in the PATH and an upgrade occurs + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + cd "$INSTALL_DIR/upgrade-getssl" + git checkout tags/v${PREVIOUS_VERSION} + + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + run bash ./getssl --check-config --upgrade ${GETSSL_CMD_HOST} + assert_success + assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" + check_output_for_errors +} diff --git a/test/test-config/getssl-http01.cfg b/test/test-config/getssl-http01.cfg index f7d75ea..9a713bc 100644 --- a/test/test-config/getssl-http01.cfg +++ b/test/test-config/getssl-http01.cfg @@ -27,3 +27,10 @@ RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /get # Define the server type and confirm correct certificate is installed SERVER_TYPE="https" CHECK_REMOTE="true" + +if [[ -s "$DOMAIN_DIR/getssl_test_specific.cfg" ]]; then + . $DOMAIN_DIR/getssl_test_specific.cfg +fi + +#_USE_DEBUG=1 +#_RUNNING_TEST=1 From 01299603dece01f0d9877b024880df2fe6099e7c Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 5 Jan 2021 18:46:47 +0000 Subject: [PATCH 183/308] Update revision history --- getssl | 1 + 1 file changed, 1 insertion(+) diff --git a/getssl b/getssl index 5d74222..4ca7f1b 100755 --- a/getssl +++ b/getssl @@ -248,6 +248,7 @@ # 2020-12-22 Fixes to get_auth_dns # 2020-12-22 Check that dig doesn't return an error (#611)(2.32) # 2020-12-29 Fix dig SOA lookup (#617)(2.33) +# 2021-01-05 Show error if running in POSIX mode (#611) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in From 3fb75d493f29d201c910068dfe5ca24b380fe213 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 5 Jan 2021 21:42:40 +0000 Subject: [PATCH 184/308] Change --$var to $var-1 for Alpine --- test/32-test-upgrade.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index 5b66dee..1c8af6d 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -9,7 +9,7 @@ load '/getssl/test/test_helper.bash' setup() { export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt CURRENT_VERSION=$(awk -F '"' '$1 == "VERSION=" {print $2}' ${CODE_DIR}/getssl) - PREVIOUS_VERSION=$(echo ${CURRENT_VERSION} | awk -F. '{ print $1 "." --$2}') + PREVIOUS_VERSION=$(echo ${CURRENT_VERSION} | awk -F. '{ print $1 "." $2-1}') run git clone https://github.com/srvrco/getssl.git "$INSTALL_DIR/upgrade-getssl" } From 79ac70653d5432eb6db3153ed6754de050a7c291 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 7 Jan 2021 21:54:16 +0000 Subject: [PATCH 185/308] Add chmod to ftp command --- getssl | 1 + 1 file changed, 1 insertion(+) diff --git a/getssl b/getssl index 4ca7f1b..9a42b28 100755 --- a/getssl +++ b/getssl @@ -859,6 +859,7 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. cd $ftpdirn lcd $fromdir put ./$fromfile + chmod 644 $fromfile _EOF elif [[ "${to:0:5}" == "sftp:" ]] ; then debug "using sftp to copy the file from $from" From 12eb0ae0d1ec2395d9a0cae5dfa914307bceae0a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 7 Jan 2021 21:55:33 +0000 Subject: [PATCH 186/308] First ftp test --- test/33-ftp.bats | 37 +++++++++++++++++++++++++++++++++++++ test/Dockerfile-ubuntu | 10 ++++++++++ test/restart-ftpd | 11 +++++++++++ test/run-test.cmd | 2 +- 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 test/33-ftp.bats create mode 100644 test/restart-ftpd diff --git a/test/33-ftp.bats b/test/33-ftp.bats new file mode 100644 index 0000000..d6387df --- /dev/null +++ b/test/33-ftp.bats @@ -0,0 +1,37 @@ +#! /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 "Use FTP to create challenge file" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + ${CODE_DIR}/test/restart-ftpd + if [[ ! -d /var/www/html/.well-known/acme-challenge ]]; then + mkdir -p /var/www/html/.well-known/acme-challenge + chgrp -R www-data /var/www/html/.well-known + chmod -R g+w /var/www/html/.well-known + fi + + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +ACL="ftp:ftpuser:ftpuser:${GETSSL_CMD_HOST}:/var/www/html/.well-known/acme-challenge" +EOF + + create_certificate -d + assert_success + check_output_for_errors +} diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index 3849e55..4e80409 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -9,6 +9,16 @@ ENV DEBIAN_FRONTEND noninteractive RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light RUN apt-get install -y vim dos2unix # for debugging +RUN apt-get install -y ftp vsftpd +RUN apt-get install -y openssh-server + +RUN echo "write_enable=YES" >> /etc/vsftpd.conf +RUN adduser ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser ftpuser www-data +RUN adduser root www-data +RUN chown -R www-data.www-data /var/www +RUN chmod g+w -R /var/www WORKDIR /root diff --git a/test/restart-ftpd b/test/restart-ftpd new file mode 100644 index 0000000..279c2ff --- /dev/null +++ b/test/restart-ftpd @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +if [ "$GETSSL_OS" = "alpine" ]; then + killall -HUP vsftpd >&3- + sleep 5 +elif [[ "$GETSSL_OS" == "centos"[78] ]]; then + pgrep vsftpd | head -1 | xargs kill -HUP + sleep 5 +else + service vsftpd restart >/dev/null >&3- +fi diff --git a/test/run-test.cmd b/test/run-test.cmd index d33c005..5908de7 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -45,7 +45,7 @@ set GETSSL_OS=alpine :Run for %%I in (.) do set CurrDirName=%%~nxI -docker build --rm -f "test\Dockerfile-%OS%" -t getssl-%OS% . +docker build --pull --rm -f "test\Dockerfile-%OS%" -t getssl-%OS% . @echo on docker run -it ^ --env GETSSL_HOST=%ALIAS% %STAGING% ^ From f46a36db8969a6fd42ef23e4958032e237613587 Mon Sep 17 00:00:00 2001 From: ionos Date: Fri, 15 Jan 2021 20:48:12 -0500 Subject: [PATCH 187/308] Fix double slash when using root directory with DAVS --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 4ca7f1b..f16da93 100755 --- a/getssl +++ b/getssl @@ -886,12 +886,13 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. davsport=$(echo "$to"| awk -F: '{print $5}') davslocn=$(echo "$to"| awk -F: '{print $6}') davsdirn=$(dirname "$davslocn") + davsdirn=$(echo "${davsdirn}/" | sed 's,//,/,g') davsfile=$(basename "$davslocn") fromdir=$(dirname "$from") fromfile=$(basename "$from") debug "davs user=$davsuser - pass=$davspass - host=$davshost port=$davsport dir=$davsdirn file=$davsfile" debug "from dir=$fromdir file=$fromfile" - curl -u "${davsuser}:${davspass}" -T "${fromdir}/${fromfile}" "https://${davshost}:${davsport}${davsdirn}/${davsfile}" + curl -u "${davsuser}:${davspass}" -T "${fromdir}/${fromfile}" "https://${davshost}:${davsport}${davsdirn}${davsfile}" else if ! mkdir -p "$(dirname "$to")" ; then error_exit "cannot create ACL directory $(basename "$to")" From 4d23e085e146b8712860e60a13a6780c35b81262 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 16 Jan 2021 15:12:22 +0000 Subject: [PATCH 188/308] Add FTP_OPTIONS --- getssl | 36 ++++++++++++++++++++++++++++++------ test/33-ftp.bats | 3 ++- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/getssl b/getssl index 9a42b28..f34cac0 100755 --- a/getssl +++ b/getssl @@ -274,6 +274,7 @@ DEACTIVATE_AUTH="false" DEFAULT_REVOKE_CA="https://acme-v02.api.letsencrypt.org" DOMAIN_KEY_LENGTH=4096 DUAL_RSA_ECDSA="false" +FTP_OPTIONS="" GETSSL_IGNORE_CP_PRESERVE="false" HTTP_TOKEN_CHECK_WAIT=0 IGNORE_DIRECTORY_DOMAIN="false" @@ -842,6 +843,9 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. if [[ "$cert" != "challenge token" ]] ; then error_exit "ftp is not a secure method for copying certificates or keys" fi + if [[ -z "$FTP_COMMAND" ]]; then + error_exit "No ftp command found" + fi debug "using ftp to copy the file from $from" ftpuser=$(echo "$to"| awk -F: '{print $2}') ftppass=$(echo "$to"| awk -F: '{print $3}') @@ -853,13 +857,18 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. fromfile=$(basename "$from") debug "ftp user=$ftpuser - pass=$ftppass - host=$ftphost dir=$ftpdirn file=$ftpfile" debug "from dir=$fromdir file=$fromfile" - ftp -n <<- _EOF - open $ftphost - user $ftpuser $ftppass + if [ -n "$FTP_OPTIONS" ]; then + # Use eval to expand any variables in FTP_OPTIONS + FTP_OPTIONS=$(eval echo "$FTP_OPTIONS") + debug "FTP_OPTIONS=$FTP_OPTIONS" + fi + $FTP_COMMAND <<- _EOF + connect $ftphost + user $ftpuser $ftppass cd $ftpdirn lcd $fromdir put ./$fromfile - chmod 644 $fromfile + $FTP_OPTIONS _EOF elif [[ "${to:0:5}" == "sftp:" ]] ; then debug "using sftp to copy the file from $from" @@ -1119,6 +1128,18 @@ find_dns_utils() { fi } +find_ftp_command() { + FTP_COMMAND="" + if [[ -n "$(command -v ftp 2>/dev/null)" ]]; then + debug "Has ftp" + FTP_COMMAND="ftp -n" + elif [[ -n "$(command -v lftp 2>/dev/null)" ]]; then + debug "Has lftp" + FTP_COMMAND="lftp" + fi +} + + fulfill_challenges() { dn=0 for d in "${alldomains[@]}"; do @@ -1268,8 +1289,8 @@ for d in "${alldomains[@]}"; do ftppass=$(echo "${t_loc}"| awk -F: '{print $3}') ftphost=$(echo "${t_loc}"| awk -F: '{print $4}') ftplocn=$(echo "${t_loc}"| awk -F: '{print $5}') - debug "ftp user=$ftpuser - pass=$ftppass - host=$ftphost location=$ftplocn" - ftp -n <<- EOF + debug "$FTP_COMMAND user=$ftpuser - pass=$ftppass - host=$ftphost location=$ftplocn" + $FTP_COMMAND <<- EOF open $ftphost user $ftpuser $ftppass cd $ftplocn @@ -2654,6 +2675,9 @@ set_server_type # check what dns utils are installed find_dns_utils +# Find what ftp client is installed +find_ftp_command + # auto upgrade clients to v2 auto_upgrade_v2 diff --git a/test/33-ftp.bats b/test/33-ftp.bats index d6387df..9c52bb2 100644 --- a/test/33-ftp.bats +++ b/test/33-ftp.bats @@ -29,9 +29,10 @@ setup() { cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg ACL="ftp:ftpuser:ftpuser:${GETSSL_CMD_HOST}:/var/www/html/.well-known/acme-challenge" +FTP_OPTIONS="chmod 644 \\\$fromfile" EOF - create_certificate -d + create_certificate assert_success check_output_for_errors } From d7869561a3ca88d76eb0fc2b48f15d2fed45df3c Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 19 Jan 2021 12:04:47 +0000 Subject: [PATCH 189/308] Change ftp command back to use `open` --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index f34cac0..69bb152 100755 --- a/getssl +++ b/getssl @@ -863,7 +863,7 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. debug "FTP_OPTIONS=$FTP_OPTIONS" fi $FTP_COMMAND <<- _EOF - connect $ftphost + open $ftphost user $ftpuser $ftppass cd $ftpdirn lcd $fromdir From e407426bdba2ed46a6d24f2f97a6d18c928b9049 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 20 Jan 2021 22:00:32 +0000 Subject: [PATCH 190/308] Move FTP_OPTIONS earlier otherwise cd and put will fail --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 69bb152..aae7ad9 100755 --- a/getssl +++ b/getssl @@ -865,10 +865,10 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. $FTP_COMMAND <<- _EOF open $ftphost user $ftpuser $ftppass + $FTP_OPTIONS cd $ftpdirn lcd $fromdir put ./$fromfile - $FTP_OPTIONS _EOF elif [[ "${to:0:5}" == "sftp:" ]] ; then debug "using sftp to copy the file from $from" From 8f32f9f0788034121f76115e794a54ad46478d31 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 20 Jan 2021 22:02:09 +0000 Subject: [PATCH 191/308] Test ftp and passive ftp --- test/33-ftp.bats | 37 +++++++- test/34-ftp-passive.bats | 67 +++++++++++++++ test/Dockerfile-alpine | 14 ++- test/Dockerfile-bash4-0 | 14 ++- test/Dockerfile-bash4-2 | 14 ++- test/Dockerfile-bash5-0 | 14 ++- test/Dockerfile-centos6 | 23 ++++- test/Dockerfile-centos7 | 15 ++++ test/Dockerfile-centos8 | 15 ++++ test/Dockerfile-debian | 13 +++ test/Dockerfile-ubuntu | 5 +- test/Dockerfile-ubuntu16 | 15 ++++ test/Dockerfile-ubuntu18 | 15 ++++ test/restart-ftpd | 2 - test/run-test.cmd | 39 +++++---- test/test-config/alpine-supervisord.conf | 9 ++ test/test-config/vsftpd.conf | 66 +++++++++++++++ test/test-config/vsftpd.initd | 103 +++++++++++++++++++++++ test/test_helper.bash | 7 +- 19 files changed, 453 insertions(+), 34 deletions(-) create mode 100644 test/34-ftp-passive.bats create mode 100644 test/test-config/vsftpd.conf create mode 100644 test/test-config/vsftpd.initd diff --git a/test/33-ftp.bats b/test/33-ftp.bats index 9c52bb2..9c0bb2f 100644 --- a/test/33-ftp.bats +++ b/test/33-ftp.bats @@ -8,6 +8,21 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl + + # enable passive and disable active mode + # https://www.pixelstech.net/article/1364817664-FTP-active-mode-and-passive-mode + cat <<- _FTP >> $VSFTPD_CONF +pasv_enable=NO +_FTP + + ${CODE_DIR}/test/restart-ftpd +} + + +teardown() { + cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF + ${CODE_DIR}/test/restart-ftpd } @@ -16,23 +31,37 @@ setup() { skip "Using staging server, skipping internal test" fi - ${CODE_DIR}/test/restart-ftpd if [[ ! -d /var/www/html/.well-known/acme-challenge ]]; then mkdir -p /var/www/html/.well-known/acme-challenge - chgrp -R www-data /var/www/html/.well-known - chmod -R g+w /var/www/html/.well-known fi + # Always change ownership and permissions in case previous tests created the directories as root + chgrp -R www-data /var/www/html/.well-known + chmod -R g+w /var/www/html/.well-known + CONFIG_FILE="getssl-http01.cfg" setup_environment init_getssl cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg ACL="ftp:ftpuser:ftpuser:${GETSSL_CMD_HOST}:/var/www/html/.well-known/acme-challenge" -FTP_OPTIONS="chmod 644 \\\$fromfile" EOF + if [[ "$GETSSL_OS" = "alpine" ]]; then + cat <<- EOF2 >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +FTP_OPTIONS="set ftp:passive-mode off" +EOF2 + elif [[ "$FTP_PASSIVE_DEFAULT" == "true" ]]; then + cat <<- EOF3 >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +FTP_OPTIONS="passive" +EOF3 + fi + create_certificate assert_success + assert_line --partial "ftp:ftpuser:ftpuser:" + if [[ "$GETSSL_OS" != "alpine" ]] && [[ "$FTP_PASSIVE_DEFAULT" == "true" ]]; then + assert_line --partial "Passive mode off" + fi check_output_for_errors } diff --git a/test/34-ftp-passive.bats b/test/34-ftp-passive.bats new file mode 100644 index 0000000..cb61dda --- /dev/null +++ b/test/34-ftp-passive.bats @@ -0,0 +1,67 @@ +#! /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 + cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl + + # enable passive and disable active mode + # https://www.pixelstech.net/article/1364817664-FTP-active-mode-and-passive-mode + cat <<- _FTP >> $VSFTPD_CONF +pasv_enable=YES +pasv_max_port=10100 +pasv_min_port=10090 +connect_from_port_20=NO +_FTP + + ${CODE_DIR}/test/restart-ftpd +} + + +teardown() { + cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF + ${CODE_DIR}/test/restart-ftpd +} + + +@test "Use Passive FTP to create challenge file" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + if [[ ! -d /var/www/html/.well-known/acme-challenge ]]; then + mkdir -p /var/www/html/.well-known/acme-challenge + fi + + # Always change ownership and permissions in case previous tests created the directories as root + chgrp -R www-data /var/www/html/.well-known + chmod -R g+w /var/www/html/.well-known + + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +ACL="ftp:ftpuser:ftpuser:${GETSSL_CMD_HOST}:/var/www/html/.well-known/acme-challenge" +EOF + if [[ "$FTP_PASSIVE_DEFAULT" == "false" ]]; then + cat <<- EOF3 >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +FTP_OPTIONS="passive" +EOF3 + fi + + create_certificate + assert_success + assert_line --partial "ftp:ftpuser:ftpuser:" + if [[ "$FTP_PASSIVE_DEFAULT" == "false" ]]; then + assert_line --partial "Passive mode on" + else + refute_line --partial "Passive mode off" + fi + check_output_for_errors +} diff --git a/test/Dockerfile-alpine b/test/Dockerfile-alpine index b609938..924950b 100644 --- a/test/Dockerfile-alpine +++ b/test/Dockerfile-alpine @@ -2,7 +2,7 @@ FROM alpine:latest # Note this image uses busybox awk instead of gawk -RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash lftp vsftpd openssh-server WORKDIR /root @@ -11,6 +11,18 @@ RUN mkdir /run/nginx RUN mkdir /etc/nginx/pki RUN mkdir /etc/nginx/pki/private +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=true +COPY ./test/test-config/vsftpd.conf /etc/vsftpd.conf +RUN echo "seccomp_sandbox=NO" >> /etc/vsftpd.conf +RUN adduser -D ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser ftpuser www-data +RUN adduser root www-data +RUN chown -R ftpuser.www-data /var/www +RUN chmod g+w -R /var/www + # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support diff --git a/test/Dockerfile-bash4-0 b/test/Dockerfile-bash4-0 index e75b74a..9b1f790 100644 --- a/test/Dockerfile-bash4-0 +++ b/test/Dockerfile-bash4-0 @@ -2,7 +2,7 @@ FROM bash:4.0 # https://hub.docker.com/_/bash -RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server WORKDIR /root @@ -11,6 +11,18 @@ RUN mkdir /run/nginx RUN mkdir /etc/nginx/pki RUN mkdir /etc/nginx/pki/private +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=true +COPY ./test/test-config/vsftpd.conf /etc/vsftpd.conf +RUN echo "seccomp_sandbox=NO" >> /etc/vsftpd.conf +RUN adduser -D ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser ftpuser www-data +RUN adduser root www-data +RUN chown -R ftpuser.www-data /var/www +RUN chmod g+w -R /var/www + # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support diff --git a/test/Dockerfile-bash4-2 b/test/Dockerfile-bash4-2 index 720884c..d9386f6 100644 --- a/test/Dockerfile-bash4-2 +++ b/test/Dockerfile-bash4-2 @@ -2,7 +2,7 @@ FROM bash:4.2 # https://hub.docker.com/_/bash -RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server WORKDIR /root @@ -11,6 +11,18 @@ RUN mkdir /run/nginx RUN mkdir /etc/nginx/pki RUN mkdir /etc/nginx/pki/private +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=true +COPY ./test/test-config/vsftpd.conf /etc/vsftpd.conf +RUN echo "seccomp_sandbox=NO" >> /etc/vsftpd.conf +RUN adduser -D ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser ftpuser www-data +RUN adduser root www-data +RUN chown -R ftpuser.www-data /var/www +RUN chmod g+w -R /var/www + # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support diff --git a/test/Dockerfile-bash5-0 b/test/Dockerfile-bash5-0 index ba0295a..2d776eb 100644 --- a/test/Dockerfile-bash5-0 +++ b/test/Dockerfile-bash5-0 @@ -2,7 +2,7 @@ FROM bash:5.0 # https://hub.docker.com/_/bash -RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server WORKDIR /root @@ -11,6 +11,18 @@ RUN mkdir /run/nginx RUN mkdir /etc/nginx/pki RUN mkdir /etc/nginx/pki/private +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=true +COPY ./test/test-config/vsftpd.conf /etc/vsftpd.conf +RUN echo "seccomp_sandbox=NO" >> /etc/vsftpd.conf +RUN adduser -D ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser ftpuser www-data +RUN adduser root www-data +RUN chown -R ftpuser.www-data /var/www +RUN chmod g+w -R /var/www + # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index 6874cb2..a8d59b0 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -5,16 +5,29 @@ FROM centos:centos6 # [wsl2] # kernelCommandLine = vsyscall=emulate -# Centos 6 is EOL and is no longer available from the usual mirrors, so switch -# to https://vault.centos.org +# Centos 6 is EOL and is no longer available from the usual mirrors, so switch to https://vault.centos.org RUN sed -i 's/enabled=1/enabled=0/g' /etc/yum/pluginconf.d/fastestmirror.conf && \ sed -i 's/^mirrorlist/#mirrorlist/g' /etc/yum.repos.d/*.repo && \ sed -i 's;^#baseurl=http://mirror;baseurl=https://vault;g' /etc/yum.repos.d/*.repo # Update and install required software -#RUN yum -y update RUN yum -y install epel-release RUN yum -y install git curl dnsutils ldns wget nginx +RUN yum -y install ftp vsftpd +RUN yum -y install openssh-server + +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=true +COPY test/test-config/vsftpd.conf /etc/vsftpd/vsftpd.conf +RUN adduser ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser www-data +RUN usermod -G www-data ftpuser +RUN usermod -G www-data root +RUN mkdir -p /var/www/.well-known/acme-challenge +RUN chown -R www-data.www-data /var/www +RUN chmod g+w -R /var/www WORKDIR /root RUN mkdir /etc/nginx/pki @@ -22,10 +35,12 @@ 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 --branch v1.2.1 +RUN git clone https://github.com/bats-core/bats-core.git /bats-core # --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support RUN git clone https://github.com/bats-core/bats-assert /bats-assert RUN /bats-core/install.sh /usr/local +# Hack to disable BATS pretty formatter which stopped working on centos6 +ENV CI=yes EXPOSE 80 443 diff --git a/test/Dockerfile-centos7 b/test/Dockerfile-centos7 index e86f521..8bf8fa9 100644 --- a/test/Dockerfile-centos7 +++ b/test/Dockerfile-centos7 @@ -4,6 +4,8 @@ FROM centos:centos7 RUN yum -y update RUN yum -y install epel-release RUN yum -y install git curl ldns bind-utils wget which nginx +RUN yum -y install ftp vsftpd +RUN yum -y install openssh-server WORKDIR /root RUN mkdir /etc/nginx/pki @@ -11,6 +13,19 @@ RUN mkdir /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=true +COPY test/test-config/vsftpd.conf /etc/vsftpd/vsftpd.conf +RUN adduser ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser www-data +RUN usermod -G www-data ftpuser +RUN usermod -G www-data root +RUN mkdir -p /var/www/.well-known/acme-challenge +RUN chown -R www-data.www-data /var/www +RUN chmod g+w -R /var/www + # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support diff --git a/test/Dockerfile-centos8 b/test/Dockerfile-centos8 index 4ccb817..64f4381 100644 --- a/test/Dockerfile-centos8 +++ b/test/Dockerfile-centos8 @@ -6,6 +6,8 @@ FROM centos:centos8 RUN yum -y update RUN yum -y install epel-release RUN yum -y install git curl bind-utils wget which nginx +RUN yum -y install ftp vsftpd +RUN yum -y install openssh-server WORKDIR /root RUN mkdir /etc/nginx/pki @@ -13,6 +15,19 @@ RUN mkdir /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=true +COPY test/test-config/vsftpd.conf /etc/vsftpd/vsftpd.conf +RUN adduser ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser www-data +RUN usermod -G www-data ftpuser +RUN usermod -G www-data root +RUN mkdir -p /var/www/.well-known/acme-challenge +RUN chown -R www-data.www-data /var/www +RUN chmod g+w -R /var/www + # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support diff --git a/test/Dockerfile-debian b/test/Dockerfile-debian index b39f915..fa74995 100644 --- a/test/Dockerfile-debian +++ b/test/Dockerfile-debian @@ -5,11 +5,24 @@ FROM debian:latest # Update and install required software RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light +RUN apt-get install -y ftp vsftpd +RUN apt-get install -y openssh-server WORKDIR /root RUN mkdir /etc/nginx/pki RUN mkdir /etc/nginx/pki/private +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=false +COPY test/test-config/vsftpd.conf /etc/vsftpd.conf +RUN adduser ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser ftpuser www-data +RUN adduser root www-data +RUN chown -R www-data.www-data /var/www +RUN chmod g+w -R /var/www + # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index 4e80409..68813f8 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -12,7 +12,10 @@ RUN apt-get install -y vim dos2unix # for debugging RUN apt-get install -y ftp vsftpd RUN apt-get install -y openssh-server -RUN echo "write_enable=YES" >> /etc/vsftpd.conf +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=false +COPY test/test-config/vsftpd.conf /etc/vsftpd.conf RUN adduser ftpuser RUN echo 'ftpuser:ftpuser' | chpasswd RUN adduser ftpuser www-data diff --git a/test/Dockerfile-ubuntu16 b/test/Dockerfile-ubuntu16 index 41be837..184db87 100644 --- a/test/Dockerfile-ubuntu16 +++ b/test/Dockerfile-ubuntu16 @@ -6,12 +6,27 @@ FROM ubuntu:xenial # Update and install required software RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light +RUN apt-get install -y ftp vsftpd +RUN apt-get install -y openssh-server 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 +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=false +COPY test/test-config/vsftpd.conf /etc/vsftpd.conf +# The default init.d script seems to have an incorrect check that vsftpd has started +COPY test/test-config/vsftpd.initd /etc/init.d/vsftpd +RUN adduser ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser ftpuser www-data +RUN adduser root www-data +RUN chown -R www-data.www-data /var/www +RUN chmod g+w -R /var/www + # BATS (Bash Automated Testings) RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 RUN git clone https://github.com/bats-core/bats-support /bats-support diff --git a/test/Dockerfile-ubuntu18 b/test/Dockerfile-ubuntu18 index 5e4c574..ed1fae3 100644 --- a/test/Dockerfile-ubuntu18 +++ b/test/Dockerfile-ubuntu18 @@ -6,12 +6,27 @@ FROM ubuntu:bionic # Update and install required software RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget gawk nginx-light +RUN apt-get install -y ftp vsftpd +RUN apt-get install -y openssh-server 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 +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=false +COPY test/test-config/vsftpd.conf /etc/vsftpd.conf +# The default init.d script seems to have an incorrect check that vsftpd has started +COPY test/test-config/vsftpd.initd /etc/init.d/vsftpd +RUN adduser ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser ftpuser www-data +RUN adduser root www-data +RUN chown -R www-data.www-data /var/www +RUN chmod g+w -R /var/www + # Prevent "Can't load /root/.rnd into RNG" error from openssl RUN touch /root/.rnd diff --git a/test/restart-ftpd b/test/restart-ftpd index 279c2ff..f87d9d8 100644 --- a/test/restart-ftpd +++ b/test/restart-ftpd @@ -2,10 +2,8 @@ if [ "$GETSSL_OS" = "alpine" ]; then killall -HUP vsftpd >&3- - sleep 5 elif [[ "$GETSSL_OS" == "centos"[78] ]]; then pgrep vsftpd | head -1 | xargs kill -HUP - sleep 5 else service vsftpd restart >/dev/null >&3- fi diff --git a/test/run-test.cmd b/test/run-test.cmd index 5908de7..61b360e 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -1,51 +1,52 @@ @echo off IF %1.==. GOTO NoOS -set OS=%1 +SET OS=%1 :CheckCommand IF %2.==. GOTO NoCmd -set COMMAND=%2 %3 +SET COMMAND=%2 %3 :CheckAlias REM check if OS *contains* staging IF NOT x%OS:duck=%==x%OS% GOTO duckdns IF NOT x%OS:dynu=%==x%OS% GOTO dynu IF NOT x%OS:bash=%==x%OS% GOTO bash -set ALIAS=%OS%.getssl.test -set STAGING= -set GETSSL_OS=%OS% +SET ALIAS=%OS%.getssl.test +SET STAGING= +SET GETSSL_OS=%OS% GOTO Run :NoOS -set OS=ubuntu +SET OS=ubuntu GOTO CheckCommand :NoCmd -REM set COMMAND=/getssl/test/run-bats.sh -set COMMAND=bats /getssl/test --timing +REM SET COMMAND=/getssl/test/run-bats.sh +SET COMMAND=bats /getssl/test --timing GOTO CheckAlias :duckdns -set ALIAS=%OS:-duckdns=%-getssl.duckdns.org -set STAGING=--env STAGING=true --env dynamic_dns=duckdns -set GETSSL_OS=%OS:-duckdns=% +SET ALIAS=%OS:-duckdns=%-getssl.duckdns.org +SET STAGING=--env STAGING=true --env dynamic_dns=duckdns +SET GETSSL_OS=%OS:-duckdns=% GOTO Run :dynu -set ALIAS=%OS:-dynu=%-getssl.freeddns.org -set STAGING=--env STAGING=true --env dynamic_dns=dynu -set GETSSL_OS=%OS:-dynu=% +SET ALIAS=%OS:-dynu=%-getssl.freeddns.org +SET STAGING=--env STAGING=true --env dynamic_dns=dynu +SET GETSSL_OS=%OS:-dynu=% GOTO Run :bash -set ALIAS=%OS%.getssl.test -set STAGING= -set GETSSL_OS=alpine +SET ALIAS=%OS%.getssl.test +SET STAGING= +SET GETSSL_OS=alpine :Run -for %%I in (.) do set CurrDirName=%%~nxI +FOR %%I in (.) DO SET CurrDirName=%%~nxI docker build --pull --rm -f "test\Dockerfile-%OS%" -t getssl-%OS% . +IF %ErrorLevel% EQU 1 GOTO End @echo on docker run -it ^ --env GETSSL_HOST=%ALIAS% %STAGING% ^ @@ -69,3 +70,5 @@ docker run -it ^ --name getssl-%OS% ^ getssl-%OS% ^ %COMMAND% + +:End diff --git a/test/test-config/alpine-supervisord.conf b/test/test-config/alpine-supervisord.conf index 9759570..bbf671e 100644 --- a/test/test-config/alpine-supervisord.conf +++ b/test/test-config/alpine-supervisord.conf @@ -12,3 +12,12 @@ stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 autorestart=false startretries=0 + +[program:vsftpd] +command=vsftpd +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +autorestart=false +startretries=0 diff --git a/test/test-config/vsftpd.conf b/test/test-config/vsftpd.conf new file mode 100644 index 0000000..59ca78a --- /dev/null +++ b/test/test-config/vsftpd.conf @@ -0,0 +1,66 @@ +# Example config file /etc/vsftpd.conf (alpine) /etc/vsftpd/vsftpd.conf +# +# The default compiled in settings are fairly paranoid. This sample file +# loosens things up a bit, to make the ftp daemon more usable. +# Please see vsftpd.conf.5 for all compiled in defaults. +# +# Run standalone? vsftpd can run either from an inetd or as a standalone +# daemon started from an initscript. +listen=YES +# +# This directive enables listening on IPv6 sockets. By default, listening +# on the IPv6 "any" address (::) will accept connections from both IPv6 +# and IPv4 clients. It is not necessary to listen on *both* IPv4 and IPv6 +# sockets. If you want that (perhaps because you want to listen on specific +# addresses) then you must run two copies of vsftpd with two configuration +# files. +#listen_ipv6=NO +# +# Allow anonymous FTP? (Disabled by default). +anonymous_enable=NO +# +# Uncomment this to allow local users to log in. +local_enable=YES +# +# Uncomment this to enable any form of FTP write command. +write_enable=YES +# +# Default umask for local users is 077. You may wish to change this to 022, +# if your users expect that (022 is used by most other ftpd's) +local_umask=022 +# +# Activate directory messages - messages given to remote users when they +# go into a certain directory. +dirmessage_enable=YES +# +# If enabled, vsftpd will display directory listings with the time +# in your local time zone. The default is to display GMT. The +# times returned by the MDTM FTP command are also affected by this +# option. +use_localtime=YES +# +# Activate logging of uploads/downloads. +xferlog_enable=YES +# +# Make sure PORT transfer connections originate from port 20 (ftp-data). +connect_from_port_20=YES +# +# You may change the default value for timing out an idle session. +#idle_session_timeout=600 +# +# You may change the default value for timing out a data connection. +#data_connection_timeout=120 +# +# You may restrict local users to their home directories. See the FAQ for +# the possible risks in this before using chroot_local_user or +# chroot_list_enable below. +chroot_local_user=NO +# +# This string is the name of the PAM service vsftpd will use. +pam_service_name=vsftpd +# +# This option specifies the location of the RSA certificate to use for SSL +# encrypted connections. +rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem +rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key +ssl_enable=NO diff --git a/test/test-config/vsftpd.initd b/test/test-config/vsftpd.initd new file mode 100644 index 0000000..d5b2b00 --- /dev/null +++ b/test/test-config/vsftpd.initd @@ -0,0 +1,103 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: vsftpd +# Required-Start: $network $remote_fs $syslog +# Required-Stop: $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Very secure FTP server +# Description: Provides a lightweight, efficient FTP server written +# for security. +### END INIT INFO + +set -e + +DAEMON="/usr/sbin/vsftpd" +NAME="vsftpd" +PATH="/sbin:/bin:/usr/sbin:/usr/bin" +LOGFILE="/var/log/vsftpd.log" +CHROOT="/var/run/vsftpd/empty" + +test -x "${DAEMON}" || exit 0 + +. /lib/lsb/init-functions + +if [ ! -e "${LOGFILE}" ] +then + touch "${LOGFILE}" + chmod 640 "${LOGFILE}" + chown root:adm "${LOGFILE}" +fi + +if [ ! -d "${CHROOT}" ] +then + mkdir -p "${CHROOT}" +fi + +case "${1}" in + start) + log_daemon_msg "Starting FTP server" "${NAME}" + + if [ -e /etc/vsftpd.conf ] && ! egrep -iq "^ *listen(_ipv6)? *= *yes" /etc/vsftpd.conf + then + log_warning_msg "vsftpd disabled - listen disabled in config." + exit 0 + fi + + start-stop-daemon --start --background -m --oknodo --pidfile /var/run/vsftpd/vsftpd.pid --exec ${DAEMON} + + n=0 + while [ ${n} -le 5 ] + do + _PID="$(if [ -e /var/run/vsftpd/vsftpd.pid ]; then cat /var/run/vsftpd/vsftpd.pid; fi)" + if ! ps -C vsftpd | grep -qs "${_PID}" + then + break + fi + sleep 1 + n=$(( $n + 1 )) + done + + if ps -C vsftpd | grep -qs "${_PID}" + then + log_warning_msg "vsftpd failed - probably invalid config." + exit 1 + fi + + log_end_msg 0 + ;; + + stop) + log_daemon_msg "Stopping FTP server" "${NAME}" + + start-stop-daemon --stop --pidfile /var/run/vsftpd/vsftpd.pid --oknodo --exec ${DAEMON} + rm -f /var/run/vsftpd/vsftpd.pid + + log_end_msg 0 + ;; + + restart) + ${0} stop + ${0} start + ;; + + reload|force-reload) + log_daemon_msg "Reloading FTP server configuration" + + start-stop-daemon --stop --pidfile /var/run/vsftpd/vsftpd.pid --signal 1 --exec $DAEMON + + log_end_msg "${?}" + ;; + + status) + status_of_proc "${DAEMON}" "FTP server" + ;; + + *) + echo "Usage: ${0} {start|stop|restart|reload|status}" + exit 1 + ;; +esac + +exit 0 diff --git a/test/test_helper.bash b/test/test_helper.bash index c5d5320..3adcdfa 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -70,16 +70,21 @@ setup_environment() { /getssl/test/restart-nginx } -# start nginx in background on alpine via supervisord +# start nginx and vsftpd in background on alpine via supervisord # shellcheck disable=SC2153 # Ignore GETSSL_OS looks like typo of GETSSL_IP if [[ -f /usr/bin/supervisord && -f /etc/supervisord.conf ]]; then if [[ ! $(pgrep supervisord) ]]; then /usr/bin/supervisord -c /etc/supervisord.conf >&3- + # Give supervisord time to start + sleep 1 fi elif [[ "$GETSSL_OS" == "centos"[78] ]]; then if [ -z "$(pgrep nginx)" ]; then nginx >&3- fi + if [ -z "$(pgrep vsftpd)" ]; then + vsftpd >&3- + fi fi # Find NGINX configuration directory for HTTP-01 testing (need to add SSL to config) From 170e65d1cdc50a961fe49b22f61173f8fe6c1fe7 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 22 Jan 2021 15:32:44 +0000 Subject: [PATCH 192/308] Add +x for scripts used in testing --- test/restart-ftpd | 0 test/test-config/vsftpd.initd | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 test/restart-ftpd mode change 100644 => 100755 test/test-config/vsftpd.initd diff --git a/test/restart-ftpd b/test/restart-ftpd old mode 100644 new mode 100755 diff --git a/test/test-config/vsftpd.initd b/test/test-config/vsftpd.initd old mode 100644 new mode 100755 From 99d1fcccf66bb35a9c6e86d35228dbae4b382e0f Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 22 Jan 2021 17:51:50 +0000 Subject: [PATCH 193/308] Fix staging tests where vsftpd is not installed --- test/33-ftp.bats | 18 +++++++++++------- test/34-ftp-passive.bats | 18 +++++++++++------- test/test_helper.bash | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/test/33-ftp.bats b/test/33-ftp.bats index 9c0bb2f..9c2e387 100644 --- a/test/33-ftp.bats +++ b/test/33-ftp.bats @@ -8,21 +8,25 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt - cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl + if [ -n "${VSFTPD_CONF}" ]; then + cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl - # enable passive and disable active mode - # https://www.pixelstech.net/article/1364817664-FTP-active-mode-and-passive-mode - cat <<- _FTP >> $VSFTPD_CONF + # enable passive and disable active mode + # https://www.pixelstech.net/article/1364817664-FTP-active-mode-and-passive-mode + cat <<- _FTP >> $VSFTPD_CONF pasv_enable=NO _FTP - ${CODE_DIR}/test/restart-ftpd + ${CODE_DIR}/test/restart-ftpd + fi } teardown() { - cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF - ${CODE_DIR}/test/restart-ftpd + if [ -n "${VSFTPD_CONF}" ]; then + cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF + ${CODE_DIR}/test/restart-ftpd + fi } diff --git a/test/34-ftp-passive.bats b/test/34-ftp-passive.bats index cb61dda..0d16574 100644 --- a/test/34-ftp-passive.bats +++ b/test/34-ftp-passive.bats @@ -8,24 +8,28 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt - cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl + if [ -n "${VSFTPD_CONF}" ]; then + cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl - # enable passive and disable active mode - # https://www.pixelstech.net/article/1364817664-FTP-active-mode-and-passive-mode - cat <<- _FTP >> $VSFTPD_CONF + # enable passive and disable active mode + # https://www.pixelstech.net/article/1364817664-FTP-active-mode-and-passive-mode + cat <<- _FTP >> $VSFTPD_CONF pasv_enable=YES pasv_max_port=10100 pasv_min_port=10090 connect_from_port_20=NO _FTP - ${CODE_DIR}/test/restart-ftpd + ${CODE_DIR}/test/restart-ftpd + fi } teardown() { - cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF - ${CODE_DIR}/test/restart-ftpd + if [ -n "${VSFTPD_CONF}" ]; then + cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF + ${CODE_DIR}/test/restart-ftpd + fi } diff --git a/test/test_helper.bash b/test/test_helper.bash index 3adcdfa..11cdf44 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -82,7 +82,7 @@ elif [[ "$GETSSL_OS" == "centos"[78] ]]; then if [ -z "$(pgrep nginx)" ]; then nginx >&3- fi - if [ -z "$(pgrep vsftpd)" ]; then + if [ -z "$(pgrep vsftpd)" ] && [ "$(command -v vsftpd)" ]; then vsftpd >&3- fi fi From 7a9a9ca684bcb2d1b56cdde1a67f4e244ca960b1 Mon Sep 17 00:00:00 2001 From: atisne Date: Wed, 27 Jan 2021 17:08:32 +0100 Subject: [PATCH 194/308] Add the ability to set several reload commands Use a bash array to set several commands. (Commands use the usual syntax.) The current syntax is unchanged when setting a single command. --- README.md | 4 +++- getssl | 41 ++++++++++++++++++++++++----------------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 11ab90e..84d2835 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,9 @@ DOMAIN_KEY_LOCATION="ssh:server5:/etc/ssl/domain.key" #DOMAIN_PEM_LOCATION="" this is the domain_key. domain cert and CA cert -# The command needed to reload apache / nginx or whatever you use +# The command needed to reload apache / nginx or whatever you use. +# Several (ssh) commands may be given using a bash array: +# RELOAD_CMD=('ssh:sshuserid@server5:systemctl reload httpd' 'logger getssl for server5 efficient.') RELOAD_CMD="service apache2 reload" # Define the server type. This can be https, ftp, ftpi, imap, imaps, pop3, pop3s, smtp, diff --git a/getssl b/getssl index 747027e..5ce3420 100755 --- a/getssl +++ b/getssl @@ -1957,22 +1957,25 @@ purge_archive() { # purge archive of old, invalid, certificates reload_service() { # Runs a command to reload services ( via ssh if needed) if [[ -n "$RELOAD_CMD" ]]; then info "reloading SSL services" - if [[ "${RELOAD_CMD:0:4}" == "ssh:" ]] ; then - sshhost=$(echo "$RELOAD_CMD"| awk -F: '{print $2}') - command=${RELOAD_CMD:(( ${#sshhost} + 5))} - debug "running following command to reload cert" - debug "ssh $SSH_OPTS $sshhost ${command}" - # shellcheck disable=SC2029 - # shellcheck disable=SC2086 - ssh $SSH_OPTS "$sshhost" "${command}" 1>/dev/null 2>&1 - # allow 2 seconds for services to restart - sleep 2 - else - debug "running reload command $RELOAD_CMD" - if ! eval "$RELOAD_CMD" ; then - error_exit "error running $RELOAD_CMD" + for ARELOAD_CMD in "${RELOAD_CMD[@]}" + do + if [[ "${ARELOAD_CMD:0:4}" == "ssh:" ]] ; then + sshhost=$(echo "$ARELOAD_CMD"| awk -F: '{print $2}') + command=${ARELOAD_CMD:(( ${#sshhost} + 5))} + debug "running following command to reload cert:" + debug "ssh $SSH_OPTS $sshhost ${command}" + # shellcheck disable=SC2029 + # shellcheck disable=SC2086 + ssh $SSH_OPTS "$sshhost" "${command}" 1>/dev/null 2>&1 + # allow 2 seconds for services to restart + sleep 2 + else + debug "running reload command: $ARELOAD_CMD" + if ! eval "$ARELOAD_CMD" ; then + error_exit "error running: $ARELOAD_CMD" + fi fi - fi + done fi } @@ -2326,7 +2329,9 @@ write_domain_template() { # write out a template file for a domain. #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 + # The command needed to reload apache / nginx or whatever you use. + # Several (ssh) commands may be given using a bash array: + # RELOAD_CMD=('ssh:sshuserid@server5:systemctl reload httpd' 'logger getssl for server5 efficient.') #RELOAD_CMD="" # Uncomment the following line to prevent non-interactive renewals of certificates @@ -2370,7 +2375,9 @@ write_getssl_template() { # write out the main template file PRIVATE_KEY_ALG="rsa" #REUSE_PRIVATE_KEY="true" - # The command needed to reload apache / nginx or whatever you use + # The command needed to reload apache / nginx or whatever you use. + # Several (ssh) commands may be given using a bash array: + # RELOAD_CMD=('ssh:sshuserid@server5:systemctl reload httpd' 'logger getssl for server5 efficient.') #RELOAD_CMD="" # The time period within which you want to allow renewal of a certificate From 858dfc75a5f84a692ceea5682f967667e57019b9 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 29 Jan 2021 17:31:50 +0000 Subject: [PATCH 195/308] Use -r option for dig to force default dig output Fixes #630 --- getssl | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/getssl b/getssl index 5ce3420..bbeb969 100755 --- a/getssl +++ b/getssl @@ -249,6 +249,10 @@ # 2020-12-22 Check that dig doesn't return an error (#611)(2.32) # 2020-12-29 Fix dig SOA lookup (#617)(2.33) # 2021-01-05 Show error if running in POSIX mode (#611) +# 2021-01-16 Fix double slash when using root directory with DAVS (ionos) +# 2021-01-22 Add FTP_OPTIONS +# 2021-01-27 Add the ability to set several reload commands (atisne) +# 2021-01-29 Use dig -r (if supported) to ignore.digrc (#630) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -1119,8 +1123,13 @@ find_dns_utils() { debug "HAS DIG_OR_DRILL=drill" HAS_DIG_OR_DRILL="drill" elif [[ -n "$(command -v dig 2>/dev/null)" ]] && dig >/dev/null 2>&1; then - debug "HAS DIG_OR_DRILL=dig" - HAS_DIG_OR_DRILL="dig" + if [[ $(dig -r >/dev/null 2>&1) ]]; then + # use dig -r so ~/.digrc is not used + HAS_DIG_OR_DRILL="dig -r" + else + HAS_DIG_OR_DRILL="dig" + fi + debug "HAS DIG_OR_DRILL=$HAS_DIG_OR_DRILL" fi if [[ -n "$(command -v host 2>/dev/null)" ]]; then @@ -1338,14 +1347,14 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n # Use SOA +trace to find the name server if [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then - if [[ "$HAS_DIG_OR_DRILL" == "dig" ]]; then - debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d $gad_s" to find primary nameserver - test_output "Using $HAS_DIG_OR_DRILL SOA" - res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W") - else + if [[ "$HAS_DIG_OR_DRILL" == "drill" ]]; then debug Using "$HAS_DIG_OR_DRILL -T $gad_d $gad_s" to find primary nameserver test_output "Using $HAS_DIG_OR_DRILL SOA" res=$($HAS_DIG_OR_DRILL -T SOA "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W") + else + debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d $gad_s" to find primary nameserver + test_output "Using $HAS_DIG_OR_DRILL SOA" + res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W") fi fi From d167d729271db12a402bd06d595951db3e062480 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 29 Jan 2021 17:32:41 +0000 Subject: [PATCH 196/308] Test specific config must be updated after setup_environment --- test/15-test-revoke-no-suffix.bats | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index 96e174b..4c54961 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -19,11 +19,13 @@ setup() { else CONFIG_FILE="getssl-http01-no-suffix.cfg" fi - echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" setup_environment init_getssl + + echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + create_certificate assert_success check_output_for_errors @@ -36,7 +38,7 @@ setup() { else CONFIG_FILE="getssl-http01.cfg" fi - echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg + echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt From 51ac8a3483f9427b298104fdec588d0d1e950d9a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 29 Jan 2021 20:05:21 +0000 Subject: [PATCH 197/308] Check for Valid ACME response and continue waiting --- getssl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index bbeb969..b14e465 100755 --- a/getssl +++ b/getssl @@ -491,8 +491,9 @@ check_challenge_completion() { # checks with the ACME server if our challenge is error_exit "$domain:Verify error:$err_detail" fi - # if ACME response is pending ( they haven't completed checks yet) then wait and try again. - if [[ "$status" == "pending" ]] ; then + # if ACME response is pending (they haven't completed checks yet) + # or valid (completed checks but not created certificate) then wait and try again. + if [[ "$status" == "pending" ]] || [[ "$status" == "valid" ]]; then info "Pending" else err_detail=$(echo "$response" | grep "detail") From 347ec532272031c835780726559dd6f20473fd3f Mon Sep 17 00:00:00 2001 From: Benno-K Date: Sun, 7 Feb 2021 16:25:48 +0100 Subject: [PATCH 198/308] Implement #634 - allow -u without domain(s) --- README.md | 2 +- getssl | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 84d2835..cad2775 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Options: -q, --quiet Quiet mode (only outputs on error, success of new cert, or getssl was upgraded) -Q, --mute Like -q, but mutes notification about successful upgrade -r, --revoke "cert" "key" [CA_server] Revoke a certificate (the cert and key are required) - -u, --upgrade Upgrade getssl if a more recent version is available + -u, --upgrade Upgrade getssl if a more recent version is available - can be used with or without domain(s) -k, --keep "#" Maximum amount of old getssl versions to keep when upgrading -U, --nocheck Do not check if a more recent version is available -w working_dir "Working directory" diff --git a/getssl b/getssl index b14e465..cad52c3 100755 --- a/getssl +++ b/getssl @@ -253,6 +253,7 @@ # 2021-01-22 Add FTP_OPTIONS # 2021-01-27 Add the ability to set several reload commands (atisne) # 2021-01-29 Use dig -r (if supported) to ignore.digrc (#630) +# 2021-02-07 Allow -u --upgrade without any domain, so that one can only update the script # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -261,7 +262,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.33" +VERSION="2.34" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -1669,7 +1670,7 @@ help_message() { # print out the help message -q, --quiet Quiet mode (only outputs on error, success of new cert, or getssl was upgraded) -Q, --mute Like -q, but also mute notification about successful upgrade -r, --revoke "cert" "key" [CA_server] Revoke a certificate (the cert and key are required) - -u, --upgrade Upgrade getssl if a more recent version is available + -u, --upgrade Upgrade getssl if a more recent version is available - can be used with or without domain(s) -k, --keep "#" Maximum number of old getssl versions to keep when upgrading -U, --nocheck Do not check if a more recent version is available -w working_dir "Working directory" @@ -2513,6 +2514,10 @@ requires mktemp # Check if upgrades are available (unless they have specified -U to ignore Upgrade checks) if [[ $_UPGRADE_CHECK -eq 1 ]]; then check_getssl_upgrade + # if nothing in command line, then exit after upgrade + if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]]; then + graceful_exit + fi fi # Revoke a certificate if requested From d616aa5d1a463923ac40ee4cbc2105cfc58978d6 Mon Sep 17 00:00:00 2001 From: Benno-K Date: Sun, 7 Feb 2021 21:27:52 +0100 Subject: [PATCH 199/308] Test revealed that revocation (-r) also should not exit after upgrade --- getssl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index cad52c3..c319eed 100755 --- a/getssl +++ b/getssl @@ -2514,8 +2514,8 @@ requires mktemp # Check if upgrades are available (unless they have specified -U to ignore Upgrade checks) if [[ $_UPGRADE_CHECK -eq 1 ]]; then check_getssl_upgrade - # if nothing in command line, then exit after upgrade - if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]]; then + # if nothing in command line and no revocation, then exit after upgrade + if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]] && [[ ${_REVOKE} -ne 1 ]]; then graceful_exit fi fi From baa87f6cdbd24b441c2ac3ed3e569e3d813dbb19 Mon Sep 17 00:00:00 2001 From: Benno-K Date: Mon, 8 Feb 2021 13:43:26 +0100 Subject: [PATCH 200/308] Trying to fix failing tests in 32-test-upgrade.bats --- getssl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index c319eed..2b70249 100755 --- a/getssl +++ b/getssl @@ -2514,8 +2514,9 @@ requires mktemp # Check if upgrades are available (unless they have specified -U to ignore Upgrade checks) if [[ $_UPGRADE_CHECK -eq 1 ]]; then check_getssl_upgrade - # if nothing in command line and no revocation, then exit after upgrade - if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]] && [[ ${_REVOKE} -ne 1 ]]; then + # if nothing in command line and no revocation and not only config check, + # then exit after upgrade + if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]] && [[ ${_REVOKE} -ne 1 ]] && [ "${_ONLY_CHECK_CONFIG}" -eq 1 ]; then graceful_exit fi fi From 9946eb789fcbee975788b8ce9ef25eb5717dd0f7 Mon Sep 17 00:00:00 2001 From: Benno-K Date: Mon, 8 Feb 2021 14:05:06 +0100 Subject: [PATCH 201/308] Still trying to fix failing tests in 32-test-upgrade.bats --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 2b70249..151cff0 100755 --- a/getssl +++ b/getssl @@ -2517,7 +2517,7 @@ if [[ $_UPGRADE_CHECK -eq 1 ]]; then # if nothing in command line and no revocation and not only config check, # then exit after upgrade if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]] && [[ ${_REVOKE} -ne 1 ]] && [ "${_ONLY_CHECK_CONFIG}" -eq 1 ]; then - graceful_exit + echo graceful_exit fi fi From 088e55131354f9e491862b4d004ce2a7bf1c57e7 Mon Sep 17 00:00:00 2001 From: Benno-K Date: Mon, 8 Feb 2021 14:15:33 +0100 Subject: [PATCH 202/308] after wild trying go back to what I think is it, even if I know that the upgrade tests fail with that --- getssl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 151cff0..f0e40ab 100755 --- a/getssl +++ b/getssl @@ -2516,8 +2516,8 @@ if [[ $_UPGRADE_CHECK -eq 1 ]]; then check_getssl_upgrade # if nothing in command line and no revocation and not only config check, # then exit after upgrade - if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]] && [[ ${_REVOKE} -ne 1 ]] && [ "${_ONLY_CHECK_CONFIG}" -eq 1 ]; then - echo graceful_exit + if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]] && [[ ${_REVOKE} -ne 1 ]] && [ "${_ONLY_CHECK_CONFIG}" -ne 1 ]; then + graceful_exit fi fi From a342bf7f4c90b369b2b8cfbff1d64cb9e03ce488 Mon Sep 17 00:00:00 2001 From: Benno-K Date: Mon, 8 Feb 2021 17:27:15 +0100 Subject: [PATCH 203/308] Changed 32-test-upgrade.bats to actually check the update functionality of the newly developped version - also change the way of determining the versions --- test/32-test-upgrade.bats | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index 1c8af6d..cb47c7e 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -8,9 +8,16 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt - CURRENT_VERSION=$(awk -F '"' '$1 == "VERSION=" {print $2}' ${CODE_DIR}/getssl) - PREVIOUS_VERSION=$(echo ${CURRENT_VERSION} | awk -F. '{ print $1 "." $2-1}') run git clone https://github.com/srvrco/getssl.git "$INSTALL_DIR/upgrade-getssl" + # Don't do version arithmetics any longer, look what there really is + cd "$INSTALL_DIR/upgrade-getssl" + CURRENT_VERSION=$(git tag -l|grep -e '^v'|tail -1|cut -b2-) + PREVIOUS_VERSION=$(git tag -l|grep -e '^v'|tail -2|head -1|cut -b2-) + # The version in the file, which we will overwrite + FILE_VERSION=$(awk -F'"' '/^VERSION=/{print $2}' "$CODE_DIR/getssl") +echo "============ FILE_VERSION ===========" +echo "${FILE_VERSION}" +echo "============ FILE_VERSION ===========" } @@ -31,6 +38,15 @@ teardown() { setup_environment init_getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + # Overwrite checked out getssl-script with copy of new one, + # but write the previous version into the copy + # Note that this way we actually downgrade getssl, but we are testing + # the upgrading of the version in development + cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" + sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_VERSION}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" +echo "============ VERSION ===========" +egrep '^VERSION=' "$INSTALL_DIR/upgrade-getssl/getssl" +echo "============ VERSION ===========" run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config ${GETSSL_CMD_HOST} assert_success #assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" @@ -45,12 +61,18 @@ teardown() { fi cd "$INSTALL_DIR/upgrade-getssl" - git checkout tags/v${PREVIOUS_VERSION} + git checkout tags/v${CURRENT_VERSION} CONFIG_FILE="getssl-http01.cfg" setup_environment init_getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + # Overwrite checked out getssl-script with copy of new one, + # but write the previous version into the copy + # Note that this way we actually downgrade getssl, but we are testing + # the upgrading of the version in development + cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" + sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_VERSION}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config --upgrade ${GETSSL_CMD_HOST} assert_success assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" @@ -71,6 +93,12 @@ teardown() { setup_environment init_getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + # Overwrite checked out getssl-script with copy of new one, + # but write the previous version into the copy + # Note that this way we actually downgrade getssl, but we are testing + # the upgrading of the version in development + cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" + sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_VERSION}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" run bash ./getssl --check-config --upgrade ${GETSSL_CMD_HOST} assert_success assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" From 15a8f9f1eeb8784e3847d6f4cf785fc2dadc7d62 Mon Sep 17 00:00:00 2001 From: Benno-K Date: Mon, 8 Feb 2021 17:42:34 +0100 Subject: [PATCH 204/308] Removed echo-statements --- test/32-test-upgrade.bats | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index cb47c7e..b8f98cd 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -15,9 +15,6 @@ setup() { PREVIOUS_VERSION=$(git tag -l|grep -e '^v'|tail -2|head -1|cut -b2-) # The version in the file, which we will overwrite FILE_VERSION=$(awk -F'"' '/^VERSION=/{print $2}' "$CODE_DIR/getssl") -echo "============ FILE_VERSION ===========" -echo "${FILE_VERSION}" -echo "============ FILE_VERSION ===========" } @@ -44,9 +41,6 @@ teardown() { # the upgrading of the version in development cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_VERSION}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" -echo "============ VERSION ===========" -egrep '^VERSION=' "$INSTALL_DIR/upgrade-getssl/getssl" -echo "============ VERSION ===========" run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config ${GETSSL_CMD_HOST} assert_success #assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" From 9853fd39d6f03bc3da0df1565755561ac687e835 Mon Sep 17 00:00:00 2001 From: Benno-K Date: Mon, 8 Feb 2021 19:18:11 +0100 Subject: [PATCH 205/308] More elegant way to get versions --- test/32-test-upgrade.bats | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index b8f98cd..baa7b0f 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -10,9 +10,11 @@ setup() { export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt run git clone https://github.com/srvrco/getssl.git "$INSTALL_DIR/upgrade-getssl" # Don't do version arithmetics any longer, look what there really is + # by getting the last line (starting with v) and the one before of the + # list of tags. cd "$INSTALL_DIR/upgrade-getssl" - CURRENT_VERSION=$(git tag -l|grep -e '^v'|tail -1|cut -b2-) - PREVIOUS_VERSION=$(git tag -l|grep -e '^v'|tail -2|head -1|cut -b2-) + # This sets CURRENT_VERSION and PREVIOUS_VERSION bash variables + eval $(git tag -l | awk 'BEGIN {cur="?.??"};/^v/{prv=cur;cur=substr($1,2)};END{ printf("CURRENT_VERSION=\"%s\";PREVIOUS_VERSION=\"%s\"\n",cur,prv)}') # The version in the file, which we will overwrite FILE_VERSION=$(awk -F'"' '/^VERSION=/{print $2}' "$CODE_DIR/getssl") } From d96414050330297abdcf73890db15aae7ac5f284 Mon Sep 17 00:00:00 2001 From: Tony Mountifield Date: Tue, 9 Feb 2021 11:54:12 +0000 Subject: [PATCH 206/308] Prevent listing the complete file if version tag missing Also added missing (2.34) tag to end of the change log. Couple of minor changes to output messages. --- getssl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/getssl b/getssl index f0e40ab..da65999 100755 --- a/getssl +++ b/getssl @@ -253,7 +253,7 @@ # 2021-01-22 Add FTP_OPTIONS # 2021-01-27 Add the ability to set several reload commands (atisne) # 2021-01-29 Use dig -r (if supported) to ignore.digrc (#630) -# 2021-02-07 Allow -u --upgrade without any domain, so that one can only update the script +# 2021-02-07 Allow -u --upgrade without any domain, so that one can only update the script (2.34) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -753,10 +753,10 @@ check_getssl_upgrade() { # check if a more recent version of code is available a fi if [[ ${_MUTE} -eq 0 ]]; then echo "Updated getssl from v${VERSION} to v${latestversion}" - echo "these update notification can be turned off using the -Q option" + echo "These update notifications can be turned off using the -Q option" echo "" echo "Updates are;" - awk "/\(${VERSION}\)$/ {s=1} s; /\(${latestversion}\)$/ {s=0}" "$TEMP_UPGRADE_FILE" | awk '{if(NR>1)print}' + awk "/\(${VERSION}\)$/ {s=1} s; /\(${latestversion}\)$/ || /^# ----/ {s=0}" "$TEMP_UPGRADE_FILE" | awk '{if(NR>1)print}' echo "" fi if [[ -n "$_KEEP_VERSIONS" ]] && [[ "$_KEEP_VERSIONS" =~ ^[0-9]+$ ]]; then @@ -786,7 +786,7 @@ check_getssl_upgrade() { # check if a more recent version of code is available a else info "" info "A more recent version (v${latestversion}) of getssl is available, please update" - info "the easiest way is to use the -u or --upgrade flag" + info "The easiest way is to use the -u or --upgrade flag" info "" fi fi From a5512c00ff7f3c10c884f6e9cfe238e3bba2ead2 Mon Sep 17 00:00:00 2001 From: Tony Mountifield Date: Tue, 9 Feb 2021 11:58:43 +0000 Subject: [PATCH 207/308] Add description of change to the change log. --- getssl | 1 + 1 file changed, 1 insertion(+) diff --git a/getssl b/getssl index da65999..583f88a 100755 --- a/getssl +++ b/getssl @@ -254,6 +254,7 @@ # 2021-01-27 Add the ability to set several reload commands (atisne) # 2021-01-29 Use dig -r (if supported) to ignore.digrc (#630) # 2021-02-07 Allow -u --upgrade without any domain, so that one can only update the script (2.34) +# 2021-02-09 Prevent listing the complete file if version tag missing (#637) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in From d9559b1e42e6bac69666c5f35c33aeb6ddb83a3d Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 10 Feb 2021 21:48:45 +0000 Subject: [PATCH 208/308] Fix tests failure when pushing new version to master --- test/32-test-upgrade.bats | 67 ++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index baa7b0f..f8fc68a 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -8,15 +8,21 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + + # Turn off warning about detached head + git config --global advice.detachedHead false run git clone https://github.com/srvrco/getssl.git "$INSTALL_DIR/upgrade-getssl" - # Don't do version arithmetics any longer, look what there really is - # by getting the last line (starting with v) and the one before of the - # list of tags. + + # Don't do version arithmetics any longer, look what was the previous version by getting the last + # line (starting with v) and the one before that from the list of tags. cd "$INSTALL_DIR/upgrade-getssl" - # This sets CURRENT_VERSION and PREVIOUS_VERSION bash variables - eval $(git tag -l | awk 'BEGIN {cur="?.??"};/^v/{prv=cur;cur=substr($1,2)};END{ printf("CURRENT_VERSION=\"%s\";PREVIOUS_VERSION=\"%s\"\n",cur,prv)}') + + # This sets CURRENT_TAG and PREVIOUS_TAG bash variables + eval $(git tag -l | awk 'BEGIN {cur="?.??"};/^v/{prv=cur;cur=substr($1,2)};END{ printf("CURRENT_TAG=\"%s\";PREVIOUS_TAG=\"%s\"\n",cur,prv)}') + # The version in the file, which we will overwrite FILE_VERSION=$(awk -F'"' '/^VERSION=/{print $2}' "$CODE_DIR/getssl") + # If FILE_VERSION > CURRENT_TAG then either we are testing a push to master or the last version wasn't released } @@ -31,22 +37,23 @@ teardown() { fi cd "$INSTALL_DIR/upgrade-getssl" - git checkout tags/v${PREVIOUS_VERSION} + git checkout tags/v${PREVIOUS_TAG} CONFIG_FILE="getssl-http01.cfg" setup_environment init_getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" - # Overwrite checked out getssl-script with copy of new one, - # but write the previous version into the copy - # Note that this way we actually downgrade getssl, but we are testing - # the upgrading of the version in development + + # Overwrite checked out getssl-script with copy of new one, but write the previous version into the copy + # Note that this way we mock downgrading getssl and are testing the upgrading of the version in development cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" - sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_VERSION}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" + sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_TAG}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" + run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config ${GETSSL_CMD_HOST} assert_success - #assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" - assert_line "A more recent version (v${CURRENT_VERSION}) of getssl is available, please update" + + # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) + assert_line --regexp "A more recent version \(v(${CURRENT_TAG}|${FILE_VERSION})\) of getssl is available, please update" check_output_for_errors } @@ -57,22 +64,23 @@ teardown() { fi cd "$INSTALL_DIR/upgrade-getssl" - git checkout tags/v${CURRENT_VERSION} + git checkout tags/v${CURRENT_TAG} CONFIG_FILE="getssl-http01.cfg" setup_environment init_getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" - # Overwrite checked out getssl-script with copy of new one, - # but write the previous version into the copy - # Note that this way we actually downgrade getssl, but we are testing - # the upgrading of the version in development + + # Overwrite checked out getssl-script with copy of new one, but write the previous version into the copy + # Note that this way we mock downgrading getssl and are testing the upgrading of the version in development cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" - sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_VERSION}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" + sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_TAG}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" + run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config --upgrade ${GETSSL_CMD_HOST} assert_success - assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" - check_output_for_errors + + # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) + assert_line --regexp "Updated getssl from v${PREVIOUS_TAG} to v(${CURRENT_TAG}|${FILE_VERSION})" } @@ -83,20 +91,21 @@ teardown() { fi cd "$INSTALL_DIR/upgrade-getssl" - git checkout tags/v${PREVIOUS_VERSION} + git checkout tags/v${PREVIOUS_TAG} CONFIG_FILE="getssl-http01.cfg" setup_environment init_getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" - # Overwrite checked out getssl-script with copy of new one, - # but write the previous version into the copy - # Note that this way we actually downgrade getssl, but we are testing - # the upgrading of the version in development + + # Overwrite checked out getssl-script with copy of new one, but write the previous version into the copy + # Note that this way we mock downgrading getssl and are testing the upgrading of the version in development cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" - sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_VERSION}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" + sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_TAG}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" + run bash ./getssl --check-config --upgrade ${GETSSL_CMD_HOST} assert_success - assert_line "Updated getssl from v${PREVIOUS_VERSION} to v${CURRENT_VERSION}" - check_output_for_errors + + # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) + assert_line --regexp "Updated getssl from v${PREVIOUS_TAG} to v(${CURRENT_TAG}|${FILE_VERSION})" } From 67a7e5d4530c901ba8985e141a5891c2df2aabf0 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 12 Feb 2021 16:05:36 +0000 Subject: [PATCH 209/308] Merge getssl-dns01 and getssl-staging-dns01 into a single cfg file --- test/10-mixed-case.bats | 6 +-- test/14-test-revoke.bats | 4 +- test/15-test-revoke-no-suffix.bats | 4 +- ...try-dns-add.bats => 18-retry-dns-add.bats} | 9 +++- test/19-test-add-to-sans.bats | 4 +- test/2-simple-dns01-dig.bats | 3 -- test/2-simple-dns01-nslookup.bats | 3 -- test/20-wildcard-simple.bats | 6 +-- test/21-wildcard-dual-rsa.bats | 12 +---- ...dcard-dual-rsa-ecdsa-copy-2-locations.bats | 6 +-- test/24-wildcard-sans.bats | 12 +---- test/26-wildcard-revoke.bats | 12 +---- test/8-staging-ecdsa.bats | 8 +-- test/test-config/getssl-dns01.cfg | 47 ++++++++++++------ test/test-config/getssl-staging-dns01.cfg | 49 ------------------- 15 files changed, 59 insertions(+), 126 deletions(-) rename test/{18-staging-retry-dns-add.bats => 18-retry-dns-add.bats} (79%) delete mode 100644 test/test-config/getssl-staging-dns01.cfg diff --git a/test/10-mixed-case.bats b/test/10-mixed-case.bats index f144058..974f669 100644 --- a/test/10-mixed-case.bats +++ b/test/10-mixed-case.bats @@ -29,11 +29,7 @@ setup() { } @test "Check that DNS-01 verification works if the domain is not lowercase" { - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - else - CONFIG_FILE="getssl-dns01.cfg" - fi + CONFIG_FILE="getssl-dns01.cfg" GETSSL_CMD_HOST=$(echo $GETSSL_HOST | tr a-z A-Z) setup_environment diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats index 5bdb72b..d31e832 100644 --- a/test/14-test-revoke.bats +++ b/test/14-test-revoke.bats @@ -15,7 +15,7 @@ setup() { @test "Create certificate to check revoke" { if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" + CONFIG_FILE="getssl-dns01.cfg" else CONFIG_FILE="getssl-http01.cfg" fi @@ -30,7 +30,7 @@ setup() { @test "Check we can revoke a certificate" { if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" + CONFIG_FILE="getssl-dns01.cfg" else CONFIG_FILE="getssl-http01.cfg" fi diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index 4c54961..30802d8 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -15,7 +15,7 @@ setup() { @test "Create certificate to check revoke (no suffix)" { if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" + CONFIG_FILE="getssl-dns01.cfg" else CONFIG_FILE="getssl-http01-no-suffix.cfg" fi @@ -34,7 +34,7 @@ setup() { @test "Check we can revoke a certificate (no suffix)" { if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" + CONFIG_FILE="getssl-dns01.cfg" else CONFIG_FILE="getssl-http01.cfg" fi diff --git a/test/18-staging-retry-dns-add.bats b/test/18-retry-dns-add.bats similarity index 79% rename from test/18-staging-retry-dns-add.bats rename to test/18-retry-dns-add.bats index bca7c05..3a79880 100644 --- a/test/18-staging-retry-dns-add.bats +++ b/test/18-retry-dns-add.bats @@ -4,14 +4,18 @@ 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 "Check retry add dns command if dns isn't updated" { - if [ -z "$STAGING" ]; then + if [ -n "$STAGING" ]; then skip "Running internal tests, skipping external test" fi - CONFIG_FILE="getssl-staging-dns01.cfg" + CONFIG_FILE="getssl-dns01.cfg" setup_environment init_getssl @@ -25,6 +29,7 @@ DNS_WAIT_COUNT=11 DNS_EXTRA_WAIT=0 CHECK_ALL_AUTH_DNS="false" CHECK_PUBLIC_DNS_SERVER="false" +DNS_WAIT_RETRY_ADD="true" EOF create_certificate -d assert_failure diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats index 8ba9f20..da9deb7 100644 --- a/test/19-test-add-to-sans.bats +++ b/test/19-test-add-to-sans.bats @@ -26,7 +26,7 @@ teardown() { skip "FIXME: Certificate is not recreated when SANS is updated" if [ -n "$STAGING" ]; then skip "Not trying on staging server yet" - CONFIG_FILE="getssl-staging-dns01.cfg" + CONFIG_FILE="getssl-dns01.cfg" else CONFIG_FILE="getssl-dns01-add-to-sans-1.cfg" fi @@ -45,7 +45,7 @@ teardown() { skip "FIXME: Certificate is not recreated when SANS is updated" if [ -n "$STAGING" ]; then skip "Not trying on staging server yet" - CONFIG_FILE="getssl-staging-dns01.cfg" + CONFIG_FILE="getssl-dns01.cfg" else CONFIG_FILE="getssl-dns01-add-to-sans-2.cfg" fi diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index 6f701b3..f8f0cb4 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -30,9 +30,6 @@ teardown() { @test "Create new certificate using DNS-01 verification (dig)" { CONFIG_FILE="getssl-dns01.cfg" - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - fi setup_environment init_getssl diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index c883485..f97b5dc 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -31,9 +31,6 @@ teardown() { @test "Create new certificate using DNS-01 verification (nslookup)" { CONFIG_FILE="getssl-dns01.cfg" - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - fi setup_environment init_getssl diff --git a/test/20-wildcard-simple.bats b/test/20-wildcard-simple.bats index e9b0f98..b56a876 100644 --- a/test/20-wildcard-simple.bats +++ b/test/20-wildcard-simple.bats @@ -14,11 +14,7 @@ setup() { @test "Create wildcard certificate" { - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - else - CONFIG_FILE="getssl-dns01.cfg" - fi + CONFIG_FILE="getssl-dns01.cfg" GETSSL_CMD_HOST="*.${GETSSL_HOST}" setup_environment diff --git a/test/21-wildcard-dual-rsa.bats b/test/21-wildcard-dual-rsa.bats index 7f0943f..550bbe0 100644 --- a/test/21-wildcard-dual-rsa.bats +++ b/test/21-wildcard-dual-rsa.bats @@ -14,11 +14,7 @@ setup() { @test "Create secp384r1 wildcard certificate" { - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - else - CONFIG_FILE="getssl-dns01.cfg" - fi + CONFIG_FILE="getssl-dns01.cfg" GETSSL_CMD_HOST="*.${GETSSL_HOST}" @@ -40,11 +36,7 @@ EOF @test "Create dual certificates using DNS-01 verification" { - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - else - CONFIG_FILE="getssl-dns01.cfg" - fi + CONFIG_FILE="getssl-dns01.cfg" GETSSL_CMD_HOST="*.${GETSSL_HOST}" diff --git a/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats index 238142e..b005af5 100644 --- a/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats @@ -14,11 +14,7 @@ setup() { @test "Create dual certificates (one wildcard) and copy RSA and ECDSA chain and key to two locations" { - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - else - CONFIG_FILE="getssl-dns01.cfg" - fi + CONFIG_FILE="getssl-dns01.cfg" GETSSL_CMD_HOST="*.${GETSSL_HOST}" diff --git a/test/24-wildcard-sans.bats b/test/24-wildcard-sans.bats index da5fea9..a9ca2a5 100644 --- a/test/24-wildcard-sans.bats +++ b/test/24-wildcard-sans.bats @@ -22,11 +22,7 @@ teardown() { @test "Check can create certificate for wildcard domain as arg and non-wildcard in SANS" { - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - else - CONFIG_FILE="getssl-dns01.cfg" - fi + CONFIG_FILE="getssl-dns01.cfg" # Staging server generates an error if try to create a certificate for *.domain and a.domain # so create for *.wild-domain and a.domain instead @@ -50,11 +46,7 @@ teardown() { @test "Check can create certificate for non-wildcard domain as arg and wildcard in SANS" { - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - else - CONFIG_FILE="getssl-dns01.cfg" - fi + CONFIG_FILE="getssl-dns01.cfg" GETSSL_CMD_HOST="${GETSSL_HOST}" setup_environment diff --git a/test/26-wildcard-revoke.bats b/test/26-wildcard-revoke.bats index 1416ef4..37f8f10 100644 --- a/test/26-wildcard-revoke.bats +++ b/test/26-wildcard-revoke.bats @@ -14,11 +14,7 @@ setup() { @test "Create certificate to check wildcard revoke" { - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - else - CONFIG_FILE="getssl-dns01.cfg" - fi + CONFIG_FILE="getssl-dns01.cfg" GETSSL_CMD_HOST="*.${GETSSL_HOST}" setup_environment @@ -30,11 +26,7 @@ setup() { @test "Check we can revoke a wildcard certificate" { - if [ -n "$STAGING" ]; then - CONFIG_FILE="getssl-staging-dns01.cfg" - else - CONFIG_FILE="getssl-dns01.cfg" - fi + CONFIG_FILE="getssl-dns01.cfg" . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" GETSSL_CMD_HOST="*.${GETSSL_HOST}" diff --git a/test/8-staging-ecdsa.bats b/test/8-staging-ecdsa.bats index 127e989..6aebd60 100644 --- a/test/8-staging-ecdsa.bats +++ b/test/8-staging-ecdsa.bats @@ -9,9 +9,9 @@ load '/getssl/test/test_helper.bash' @test "Create new certificate using staging server and prime256v1" { if [ -z "$STAGING" ]; then - skip "Running internal tests, skipping external test" + skip "Running external tests, skipping internal testing" fi - CONFIG_FILE="getssl-staging-dns01.cfg" + CONFIG_FILE="getssl-dns01.cfg" setup_environment init_getssl @@ -35,9 +35,9 @@ load '/getssl/test/test_helper.bash' @test "Create new certificate using staging server and secp384r1" { if [ -z "$STAGING" ]; then - skip "Running internal tests, skipping external test" + skip "Running external tests, skipping internal testing" fi - CONFIG_FILE="getssl-staging-dns01.cfg" + CONFIG_FILE="getssl-dns01.cfg" setup_environment init_getssl diff --git a/test/test-config/getssl-dns01.cfg b/test/test-config/getssl-dns01.cfg index c67f995..bd02c50 100644 --- a/test/test-config/getssl-dns01.cfg +++ b/test/test-config/getssl-dns01.cfg @@ -1,19 +1,38 @@ -# 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" +# Test that the script works with dns 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 - -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 -DNS_EXTRA_WAIT=0 - +if [ -z "$STAGING" ]; then + # Settings for challtestserv dns provider running in local docker + CA="https://pebble:14000/dir" + + 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 + + # Speed up the test by reducing the number or retries and the wait between retries. + DNS_WAIT=2 + DNS_WAIT_COUNT=11 + DNS_EXTRA_WAIT=0 +else + # Settings for external dns provider and staging server + CA="https://acme-staging-v02.api.letsencrypt.org/directory" + + DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_${dynamic_dns}" + DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_${dynamic_dns}" + PUBLIC_DNS_SERVER="8.8.8.8 resolver1.infoserve.de" + if [[ "${dynamic_dns}" == "dynu" ]]; then + AUTH_DNS_SERVER=ns1.dynu.com + else + AUTH_DNS_SERVER=ns1.duckdns.org + fi + CHECK_ALL_AUTH_DNS="true" + CHECK_PUBLIC_DNS_SERVER="true" + DNS_EXTRA_WAIT=120 + + DNS_WAIT_COUNT=20 + DNS_WAIT=30 + DNS_WAIT_RETRY_ADD="true" +fi # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="" diff --git a/test/test-config/getssl-staging-dns01.cfg b/test/test-config/getssl-staging-dns01.cfg deleted file mode 100644 index 8859686..0000000 --- a/test/test-config/getssl-staging-dns01.cfg +++ /dev/null @@ -1,49 +0,0 @@ -# Test that the script works with external dns provider and staging server -# -CA="https://acme-staging-v02.api.letsencrypt.org/directory" - -VALIDATE_VIA_DNS=true -DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_${dynamic_dns}" -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_${dynamic_dns}" -PUBLIC_DNS_SERVER="8.8.8.8 resolver1.infoserve.de" -if [[ "${dynamic_dns}" == "dynu" ]]; then - AUTH_DNS_SERVER=ns1.dynu.com -else - AUTH_DNS_SERVER=ns1.duckdns.org -fi -CHECK_ALL_AUTH_DNS="true" -CHECK_PUBLIC_DNS_SERVER="true" -DNS_EXTRA_WAIT=120 - -# Speed up the test by reducing the number or retries and retrying DNS_ADD after 10 failures -DNS_WAIT_COUNT=20 -DNS_WAIT=30 -DNS_WAIT_RETRY_ADD="true" - -ACCOUNT_KEY_TYPE="rsa" -PRIVATE_KEY_ALG="rsa" - -# Additional domains - this could be multiple domains / subdomains in a comma separated list -SANS="" - -# 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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" - -# Define the server type and confirm correct certificate is installed -SERVER_TYPE="https" -CHECK_REMOTE="true" - -if [[ -s "$DOMAIN_DIR/getssl_test_specific.cfg" ]]; then - . $DOMAIN_DIR/getssl_test_specific.cfg -fi - -#_RUNNING_TEST=1 -#_USE_DEBUG=1 From afabbc6506f9a3e9acfe9bf19bd6905fa413e4bc Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 12 Feb 2021 16:06:26 +0000 Subject: [PATCH 210/308] Add PREFERED_CHAIN --- getssl | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/getssl b/getssl index 583f88a..08487b4 100755 --- a/getssl +++ b/getssl @@ -253,8 +253,9 @@ # 2021-01-22 Add FTP_OPTIONS # 2021-01-27 Add the ability to set several reload commands (atisne) # 2021-01-29 Use dig -r (if supported) to ignore.digrc (#630) -# 2021-02-07 Allow -u --upgrade without any domain, so that one can only update the script (2.34) -# 2021-02-09 Prevent listing the complete file if version tag missing (#637) +# 2021-02-07 Allow -u --upgrade without any domain, so that one can only update the script (Benno-K)(2.34) +# 2021-02-09 Prevent listing the complete file if version tag missing (#637)(softins) +# 2021-02-12 Add PREFERRED_CHAIN # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -285,6 +286,7 @@ GETSSL_IGNORE_CP_PRESERVE="false" HTTP_TOKEN_CHECK_WAIT=0 IGNORE_DIRECTORY_DOMAIN="false" ORIG_UMASK=$(umask) +PREFERRED_CHAIN="" # Set this to use an alternative root certificate PREVIOUSLY_VALIDATED="true" PRIVATE_KEY_ALG="rsa" RELOAD_CMD="" @@ -1556,7 +1558,32 @@ get_certificate() { # get certificate for csr, if all domains validated. info "Requesting certificate" CertData=$(json_get "$response" "certificate") send_signed_request "$CertData" "" "" "$gc_fullchain" - info "Full certificate saved in $gc_fullchain" + IFS=$'\n' read -r -d '' -a alternate_links < <(echo "$responseHeaders" | grep "^Link" | grep "alternate" | awk -F"[<>]" '{print $2}') + debug "Alternate Links are ${alternate_links[*]}" + if [[ -n "$PREFERRED_CHAIN" ]]; then + cert_to_check=$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX) || error_exit "mktemp failed" + # Check the default certificate to see if that has the required chain + cp "$gc_fullchain" "$cert_to_check" + i=0 + while [[ $i -le ${#alternate_links[@]} ]]; do + cert_issuer=$(openssl crl2pkcs7 -nocrl -certfile "$cert_to_check" | openssl pkcs7 -print_certs -text -noout | grep 'Issuer:' | tail -1 | cut -d= -f2) + debug Certificate issued by "$cert_issuer" + if [[ $cert_issuer = *${PREFERRED_CHAIN}* ]]; then + debug "Found required certificate" + cp "$cert_to_check" "$gc_fullchain" + break + fi + + if [[ $i -lt ${#alternate_links[@]} ]]; then + debug "Fetching next alternate certificate $i ${alternate_links[$i]}" + send_signed_request "${alternate_links[$i]}" "" "" "$cert_to_check" + fi + i=$(( i + 1 )) + done + + # tidy up + rm -f "$cert_to_check" + fi awk -v CERT_FILE="$gc_certfile" -v CA_CERT="$gc_cafile" 'BEGIN {outfile=CERT_FILE} split_after==1 {outfile=CA_CERT;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > outfile}' "$gc_fullchain" info "Certificate saved in $gc_certfile" fi @@ -1675,6 +1702,7 @@ help_message() { # print out the help message -k, --keep "#" Maximum number of old getssl versions to keep when upgrading -U, --nocheck Do not check if a more recent version is available -w working_dir "Working directory" + --preferred-chain "chain" Use an alternate chain for the certificate _EOF_ } @@ -2278,7 +2306,8 @@ urlbase64_decode() { usage() { # echos out the program usage echo "Usage: $PROGNAME [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet]"\ - "[-Q|--mute] [-u|--upgrade] [-k|--keep #] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir] domain" + "[-Q|--mute] [-u|--upgrade] [-k|--keep #] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir]"\ + "[--preferred-chain chain] domain" } write_domain_template() { # write out a template file for a domain. @@ -2333,6 +2362,11 @@ write_domain_template() { # write out a template file for a domain. # Set USE_SINGLE_ACL="true" to use a single ACL for all checks #USE_SINGLE_ACL="false" + # Preferred Chain - use an different certificate root from the default + # Staging options are: "Fake LE Root X1" and "Fake LE Root X2" + # Production options are: "ISRG Root X1" and "ISRG Root X2" + #PREFERRED_CHAIN="" + # 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/ssl/${DOMAIN}.crt" # this is domain cert @@ -2387,6 +2421,11 @@ write_getssl_template() { # write out the main template file PRIVATE_KEY_ALG="rsa" #REUSE_PRIVATE_KEY="true" + # Preferred Chain - use an different certificate root from the default + # Staging options are: "Fake LE Root X1" and "Fake LE Root X2" + # Production options are: "ISRG Root X1" and "ISRG Root X2" + #PREFERRED_CHAIN="" + # The command needed to reload apache / nginx or whatever you use. # Several (ssh) commands may be given using a bash array: # RELOAD_CMD=('ssh:sshuserid@server5:systemctl reload httpd' 'logger getssl for server5 efficient.') @@ -2469,6 +2508,8 @@ while [[ -n ${1+defined} ]]; do _ONLY_CHECK_CONFIG=1 ;; -w) shift; WORKING_DIR="$1" ;; + -preferred-chain) + shift; PREFERRED_CHAIN="$1" ;; --source) return ;; -*) From fa89d7bfedd6448860196aa966ad623ea45ac9cf Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 12 Feb 2021 16:06:51 +0000 Subject: [PATCH 211/308] Add tests for PREFERRED_CHAIN --- docker-compose.yml | 1 + test/35-preferred-chain.bats | 95 ++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 test/35-preferred-chain.bats diff --git a/docker-compose.yml b/docker-compose.yml index ec5c24a..f2b1489 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,7 @@ services: environment: # with Go 1.13.x which defaults TLS 1.3 to on GODEBUG: "tls13=1" + PEBBLE_ALTERNATE_ROOTS: 2 ports: - 14000:14000 # HTTPS ACME API - 15000:15000 # HTTPS Management API diff --git a/test/35-preferred-chain.bats b/test/35-preferred-chain.bats new file mode 100644 index 0000000..4389d3b --- /dev/null +++ b/test/35-preferred-chain.bats @@ -0,0 +1,95 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Use PREFERRED_CHAIN to select an alternate root" { + if [ -n "$STAGING" ]; then + PREFERRED_CHAIN="Fake LE Root X2" + else + PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | cut -d= -f2) + PREFERRED_CHAIN="${PREFERRED_CHAIN# }" # remove leading whitespace + fi + + CONFIG_FILE="getssl-dns01.cfg" + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +PREFERRED_CHAIN="${PREFERRED_CHAIN}" +EOF + + create_certificate + assert_success + check_output_for_errors + + issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | cut -d= -f2) + # verify certificate is issued by preferred chain root + [ "$PREFERRED_CHAIN" = "$issuer" ] +} + + +@test "Use PREFERRED_CHAIN to select the default root" { + if [ -n "$STAGING" ]; then + PREFERRED_CHAIN="Fake LE Root X1" + else + PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/0 | openssl x509 -text -noout | grep Issuer: | cut -d= -f2 ) + PREFERRED_CHAIN="${PREFERRED_CHAIN# }" # remove leading whitespace + fi + + CONFIG_FILE="getssl-dns01.cfg" + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +PREFERRED_CHAIN="${PREFERRED_CHAIN}" +EOF + + create_certificate + assert_success + check_output_for_errors + + issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | cut -d= -f2) + # verify certificate is issued by preferred chain root + [ "$PREFERRED_CHAIN" = "$issuer" ] +} + + +@test "Use PREFERRED_CHAIN to select an alternate root by suffix" { + if [ -n "$STAGING" ]; then + FULL_PREFERRED_CHAIN="Fake LE Root X2" + else + FULL_PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | cut -d= -f2) + FULL_PREFERRED_CHAIN="${FULL_PREFERRED_CHAIN# }" # remove leading whitespace + fi + + # Take the last word from FULL_PREFERRED_CHAIN as the chain to use + PREFERRED_CHAIN="${FULL_PREFERRED_CHAIN##* }" + CONFIG_FILE="getssl-dns01.cfg" + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +PREFERRED_CHAIN="${PREFERRED_CHAIN}" +EOF + + create_certificate + assert_success + check_output_for_errors + + issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | cut -d= -f2) + # verify certificate is issued by preferred chain root + echo "# ${issuer}" + echo "# ${FULL_PREFERRED_CHAIN}" + [ "$FULL_PREFERRED_CHAIN" = "$issuer" ] +} From 10061936bd5c6aec85251d8658e0157bed203b46 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 12 Feb 2021 16:36:23 +0000 Subject: [PATCH 212/308] Fix interpreter line in dns_add_fail --- test/dns_add_fail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dns_add_fail b/test/dns_add_fail index 44ab42b..c39a89a 100755 --- a/test/dns_add_fail +++ b/test/dns_add_fail @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Special test script which will always fail to update dns From 973f5886ae0a4b5d585747dfdc6171074d58f541 Mon Sep 17 00:00:00 2001 From: update process Date: Mon, 15 Feb 2021 08:26:44 +0100 Subject: [PATCH 213/308] ftpes added to curl upload of challenge --- getssl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 08487b4..30cbdbe 100755 --- a/getssl +++ b/getssl @@ -912,6 +912,19 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. debug "davs user=$davsuser - pass=$davspass - host=$davshost port=$davsport dir=$davsdirn file=$davsfile" debug "from dir=$fromdir file=$fromfile" curl -u "${davsuser}:${davspass}" -T "${fromdir}/${fromfile}" "https://${davshost}:${davsport}${davsdirn}${davsfile}" + elif [[ "${to:0:6}" == "ftpes:" ]] ; then + debug "using ftp to copy the file from $from" + ftpuser=$(echo "$to"| awk -F: '{print $2}') + ftppass=$(echo "$to"| awk -F: '{print $3}') + ftphost=$(echo "$to"| awk -F: '{print $4}') + ftplocn=$(echo "$to"| awk -F: '{print $5}') + ftpdirn=$(dirname "$ftplocn") + ftpfile=$(basename "$ftplocn") + fromdir=$(dirname "$from") + fromfile=$(basename "$from") + debug "ftp user=$ftpuser - pass=$ftppass - host=$ftphost dir=$ftpdirn file=$ftpfile" + debug "from dir=$fromdir file=$fromfile" + curl --insecure --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" else if ! mkdir -p "$(dirname "$to")" ; then error_exit "cannot create ACL directory $(basename "$to")" @@ -2343,7 +2356,7 @@ write_domain_template() { # write out a template file for a domain. # 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 + # If these start with ftp:/ftpes: 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. # You can also user WebDAV over HTTPS as transport mechanism. To do so, start with davs: followed by username, @@ -2353,7 +2366,8 @@ write_domain_template() { # write out a template file for a domain. # 'ssh:server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' # 'ftp:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge' - # 'davs:davsuserid:davspassword:{DOMAIN}:443:/web/.well-known/acme-challenge') + # 'davs:davsuserid:davspassword:{DOMAIN}:443:/web/.well-known/acme-challenge' + # 'ftpes:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge') # Specify SSH options, e.g. non standard port in SSH_OPTS # (Can also use SCP_OPTS and SFTP_OPTS) From aae71fd7638e3fcfacd28ac53853d68eb91706cc Mon Sep 17 00:00:00 2001 From: update process Date: Mon, 15 Feb 2021 08:33:51 +0100 Subject: [PATCH 214/308] ftpes added to curl upload of challenge --- getssl | 1 + 1 file changed, 1 insertion(+) diff --git a/getssl b/getssl index 30cbdbe..066a83c 100755 --- a/getssl +++ b/getssl @@ -256,6 +256,7 @@ # 2021-02-07 Allow -u --upgrade without any domain, so that one can only update the script (Benno-K)(2.34) # 2021-02-09 Prevent listing the complete file if version tag missing (#637)(softins) # 2021-02-12 Add PREFERRED_CHAIN +# 2021-02-15 ADD ftp explicit SSL with curl for upload the challenge # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in From 522918f023d2be3093583c834efc48db74627ffb Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 18 Feb 2021 17:06:13 +0000 Subject: [PATCH 215/308] Add FULL_CHAIN_INCLUDE_ROOT Fixes #594 #272 #564 --- getssl | 30 +++++++++++- test/36-full-chain-inc-root.bats | 81 ++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 test/36-full-chain-inc-root.bats diff --git a/getssl b/getssl index 066a83c..80a3fae 100755 --- a/getssl +++ b/getssl @@ -256,7 +256,8 @@ # 2021-02-07 Allow -u --upgrade without any domain, so that one can only update the script (Benno-K)(2.34) # 2021-02-09 Prevent listing the complete file if version tag missing (#637)(softins) # 2021-02-12 Add PREFERRED_CHAIN -# 2021-02-15 ADD ftp explicit SSL with curl for upload the challenge +# 2021-02-15 ADD ftp explicit SSL with curl for upload the challenge (CoolMischa) +# 2021-02-18 Add FULL_CHAIN_INCLUDE_ROOT # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -283,6 +284,7 @@ DEFAULT_REVOKE_CA="https://acme-v02.api.letsencrypt.org" DOMAIN_KEY_LENGTH=4096 DUAL_RSA_ECDSA="false" FTP_OPTIONS="" +FULL_CHAIN_INCLUDE_ROOT="false" GETSSL_IGNORE_CP_PRESERVE="false" HTTP_TOKEN_CHECK_WAIT=0 IGNORE_DIRECTORY_DOMAIN="false" @@ -1598,7 +1600,27 @@ get_certificate() { # get certificate for csr, if all domains validated. # tidy up rm -f "$cert_to_check" fi + awk -v CERT_FILE="$gc_certfile" -v CA_CERT="$gc_cafile" 'BEGIN {outfile=CERT_FILE} split_after==1 {outfile=CA_CERT;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > outfile}' "$gc_fullchain" + if [[ "$FULL_CHAIN_INCLUDE_ROOT" = "true" ]]; then + # Some of the code below was copied from zakjan/cert-chain-resolver + + # Download the certificate for the issuer using the "CA Issuers" attribute from the AIA x509 extension + issuer_url=$(openssl x509 -inform pem -noout -text -in "$gc_certfile" | awk 'BEGIN {FS="CA Issuers - URI:"} NF==2 {print $2; exit}') + debug Issuer for "$gc_certfile" is "$issuer_url" + + # Keep downloading issuer certficates until we find the root certificate (which doesn't have a "CA Issuers" attribure) + cp "$gc_certfile" "$gc_fullchain" + while [[ -n "$issuer_url" ]]; do + debug Fetching certificate issuer from "$issuer_url" + issuer_cert=$(curl --user-agent "$CURL_USERAGENT" --silent "$issuer_url" | openssl x509 -inform der -outform pem) + debug Fetched issuer certificate "$(echo "$issuer_cert" | openssl x509 -inform pem -noout -text | awk 'BEGIN {FS="Subject: "} NF==2 {print $2; exit}')" + echo "$issuer_cert" >> "$gc_fullchain" + + # get issuer for the certificate that's just been downloaded + issuer_url=$(echo "$issuer_cert" | openssl x509 -inform pem -noout -text | awk 'BEGIN {FS="CA Issuers - URI:"} NF==2 {print $2; exit}') + done + fi info "Certificate saved in $gc_certfile" fi } @@ -2382,6 +2404,9 @@ write_domain_template() { # write out a template file for a domain. # Production options are: "ISRG Root X1" and "ISRG Root X2" #PREFERRED_CHAIN="" + # Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism) + #FULL_CHAIN_INCLUDE_ROOT="true" + # 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/ssl/${DOMAIN}.crt" # this is domain cert @@ -2441,6 +2466,9 @@ write_getssl_template() { # write out the main template file # Production options are: "ISRG Root X1" and "ISRG Root X2" #PREFERRED_CHAIN="" + # Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism) + #FULL_CHAIN_INCLUDE_ROOT="true" + # The command needed to reload apache / nginx or whatever you use. # Several (ssh) commands may be given using a bash array: # RELOAD_CMD=('ssh:sshuserid@server5:systemctl reload httpd' 'logger getssl for server5 efficient.') diff --git a/test/36-full-chain-inc-root.bats b/test/36-full-chain-inc-root.bats new file mode 100644 index 0000000..5932ea7 --- /dev/null +++ b/test/36-full-chain-inc-root.bats @@ -0,0 +1,81 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + fi +} + + +@test "Use FULL_CHAIN_INCLUDE_ROOT to include the root certificate in the fullchain" { + CONFIG_FILE="getssl-dns01.cfg" + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +FULL_CHAIN_INCLUDE_ROOT="true" +EOF + + create_certificate + assert_success + check_output_for_errors + + if [ -n "$STAGING" ]; then + PREFERRED_CHAIN="Fake LE Root X1" + else + # pebble doesn't support CA Issuers so the fullchain.crt will just contain the certificate (code path means it won't contain the intermediate cert in this case) + # This is testing that requesting FULL_CHAIN_INCLUDE_ROOT doesn't fail if there is no CA Issuers in the certificate + PREFERRED_CHAIN=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) + fi + + final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) + # verify certificate includes the chain root + [ "$PREFERRED_CHAIN" = "$final_issuer" ] +} + + +@test "Use FULL_CHAIN_INCLUDE_ROOT with dual certificates" { + if [ -n "$STAGING" ]; then + PREFERRED_CHAIN="Fake LE Root X1" + fi + + CONFIG_FILE="getssl-dns01.cfg" + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +FULL_CHAIN_INCLUDE_ROOT="true" +DUAL_RSA_ECDSA="true" +ACCOUNT_KEY_TYPE="prime256v1" +PRIVATE_KEY_ALG="prime256v1" +CHECK_REMOTE="false" +EOF + + create_certificate + assert_success + check_output_for_errors + check_certificates + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.ec.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" ] + assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.ec.crt" ] + + if [ -n "$STAGING" ]; then + PREFERRED_CHAIN="Fake LE Root X1" + else + # pebble doesn't support CA Issuers so the fullchain.crt will just contain the certificate (code path means it won't contain the intermediate cert in this case) + # This is testing that requesting FULL_CHAIN_INCLUDE_ROOT doesn't fail if there is no CA Issuers in the certificate + PREFERRED_CHAIN=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) + fi + + # verify both rsa and ecdsa certificates include the chain root + final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) + [ "$PREFERRED_CHAIN" = "$final_issuer" ] + ecdsa_final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) + [ "$PREFERRED_CHAIN" = "$ecdsa_final_issuer" ] +} From e19afe87af0863c95f570997c537e8bbad3d006a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 18 Feb 2021 17:14:44 +0000 Subject: [PATCH 216/308] Fixes double slash reported in #585 --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 80a3fae..88b4d9f 100755 --- a/getssl +++ b/getssl @@ -302,7 +302,7 @@ OCSP_MUST_STAPLE="false" TEMP_UPGRADE_FILE="" TOKEN_USER_ID="" USE_SINGLE_ACL="false" -WORKING_DIR_CANDIDATES=("/etc/getssl/" "${PROGDIR}/conf" "${PROGDIR}/.getssl" "${HOME}/.getssl") +WORKING_DIR_CANDIDATES=("/etc/getssl" "${PROGDIR}/conf" "${PROGDIR}/.getssl" "${HOME}/.getssl") # Variables used when validating using a DNS entry VALIDATE_VIA_DNS="" # Set this to "true" to enable DNS validation From 27af6d9f2f8043e4df47e1df2a23c2bf0c9de7ee Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 19 Feb 2021 15:51:56 +0000 Subject: [PATCH 217/308] Fix test scripts to add to dns once and remove once --- test/17-test-spaces-in-sans-dns01.bats | 19 +++++-------------- test/17-test-spaces-in-sans-http01.bats | 19 +++++-------------- 2 files changed, 10 insertions(+), 28 deletions(-) diff --git a/test/17-test-spaces-in-sans-dns01.bats b/test/17-test-spaces-in-sans-dns01.bats index 9f3b3dc..9d425af 100644 --- a/test/17-test-spaces-in-sans-dns01.bats +++ b/test/17-test-spaces-in-sans-dns01.bats @@ -50,11 +50,6 @@ setup() { CONFIG_FILE="getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg" setup_environment - # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) - for prefix in a b c; do - curl --silent -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 @@ -70,10 +65,6 @@ setup() { assert_success check_output_for_errors cleanup_environment - - for prefix in a b c; do - curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a - done } @@ -84,13 +75,13 @@ setup() { CONFIG_FILE="getssl-dns01-spaces-and-commas-sans.cfg" setup_environment - # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) - for prefix in a b c; do - curl --silent -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 check_output_for_errors + cleanup_environment + + for prefix in a b c; do + curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a + done } diff --git a/test/17-test-spaces-in-sans-http01.bats b/test/17-test-spaces-in-sans-http01.bats index fab530f..1730e99 100644 --- a/test/17-test-spaces-in-sans-http01.bats +++ b/test/17-test-spaces-in-sans-http01.bats @@ -50,11 +50,6 @@ setup() { CONFIG_FILE="getssl-http01-spaces-sans-and-ignore-dir-domain.cfg" setup_environment - # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) - for prefix in a b c; do - curl --silent -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 @@ -70,10 +65,6 @@ setup() { assert_success check_output_for_errors cleanup_environment - - for prefix in a b c; do - curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a - done } @@ -84,13 +75,13 @@ setup() { CONFIG_FILE="getssl-http01-spaces-and-commas-sans.cfg" setup_environment - # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) - for prefix in a b c; do - curl --silent -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 check_output_for_errors + cleanup_environment + + for prefix in a b c; do + curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a + done } From 2863e9e52d0f2c65536a41891fe7be79ede80253 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 19 Feb 2021 15:52:24 +0000 Subject: [PATCH 218/308] Clear previous dns entries before adding a new entry --- test/test_helper.bash | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_helper.bash b/test/test_helper.bash index 11cdf44..48a8d4b 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -64,6 +64,8 @@ setup_environment() { fi if [ -z "$STAGING" ]; then + # Make sure that we have cleared any previous entries, otherwise get random dns failures + curl --silent -X POST -d '{"host":"'"$GETSSL_HOST"'"}' http://10.30.50.3:8055/clear-a curl --silent -X POST -d '{"host":"'"$GETSSL_HOST"'", "addresses":["'"$GETSSL_IP"'"]}' http://10.30.50.3:8055/add-a fi cp ${CODE_DIR}/test/test-config/nginx-ubuntu-no-ssl "${NGINX_CONFIG}" From 4f5b518038116405aef6ed554fab6bd54b392e8d Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 20 Feb 2021 11:55:20 +0000 Subject: [PATCH 219/308] Update staging certificate names --- getssl | 12 +++++---- test/35-preferred-chain.bats | 45 +++++++++++++++++++++----------- test/36-full-chain-inc-root.bats | 35 +++++++++++++++++-------- 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/getssl b/getssl index 88b4d9f..d73faea 100755 --- a/getssl +++ b/getssl @@ -1582,7 +1582,7 @@ get_certificate() { # get certificate for csr, if all domains validated. cp "$gc_fullchain" "$cert_to_check" i=0 while [[ $i -le ${#alternate_links[@]} ]]; do - cert_issuer=$(openssl crl2pkcs7 -nocrl -certfile "$cert_to_check" | openssl pkcs7 -print_certs -text -noout | grep 'Issuer:' | tail -1 | cut -d= -f2) + cert_issuer=$(openssl crl2pkcs7 -nocrl -certfile "$cert_to_check" | openssl pkcs7 -print_certs -text -noout | grep 'Issuer:' | tail -1 | awk -F"CN=" '{ print $2 }') debug Certificate issued by "$cert_issuer" if [[ $cert_issuer = *${PREFERRED_CHAIN}* ]]; then debug "Found required certificate" @@ -2400,9 +2400,10 @@ write_domain_template() { # write out a template file for a domain. #USE_SINGLE_ACL="false" # Preferred Chain - use an different certificate root from the default - # Staging options are: "Fake LE Root X1" and "Fake LE Root X2" + # This uses wildcard matching so requesting "X1" returns the correct certificate - may need to escape characters + # Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1" # Production options are: "ISRG Root X1" and "ISRG Root X2" - #PREFERRED_CHAIN="" + #PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1" # Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism) #FULL_CHAIN_INCLUDE_ROOT="true" @@ -2462,9 +2463,10 @@ write_getssl_template() { # write out the main template file #REUSE_PRIVATE_KEY="true" # Preferred Chain - use an different certificate root from the default - # Staging options are: "Fake LE Root X1" and "Fake LE Root X2" + # This uses wildcard matching so requesting "X1" returns the correct certificate - may need to escape characters + # Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1" # Production options are: "ISRG Root X1" and "ISRG Root X2" - #PREFERRED_CHAIN="" + #PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1" # Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism) #FULL_CHAIN_INCLUDE_ROOT="true" diff --git a/test/35-preferred-chain.bats b/test/35-preferred-chain.bats index 4389d3b..0a5821c 100644 --- a/test/35-preferred-chain.bats +++ b/test/35-preferred-chain.bats @@ -15,10 +15,12 @@ setup() { @test "Use PREFERRED_CHAIN to select an alternate root" { if [ -n "$STAGING" ]; then - PREFERRED_CHAIN="Fake LE Root X2" + PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1" + CHECK_CHAIN="(STAGING) Pretend Pear X1" else - PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | cut -d= -f2) + PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | awk -F"CN=" '{ print $2 }') PREFERRED_CHAIN="${PREFERRED_CHAIN# }" # remove leading whitespace + CHECK_CHAIN=$PREFERRED_CHAIN fi CONFIG_FILE="getssl-dns01.cfg" @@ -29,21 +31,27 @@ setup() { PREFERRED_CHAIN="${PREFERRED_CHAIN}" EOF - create_certificate + create_certificate -d assert_success check_output_for_errors - issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | cut -d= -f2) + issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | awk -F"CN=" '{ print $2 }') # verify certificate is issued by preferred chain root - [ "$PREFERRED_CHAIN" = "$issuer" ] + if [[ "${CHECK_CHAIN}" != "$issuer" ]]; then + echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" + echo "# issuer=$issuer" + fi + + [ "${CHECK_CHAIN}" = "$issuer" ] } @test "Use PREFERRED_CHAIN to select the default root" { if [ -n "$STAGING" ]; then - PREFERRED_CHAIN="Fake LE Root X1" + PREFERRED_CHAIN="\(STAGING\) Doctored Durian Root CA X3" + CHECK_CHAIN="(STAGING) Doctored Durian Root CA X3" else - PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/0 | openssl x509 -text -noout | grep Issuer: | cut -d= -f2 ) + PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/0 | openssl x509 -text -noout | grep Issuer: | awk -F"CN=" '{ print $2 }') PREFERRED_CHAIN="${PREFERRED_CHAIN# }" # remove leading whitespace fi @@ -59,17 +67,21 @@ EOF assert_success check_output_for_errors - issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | cut -d= -f2) + issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | awk -F"CN=" '{ print $2 }') # verify certificate is issued by preferred chain root - [ "$PREFERRED_CHAIN" = "$issuer" ] + if [[ "${CHECK_CHAIN}" != "$issuer" ]]; then + echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" + echo "# issuer=$issuer" + fi + [ "${CHECK_CHAIN}" = "$issuer" ] } @test "Use PREFERRED_CHAIN to select an alternate root by suffix" { if [ -n "$STAGING" ]; then - FULL_PREFERRED_CHAIN="Fake LE Root X2" + FULL_PREFERRED_CHAIN="(STAGING) Pretend Pear X1" else - FULL_PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | cut -d= -f2) + FULL_PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | awk -F"CN=" '{ print $2 }') FULL_PREFERRED_CHAIN="${FULL_PREFERRED_CHAIN# }" # remove leading whitespace fi @@ -87,9 +99,12 @@ EOF assert_success check_output_for_errors - issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | cut -d= -f2) + issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | awk -F"CN=" '{ print $2 }') # verify certificate is issued by preferred chain root - echo "# ${issuer}" - echo "# ${FULL_PREFERRED_CHAIN}" - [ "$FULL_PREFERRED_CHAIN" = "$issuer" ] + if [[ "${FULL_PREFERRED_CHAIN}" != "$issuer" ]]; then + echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" + echo "# FULL_PREFERRED_CHAIN=$FULL_PREFERRED_CHAIN" + echo "# issuer=$issuer" + fi + [ "${FULL_PREFERRED_CHAIN}" = "$issuer" ] } diff --git a/test/36-full-chain-inc-root.bats b/test/36-full-chain-inc-root.bats index 5932ea7..5b29d0b 100644 --- a/test/36-full-chain-inc-root.bats +++ b/test/36-full-chain-inc-root.bats @@ -27,22 +27,27 @@ EOF check_output_for_errors if [ -n "$STAGING" ]; then - PREFERRED_CHAIN="Fake LE Root X1" + PREFERRED_CHAIN="(STAGING) Doctored Durian Root CA X3" else # pebble doesn't support CA Issuers so the fullchain.crt will just contain the certificate (code path means it won't contain the intermediate cert in this case) # This is testing that requesting FULL_CHAIN_INCLUDE_ROOT doesn't fail if there is no CA Issuers in the certificate - PREFERRED_CHAIN=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) + PREFERRED_CHAIN=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') fi - final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) + final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') + # verify certificate includes the chain root - [ "$PREFERRED_CHAIN" = "$final_issuer" ] + if [[ "${PREFERRED_CHAIN}" != "$final_issuer" ]]; then + echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" + echo "# final_issuer=$final_issuer" + fi + [ "${PREFERRED_CHAIN}" = "$final_issuer" ] } @test "Use FULL_CHAIN_INCLUDE_ROOT with dual certificates" { if [ -n "$STAGING" ]; then - PREFERRED_CHAIN="Fake LE Root X1" + PREFERRED_CHAIN="(STAGING) Doctored Durian Root CA X3" fi CONFIG_FILE="getssl-dns01.cfg" @@ -66,16 +71,24 @@ EOF assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.ec.crt" ] if [ -n "$STAGING" ]; then - PREFERRED_CHAIN="Fake LE Root X1" + PREFERRED_CHAIN="(STAGING) Doctored Durian Root CA X3" else # pebble doesn't support CA Issuers so the fullchain.crt will just contain the certificate (code path means it won't contain the intermediate cert in this case) # This is testing that requesting FULL_CHAIN_INCLUDE_ROOT doesn't fail if there is no CA Issuers in the certificate - PREFERRED_CHAIN=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) + PREFERRED_CHAIN=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') fi # verify both rsa and ecdsa certificates include the chain root - final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) - [ "$PREFERRED_CHAIN" = "$final_issuer" ] - ecdsa_final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | cut -d= -f2) - [ "$PREFERRED_CHAIN" = "$ecdsa_final_issuer" ] + final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') + if [[ "${PREFERRED_CHAIN}" != "$final_issuer" ]]; then + echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" + echo "# final_issuer=$final_issuer" + fi + [ "${PREFERRED_CHAIN}" = "$final_issuer" ] + ecdsa_final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') + if [[ "$PREFERRED_CHAIN" != "$ecdsa_final_issuer" ]]; then + echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" + echo "# ecdsa_final_issuer=$ecdsa_final_issuer" + fi + [ "${PREFERRED_CHAIN}" = "$ecdsa_final_issuer" ] } From da63cf3ac42b43c18af8e42a982bdc236c80e668 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 20 Feb 2021 15:07:58 +0000 Subject: [PATCH 220/308] Fix awk command for pebble --- test/35-preferred-chain.bats | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/35-preferred-chain.bats b/test/35-preferred-chain.bats index 0a5821c..b16e77a 100644 --- a/test/35-preferred-chain.bats +++ b/test/35-preferred-chain.bats @@ -18,7 +18,7 @@ setup() { PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1" CHECK_CHAIN="(STAGING) Pretend Pear X1" else - PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | awk -F"CN=" '{ print $2 }') + PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | awk -F"CN *= *" '{ print $2 }') PREFERRED_CHAIN="${PREFERRED_CHAIN# }" # remove leading whitespace CHECK_CHAIN=$PREFERRED_CHAIN fi @@ -51,8 +51,9 @@ EOF PREFERRED_CHAIN="\(STAGING\) Doctored Durian Root CA X3" CHECK_CHAIN="(STAGING) Doctored Durian Root CA X3" else - PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/0 | openssl x509 -text -noout | grep Issuer: | awk -F"CN=" '{ print $2 }') + PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/0 | openssl x509 -text -noout | grep Issuer: | awk -F"CN *= *" '{ print $2 }') PREFERRED_CHAIN="${PREFERRED_CHAIN# }" # remove leading whitespace + CHECK_CHAIN=$PREFERRED_CHAIN fi CONFIG_FILE="getssl-dns01.cfg" @@ -81,7 +82,7 @@ EOF if [ -n "$STAGING" ]; then FULL_PREFERRED_CHAIN="(STAGING) Pretend Pear X1" else - FULL_PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | awk -F"CN=" '{ print $2 }') + FULL_PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | awk -F"CN *= *" '{ print $2 }') FULL_PREFERRED_CHAIN="${FULL_PREFERRED_CHAIN# }" # remove leading whitespace fi From 8bb211417457bf20e0a964d703a86acb9bf83023 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 20 Feb 2021 15:49:37 +0000 Subject: [PATCH 221/308] Remove debug --- test/35-preferred-chain.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/35-preferred-chain.bats b/test/35-preferred-chain.bats index b16e77a..9c3fc6b 100644 --- a/test/35-preferred-chain.bats +++ b/test/35-preferred-chain.bats @@ -31,7 +31,7 @@ setup() { PREFERRED_CHAIN="${PREFERRED_CHAIN}" EOF - create_certificate -d + create_certificate assert_success check_output_for_errors From 39ddb2da7a116d6499b5aa06ea304e5339a2dd97 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 13 Mar 2021 20:27:07 +0000 Subject: [PATCH 222/308] Tweaked code in requires() so it doesn't break function auto complete in vscode --- getssl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/getssl b/getssl index d73faea..1f1ca7c 100755 --- a/getssl +++ b/getssl @@ -2073,16 +2073,18 @@ revoke_certificate() { # revoke a certificate } requires() { # check if required function is available + args=("${@}") + lastarg=${args[${#args[@]}-1]} if [[ "$#" -gt 1 ]]; then # if more than 1 value, check list for i in "$@"; do - if [[ "$i" == "${!#}" ]]; then # if on last variable then exit as not found + if [[ "$i" == "$lastarg" ]]; then # if on last variable then exit as not found error_exit "this script requires one of: ${*:1:$(($#-1))}" fi res=$(command -v "$i" 2>/dev/null) debug "checking for $i ... $res" if [[ -n "$res" ]]; then # if function found, then set variable to function and return - debug "function $i found at $res - setting ${!#} to $i" - eval "${!#}=\$i" + debug "function $i found at $res - setting ${lastarg} to $i" + eval "${lastarg}=\$i" return fi done From 761e61fdeda1c0fc768c0327e455c5c701ea145e Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 13 Mar 2021 20:27:42 +0000 Subject: [PATCH 223/308] Add dns scripts for cpanel --- dns_scripts/dns_add_cpanel | 76 ++++++++++++++++++++++++++++++++++++++ dns_scripts/dns_del_cpanel | 69 ++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 dns_scripts/dns_add_cpanel create mode 100644 dns_scripts/dns_del_cpanel diff --git a/dns_scripts/dns_add_cpanel b/dns_scripts/dns_add_cpanel new file mode 100644 index 0000000..24a1ca8 --- /dev/null +++ b/dns_scripts/dns_add_cpanel @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +# Need to add your email address and API key to cpanel below or set as env variables +user=${CPANEL_USERNAME:-''} +password=${CPANEL_PASSWORD:-''} +url=${CPANEL_URL:-''} # e.g. https://www.cpanel-host.test:2083 +apitoken=${CPANEL_APITOKEN:-''} + +fulldomain="${1}" +token="${2}" + +# Check initial parameters +if [[ -z "$fulldomain" ]]; then + echo "DNS script requires full domain name as first parameter" + exit 1 +fi +if [[ -z "$token" ]]; then + echo "DNS script requires challenge token as second parameter" + exit 1 +fi +if [[ -z "$user" ]]; then + echo "CPANEL_USERNAME (username) parameter not set" + exit 1 +fi +if [[ -z "$apitoken" ]] && [[ -z "$password" ]]; then + echo "Must set either CPANEL_APITOKEN or CPANEL_PASSWORD in dns script, environment variable or getssl.cfg" + exit 1 +fi +if [[ -z "$url" ]]; then + echo "CPANEL_URL (url) parameter not set" + exit 1 +fi + +# Setup +request_func="${url}/json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit" +if [[ -n $apitoken ]]; then + curl_params=( -H "Authorization: cpanel $user:$apitoken" ) +else + auth_string=$(echo -ne "$user:$password" | base64 --wrap 0) + curl_params=( -H "Authorization: Basic $auth_string" ) +fi + +# Check if domain is a CNAME +res=$(dig CNAME "$fulldomain") +domain=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') +if [[ -n "$domain" ]]; then + name=".${fulldomain%.$domain}" +else + domain=$fulldomain + name="" +fi + +# Check to see if challenge dns entry already exists (update or delete?) +request_params="&cpanel_jsonapi_func=fetchzone_records&domain=${domain}&type=TXT&name=_acme-challenge.${fulldomain}." +resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params") +if [[ "$resp" = *\"error\":* ]]; then + echo -n "cpanel fetchzone records failed: " + echo "$resp" | awk -F"error" '{ print $2 }' | awk -F\" '{ print $3 }' + exit 1 +fi + +# If no existing record, create a new TXT record, otherwise edit the existing record +if [[ "$resp" == *\"data\":[]* ]]; then + request_params="&cpanel_jsonapi_func=add_zone_record&domain=$domain&type=TXT&name=_acme-challenge$name&txtdata=$token" +else + # shellcheck disable=SC2001 + line=$(echo "$resp" | sed -e 's/.*line":\([0-9]*\),.*/\1/') + request_params="&cpanel_jsonapi_func=edit_zone_record&domain=$domain&type=TXT&name=_acme-challenge$name&txtdata=${token}&line=${line}" +fi +resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params") + +if [[ "$resp" = *\"status\":0* ]]; then + echo -n "cpanel edit zone record failed: " + echo "$resp" | awk -F"statusmsg" '{ print $2 }' | awk -F\" '{ print $3 }' + exit 1 +fi diff --git a/dns_scripts/dns_del_cpanel b/dns_scripts/dns_del_cpanel new file mode 100644 index 0000000..922151a --- /dev/null +++ b/dns_scripts/dns_del_cpanel @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +# Need to add your email address and API key to cpanel below or set as env variables +user=${CPANEL_USERNAME:-''} +password=${CPANEL_PASSWORD:-''} +url=${CPANEL_URL:-''} # e.g. https://www.cpanel-host.test:2083 +apitoken=${CPANEL_APITOKEN:-''} + +fulldomain="${1}" + +# Check initial parameters +if [[ -z "$fulldomain" ]]; then + echo "DNS script requires full domain name as first parameter" + exit 1 +fi +if [[ -z "$user" ]]; then + echo "CPANEL_USERNAME (username) parameter not set" + exit 1 +fi +if [[ -z "$apitoken" ]] && [[ -z "$password" ]]; then + echo "Must set either CPANEL_APITOKEN or CPANEL_PASSWORD in dns script, environment variable or getssl.cfg" + exit 1 +fi +if [[ -z "$url" ]]; then + echo "CPANEL_URL (url) parameter not set" + exit 1 +fi + +# Setup +request_func="${url}/json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit" +if [[ -n $apitoken ]]; then + curl_params=( -H "Authorization: cpanel $user:$apitoken" ) +else + auth_string=$(echo -ne "$user:$password" | base64 --wrap 0) + curl_params=( -H "Authorization: Basic $auth_string" ) +fi + +# Check if domain is a CNAME +res=$(dig CNAME "$fulldomain") +domain=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') +if [[ -n "$domain" ]]; then + name=".${fulldomain%.$domain}" +else + domain=$fulldomain + name="" +fi + +# Find line number of existing record +request_params="&cpanel_jsonapi_func=fetchzone_records&domain=${domain}&type=TXT&name=_acme-challenge.${fulldomain}." +resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params") +if [[ "$resp" = *\"error\":* ]]; then + echo -n "cpanel fetchzone records failed: " + echo "$resp" | awk -F"error" '{ print $2 }' | awk -F\" '{ print $3 }' + exit 1 +fi + +# shellcheck disable=SC2001 +line=$(echo "$resp" | sed -e 's/.*line":\([0-9]*\),.*/\1/') +if [[ "$line" != "" ]]; then + # Delete the challenge token + request_params="&cpanel_jsonapi_func=remove_zone_record&domain=$domain&type=TXT&name=_acme-challenge$name&line=$line" + resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params") +fi + +if [[ "$resp" = *\"status\":0* ]]; then + echo -n "cpanel remove zone record failed: " + echo "$resp" | awk -F"statusmsg" '{ print $2 }' | awk -F\" '{ print $3 }' + exit 1 +fi From 349210e2d924c445b39f0e7fef8cf9d509e9afff Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 13 Mar 2021 20:29:52 +0000 Subject: [PATCH 224/308] Document wildcards, PREFERRED_CHAIN and FULL_CHAIN_INCLUDE_ROOT --- README.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cad2775..cb226e3 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,23 @@ -# getssl +# getssl ![Run all tests](https://github.com/srvrco/getssl/workflows/Run%20all%20tests/badge.svg) ![shellcheck](https://github.com/srvrco/getssl/workflows/shellcheck/badge.svg) Obtain SSL certificates from the letsencrypt.org ACME server. Suitable for automating the process on remote servers. -## Table of Contents - +## Table of Contents - [Features](#features) - [Installation](#installation) - [Overview](#overview) - [Getting started](#getting-started) +- [Wildcard certificates](#wildcard-certificates) - [Automating updates](#automating-updates) - [Structure](#structure) - [Server-Types](#server-types) - [Revoke a certificate](#revoke-a-certificate) - [Elliptic curve keys](#elliptic-curve-keys) +- [Preferred Chain](#preferred-chain) +- [Full chain](#full-chain) - [Issues / problems / help](#issues--problems--help) ## Features @@ -163,9 +165,35 @@ Change the server in your config file to get a fully valid certificate. dns. The certificate can be used (and checked with getssl) on alternate ports. +## Wildcard certificates + +`getssl` supports creating wildcard certificates, i.e. _*.example.com_ which allows a single certificate to be used for any domain under *example.com*, e.g. *www.example.com*, *mail.example.com*. These must be validated using the dns-01 method. + +A *partial* example `getssl.cfg` file is: + +```sh +VALIDATE_VIA_DNS=true +export CPANEL_USERNAME='' +export CPANEL_URL='https://www.cpanel.host:2083' +export CPANEL_APITOKEN='1ABC2DEF3GHI4JKL5MNO6PQR7STU8VWX9YZA' +DNS_ADD_COMMAND=/home/root/getssl/dns_scripts/dns_add_cpanel +DNS_DEL_COMMAND=/home/root/getssl/dns_scripts/dns_del_cpanel +``` + +Create the wildcard certificate (need to use quotes to prevent globbing): + +```sh +getssl "*.example.domain" +``` + +You can renew the certificate using `getssl -a` to renew all configured certificates. + +You can also specify additional domains in the `SANS` line, e.g. `SANS="www.test.example.com"`. +This cannot contain any of the domains which would be covered by the wildcard certificate. + ## Automating updates -I use the following cron +I use the following **cron** job ```cron 23 5 * * * /root/scripts/getssl -u -a -q @@ -353,6 +381,34 @@ key (different of course, don't use the same key for both). prime256v1 secp521r1 (NIST P-521) is included in the code, but not currently supported by Let's Encrypt). +## Preferred Chain + +If a CA offers multiple chains then it is possible to select which chain +is used by using the `PREFERRED_CHAIN` variable in `getssl.cfg` or specifying + `--preferred-chain` in the call to `getssl` + +This uses wildcard matching so requesting "X1" returns the first certificate +returned by the CA which contains the text "X1", Note you may need to escape +any characters which special characters, e.g. +` PREFERRED_CHAIN="\(STAGING\) Doctored Durian Root CA X3"` + +* Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1" +* Production options are: "ISRG Root X1" and "ISRG Root X2" + +## Full chain + +Some servers, including those that use Java keystores, will not accept a server certificate if it cannot valid the full chain of signers. + +Specifically, Nutanix Prism (Element and Central) will not accept the `fullchain.crt` until the root CA's certificate has been appended to it manually. + +If your application requires the full chain, i.e. including the +root certificate of the CA, then this can be included in the `fullchain.crt` file by +adding the following line to `getssl.cfg` + +```sh +FULL_CHAIN_INCLUDE_ROOT="true" +``` + ## Issues / problems / help If you have any issues, please log them at From 2dd9e9acd41cd68ef5ab637b369b3dce3738211e Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 16 Mar 2021 12:02:03 +0000 Subject: [PATCH 225/308] Tweak full chain heading --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cb226e3..def44c5 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ for automating the process on remote servers. - [Revoke a certificate](#revoke-a-certificate) - [Elliptic curve keys](#elliptic-curve-keys) - [Preferred Chain](#preferred-chain) -- [Full chain](#full-chain) +- [Include Root certificate in full chain](#include-root-certificate-in-full-chain) - [Issues / problems / help](#issues--problems--help) ## Features @@ -395,7 +395,7 @@ any characters which special characters, e.g. * Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1" * Production options are: "ISRG Root X1" and "ISRG Root X2" -## Full chain +## Include Root certificate in full chain Some servers, including those that use Java keystores, will not accept a server certificate if it cannot valid the full chain of signers. From 073b33c7f617ded56e3533a9e4b240825c1d0e4b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 16 Mar 2021 12:03:14 +0000 Subject: [PATCH 226/308] Add more info to message for "Certificate on remote domain does not match" --- getssl | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/getssl b/getssl index 1f1ca7c..cebd7f7 100755 --- a/getssl +++ b/getssl @@ -2401,14 +2401,14 @@ write_domain_template() { # write out a template file for a domain. # Set USE_SINGLE_ACL="true" to use a single ACL for all checks #USE_SINGLE_ACL="false" - # Preferred Chain - use an different certificate root from the default - # This uses wildcard matching so requesting "X1" returns the correct certificate - may need to escape characters - # Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1" - # Production options are: "ISRG Root X1" and "ISRG Root X2" - #PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1" + # Preferred Chain - use an different certificate root from the default + # This uses wildcard matching so requesting "X1" returns the correct certificate - may need to escape characters + # Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1" + # Production options are: "ISRG Root X1" and "ISRG Root X2" + #PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1" - # Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism) - #FULL_CHAIN_INCLUDE_ROOT="true" + # Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism) + #FULL_CHAIN_INCLUDE_ROOT="true" # Location for all your certs, these can either be on the server (full path name) # or using ssh /sftp as for the ACL @@ -2464,14 +2464,14 @@ write_getssl_template() { # write out the main template file PRIVATE_KEY_ALG="rsa" #REUSE_PRIVATE_KEY="true" - # Preferred Chain - use an different certificate root from the default - # This uses wildcard matching so requesting "X1" returns the correct certificate - may need to escape characters - # Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1" - # Production options are: "ISRG Root X1" and "ISRG Root X2" - #PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1" + # Preferred Chain - use an different certificate root from the default + # This uses wildcard matching so requesting "X1" returns the correct certificate - may need to escape characters + # Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1" + # Production options are: "ISRG Root X1" and "ISRG Root X2" + #PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1" - # Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism) - #FULL_CHAIN_INCLUDE_ROOT="true" + # Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism) + #FULL_CHAIN_INCLUDE_ROOT="true" # The command needed to reload apache / nginx or whatever you use. # Several (ssh) commands may be given using a bash array: @@ -2857,7 +2857,7 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then else # check if the certificate is for the right domain EX_CERT_DOMAIN=$(echo "$EX_CERT" | openssl x509 -text \ - | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \ + | sed -n -e 's/^ *Subject: .*CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \ | sort -u | grep "^$DOMAIN\$") if [[ "$EX_CERT_DOMAIN" == "$DOMAIN" ]]; then # check renew-date on ex_cert and compare to local ( if local exists) @@ -2901,7 +2901,11 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then reload_service fi else - info "${DOMAIN}: Certificate on remote domain does not match, ignoring remote certificate" + # Get the domain from the existing certificate for the error message + EX_CERT_DOMAIN=$(echo "$EX_CERT" | openssl x509 -text \ + | sed -n -e 's/^ *Subject: .*CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \ + | sort -u | head -1) + info "${DOMAIN}: Certificate on remote domain does not match, ignoring remote certificate ($EX_CERT_DOMAIN != $real_d)" fi fi else From 8d24863cb940ae523491cf25dd5b5f483fc4912c Mon Sep 17 00:00:00 2001 From: Maciej Modzelewski Date: Fri, 19 Mar 2021 06:21:36 +0100 Subject: [PATCH 227/308] Update GoDaddy DNS scripts --- dns_scripts/dns_add_godaddy | 2 +- dns_scripts/dns_godaddy | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dns_scripts/dns_add_godaddy b/dns_scripts/dns_add_godaddy index dfd3b3b..835bb22 100755 --- a/dns_scripts/dns_add_godaddy +++ b/dns_scripts/dns_add_godaddy @@ -37,4 +37,4 @@ fi export GODADDY_KEY export GODADDY_SECRET -$GODADDY_SCRIPT -q add "${fulldomain}" "_acme-challenge.${fulldomain}." "${token}" +$GODADDY_SCRIPT -q add "${fulldomain}" "_acme-challenge" "${token}" diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy index 4443bd4..7c36d19 100644 --- a/dns_scripts/dns_godaddy +++ b/dns_scripts/dns_godaddy @@ -155,7 +155,6 @@ if [ -z "$name" ]; then echo "'name' parameter is required, see -h" >&2 exit 3 fi -! [[ "$name" =~ [.]$ ]] && name="${name}.${domain}." data="$4" if [ -z "$data" ]; then echo "'data' parameter is required, see -h" >&2 @@ -209,7 +208,7 @@ if [ "$op" = "add" ]; then url="$API/$domain/records/TXT/$name" - request='{"data":"'$data'","ttl":'$ttl'}' + request='[{"data":"'$data'","ttl":'$ttl'}]' [ -n "$DEBUG" ] && cat >&2 < Date: Tue, 23 Mar 2021 12:29:16 +0800 Subject: [PATCH 228/308] Create Aliyun DNS Scripts Founded in 2009, Aliyun is a leading cloud computing and artificial intelligence technology company in China --- dns_scripts/dns_add_del_aliyun.sh | 182 ++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 dns_scripts/dns_add_del_aliyun.sh diff --git a/dns_scripts/dns_add_del_aliyun.sh b/dns_scripts/dns_add_del_aliyun.sh new file mode 100644 index 0000000..de324e0 --- /dev/null +++ b/dns_scripts/dns_add_del_aliyun.sh @@ -0,0 +1,182 @@ +#!/bin/bash +#https://blog.aymar.cn +#https://protocol.aymar.cn +PROGNAME=${0##*/} +VERSION="2021年3月22日 16:07:05" +Ali_API="https://dns.aliyuncs.com/" +_timestamp=$(date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ") +__debug="0" +__delete="0" + +#Wildcard certificates +#A partial example getssl.cfg file is: +#VALIDATE_VIA_DNS=true +#DNS_ADD_COMMAND=/root/.getssl/dns_add_del_aliyun.sh +#DNS_DEL_COMMAND=/root/.getssl/dns_add_del_aliyun.sh + +# either configure KeyId & KeySecret here or export environment variables in getssl.cfg +AccessKeyId=${ALI_KeyId:-''} +AccessKeySecret=${ALI_KeySecret:-''} + +usage() { # print out the program usage + echo "Usage: $PROGNAME [-a|--add ] [-d|--delete ] [-s|--search ] [-h|--help] [-t|--type] "\ + "[-q|--quiet] [-c|--check] [-S|--status] [-l|--lock #] [-T|--ttl] [-u|--update] [-w|--weight] [-L|--Line]" +} + +help_message() { # print out the help message + cat <<- _EOF_ + $PROGNAME Version. $VERSION + $(usage) + + Options: + -a, --add Add Domain Record 域名 ip (默认类型TXT) + -d, --delete Delete Domain Record 域名 (默认类型TXT) + -s, --search Search Domain Record 域名 + -t, --type Record Type 类型(A、MX、CNAME、TXT、REDIRECT_URL、FORWORD_URL、NS、AAAA、SRV) + _EOF_ +} + +_arg_check(){ + [ -z "$1" ] || _arg_count=$1 + shift + [ ${#} -lt $_arg_count ] && help_message && exit 1 || (echo $2 | grep "^-") && help_message && exit 1 + #If the number of arguments <$_ARG_COUNT print help and exit, and if the second argument begins with “-” print help and exit + return 0 +} + +#[ ${#} -lt 2 ] && help_message && exit 1 #Same as below +#[ -z "$2" ] && help_message && exit 1 #Same as below +_arg_check 2 $@ + +_debug (){ + if [ "$__debug" -eq 1 ]; then + echo -e "\033[1;31m # debug: $(date "+%m %d %T") | Func: ${FUNCNAME[@]} | Line:${BASH_LINENO[@]} \033[0m" "\n $@ " #"Current FUNCNAME ${FUNCNAME} #$LINENO " #"$(($RANDOM%10))" + fi + return 0 +} + +_requires() { + _cmds='' # Check if the commands exists + if [[ "$#" -gt 0 ]]; then + for i in "$@"; do + if eval type type >/dev/null 2>&1; then + eval type "$i" >/dev/null 2>&1 + elif command >/dev/null 2>&1; then + command -v "$i" >/dev/null 2>&1 + else + which "$i" >/dev/null 2>&1 + fi + #[ "$?" -eq 0 ] && _debug "checking for $i exists = ok" || _cmds=$_cmds"$i: " + if [ "$?" -eq 0 ]; then + #_debug "checking for $i exists = ok" + continue + else + _cmds=$_cmds"$i: " + fi + done + else + echo "Usage: _requires [command] " + return 1 + fi + [ -n "$_cmds" ] && { echo -e "\033[1;31m $_cmds command not found \033[0m" && return 1 ;} || return 0 +} + +_requires openssl + +_hex_dump() { #ascii hex + local _str='' + [ $# -gt 0 ] && _str=$@ || read _str + local _str_len=${#_str} + local i=1 + while [ "$i" -le "$_str_len" ]; do + local _str_c="$(printf "%s" "$_str" | cut -c "$i")" + printf " %02x" "'$_str_c" + i=$(($i + 1)) + done + #printf "%s" " 0a" +} + +_urlencode() { + local length="${#1}" + local i='' + for i in $(awk "BEGIN { for ( i=0; i<$length; i++ ) print i }") + do + #local _strc="$(printf "%s" "$1" | cut -c "$i")" #i=1; i<=$length; i++ + local _strc="${1:$i:1}" + case $_strc in [a-zA-Z0-9.~_-]) printf "%s" "$_strc" ;; *) printf "%%%02X" "'$_strc" ;; + esac + done +} + +_signature(){ + signature='' + _hexkey=$(printf "%s" "$AccessKeySecret&" | _hex_dump |sed 's/ //g') + #signature=$(printf "%s" "GET&%2F&$(_urlencode "$query")" | openssl dgst -sha1 -hmac $(printf "%s" "$AccessKeySecret&" | _hex_dump |sed 's/ //g'| xxd -r -p ) -binary | openssl base64 -e) + signature=$(printf "%s" "GET&%2F&$(_urlencode "$query")" | openssl dgst -sha1 -mac HMAC -macopt "hexkey:$_hexkey" -binary | openssl base64 -e) + signature=$(_urlencode "$signature") + } + +_query() { + [ -n "$__type" ] && { [[ "$_Action" = "AddDomainRecord" ]] && _Type="$__type" || { [ "$_Action" = "DescribeDomainRecords" ] && _TypeKeyWord="$__type"; } ; } + query='' + [ -n $AccessKeyId ] && query=$query'AccessKeyId='$AccessKeyId + query=$query'&Action='"$1" + [ -z $_DomainNames ] || query=$query'&DomainName='$_DomainNames + query=$query'&Format=json' + [ -z $_RR ] || query=$query'&RR='$_RR + [ -z $_RRKeyWord ] || query=$query'&RRKeyWord='$_RRKeyWord + [ -z $_RecordId ] || query=$query'&RecordId='$_RecordId + query=$query'&SignatureMethod=HMAC-SHA1' + query=$query"&SignatureNonce=$(date +"%s%N")" + query=$query'&SignatureVersion=1.0' + query=$query'&Timestamp='$_timestamp + [ -z $_Type ] || query=$query'&Type='$_Type + [ -z $_TypeKeyWord ] || query=$query'&TypeKeyWord='$_TypeKeyWord + [ -z $_Value ] || query=$query'&Value='$_Value + [ -z $_ValueKeyWord ] || query=$query'&ValueKeyWord='$_ValueKeyWord + query=$query'&Version=2015-01-09' + #_debug "$query" + _signature + return 0 +} + +_Get_RecordIds(){ + _Action="DescribeDomainRecords" + _query $_Action $_DomainNames + url="${Ali_API}?${query}&Signature=${signature}" + _debug $url + _RecordIds=$(curl -k -s $url | grep -Po 'RecordId[": "]+\K[^"]+') && __delete="1" #RecordId requisite + _debug $_RecordIds + return 0 +} + +__type='TXT' +_DomainNames=$(printf "%s" $1| awk -F"." '{if(NF>=2){print $(NF-1)"."$NF}}') #awk -F\. '{print $(NF-1) FS $NF}') #requisite +_RRKeyWord="_acme-challenge" +#_ValueKeyWord=$2 +_Get_RecordIds +_RRKeyWord='' +_TypeKeyWord='' +_ValueKeyWord='' + +if [ "$__delete" = "1" ];then + _Action="DeleteDomainRecord" #Action requisite + _DomainNames='' + for _RecordId in ${_RecordIds[@]} #Delete multiple txt domain record + do + _debug "_RecordId" $_RecordId + _query $_Action $_RecordId + url="${Ali_API}?${query}&Signature=${signature}" + _debug $url + curl -k -s $url && ( echo -e "\n\033[1;32m Aliyun DNS record _acme-challenge.$1 has been deleted \033[0m") + done +else +_Action="AddDomainRecord" #requisite +_RR=$(printf "_acme-challenge.%s" $1| awk -F'.' '{if(NF>2){gsub("."$(NF-1)"."$NF,"");print}}') #requisite +_Value=$2 #requisite +_query $_Action $_DomainNames +url="${Ali_API}?${query}&Signature=${signature}" +_debug $url +curl -k -s $url && (echo -e "\n\033[1;32m Start Checking aliyun DNS record _acme-challenge.$1 \033[0m") +exit 0 +fi \ No newline at end of file From efbe5ce7d366d50ed310186f02aa32eab8200849 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 23 Mar 2021 20:30:16 +0000 Subject: [PATCH 229/308] ignore some shellcheck warnings indentation / whitespace changes --- dns_scripts/dns_add_del_aliyun.sh | 125 +++++++++++++++--------------- 1 file changed, 64 insertions(+), 61 deletions(-) diff --git a/dns_scripts/dns_add_del_aliyun.sh b/dns_scripts/dns_add_del_aliyun.sh index de324e0..d6d9461 100644 --- a/dns_scripts/dns_add_del_aliyun.sh +++ b/dns_scripts/dns_add_del_aliyun.sh @@ -8,7 +8,7 @@ _timestamp=$(date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ") __debug="0" __delete="0" -#Wildcard certificates +#Wildcard certificates #A partial example getssl.cfg file is: #VALIDATE_VIA_DNS=true #DNS_ADD_COMMAND=/root/.getssl/dns_add_del_aliyun.sh @@ -20,7 +20,7 @@ AccessKeySecret=${ALI_KeySecret:-''} usage() { # print out the program usage echo "Usage: $PROGNAME [-a|--add ] [-d|--delete ] [-s|--search ] [-h|--help] [-t|--type] "\ - "[-q|--quiet] [-c|--check] [-S|--status] [-l|--lock #] [-T|--ttl] [-u|--update] [-w|--weight] [-L|--Line]" + "[-q|--quiet] [-c|--check] [-S|--status] [-l|--lock #] [-T|--ttl] [-u|--update] [-w|--weight] [-L|--Line]" } help_message() { # print out the help message @@ -38,7 +38,7 @@ help_message() { # print out the help message _arg_check(){ [ -z "$1" ] || _arg_count=$1 - shift + shift [ ${#} -lt $_arg_count ] && help_message && exit 1 || (echo $2 | grep "^-") && help_message && exit 1 #If the number of arguments <$_ARG_COUNT print help and exit, and if the second argument begins with “-” print help and exit return 0 @@ -50,39 +50,41 @@ _arg_check 2 $@ _debug (){ if [ "$__debug" -eq 1 ]; then - echo -e "\033[1;31m # debug: $(date "+%m %d %T") | Func: ${FUNCNAME[@]} | Line:${BASH_LINENO[@]} \033[0m" "\n $@ " #"Current FUNCNAME ${FUNCNAME} #$LINENO " #"$(($RANDOM%10))" + echo -e "\033[1;31m # debug: $(date "+%m %d %T") | Func: ${FUNCNAME[@]} | Line:${BASH_LINENO[@]} \033[0m" "\n $@ " #"Current FUNCNAME ${FUNCNAME} #$LINENO " #"$(($RANDOM%10))" fi return 0 } -_requires() { +_requires() { _cmds='' # Check if the commands exists if [[ "$#" -gt 0 ]]; then for i in "$@"; do - if eval type type >/dev/null 2>&1; then - eval type "$i" >/dev/null 2>&1 - elif command >/dev/null 2>&1; then - command -v "$i" >/dev/null 2>&1 - else - which "$i" >/dev/null 2>&1 - fi - #[ "$?" -eq 0 ] && _debug "checking for $i exists = ok" || _cmds=$_cmds"$i: " - if [ "$?" -eq 0 ]; then - #_debug "checking for $i exists = ok" - continue - else - _cmds=$_cmds"$i: " - fi + if eval type type >/dev/null 2>&1; then + eval type "$i" >/dev/null 2>&1 + elif command >/dev/null 2>&1; then + command -v "$i" >/dev/null 2>&1 + else + which "$i" >/dev/null 2>&1 + fi + #[ "$?" -eq 0 ] && _debug "checking for $i exists = ok" || _cmds=$_cmds"$i: " + #shellcheck disable=SC2181 + if [ "$?" -eq 0 ]; then + #_debug "checking for $i exists = ok" + continue + else + _cmds=$_cmds"$i: " + fi done - else - echo "Usage: _requires [command] " - return 1 + else + echo "Usage: _requires [command] " + return 1 fi - [ -n "$_cmds" ] && { echo -e "\033[1;31m $_cmds command not found \033[0m" && return 1 ;} || return 0 + [ -n "$_cmds" ] && { echo -e "\033[1;31m $_cmds command not found \033[0m" && return 1 ;} || return 0 } _requires openssl +#shellcheck disable=SC2120 _hex_dump() { #ascii hex local _str='' [ $# -gt 0 ] && _str=$@ || read _str @@ -99,12 +101,12 @@ _hex_dump() { #ascii hex _urlencode() { local length="${#1}" local i='' - for i in $(awk "BEGIN { for ( i=0; i<$length; i++ ) print i }") - do - #local _strc="$(printf "%s" "$1" | cut -c "$i")" #i=1; i<=$length; i++ - local _strc="${1:$i:1}" - case $_strc in [a-zA-Z0-9.~_-]) printf "%s" "$_strc" ;; *) printf "%%%02X" "'$_strc" ;; - esac + for i in $(awk "BEGIN { for ( i=0; i<$length; i++ ) print i }") + do + #local _strc="$(printf "%s" "$1" | cut -c "$i")" #i=1; i<=$length; i++ + local _strc="${1:$i:1}" + case $_strc in [a-zA-Z0-9.~_-]) printf "%s" "$_strc" ;; *) printf "%%%02X" "'$_strc" ;; + esac done } @@ -114,7 +116,7 @@ _signature(){ #signature=$(printf "%s" "GET&%2F&$(_urlencode "$query")" | openssl dgst -sha1 -hmac $(printf "%s" "$AccessKeySecret&" | _hex_dump |sed 's/ //g'| xxd -r -p ) -binary | openssl base64 -e) signature=$(printf "%s" "GET&%2F&$(_urlencode "$query")" | openssl dgst -sha1 -mac HMAC -macopt "hexkey:$_hexkey" -binary | openssl base64 -e) signature=$(_urlencode "$signature") - } +} _query() { [ -n "$__type" ] && { [[ "$_Action" = "AddDomainRecord" ]] && _Type="$__type" || { [ "$_Action" = "DescribeDomainRecords" ] && _TypeKeyWord="$__type"; } ; } @@ -138,45 +140,46 @@ _query() { #_debug "$query" _signature return 0 -} - -_Get_RecordIds(){ - _Action="DescribeDomainRecords" - _query $_Action $_DomainNames - url="${Ali_API}?${query}&Signature=${signature}" - _debug $url - _RecordIds=$(curl -k -s $url | grep -Po 'RecordId[": "]+\K[^"]+') && __delete="1" #RecordId requisite - _debug $_RecordIds - return 0 +} + +_Get_RecordIds(){ + _Action="DescribeDomainRecords" + _query $_Action $_DomainNames + url="${Ali_API}?${query}&Signature=${signature}" + _debug $url + _RecordIds=$(curl -k -s $url | grep -Po 'RecordId[": "]+\K[^"]+') && __delete="1" #RecordId requisite + _debug $_RecordIds + return 0 } __type='TXT' _DomainNames=$(printf "%s" $1| awk -F"." '{if(NF>=2){print $(NF-1)"."$NF}}') #awk -F\. '{print $(NF-1) FS $NF}') #requisite _RRKeyWord="_acme-challenge" -#_ValueKeyWord=$2 + _Get_RecordIds + _RRKeyWord='' -_TypeKeyWord='' +_TypeKeyWord='' _ValueKeyWord='' if [ "$__delete" = "1" ];then - _Action="DeleteDomainRecord" #Action requisite - _DomainNames='' - for _RecordId in ${_RecordIds[@]} #Delete multiple txt domain record - do - _debug "_RecordId" $_RecordId - _query $_Action $_RecordId - url="${Ali_API}?${query}&Signature=${signature}" - _debug $url - curl -k -s $url && ( echo -e "\n\033[1;32m Aliyun DNS record _acme-challenge.$1 has been deleted \033[0m") - done + _Action="DeleteDomainRecord" #Action requisite + _DomainNames='' + for _RecordId in ${_RecordIds[@]} #Delete multiple txt domain record + do + _debug "_RecordId" $_RecordId + _query $_Action $_RecordId + url="${Ali_API}?${query}&Signature=${signature}" + _debug $url + curl -k -s $url && ( echo -e "\n\033[1;32m Aliyun DNS record _acme-challenge.$1 has been deleted \033[0m") + done else -_Action="AddDomainRecord" #requisite -_RR=$(printf "_acme-challenge.%s" $1| awk -F'.' '{if(NF>2){gsub("."$(NF-1)"."$NF,"");print}}') #requisite -_Value=$2 #requisite -_query $_Action $_DomainNames -url="${Ali_API}?${query}&Signature=${signature}" -_debug $url -curl -k -s $url && (echo -e "\n\033[1;32m Start Checking aliyun DNS record _acme-challenge.$1 \033[0m") -exit 0 -fi \ No newline at end of file + _Action="AddDomainRecord" #requisite + _RR=$(printf "_acme-challenge.%s" $1| awk -F'.' '{if(NF>2){gsub("."$(NF-1)"."$NF,"");print}}') #requisite + _Value=$2 #requisite + _query $_Action $_DomainNames + url="${Ali_API}?${query}&Signature=${signature}" + _debug $url + curl -k -s $url && (echo -e "\n\033[1;32m Start Checking aliyun DNS record _acme-challenge.$1 \033[0m") + exit 0 +fi From 3eb7ba35406c9759d9467e8d662327adfb34d565 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 25 Mar 2021 17:23:48 +0100 Subject: [PATCH 230/308] Split DNS add and remove into separate functions --- getssl | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/getssl b/getssl index cebd7f7..ff97639 100755 --- a/getssl +++ b/getssl @@ -573,20 +573,18 @@ check_challenge_completion_dns() { # perform validation via DNS challenge ntries=$(( ntries + 1 )) if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 )) == 0 ]]; then - debug "Retrying adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" - test_output "Retrying adding dns via command: $DNS_ADD_COMMAND" - eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" - if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then - error_exit "DNS_ADD_COMMAND failed for domain $d" - fi - + test_output "Deleting DNS RR via command: ${DNS_DEL_COMMAND}" + del_dns_rr "${lower_d}" "${auth_key}" + test_output "Retrying adding DNS via command: ${DNS_ADD_COMMAND}" + add_dns_rr "${lower_d}" "${auth_key}" \ + || error_exit "DNS_ADD_COMMAND failed for domain ${d}" fi info "checking DNS at ${ns} for ${lower_d}. Attempt $ntries/${DNS_WAIT_COUNT} gave wrong result, "\ "waiting $DNS_WAIT secs before checking again" sleep $DNS_WAIT else debug "dns check failed - removing existing value" - eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" + del_dns_rr "${lower_d}" "${auth_key}" error_exit "checking _acme-challenge.${lower_d} gave $check_result not $auth_key" fi @@ -601,10 +599,7 @@ check_challenge_completion_dns() { # perform validation via DNS challenge check_challenge_completion "$uri" "$d" "$keyauthorization" - debug "remove DNS entry" - # shellcheck disable=SC2018,SC2019 - lower_d=$(echo "${d##\*.}" | tr A-Z a-z) - eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key" + del_dns_rr "${d}" "${auth_key}" } # end of ... perform validation if via DNS challenge @@ -807,7 +802,7 @@ clean_up() { # Perform pre-exit housekeeping # shellcheck source=/dev/null . "$dnsfile" debug "attempting to clean up DNS entry for $d" - eval "$DNS_DEL_COMMAND" "${d##\*.}" "$auth_key" + del_dns_rr "${d}" "${auth_key}" done shopt -u nullglob fi @@ -1171,6 +1166,26 @@ find_ftp_command() { } +add_dns_rr() { + d=${1} + auth_key=${2} + + # shellcheck disable=SC2018,SC2019 + lower_d=$(printf '%s' "${d#\*.}" | tr 'A-Z' 'a-z') + debug "adding DNS RR via command: ${DNS_ADD_COMMAND} ${lower_d} ${auth_key}" + eval "${DNS_ADD_COMMAND}" "${lower_d}" "${auth_key}" +} + +del_dns_rr() { + d=${1} + auth_key=${2} + + # shellcheck disable=SC2018,SC2019 + lower_d=$(printf '%s' "${d#\*.}" | tr 'A-Z' 'a-z') + debug "removing DNS RR via command: ${DNS_DEL_COMMAND} ${lower_d} ${auth_key}" + eval "${DNS_DEL_COMMAND}" "${lower_d}" "${auth_key}" +} + fulfill_challenges() { dn=0 for d in "${alldomains[@]}"; do @@ -1236,12 +1251,8 @@ for d in "${alldomains[@]}"; do | sed -e 's:=*$::g' -e 'y:+/:-_:') debug auth_key "$auth_key" - # shellcheck disable=SC2018,SC2019 - lower_d=$(echo "${d##\*.}" | tr A-Z a-z) - debug "adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key" - if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then - error_exit "DNS_ADD_COMMAND failed for domain $d" - fi + add_dns_rr "${d}" "${auth_key}" \ + || error_exit "DNS_ADD_COMMAND failed for domain $d" # find a primary / authoritative DNS server for the domain if [[ -z "$AUTH_DNS_SERVER" ]]; then From 87ae2500d970cc6dd60b22903b6169760909f47d Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 25 Mar 2021 17:44:01 +0100 Subject: [PATCH 231/308] Fix DNS challenge completion check if CNAMEs on different NS are used --- getssl | 65 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/getssl b/getssl index ff97639..e485737 100755 --- a/getssl +++ b/getssl @@ -518,48 +518,42 @@ check_challenge_completion() { # checks with the ACME server if our challenge is } check_challenge_completion_dns() { # perform validation via DNS challenge - token=$1 - uri=$2 - keyauthorization=$3 - d=$4 - primary_ns=$5 - auth_key=$6 - - # Always use lowercase domain name when querying DNS servers - # shellcheck disable=SC2018,SC2019 - lower_d=$(echo "${d##\*.}" | tr A-Z a-z) + d=${1} + rr=${2} + primary_ns=${3} + auth_key=${4} # check for token at public dns server, waiting for a valid response. for ns in $primary_ns; do - info "checking dns at $ns" + info "checking DNS at $ns" ntries=0 check_dns="fail" while [[ "$check_dns" == "fail" ]]; do if [[ "$os" == "cygwin" ]]; then - check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ + check_result=$(nslookup -type=txt "${rr}" "${ns}" \ | grep ^_acme -A2\ | grep '"'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - debug "$DNS_CHECK_FUNC" TXT "_acme-challenge.${lower_d}" "@${ns}" - check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${lower_d}" "@${ns}" \ - | grep -i "^_acme-challenge.${lower_d}" \ + debug "$DNS_CHECK_FUNC" TXT "${rr}" "@${ns}" + check_result=$($DNS_CHECK_FUNC TXT "${rr}" "@${ns}" \ + | grep -i "^${rr}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') debug "check_result=$check_result" if [[ -z "$check_result" ]]; then - debug "$DNS_CHECK_FUNC" ANY "_acme-challenge.${lower_d}" "@${ns}" - check_result=$($DNS_CHECK_FUNC ANY "_acme-challenge.${lower_d}" "@${ns}" \ - | grep -i "^_acme-challenge.${lower_d}" \ + debug "$DNS_CHECK_FUNC" ANY "${rr}" "@${ns}" + check_result=$($DNS_CHECK_FUNC ANY "${rr}" "@${ns}" \ + | grep -i "^${rr}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') debug "check_result=$check_result" fi elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then - check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${lower_d}" "${ns}" \ + check_result=$($DNS_CHECK_FUNC -t TXT "${rr}" "${ns}" \ | grep 'descriptive text'|awk -F'"' '{ print $2}') else - check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \ + check_result=$(nslookup -type=txt "${rr}" "${ns}" \ | grep 'text ='|awk -F'"' '{ print $2}') if [[ -z "$check_result" ]]; then - check_result=$(nslookup -type=any "_acme-challenge.${lower_d}" "${ns}" \ + check_result=$(nslookup -type=any "${rr}" "${ns}" \ | grep 'text ='|awk -F'"' '{ print $2}') fi fi @@ -574,19 +568,19 @@ check_challenge_completion_dns() { # perform validation via DNS challenge if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 )) == 0 ]]; then test_output "Deleting DNS RR via command: ${DNS_DEL_COMMAND}" - del_dns_rr "${lower_d}" "${auth_key}" + del_dns_rr "${d}" "${auth_key}" test_output "Retrying adding DNS via command: ${DNS_ADD_COMMAND}" - add_dns_rr "${lower_d}" "${auth_key}" \ + add_dns_rr "${d}" "${auth_key}" \ || error_exit "DNS_ADD_COMMAND failed for domain ${d}" fi - info "checking DNS at ${ns} for ${lower_d}. Attempt $ntries/${DNS_WAIT_COUNT} gave wrong result, "\ + info "checking DNS at ${ns} for ${rr}. Attempt $ntries/${DNS_WAIT_COUNT} gave wrong result, "\ "waiting $DNS_WAIT secs before checking again" sleep $DNS_WAIT else debug "dns check failed - removing existing value" - del_dns_rr "${lower_d}" "${auth_key}" + del_dns_rr "${d}" "${auth_key}" - error_exit "checking _acme-challenge.${lower_d} gave $check_result not $auth_key" + error_exit "checking ${rr} gave $check_result not $auth_key" fi fi done @@ -596,10 +590,6 @@ check_challenge_completion_dns() { # perform validation via DNS challenge info "sleeping $DNS_EXTRA_WAIT seconds before asking the ACME server to check the dns" sleep "$DNS_EXTRA_WAIT" fi - - check_challenge_completion "$uri" "$d" "$keyauthorization" - - del_dns_rr "${d}" "${auth_key}" } # end of ... perform validation if via DNS challenge @@ -1256,7 +1246,12 @@ for d in "${alldomains[@]}"; do # find a primary / authoritative DNS server for the domain if [[ -z "$AUTH_DNS_SERVER" ]]; then - get_auth_dns "$d" + # shellcheck disable=SC2018,SC2019 + rr="_acme-challenge.$(printf '%s' "${d#\*.}" | tr 'A-Z' 'a-z')" + get_auth_dns "${rr}" + if test -n "${cname}"; then + rr=${cname} + fi elif [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then primary_ns="$AUTH_DNS_SERVER $PUBLIC_DNS_SERVER" else @@ -1264,7 +1259,13 @@ for d in "${alldomains[@]}"; do fi debug set primary_ns = "$primary_ns" - check_challenge_completion_dns "${token}" "${uri}" "${keyauthorization}" "${d}" "${primary_ns}" "${auth_key}" + # internal check + check_challenge_completion_dns "${d}" "${rr}" "${primary_ns}" "${auth_key}" + + # let Let's Encrypt check + check_challenge_completion "${uri}" "${d}" "${keyauthorization}" + + del_dns_rr "${d}" "${auth_key}" else # set up the correct http token for verification if [[ $API -eq 1 ]]; then # get the token from the http component From 20fc8affa6e926a82d1eceb1750ab0a810344370 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 25 Mar 2021 18:53:19 +0100 Subject: [PATCH 232/308] Resolve CNAMEs before searching for authoritative DNS server --- getssl | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/getssl b/getssl index e485737..8de8353 100755 --- a/getssl +++ b/getssl @@ -1378,6 +1378,27 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n gad_s="@$gad_s" fi + # Check if domain is a CNAME, first + test_output "Using $HAS_DIG_OR_DRILL CNAME" + + # Two options here; either dig CNAME will return the CNAME and the NS or just the CNAME + debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d $gad_s" + res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" $gad_s| grep "^$gad_d") + cname=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') + + if [[ $_TEST_SKIP_CNAME_CALL == 0 ]]; then + debug Checking if CNAME result contains NS records + res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" $gad_s| grep -E "IN\W(NS|SOA)\W") + else + res= + fi + + if [[ -n "${cname}" ]]; then + # domain is a CNAME: resolve it and continue with that + debug Domain is a CNAME, actual domain is "$cname" + gad_d=${cname} + fi + # Use SOA +trace to find the name server if [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then if [[ "$HAS_DIG_OR_DRILL" == "drill" ]]; then @@ -1391,27 +1412,6 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n fi fi - # Check if domain is a CNAME - if [[ -z "$res" ]]; then - test_output "Using $HAS_DIG_OR_DRILL CNAME" - - # Two options here; either dig CNAME will return the CNAME and the NS or just the CNAME - debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d $gad_s" - res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" $gad_s| grep "^$gad_d") - cname=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') - - if [[ $_TEST_SKIP_CNAME_CALL == 0 ]]; then - debug Checking if CNAME result contains NS records - res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" $gad_s| grep -E "IN\W(NS|SOA)\W") - else - res="" - fi - - if [[ -n "$cname" ]]; then # domain is a CNAME so get main domain - debug Domain is a CNAME, actual domain is "$cname" - fi - fi - # Query for NS records if [[ -z "$res" ]]; then test_output "Using $HAS_DIG_OR_DRILL NS" From 4c3be42e97b288697c7e041cac22b1ab46fdc681 Mon Sep 17 00:00:00 2001 From: mokaton Date: Fri, 26 Mar 2021 22:12:42 +0300 Subject: [PATCH 233/308] DeprecationWarning: please use dns.resolver.Resolver.resolve() Fixed issue with deprecated function query for dns.resolver.Resolver --- dns_scripts/dns_route53.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dns_scripts/dns_route53.py b/dns_scripts/dns_route53.py index f2011bf..6b88b37 100755 --- a/dns_scripts/dns_route53.py +++ b/dns_scripts/dns_route53.py @@ -70,7 +70,7 @@ if action == 'UPSERT': try: my_resolver = dns.resolver.Resolver(configure=False) my_resolver.nameservers = ['8.8.8.8', '8.8.4.4'] - results = my_resolver.query(challenge_fqdn, 'TXT') + results = my_resolver.resolve(challenge_fqdn, 'TXT') data = str(results.response.answer[0][0]).strip('\"') if data == challenge: print("found {f} entry".format(f=challenge_fqdn)) From 4846512269497a166aa9648b4e30bc277b8cdf9b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 29 Mar 2021 12:56:48 +0100 Subject: [PATCH 234/308] Tweaks so non-cname domains work, fix broken retry dns add test --- getssl | 13 ++++++++++--- test/18-retry-dns-add.bats | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index 8de8353..1cf1454 100755 --- a/getssl +++ b/getssl @@ -1244,14 +1244,21 @@ for d in "${alldomains[@]}"; do add_dns_rr "${d}" "${auth_key}" \ || error_exit "DNS_ADD_COMMAND failed for domain $d" + # shellcheck disable=SC2018,SC2019 + rr="_acme-challenge.$(printf '%s' "${d#\*.}" | tr 'A-Z' 'a-z')" + # find a primary / authoritative DNS server for the domain if [[ -z "$AUTH_DNS_SERVER" ]]; then - # shellcheck disable=SC2018,SC2019 - rr="_acme-challenge.$(printf '%s' "${d#\*.}" | tr 'A-Z' 'a-z')" + # Find authorative dns server for _acme-challenge.{domain} (for CNAMES/acme-dns) get_auth_dns "${rr}" if test -n "${cname}"; then rr=${cname} fi + + # If no authorative dns server found, try again for {domain} + if [[ -z "$primary_ns" ]]; then + get_auth_dns "$d" + fi elif [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then primary_ns="$AUTH_DNS_SERVER $PUBLIC_DNS_SERVER" else @@ -1400,7 +1407,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n fi # Use SOA +trace to find the name server - if [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then + if [[ -z "$res" ]] && [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then if [[ "$HAS_DIG_OR_DRILL" == "drill" ]]; then debug Using "$HAS_DIG_OR_DRILL -T $gad_d $gad_s" to find primary nameserver test_output "Using $HAS_DIG_OR_DRILL SOA" diff --git a/test/18-retry-dns-add.bats b/test/18-retry-dns-add.bats index 3a79880..25318de 100644 --- a/test/18-retry-dns-add.bats +++ b/test/18-retry-dns-add.bats @@ -30,8 +30,9 @@ DNS_EXTRA_WAIT=0 CHECK_ALL_AUTH_DNS="false" CHECK_PUBLIC_DNS_SERVER="false" DNS_WAIT_RETRY_ADD="true" +_RUNNING_TEST=1 EOF - create_certificate -d + create_certificate assert_failure - assert_line --partial "Retrying adding dns via command" + assert_line --partial "Retrying adding DNS via command" } From 8625e0774b80c9a1c9a8e02f668a55bfc3b52f22 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 29 Mar 2021 20:54:38 +0100 Subject: [PATCH 235/308] Update change log and version --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 1cf1454..bbc7afd 100755 --- a/getssl +++ b/getssl @@ -258,6 +258,7 @@ # 2021-02-12 Add PREFERRED_CHAIN # 2021-02-15 ADD ftp explicit SSL with curl for upload the challenge (CoolMischa) # 2021-02-18 Add FULL_CHAIN_INCLUDE_ROOT +# 2021-03-25 Fix DNS challenge completion check if CNAMEs on different NS are used (sideeffect42)(2.35) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -266,7 +267,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.34" +VERSION="2.35" # defaults ACCOUNT_KEY_LENGTH=4096 From d8006d6585979b2cde6f02ee93b585db9811b577 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 1 Apr 2021 11:57:53 +0100 Subject: [PATCH 236/308] Update README.md --- README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index def44c5..7ff8b2e 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ for automating the process on remote servers. - [Installation](#installation) - [Overview](#overview) - [Getting started](#getting-started) +- [Detailed guide to getting started with more examples](#detailed-guide-to-getting-started-with-more-examples) - [Wildcard certificates](#wildcard-certificates) - [Automating updates](#automating-updates) - [Structure](#structure) @@ -87,25 +88,27 @@ desktop computer, or even a virtualbox) and add the checks, and certificates to a remote server ( providing you have a ssh with key, sftp or ftp access to the remote server). -```getssl -getssl ver. 2.02 +```getssl -h +getssl ver. 2.35 Obtain SSL certificates from the letsencrypt.org ACME server -Usage: getssl [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet] [-Q|--mute] [-u|--upgrade] [-k|--keep #] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir] domain +Usage: getssl [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet] [-Q|--mute] [-u|--upgrade] [-k|--keep #] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir] [--preferred-chain chain] domain Options: -a, --all Check all certificates - -d, --debug Outputs debug information + -d, --debug Output debug information -c, --create Create default config files -f, --force Force renewal of cert (overrides expiry checks) -h, --help Display this help message and exit + -i, --install Install certificates and reload service -q, --quiet Quiet mode (only outputs on error, success of new cert, or getssl was upgraded) - -Q, --mute Like -q, but mutes notification about successful upgrade + -Q, --mute Like -q, but also mute notification about successful upgrade -r, --revoke "cert" "key" [CA_server] Revoke a certificate (the cert and key are required) -u, --upgrade Upgrade getssl if a more recent version is available - can be used with or without domain(s) - -k, --keep "#" Maximum amount of old getssl versions to keep when upgrading + -k, --keep "#" Maximum number of old getssl versions to keep when upgrading -U, --nocheck Do not check if a more recent version is available -w working_dir "Working directory" + --preferred-chain "chain" Use an alternate chain for the certificate ``` ## Getting started @@ -165,6 +168,10 @@ Change the server in your config file to get a fully valid certificate. dns. The certificate can be used (and checked with getssl) on alternate ports. +## Detailed guide to getting started with more examples + +[Guide to getting a certificate for example.com and www.example.com](https://github.com/srvrco/getssl/wiki/Guide-to-getting-a-certificate-for-example.com-and-www.example.com) + ## Wildcard certificates `getssl` supports creating wildcard certificates, i.e. _*.example.com_ which allows a single certificate to be used for any domain under *example.com*, e.g. *www.example.com*, *mail.example.com*. These must be validated using the dns-01 method. From ff2a55622492bb1b73b015c011235f4132662ab5 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Sat, 8 May 2021 16:48:45 -0400 Subject: [PATCH 237/308] Update README Add --version Update default endpoint to acme-v02. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7ff8b2e..454a388 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ certificates to a remote server ( providing you have a ssh with key, sftp or ftp access to the remote server). ```getssl -h -getssl ver. 2.35 +getssl ver. 2.36 Obtain SSL certificates from the letsencrypt.org ACME server Usage: getssl [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet] [-Q|--mute] [-u|--upgrade] [-k|--keep #] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir] [--preferred-chain chain] domain @@ -107,6 +107,7 @@ Options: -u, --upgrade Upgrade getssl if a more recent version is available - can be used with or without domain(s) -k, --keep "#" Maximum number of old getssl versions to keep when upgrading -U, --nocheck Do not check if a more recent version is available + -v --version Display current version of getssl -w working_dir "Working directory" --preferred-chain "chain" Use an alternate chain for the certificate ``` @@ -376,7 +377,7 @@ Usage: `getssl -r path/to/cert path/to/key [CA_server]` You need to specify both the certificate you want to revoke, and the account or private domain key which was used to sign / obtain the original certificate. The `CA_server` is an optional parameter and -defaults to Let's Encrypt ("") as +defaults to Let's Encrypt ("") as that is currently the only Certificate Authority using the ACME protocol. From e315d870e4d0ca46e0a0da4ec8c7d8a6a68268b1 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Sat, 8 May 2021 17:51:11 -0400 Subject: [PATCH 238/308] Fix lint from merge --- dns_scripts/dns_add_godaddy | 2 +- dns_scripts/dns_del_godaddy | 2 +- dns_scripts/dns_godaddy | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dns_scripts/dns_add_godaddy b/dns_scripts/dns_add_godaddy index fc08f09..f9be745 100755 --- a/dns_scripts/dns_add_godaddy +++ b/dns_scripts/dns_add_godaddy @@ -38,4 +38,4 @@ export GODADDY_KEY export GODADDY_SECRET export GODADDY_BASE -$GODADDY_SCRIPT -q add ${fulldomain} "_acme-challenge.${fulldomain}." "${token}" +$GODADDY_SCRIPT -q add "${fulldomain}" "_acme-challenge.${fulldomain}." "${token}" diff --git a/dns_scripts/dns_del_godaddy b/dns_scripts/dns_del_godaddy index 120430f..4a3228f 100755 --- a/dns_scripts/dns_del_godaddy +++ b/dns_scripts/dns_del_godaddy @@ -36,4 +36,4 @@ export GODADDY_KEY export GODADDY_SECRET export GODADDY_BASE -$GODADDY_SCRIPT -q del ${fulldomain} "_acme-challenge.${fulldomain}." "${token}" +$GODADDY_SCRIPT -q del "${fulldomain}" "_acme-challenge.${fulldomain}." "${token}" diff --git a/dns_scripts/dns_godaddy b/dns_scripts/dns_godaddy index a89a855..0d41e6a 100755 --- a/dns_scripts/dns_godaddy +++ b/dns_scripts/dns_godaddy @@ -237,6 +237,7 @@ Add request to: $url $request" -------- EOF + result="$(curl -i -s -X PUT -d "$request" --config - "$url" < Date: Sat, 8 May 2021 19:05:50 -0400 Subject: [PATCH 239/308] Fix test errors caused by DNS_CHECK_OPTIONS Use a regexp rather than a partial match to skip any DNS_CHECK_OPTIONS, which in the current tests create whitespace, but could be anything. Catch a missing inclusion of DNS_CHECK_OPTIONS for dig CNAME --- getssl | 4 ++-- test/u1-test-get_auth_dns-dig.bats | 14 +++++++------- test/u2-test-get_auth_dns-drill.bats | 14 +++++++------- test/u5-test-get_auth_dns-no-root-servers.bats | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/getssl b/getssl index 4f5fa34..6ba6523 100755 --- a/getssl +++ b/getssl @@ -674,7 +674,7 @@ check_config() { # check the config files for all obvious errors # check domain exists using all DNS utilities. DNS_CHECK_OPTIONS may bind IP address or provide TSIG found_ip=false if [[ -n "$HAS_DIG_OR_DRILL" ]]; then - debug "DNS lookup using $HAS_DIG_OR_DRILL ${d}" + debug "DNS lookup using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS ${d}" if [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t SOA "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then found_ip=true elif [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t A "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then @@ -1389,7 +1389,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n fi # Check if domain is a CNAME, first - test_output "Using $HAS_DIG_OR_DRILL CNAME" + test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME" # Two options here; either dig CNAME will return the CNAME and the NS or just the CNAME debug Checking for CNAME using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME $gad_d $gad_s" diff --git a/test/u1-test-get_auth_dns-dig.bats b/test/u1-test-get_auth_dns-dig.bats index 6e64e68..471732f 100644 --- a/test/u1-test-get_auth_dns-dig.bats +++ b/test/u1-test-get_auth_dns-dig.bats @@ -61,7 +61,7 @@ teardown() { # Assert that we've found the primary_ns server assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we had to use dig NS - assert_line --partial 'Using dig NS' + assert_line --regexp 'Using dig.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true @@ -89,8 +89,8 @@ teardown() { assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we had to use dig NS - assert_line --partial 'Using dig SOA' - refute_line --partial 'Using dig NS' + assert_line --regexp 'Using dig.* SOA' + refute_line --regexp 'Using dig.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true @@ -125,8 +125,8 @@ teardown() { assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' # Assert that we found a CNAME and use dig NS - assert_line --partial 'Using dig CNAME' - assert_line --partial 'Using dig NS' + assert_line --regexp 'Using dig.* CNAME' + assert_line --regexp 'Using dig.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true @@ -168,8 +168,8 @@ teardown() { assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we found a CNAME but didn't use dig NS - assert_line --partial 'Using dig CNAME' - refute_line --partial 'Using dig NS' + assert_line --regexp 'Using dig.* CNAME' + refute_line --regexp 'Using dig.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true diff --git a/test/u2-test-get_auth_dns-drill.bats b/test/u2-test-get_auth_dns-drill.bats index 33b2277..434a9b5 100644 --- a/test/u2-test-get_auth_dns-drill.bats +++ b/test/u2-test-get_auth_dns-drill.bats @@ -67,7 +67,7 @@ teardown() { # Assert that we've found the primary_ns server assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we had to use drill NS - assert_line --partial 'Using drill NS' + assert_line --regexp 'Using drill.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true @@ -100,8 +100,8 @@ teardown() { assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we had to use drill NS - assert_line --partial 'Using drill SOA' - refute_line --partial 'Using drill NS' + assert_line --regexp 'Using drill.* SOA' + refute_line --regexp 'Using drill.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true @@ -141,8 +141,8 @@ teardown() { assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' # Assert that we found a CNAME and use drill NS - assert_line --partial 'Using drill CNAME' - assert_line --partial 'Using drill NS' + assert_line --regexp 'Using drill.* CNAME' + assert_line --regexp 'Using drill.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true @@ -192,8 +192,8 @@ teardown() { assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' # Assert that we found a CNAME but didn't use drill NS - assert_line --partial 'Using drill CNAME' - refute_line --partial 'Using drill NS' + assert_line --regexp 'Using drill.* CNAME' + refute_line --regexp 'Using drill.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true diff --git a/test/u5-test-get_auth_dns-no-root-servers.bats b/test/u5-test-get_auth_dns-no-root-servers.bats index b88fd41..d218eb9 100644 --- a/test/u5-test-get_auth_dns-no-root-servers.bats +++ b/test/u5-test-get_auth_dns-no-root-servers.bats @@ -60,7 +60,7 @@ teardown() { # Assert that we've found the primary_ns server assert_output --regexp 'set primary_ns = ' # Assert that we had to use dig NS - assert_line --partial 'Using dig NS' + assert_line --regexp 'Using dig.* NS' # Check we didn't include any root servers refute_line --partial 'root-servers.net' @@ -89,7 +89,7 @@ teardown() { # Assert that we've found the primary_ns server assert_output --regexp 'set primary_ns = ' # Assert that we had to use dig SOA - assert_line --partial 'Using dig SOA' + assert_line --regexp 'Using dig.* SOA' # Check we didn't include any root servers refute_line --partial 'root-servers.net' From 3ebb9a5a37be1559ff36d5f17922bde2473b12a2 Mon Sep 17 00:00:00 2001 From: Yannic Haupenthal Date: Mon, 7 Jun 2021 18:50:48 +0700 Subject: [PATCH 240/308] shellcheck disable=SC2086 --- getssl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 6ba6523..1998d82 100755 --- a/getssl +++ b/getssl @@ -675,6 +675,7 @@ check_config() { # check the config files for all obvious errors found_ip=false if [[ -n "$HAS_DIG_OR_DRILL" ]]; then debug "DNS lookup using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS ${d}" + # shellcheck disable=SC2086 if [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t SOA "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then found_ip=true elif [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t A "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then @@ -686,6 +687,7 @@ check_config() { # check the config files for all obvious errors if [[ "$HAS_HOST" == "true" ]]; then debug "DNS lookup using host ${d}" + # shellcheck disable=SC2086 if [[ "$(host $DNS_CHECK_OPTIONS "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then found_ip=true fi @@ -693,6 +695,7 @@ check_config() { # check the config files for all obvious errors if [[ "$HAS_NSLOOKUP" == "true" ]]; then debug "DNS lookup using nslookup -query AAAA ${d}" + # shellcheck disable=SC2086 if [[ "$(nslookup $DNS_CHECK_OPTIONS -query=AAAA "${d}"|grep -c -i "^${d}.*has AAAA address")" -ge 1 ]]; then debug "found IPv6 record for ${d}" found_ip=true @@ -1393,11 +1396,13 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n # Two options here; either dig CNAME will return the CNAME and the NS or just the CNAME debug Checking for CNAME using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME $gad_d $gad_s" + # shellcheck disable=SC2086 res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME "$gad_d" $gad_s| grep "^$gad_d") cname=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') if [[ $_TEST_SKIP_CNAME_CALL == 0 ]]; then debug Checking if CNAME result contains NS records + # shellcheck disable=SC2086 res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME "$gad_d" $gad_s| grep -E "IN\W(NS|SOA)\W") else res= @@ -1411,6 +1416,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n # Use SOA +trace to find the name server if [[ -z "$res" ]] && [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then + # shellcheck disable=SC2086 if [[ "$HAS_DIG_OR_DRILL" == "drill" ]]; then debug Using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -T $gad_d $gad_s" to find primary nameserver test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS SOA" @@ -1426,6 +1432,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ -z "$res" ]]; then test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS NS" debug Using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS NS $gad_d $gad_s" to find primary nameserver + # shellcheck disable=SC2086 res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS NS "$gad_d" $gad_s | grep -E "IN\W(NS|SOA)\W") fi @@ -1465,10 +1472,10 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ "$HAS_HOST" == "true" ]]; then gad_d="$orig_gad_d" debug Using "host -t NS" to find primary name server for "$gad_d" + # shellcheck disable=SC2086 if [[ -z "$gad_s" ]]; then res=$(host $DNS_CHECK_OPTIONS -t NS "$gad_d"| grep "name server") else - # shellcheck disable=SC2086 res=$(host $DNS_CHECK_OPTIONS -t NS "$gad_d" $gad_s| grep "name server") fi if [[ -n "$res" ]]; then From aef54af46697eb988ebd01e821cdcc3a8e54cd58 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 28 Jun 2021 09:42:03 +0100 Subject: [PATCH 241/308] Request new certificate if SANs changed --- getssl | 27 +++--- test/19-test-add-to-sans.bats | 38 ++++---- test/7-test-renewal.bats | 96 +++++++++++++++++++ .../getssl-dns01-add-to-sans-1.cfg | 37 ------- .../getssl-dns01-add-to-sans-2.cfg | 37 ------- 5 files changed, 133 insertions(+), 102 deletions(-) create mode 100644 test/7-test-renewal.bats delete mode 100644 test/test-config/getssl-dns01-add-to-sans-1.cfg delete mode 100644 test/test-config/getssl-dns01-add-to-sans-2.cfg diff --git a/getssl b/getssl index 1998d82..dac2d2d 100755 --- a/getssl +++ b/getssl @@ -2972,14 +2972,26 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then fi # end of .... check_remote is true then connect and obtain the current certificate +#create SAN +if [[ -z "$SANS" ]]; then + SANLIST="subjectAltName=DNS:${DOMAIN}" +elif [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then + SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" +else + SANLIST="subjectAltName=DNS:${DOMAIN},DNS:${SANS//[, ]/,DNS:}" +fi +debug "created SAN list = $SANLIST" + # if there is an existing certificate file, check details. if [[ -s "$CERT_FILE" ]]; then debug "certificate $CERT_FILE exists" enddate=$(openssl x509 -in "$CERT_FILE" -noout -enddate 2>/dev/null| cut -d= -f 2-) debug "local cert is valid until $enddate" + existing_sanlist=$(openssl x509 -in "$CERT_FILE" -noout -text | grep "DNS:" | sed 's/^ *//g') + debug "local cert is for domains: ${existing_sanlist}" if [[ "$enddate" != "-" ]]; then enddate_s=$(date_epoc "$enddate") - if [[ $(date_renew) -lt "$enddate_s" ]] && [[ $_FORCE_RENEW -ne 1 ]]; then + if [[ $(date_renew) -lt "$enddate_s" ]] && [[ $_FORCE_RENEW -ne 1 ]] && [[ "subjectAltName=$existing_sanlist" == "$SANLIST" ]]; then issuer=$(openssl x509 -in "$CERT_FILE" -noout -issuer 2>/dev/null) if [[ "$issuer" == *"Fake LE Intermediate"* ]] && [[ "$CA" == "https://acme-v02.api.letsencrypt.org" ]]; then debug "upgrading from fake cert to real" @@ -2989,6 +3001,9 @@ if [[ -s "$CERT_FILE" ]]; then graceful_exit $_NOTIFY_VALID fi else + if [[ "subjectAltName=$existing_sanlist" != "$SANLIST" ]]; then + info "Domain list in existing certificate ($existing_sanlist) does not match domains requested ($SANLIST), so recreating certificate" + fi debug "${DOMAIN}: certificate needs renewal" fi fi @@ -3027,16 +3042,6 @@ else fi # End of creating domain keys. -#create SAN -if [[ -z "$SANS" ]]; then - SANLIST="subjectAltName=DNS:${DOMAIN}" -elif [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then - SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" -else - SANLIST="subjectAltName=DNS:${DOMAIN},DNS:${SANS//[, ]/,DNS:}" -fi -debug "created SAN list = $SANLIST" - #create CSR's if [[ "$DUAL_RSA_ECDSA" == "false" ]]; then create_csr "$DOMAIN_DIR/${DOMAIN}.csr" "$DOMAIN_DIR/${DOMAIN}.key" diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats index da9deb7..f00bb4e 100644 --- a/test/19-test-add-to-sans.bats +++ b/test/19-test-add-to-sans.bats @@ -10,31 +10,24 @@ setup() { if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a - curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a fi } teardown() { if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a - curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a fi } @test "Create certificate to check can add to SANS" { - skip "FIXME: Certificate is not recreated when SANS is updated" if [ -n "$STAGING" ]; then skip "Not trying on staging server yet" - CONFIG_FILE="getssl-dns01.cfg" - else - CONFIG_FILE="getssl-dns01-add-to-sans-1.cfg" fi - . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CONFIG_FILE="getssl-dns01.cfg" setup_environment - - init_getssl + create_certificate assert_success check_output_for_errors @@ -42,23 +35,34 @@ teardown() { @test "Check we can add a new domain to SANS" { - skip "FIXME: Certificate is not recreated when SANS is updated" if [ -n "$STAGING" ]; then skip "Not trying on staging server yet" - CONFIG_FILE="getssl-dns01.cfg" - else - CONFIG_FILE="getssl-dns01-add-to-sans-2.cfg" fi - # . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" - # CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt - # KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key - # cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + CONFIG_FILE="getssl-dns01.cfg" + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +SANS="a.${GETSSL_HOST}" +EOF + + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt create_certificate assert_success check_output_for_errors # As the SANS list changed, a new certificate is needed + assert_line --partial "does not match domains requested" + assert_line --partial "does not have the same domains as the config - re-create-csr" assert_line --partial "certificate installed OK on server" refute_line --partial 'certificate is valid for more than' + + # Check that the SAN list in the certificate matches the expected value + SAN_IN_CERT=$(openssl x509 -in "$CERT" -noout -text | grep "DNS:" | sed 's/^ *//g') + SAN_EXPECTED="DNS:${GETSSL_HOST}, DNS:a.${GETSSL_HOST}" + if [[ "$SAN_IN_CERT" != "$SAN_EXPECTED" ]]; then + echo "# SAN_IN_CERT=$SAN_IN_CERT" + echo "# SAN_EXPECTED=$SAN_EXPECTED" + fi + [ "${SAN_IN_CERT}" = "$SAN_EXPECTED" ] } diff --git a/test/7-test-renewal.bats b/test/7-test-renewal.bats new file mode 100644 index 0000000..074f882 --- /dev/null +++ b/test/7-test-renewal.bats @@ -0,0 +1,96 @@ +#! /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() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + fi +} + +teardown() { + if [ -z "$STAGING" ]; then + curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + fi +} + + +@test "Create certificate to check renewal" { + if [ -n "$STAGING" ]; then + skip "Not testing renewal on staging server" + fi + CONFIG_FILE="getssl-dns01.cfg" + setup_environment + init_getssl + + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check that trying to renew a certificate which doesn't need renewing doesn't do anything" { + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + fi + + CONFIG_FILE="getssl-dns01.cfg" + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + ORIGINAL_ENDDATE=$(openssl x509 -in "$CERT" -noout -enddate 2>/dev/null| cut -d= -f 2-) + + create_certificate + assert_success + check_output_for_errors + + # Check that getssl didn't renew the certificate + refute_line --partial "certificate needs renewal" + assert_line --partial 'certificate is valid for more than' + + # Check that the end date in the certificate hasn't changed + UPDATED_ENDDATE=$(openssl x509 -in "$CERT" -noout -enddate 2>/dev/null| cut -d= -f 2-) + if [[ "$ORIGINAL_ENDDATE" != "$UPDATED_ENDDATE" ]]; then + echo "# ORIGINAL_ENDDATE=$ORIGINAL_ENDDATE" + echo "# UPDATED_ENDDATE =$UPDATED_ENDDATE" + fi + [[ "$ORIGINAL_ENDDATE" = "$UPDATED_ENDDATE" ]] +} + + + +@test "Check that we can renew a certificate which does need renewing" { + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + fi + + CONFIG_FILE="getssl-dns01.cfg" + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +RENEW_ALLOW=2000 +EOF + + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + ORIGINAL_ENDDATE=$(openssl x509 -in "$CERT" -noout -enddate 2>/dev/null| cut -d= -f 2-) + + create_certificate + assert_success + check_output_for_errors + + # Check that getssl didn't renew the certificate + refute_line --partial 'certificate is valid for more than' + + # Check that the end date in the certificate hasn't changed + UPDATED_ENDDATE=$(openssl x509 -in "$CERT" -noout -enddate 2>/dev/null| cut -d= -f 2-) + if [[ "$ORIGINAL_ENDDATE" = "$UPDATED_ENDDATE" ]]; then + echo "# ORIGINAL_ENDDATE=$ORIGINAL_ENDDATE" + echo "# UPDATED_ENDDATE =$UPDATED_ENDDATE" + fi + [[ "$ORIGINAL_ENDDATE" != "$UPDATED_ENDDATE" ]] +} diff --git a/test/test-config/getssl-dns01-add-to-sans-1.cfg b/test/test-config/getssl-dns01-add-to-sans-1.cfg deleted file mode 100644 index ddb514a..0000000 --- a/test/test-config/getssl-dns01-add-to-sans-1.cfg +++ /dev/null @@ -1,37 +0,0 @@ -# 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" - -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 - -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 -DNS_EXTRA_WAIT=0 - -# Additional domains - this could be multiple domains / subdomains in a comma separated list -SANS="a.${GETSSL_HOST}" - -# 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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" - -# Define the server type and confirm correct certificate is installed -SERVER_TYPE="https" -CHECK_REMOTE="true" -IGNORE_DIRECTORY_DOMAIN="true" - -#_USE_DEBUG=1 -#_RUNNING_TEST=1 diff --git a/test/test-config/getssl-dns01-add-to-sans-2.cfg b/test/test-config/getssl-dns01-add-to-sans-2.cfg deleted file mode 100644 index 9196905..0000000 --- a/test/test-config/getssl-dns01-add-to-sans-2.cfg +++ /dev/null @@ -1,37 +0,0 @@ -# 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" - -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 - -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 -DNS_EXTRA_WAIT=0 - -# Additional domains - this could be multiple domains / subdomains in a comma separated list -SANS="b.${GETSSL_HOST}, a.${GETSSL_HOST}" - -# 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 ${NGINX_CONFIG} && /getssl/test/restart-nginx" - -# Define the server type and confirm correct certificate is installed -SERVER_TYPE="https" -CHECK_REMOTE="false" -IGNORE_DIRECTORY_DOMAIN="true" - -#_USE_DEBUG=1 -#_RUNNING_TEST=1 From bfd68f87251eceb78e57c2e9f0b071fcc1e1487b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 28 Jun 2021 09:48:57 +0100 Subject: [PATCH 242/308] Fix tests (new duckdns servers) --- test/u1-test-get_auth_dns-dig.bats | 20 ++++++++++---------- test/u2-test-get_auth_dns-drill.bats | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/test/u1-test-get_auth_dns-dig.bats b/test/u1-test-get_auth_dns-dig.bats index 471732f..ac11c1d 100644 --- a/test/u1-test-get_auth_dns-dig.bats +++ b/test/u1-test-get_auth_dns-dig.bats @@ -59,14 +59,14 @@ teardown() { run get_auth_dns ubuntu-getssl.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-9]+\.duckdns\.org' # Assert that we had to use dig NS assert_line --regexp 'Using dig.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = (ns[1-9]+\.duckdns\.org )+' } @@ -86,7 +86,7 @@ teardown() { run get_auth_dns ubuntu-getssl.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-9]+\.duckdns\.org' # Assert that we had to use dig NS assert_line --regexp 'Using dig.* SOA' @@ -95,12 +95,12 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = (ns[1-9]+\.duckdns\.org )+' # Check that we also check the public DNS server if requested CHECK_PUBLIC_DNS_SERVER=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org 1\.0\.0\.1' + assert_output --regexp 'set primary_ns = (ns[1-9]+\.duckdns\.org )+1\.0\.0\.1' } @@ -122,7 +122,7 @@ teardown() { run get_auth_dns www.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.net' # Assert that we found a CNAME and use dig NS assert_line --regexp 'Using dig.* CNAME' @@ -131,12 +131,12 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns www.duckdns.org - assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.net' # Check that we also check the public DNS server if requested CHECK_PUBLIC_DNS_SERVER=true run get_auth_dns www.duckdns.org - assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com 1\.0\.0\.1' + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.net 1\.0\.0\.1' } @@ -165,7 +165,7 @@ teardown() { run get_auth_dns www.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-9]+\.duckdns\.org' # Assert that we found a CNAME but didn't use dig NS assert_line --regexp 'Using dig.* CNAME' @@ -174,5 +174,5 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns www.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = (ns[1-9]+\.duckdns\.org )+' } diff --git a/test/u2-test-get_auth_dns-drill.bats b/test/u2-test-get_auth_dns-drill.bats index 434a9b5..d20079c 100644 --- a/test/u2-test-get_auth_dns-drill.bats +++ b/test/u2-test-get_auth_dns-drill.bats @@ -65,14 +65,14 @@ teardown() { run get_auth_dns ubuntu-getssl.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-9]+\.duckdns\.org' # Assert that we had to use drill NS assert_line --regexp 'Using drill.* NS' # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = (ns[1-9]+\.duckdns\.org )+' } @@ -97,7 +97,7 @@ teardown() { run get_auth_dns ubuntu-getssl.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-9]+\.duckdns\.org' # Assert that we had to use drill NS assert_line --regexp 'Using drill.* SOA' @@ -106,12 +106,12 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = (ns[1-9]+\.duckdns\.org )+' # Check that we also check the public DNS server if requested CHECK_PUBLIC_DNS_SERVER=true run get_auth_dns ubuntu-getssl.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org 1\.0\.0\.1' + assert_output --regexp 'set primary_ns = (ns[1-9]+\.duckdns\.org )+1\.0\.0\.1' } @@ -138,7 +138,7 @@ teardown() { run get_auth_dns www.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.net' # Assert that we found a CNAME and use drill NS assert_line --regexp 'Using drill.* CNAME' @@ -147,12 +147,12 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns www.duckdns.org - assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com' + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.net' # Check that we also check the public DNS server if requested CHECK_PUBLIC_DNS_SERVER=true run get_auth_dns www.duckdns.org - assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.com 1\.0\.0\.1' + assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.net 1\.0\.0\.1' } @@ -189,7 +189,7 @@ teardown() { run get_auth_dns www.duckdns.org # Assert that we've found the primary_ns server - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = ns[1-9]+\.duckdns\.org' # Assert that we found a CNAME but didn't use drill NS assert_line --regexp 'Using drill.* CNAME' @@ -198,5 +198,5 @@ teardown() { # Check all Authoritive DNS servers are returned if requested CHECK_ALL_AUTH_DNS=true run get_auth_dns www.duckdns.org - assert_output --regexp 'set primary_ns = ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org ns[1-4]+\.duckdns\.org' + assert_output --regexp 'set primary_ns = (ns[1-9]+\.duckdns\.org )+' } From c5c2b0e7be055e60d655343c50930c364c64ac36 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 28 Jun 2021 11:19:05 +0100 Subject: [PATCH 243/308] Update alpine nginx config --- test/Dockerfile-alpine | 2 +- test/test_helper.bash | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/Dockerfile-alpine b/test/Dockerfile-alpine index 2c28f48..b0a0ae1 100644 --- a/test/Dockerfile-alpine +++ b/test/Dockerfile-alpine @@ -7,7 +7,7 @@ RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx b WORKDIR /root # Create nginx directories in standard places -RUN mkdir /run/nginx +RUN mkdir -p /run/nginx RUN mkdir -p /etc/nginx/pki/private # Setup ftp diff --git a/test/test_helper.bash b/test/test_helper.bash index 48a8d4b..5745332 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -92,6 +92,8 @@ fi # Find NGINX configuration directory for HTTP-01 testing (need to add SSL to config) if [[ -f /etc/nginx/conf.d/default.conf ]]; then export NGINX_CONFIG=/etc/nginx/conf.d/default.conf +elif [[ -f /etc/nginx/http.d/default.conf ]]; then + export NGINX_CONFIG=/etc/nginx/http.d/default.conf elif [[ -f /etc/nginx/sites-enabled/default ]]; then export NGINX_CONFIG=/etc/nginx/sites-enabled/default else From 279527ea2b3d2686c6329688102642ad191ef0f7 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 1 Jul 2021 15:14:48 +0100 Subject: [PATCH 244/308] Move from gatsbyjs fork back to actions --- .github/workflows/stale2.yml | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/.github/workflows/stale2.yml b/.github/workflows/stale2.yml index ce6f9c1..9d5511b 100644 --- a/.github/workflows/stale2.yml +++ b/.github/workflows/stale2.yml @@ -1,31 +1,16 @@ +name: 'Close stale issues and PRs' on: schedule: - - cron: "0 0 * * *" - -name: Run Stale Bot on Issue Comments + - cron: '45 2 * * *' jobs: - build: - name: stale + stale: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - name: stale - uses: gatsbyjs/stale@master + - uses: actions/stale@v3 with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DRY_RUN: true - DAYS_BEFORE_STALE: 60 - DAYS_BEFORE_CLOSE: 30 - STALE_ISSUE_LABEL: 'stale' - STALE_PR_LABEL: 'stale' - OPERATIONS_PER_RUN: 30 - STALE_ISSUE_MESSAGE: 'This issue will be closed as no updates for 60 days' - CLOSE_MESSAGE: 'Closing stale issue after 90 days of inactivity' - EXEMPT_ISSUE_LABELS: | - bug - documentation - enhancement - feature - help wanted - rfc + stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days.' + days-before-stale: 60 + days-before-close: 30 + any-of-labels: 'needs more information' + debug-only: true From 2c315e717be65ec6384f5111f2923e46e16b917e Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 1 Jul 2021 16:41:50 +0100 Subject: [PATCH 245/308] Move to checkout v2, don't run tests when changing github actions --- .github/workflows/run-tests-pebble.yml | 10 ++++++---- .github/workflows/run-tests-staging-duckdns.yml | 6 ++++-- .github/workflows/run-tests-staging-dynu.yml | 6 ++++-- .github/workflows/shellcheck.yml | 6 ++++-- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/run-tests-pebble.yml b/.github/workflows/run-tests-pebble.yml index 5dc53a4..874ceea 100644 --- a/.github/workflows/run-tests-pebble.yml +++ b/.github/workflows/run-tests-pebble.yml @@ -1,6 +1,8 @@ name: Run all tests on pebble on: push: + paths-ignore: + - '.github/workflows/*' branches: - master pull_request: @@ -10,7 +12,7 @@ jobs: test-alpine: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on Alpine @@ -18,7 +20,7 @@ jobs: test-bash-4-0: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on Alpine using Bash 4.0 @@ -26,7 +28,7 @@ jobs: test-bash-4-2: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on Alpine using Bash 4.2 @@ -34,7 +36,7 @@ jobs: test-bash-5-0: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on Alpine using Bash 5 diff --git a/.github/workflows/run-tests-staging-duckdns.yml b/.github/workflows/run-tests-staging-duckdns.yml index 54da950..a6348bc 100644 --- a/.github/workflows/run-tests-staging-duckdns.yml +++ b/.github/workflows/run-tests-staging-duckdns.yml @@ -1,6 +1,8 @@ name: Run all tests using DuckDNS on: push: + paths-ignore: + - '.github/workflows/*' branches: - master pull_request: @@ -10,7 +12,7 @@ jobs: test-centos7-duckdns: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on CentOS7 against Staging using DuckDNS @@ -18,7 +20,7 @@ jobs: test-ubuntu-duckdns: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on Ubuntu against Staging using DuckDNS diff --git a/.github/workflows/run-tests-staging-dynu.yml b/.github/workflows/run-tests-staging-dynu.yml index c523278..1f55bae 100644 --- a/.github/workflows/run-tests-staging-dynu.yml +++ b/.github/workflows/run-tests-staging-dynu.yml @@ -1,6 +1,8 @@ name: Run all tests using Dynu on: push: + paths-ignore: + - '.github/workflows/*' branches: - master pull_request: @@ -10,7 +12,7 @@ jobs: test-centos7-dynu: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on CentOS7 against Staging using Dynu @@ -18,7 +20,7 @@ jobs: test-ubuntu-dynu: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Build the docker-compose stack run: docker-compose up -d --build - name: Run test suite on Ubuntu against Staging using Dynu diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 37b9cad..baf6603 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -2,6 +2,8 @@ name: shellcheck on: push: + paths-ignore: + - '.github/workflows/*' branches: [ master ] pull_request: branches: [ master ] @@ -10,8 +12,8 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Lint check - uses: azohra/shell-linter@v0.3.0 + uses: azohra/shell-linter@latest with: path: "getssl" From e4c17c8d5625eaba339073ce962dc97c780405d6 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 7 Jul 2021 22:58:34 +0100 Subject: [PATCH 246/308] Remove spaces and sort when checking if SANS list changed --- getssl | 9 +-- test/19-test-add-to-sans.bats | 101 +++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index dac2d2d..8d1eee1 100755 --- a/getssl +++ b/getssl @@ -2987,11 +2987,12 @@ if [[ -s "$CERT_FILE" ]]; then debug "certificate $CERT_FILE exists" enddate=$(openssl x509 -in "$CERT_FILE" -noout -enddate 2>/dev/null| cut -d= -f 2-) debug "local cert is valid until $enddate" - existing_sanlist=$(openssl x509 -in "$CERT_FILE" -noout -text | grep "DNS:" | sed 's/^ *//g') + existing_sanlist=$(openssl x509 -in "$CERT_FILE" -noout -text | grep "DNS:" | sed '{ s/ *DNS://g; y/,/\n/; }' | sort -u | xargs | sed 's/ /,/g') + sorted_sanlist=$(echo "$SANLIST" | sed '{ s/subjectAltName=//; s/ *DNS://g; y/,/\n/; }' | sort -u | xargs | sed 's/ /,/g') debug "local cert is for domains: ${existing_sanlist}" if [[ "$enddate" != "-" ]]; then enddate_s=$(date_epoc "$enddate") - if [[ $(date_renew) -lt "$enddate_s" ]] && [[ $_FORCE_RENEW -ne 1 ]] && [[ "subjectAltName=$existing_sanlist" == "$SANLIST" ]]; then + if [[ $(date_renew) -lt "$enddate_s" ]] && [[ $_FORCE_RENEW -ne 1 ]] && [[ "$existing_sanlist" == "$sorted_sanlist" ]]; then issuer=$(openssl x509 -in "$CERT_FILE" -noout -issuer 2>/dev/null) if [[ "$issuer" == *"Fake LE Intermediate"* ]] && [[ "$CA" == "https://acme-v02.api.letsencrypt.org" ]]; then debug "upgrading from fake cert to real" @@ -3001,8 +3002,8 @@ if [[ -s "$CERT_FILE" ]]; then graceful_exit $_NOTIFY_VALID fi else - if [[ "subjectAltName=$existing_sanlist" != "$SANLIST" ]]; then - info "Domain list in existing certificate ($existing_sanlist) does not match domains requested ($SANLIST), so recreating certificate" + if [[ "$existing_sanlist" != "$sorted_sanlist" ]]; then + info "Domain list in existing certificate ($existing_sanlist) does not match domains requested ($sorted_sanlist), so recreating certificate" fi debug "${DOMAIN}: certificate needs renewal" fi diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats index f00bb4e..d7ea78d 100644 --- a/test/19-test-add-to-sans.bats +++ b/test/19-test-add-to-sans.bats @@ -34,7 +34,37 @@ teardown() { } -@test "Check we can add a new domain to SANS" { +@test "Check that if the SANS doesn't change, we don't re-create the certificate (single domain)" { + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + fi + CONFIG_FILE="getssl-dns01.cfg" + + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + + create_certificate + assert_success + check_output_for_errors + + # As the SANS list changed, a new certificate is needed + refute_line --partial "does not match domains requested" + refute_line --partial "does not have the same domains as the config - re-create-csr" + refute_line --partial "certificate installed OK on server" + assert_line --partial 'certificate is valid for more than' + + # Check that the SAN list in the certificate matches the expected value + SAN_IN_CERT=$(openssl x509 -in "$CERT" -noout -text | grep "DNS:" | sed 's/^ *//g') + SAN_EXPECTED="DNS:${GETSSL_HOST}" + if [[ "$SAN_IN_CERT" != "$SAN_EXPECTED" ]]; then + echo "# SAN_IN_CERT=$SAN_IN_CERT" + echo "# SAN_EXPECTED=$SAN_EXPECTED" + fi + [ "${SAN_IN_CERT}" = "$SAN_EXPECTED" ] +} + + +@test "Check certificate is recreated if we add a new domain to SANS" { if [ -n "$STAGING" ]; then skip "Not trying on staging server yet" fi @@ -66,3 +96,72 @@ EOF fi [ "${SAN_IN_CERT}" = "$SAN_EXPECTED" ] } + + +@test "Check that if the SANS doesn't change, we don't re-create the certificate (multiple domains)" { + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + fi + CONFIG_FILE="getssl-dns01.cfg" + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +SANS="a.${GETSSL_HOST}" +EOF + + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + + create_certificate + assert_success + check_output_for_errors + + # As the SANS list changed, a new certificate is needed + refute_line --partial "does not match domains requested" + refute_line --partial "does not have the same domains as the config - re-create-csr" + refute_line --partial "certificate installed OK on server" + assert_line --partial 'certificate is valid for more than' + + # Check that the SAN list in the certificate matches the expected value + SAN_IN_CERT=$(openssl x509 -in "$CERT" -noout -text | grep "DNS:" | sed 's/^ *//g') + SAN_EXPECTED="DNS:${GETSSL_HOST}, DNS:a.${GETSSL_HOST}" + if [[ "$SAN_IN_CERT" != "$SAN_EXPECTED" ]]; then + echo "# SAN_IN_CERT=$SAN_IN_CERT" + echo "# SAN_EXPECTED=$SAN_EXPECTED" + fi + [ "${SAN_IN_CERT}" = "$SAN_EXPECTED" ] +} + + +@test "Check that if the SANS doesn't change, we don't re-create the certificate (reordered domains)" { + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + fi + CONFIG_FILE="getssl-dns01.cfg" + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +IGNORE_DIRECTORY_DOMAIN="true" +SANS="a.${GETSSL_HOST}, ${GETSSL_HOST}" +EOF + + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + + create_certificate + assert_success + check_output_for_errors + + # As the SANS list changed, a new certificate is needed + refute_line --partial "does not match domains requested" + refute_line --partial "does not have the same domains as the config - re-create-csr" + refute_line --partial "certificate installed OK on server" + assert_line --partial 'certificate is valid for more than' + + # Check that the SAN list in the certificate matches the expected value + SAN_IN_CERT=$(openssl x509 -in "$CERT" -noout -text | grep "DNS:" | sed 's/^ *//g') + SAN_EXPECTED="DNS:${GETSSL_HOST}, DNS:a.${GETSSL_HOST}" + if [[ "$SAN_IN_CERT" != "$SAN_EXPECTED" ]]; then + echo "# SAN_IN_CERT=$SAN_IN_CERT" + echo "# SAN_EXPECTED=$SAN_EXPECTED" + fi + [ "${SAN_IN_CERT}" = "$SAN_EXPECTED" ] +} From 32f56a9b4ef0967f6c0a31ed0e2466a4c60a9b33 Mon Sep 17 00:00:00 2001 From: atisne Date: Mon, 12 Jul 2021 18:48:56 +0200 Subject: [PATCH 247/308] Do not redirect outputs on remote commands when the debug option is used When the debug option is used, it may be useful to see errors that may occured on remote calls (ssh). --- getssl | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index 8d1eee1..ad8ee66 100755 --- a/getssl +++ b/getssl @@ -260,6 +260,7 @@ # 2021-02-18 Add FULL_CHAIN_INCLUDE_ROOT # 2021-03-25 Fix DNS challenge completion check if CNAMEs on different NS are used (sideeffect42)(2.35) # 2021-05-08 Merge from tlhackque/getssl: GoDaddy, split-view, tempfile permissions fixes, --version(2.36) +# 2021-07-12 Do not redirect outputs on remote commands when the debug option is used (atisne) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -329,6 +330,7 @@ _MUTE=0 _NOTIFY_VALID=0 _QUIET=0 _RECREATE_CSR=0 +_REDIRECT_OUTPUT="1>/dev/null 2>&1" _REVOKE=0 _RUNNING_TEST=0 _TEST_SKIP_CNAME_CALL=0 @@ -1334,10 +1336,10 @@ for d in "${alldomains[@]}"; do if [[ "${t_loc:0:4}" == "ssh:" ]] ; then sshhost=$(echo "${t_loc}"| awk -F: '{print $2}') command="rm -f ${t_loc:(( ${#sshhost} + 5))}/${token:?}" - debug "running following command to remove token" - debug "ssh $SSH_OPTS $sshhost ${command}" + debug "running following command to remove token:" + debug "ssh $SSH_OPTS $sshhost ${command} $_REDIRECT_OUTPUT" # shellcheck disable=SC2029 disable=SC2086 - ssh $SSH_OPTS "$sshhost" "${command}" 1>/dev/null 2>&1 + ssh $SSH_OPTS "$sshhost" "${command}" $_REDIRECT_OUTPUT rm -f "${TEMP_DIR:?}/${token:?}" elif [[ "${t_loc:0:4}" == "ftp:" ]] ; then debug "using ftp to remove token file" @@ -2070,10 +2072,10 @@ reload_service() { # Runs a command to reload services ( via ssh if needed) sshhost=$(echo "$ARELOAD_CMD"| awk -F: '{print $2}') command=${ARELOAD_CMD:(( ${#sshhost} + 5))} debug "running following command to reload cert:" - debug "ssh $SSH_OPTS $sshhost ${command}" + debug "ssh $SSH_OPTS $sshhost ${command} $_REDIRECT_OUTPUT" # shellcheck disable=SC2029 # shellcheck disable=SC2086 - ssh $SSH_OPTS "$sshhost" "${command}" 1>/dev/null 2>&1 + ssh $SSH_OPTS "$sshhost" "${command}" $_REDIRECT_OUTPUT # allow 2 seconds for services to restart sleep 2 else @@ -2620,6 +2622,11 @@ while [[ -n ${1+defined} ]]; do shift done +if [[ ${_USE_DEBUG} -eq 1 ]]; then + # Do not hide outputs when debug mode is on + _REDIRECT_OUTPUT="" +fi + # Main logic ############ From b54acaeab75a73eb0a1d400c817bcb559bb83c23 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 17 Jul 2021 12:45:13 +0100 Subject: [PATCH 248/308] Fix comments --- test/19-test-add-to-sans.bats | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats index d7ea78d..a0a6d71 100644 --- a/test/19-test-add-to-sans.bats +++ b/test/19-test-add-to-sans.bats @@ -47,7 +47,7 @@ teardown() { assert_success check_output_for_errors - # As the SANS list changed, a new certificate is needed + # As the SANS list didn't change, a new certificate isn't needed refute_line --partial "does not match domains requested" refute_line --partial "does not have the same domains as the config - re-create-csr" refute_line --partial "certificate installed OK on server" @@ -115,7 +115,7 @@ EOF assert_success check_output_for_errors - # As the SANS list changed, a new certificate is needed + # As the SANS list didn't change, a new certificate isn't needed refute_line --partial "does not match domains requested" refute_line --partial "does not have the same domains as the config - re-create-csr" refute_line --partial "certificate installed OK on server" @@ -150,7 +150,7 @@ EOF assert_success check_output_for_errors - # As the SANS list changed, a new certificate is needed + # As the SANS list didn't change, a new certificate isn't needed refute_line --partial "does not match domains requested" refute_line --partial "does not have the same domains as the config - re-create-csr" refute_line --partial "certificate installed OK on server" From dd2de27ae59e43a813edbc2c28b135c7fe374880 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 18 Jul 2021 14:58:42 +0100 Subject: [PATCH 249/308] Use +noidnout for dig and drill if IDN domain --- getssl | 38 +++++++++++++++++++--- test/37-idn.bats | 80 ++++++++++++++++++++++++++++++++++++++++++++++ test/idn-domain.md | 22 +++++++++++++ test/run-test.cmd | 2 ++ test/run-test.sh | 2 ++ 5 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 test/37-idn.bats create mode 100644 test/idn-domain.md diff --git a/getssl b/getssl index 8d1eee1..bb48e09 100755 --- a/getssl +++ b/getssl @@ -529,6 +529,17 @@ check_challenge_completion_dns() { # perform validation via DNS challenge # check for token at public dns server, waiting for a valid response. for ns in $primary_ns; do info "checking DNS at $ns" + + # add +noidnout if idn-domain so search for domain in results works + if [[ "${d}" == xn--* || "${d}" == *".xn--"* ]]; then + if [[ "$DNS_CHECK_FUNC" == "nslookup" || "$DNS_CHECK_FUNC" == "host" || ("$DNS_CHECK_FUNC" == "dig" && "$DIG_SUPPORTS_NOIDNOUT" == "false") ]]; then + info "Warning: idn domain but $DNS_CHECK_FUNC doesn't support +noidnout" + else + debug "adding +noidnout to DNS_CHECK_OPTIONS" + DNS_CHECK_OPTIONS="$DNS_CHECK_OPTIONS +noidnout" + fi + fi + ntries=0 check_dns="fail" while [[ "$check_dns" == "fail" ]]; do @@ -537,14 +548,18 @@ check_challenge_completion_dns() { # perform validation via DNS challenge | grep ^_acme -A2\ | grep '"'|awk -F'"' '{ print $2}') elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then - debug "$DNS_CHECK_FUNC" TXT "${rr}" "@${ns}" - check_result=$($DNS_CHECK_FUNC TXT "${rr}" "@${ns}" \ + # shellcheck disable=SC2086 + debug "$DNS_CHECK_FUNC" $DNS_CHECK_OPTIONS TXT "${rr}" "@${ns}" + # shellcheck disable=SC2086 + check_result=$($DNS_CHECK_FUNC $DNS_CHECK_OPTIONS TXT "${rr}" "@${ns}" \ | grep -i "^${rr}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') debug "check_result=$check_result" if [[ -z "$check_result" ]]; then - debug "$DNS_CHECK_FUNC" ANY "${rr}" "@${ns}" - check_result=$($DNS_CHECK_FUNC ANY "${rr}" "@${ns}" \ + # shellcheck disable=SC2086 + debug "$DNS_CHECK_FUNC" $DNS_CHECK_OPTIONS ANY "${rr}" "@${ns}" + # shellcheck disable=SC2086 + check_result=$($DNS_CHECK_FUNC $DNS_CHECK_OPTIONS ANY "${rr}" "@${ns}" \ | grep -i "^${rr}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') debug "check_result=$check_result" @@ -649,6 +664,7 @@ check_config() { # check the config files for all obvious errors tmplist=$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX) || error_exit "mktemp failed" for d in "${alldomains[@]}"; do # loop over domains (dn is domain number) debug "checking domain $d" + if [[ "$(grep "^${d}$" "$tmplist")" = "$d" ]]; then info "${DOMAIN}: $d appears to be duplicated in domain, SAN list" config_errors=true @@ -672,6 +688,14 @@ check_config() { # check the config files for all obvious errors fi # check domain exists using all DNS utilities. DNS_CHECK_OPTIONS may bind IP address or provide TSIG + + # add +noidnout if idn-domain so search for domain in results works + if [[ "${d}" == xn--* || "${d}" == *".xn--"* ]]; then + if [[ "$HAS_DIG_OR_DRILL" != "dig" || "$DIG_SUPPORTS_NOIDNOUT" == "true" ]]; then + DNS_CHECK_OPTIONS="$DNS_CHECK_OPTIONS +noidnout" + fi + fi + found_ip=false if [[ -n "$HAS_DIG_OR_DRILL" ]]; then debug "DNS lookup using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS ${d}" @@ -1125,6 +1149,7 @@ error_exit() { # give error message on error exit find_dns_utils() { HAS_NSLOOKUP=false HAS_DIG_OR_DRILL="" + DIG_SUPPORTS_NOIDNOUT=false HAS_HOST=false if [[ -n "$(command -v nslookup 2>/dev/null)" ]]; then debug "HAS NSLOOKUP=true" @@ -1141,6 +1166,11 @@ find_dns_utils() { else HAS_DIG_OR_DRILL="dig" fi + + if [[ $(${HAS_DIG_OR_DRILL} +noidnout >/dev/null 2>&1) ]]; then + DIG_SUPPORTS_NOIDNOUT=true + fi + debug "HAS DIG_OR_DRILL=$HAS_DIG_OR_DRILL" fi diff --git a/test/37-idn.bats b/test/37-idn.bats new file mode 100644 index 0000000..7b91827 --- /dev/null +++ b/test/37-idn.bats @@ -0,0 +1,80 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + +setup_file() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + GETSSL_CMD_HOST=${GETSSL_HOST/getssl/xn--t-r1a81lydm69gz81r} + curl --silent -X POST -d '{"host":"'$GETSSL_CMD_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + fi +} + +# This is run for every test +setup() { + GETSSL_CMD_HOST=${GETSSL_HOST/getssl/xn--t-r1a81lydm69gz81r} + + # use the test description to move tools we don't want to test out of the way + DNS_TOOL=${BATS_TEST_DESCRIPTION##*:} + for tool in dig drill host nslookup + do + if [[ "$tool" != "$DNS_TOOL" && -f /usr/bin/$tool ]]; then + mv /usr/bin/$tool /usr/bin/${tool}.getssl + fi + done +} + +teardown() { + # use the test description to move tools we didn't want to test back + DNS_TOOL=${BATS_TEST_DESCRIPTION##*-} + for tool in dig drill host nslookup + do + if [[ "$tool" != "$DNS_TOOL" && -f /usr/bin/${tool}.getssl ]]; then + mv /usr/bin/${tool}.getssl /usr/bin/${tool} + fi + done +} + +teardown_file() { + if [ -z "$STAGING" ]; then + curl --silent -X POST -d '{"host":"'$GETSSL_CMD_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + fi +} + +@test "Check that DNS-01 verification works if the domain is idn:dig" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + CONFIG_FILE="getssl-dns01.cfg" + + setup_environment + init_getssl + create_certificate -d + + assert_success + assert_output --partial "dig" + check_output_for_errors "debug" +} + +@test "Check that DNS-01 verification works if the domain is idn:drill" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + if [ ! -f /usr/bin/drill ]; then + # Can't find drill package for centos8 / rockylinux8 + skip "Drill not installed on this system" + fi + + CONFIG_FILE="getssl-dns01.cfg" + + setup_environment + init_getssl + create_certificate -d + + assert_success + assert_output --partial "drill" + check_output_for_errors "debug" +} diff --git a/test/idn-domain.md b/test/idn-domain.md new file mode 100644 index 0000000..2f25f0e --- /dev/null +++ b/test/idn-domain.md @@ -0,0 +1,22 @@ +# Convert getssl.test into IDN version using confusable letters + + + +## Unicode characters + +* ɡ 0261 LATIN SMALL LETTER SCRIPT G +* е 0435 CYRILLIC SMALL LETTER IE +* t +* ѕ 0455 CYRILLIC SMALL LETTER DZE +* ꜱ A731 LATIN LETTER SMALL CAPITAL S +* ᛁ 16C1 RUNIC LETTER ISAZ IS ISS I + +## IDN version of getssl.test + +ɡеtѕꜱᛁ.test + +## ACE version of IDN ɡеtѕꜱᛁ.test + + + +xn--t-r1a81lydm69gz81r.test diff --git a/test/run-test.cmd b/test/run-test.cmd index 61b360e..88e692d 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -12,6 +12,7 @@ IF NOT x%OS:duck=%==x%OS% GOTO duckdns IF NOT x%OS:dynu=%==x%OS% GOTO dynu IF NOT x%OS:bash=%==x%OS% GOTO bash SET ALIAS=%OS%.getssl.test +SET IDN=%OS%.xn--t-r1a81lydm69gz81r.test SET STAGING= SET GETSSL_OS=%OS% GOTO Run @@ -55,6 +56,7 @@ docker run -it ^ --rm ^ --network %CurrDirName%_acmenet ^ --network-alias %ALIAS% ^ + --network-alias %IDN% ^ --network-alias a.%OS%.getssl.test ^ --network-alias b.%OS%.getssl.test ^ --network-alias c.%OS%.getssl.test ^ diff --git a/test/run-test.sh b/test/run-test.sh index ef7e403..8f405e1 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -15,6 +15,7 @@ else fi ALIAS="$OS.getssl.test" +IDN="$OS.xn--t-r1a81lydm69gz81r.test" STAGING="" GETSSL_OS=$OS @@ -39,6 +40,7 @@ docker run \ --rm \ --network ${PWD##*/}_acmenet \ --network-alias $ALIAS \ + --network-alias $IDN \ --network-alias "a.$OS.getssl.test" \ --network-alias "b.$OS.getssl.test" \ --network-alias "c.$OS.getssl.test" \ From 529a4e1feec9658455a2bb97dffda26c9d002c9a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 18 Jul 2021 15:00:41 +0100 Subject: [PATCH 250/308] Update dockerfiles to set locale to en_US (needed for idn testing) --- test/Dockerfile-centos7 | 5 +++++ test/Dockerfile-centos7-duckdns | 5 +++++ test/Dockerfile-centos7-dynu | 5 +++++ test/Dockerfile-centos8 | 7 ++++++- test/Dockerfile-debian | 7 +++++++ test/Dockerfile-ubuntu | 7 +++++++ test/Dockerfile-ubuntu-duckdns | 7 +++++++ test/Dockerfile-ubuntu-dynu | 7 +++++++ test/Dockerfile-ubuntu16 | 7 +++++++ test/Dockerfile-ubuntu18 | 7 +++++++ 10 files changed, 63 insertions(+), 1 deletion(-) diff --git a/test/Dockerfile-centos7 b/test/Dockerfile-centos7 index 794e0bd..56dff7d 100644 --- a/test/Dockerfile-centos7 +++ b/test/Dockerfile-centos7 @@ -7,6 +7,11 @@ RUN yum -y install git curl ldns bind-utils wget which nginx RUN yum -y install ftp vsftpd RUN yum -y install openssh-server +# Set locale +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + WORKDIR /root RUN mkdir -p /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf diff --git a/test/Dockerfile-centos7-duckdns b/test/Dockerfile-centos7-duckdns index bf85592..be26c79 100644 --- a/test/Dockerfile-centos7-duckdns +++ b/test/Dockerfile-centos7-duckdns @@ -7,6 +7,11 @@ RUN yum -y update RUN yum -y install epel-release RUN yum -y install git curl bind-utils ldns wget which nginx +# Set locale +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + ENV staging "true" ENV dynamic_dns "dynu" ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb diff --git a/test/Dockerfile-centos7-dynu b/test/Dockerfile-centos7-dynu index 01d41a7..65c8051 100644 --- a/test/Dockerfile-centos7-dynu +++ b/test/Dockerfile-centos7-dynu @@ -7,6 +7,11 @@ RUN yum -y update RUN yum -y install epel-release RUN yum -y install git curl bind-utils ldns wget which nginx +# Set locale +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + ENV staging "true" ENV dynamic_dns "duckdns" ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 diff --git a/test/Dockerfile-centos8 b/test/Dockerfile-centos8 index 210bd8e..4ac3114 100644 --- a/test/Dockerfile-centos8 +++ b/test/Dockerfile-centos8 @@ -1,6 +1,6 @@ FROM centos:centos8 -# Note this image uses drill, does not have dig or nslookup installed +# Note this image does not have drill # Update and install required software RUN yum -y update @@ -9,6 +9,11 @@ RUN yum -y install git curl bind-utils wget which nginx RUN yum -y install ftp vsftpd RUN yum -y install openssh-server +# Set locale +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + WORKDIR /root RUN mkdir -p /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf diff --git a/test/Dockerfile-debian b/test/Dockerfile-debian index 04e5232..1a57107 100644 --- a/test/Dockerfile-debian +++ b/test/Dockerfile-debian @@ -7,6 +7,13 @@ RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light RUN apt-get install -y ftp vsftpd RUN apt-get install -y openssh-server +RUN apt-get install -y locales # for idn testing + +# Set locale +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 WORKDIR /root RUN mkdir -p /etc/nginx/pki/private diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index dd8338d..5dee554 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -11,6 +11,13 @@ RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light RUN apt-get install -y vim dos2unix # for debugging RUN apt-get install -y ftp vsftpd RUN apt-get install -y openssh-server +RUN apt-get install -y locales # for idn testing + +# Set locale +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 # Setup ftp ENV VSFTPD_CONF=/etc/vsftpd.conf diff --git a/test/Dockerfile-ubuntu-duckdns b/test/Dockerfile-ubuntu-duckdns index a07bb23..f0f2edd 100644 --- a/test/Dockerfile-ubuntu-duckdns +++ b/test/Dockerfile-ubuntu-duckdns @@ -14,6 +14,13 @@ ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light RUN apt-get install -y vim dos2unix # for debugging +RUN apt-get install -y locales # for idn testing + +# Set locale +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 WORKDIR /root diff --git a/test/Dockerfile-ubuntu-dynu b/test/Dockerfile-ubuntu-dynu index 2ea8c31..b010293 100644 --- a/test/Dockerfile-ubuntu-dynu +++ b/test/Dockerfile-ubuntu-dynu @@ -14,6 +14,13 @@ ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light RUN apt-get install -y vim dos2unix # for debugging +RUN apt-get install -y locales # for idn testing + +# Set locale +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 WORKDIR /root diff --git a/test/Dockerfile-ubuntu16 b/test/Dockerfile-ubuntu16 index 00a4589..8e4ecae 100644 --- a/test/Dockerfile-ubuntu16 +++ b/test/Dockerfile-ubuntu16 @@ -8,6 +8,13 @@ RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light RUN apt-get install -y ftp vsftpd RUN apt-get install -y openssh-server +RUN apt-get install -y locales # for idn testing + +# Set locale +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 WORKDIR /root RUN mkdir -p /etc/nginx/pki/private diff --git a/test/Dockerfile-ubuntu18 b/test/Dockerfile-ubuntu18 index 91a0429..98b62d5 100644 --- a/test/Dockerfile-ubuntu18 +++ b/test/Dockerfile-ubuntu18 @@ -8,6 +8,13 @@ RUN apt-get update --fix-missing RUN apt-get install -y git curl dnsutils ldnsutils wget gawk nginx-light RUN apt-get install -y ftp vsftpd RUN apt-get install -y openssh-server +RUN apt-get install -y locales # for idn testing + +# Set locale +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 WORKDIR /root RUN mkdir -p /etc/nginx/pki/private From f38b8212a365cc6ad438c0687e7b47b2fdf17543 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 18 Jul 2021 15:01:04 +0100 Subject: [PATCH 251/308] Test on rockylinux --- .github/workflows/run-tests-pebble.yml | 8 ++++++ test/Dockerfile-rockylinux8 | 38 ++++++++++++++++++++++++++ test/restart-ftpd | 2 +- test/restart-nginx | 2 +- test/test_helper.bash | 2 +- 5 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 test/Dockerfile-rockylinux8 diff --git a/.github/workflows/run-tests-pebble.yml b/.github/workflows/run-tests-pebble.yml index 874ceea..fe82ad6 100644 --- a/.github/workflows/run-tests-pebble.yml +++ b/.github/workflows/run-tests-pebble.yml @@ -73,6 +73,14 @@ jobs: run: docker-compose up -d --build - name: Run test suite on Debian run: test/run-test.sh debian + test-rockylinux8: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Build the docker-compose stack + run: docker-compose up -d --build + - name: Run test suite on RockyLinux8 + run: test/run-test.sh rockylinux8 test-ubuntu: runs-on: ubuntu-latest steps: diff --git a/test/Dockerfile-rockylinux8 b/test/Dockerfile-rockylinux8 new file mode 100644 index 0000000..4b7a135 --- /dev/null +++ b/test/Dockerfile-rockylinux8 @@ -0,0 +1,38 @@ +FROM rockylinux/rockylinux:8 + +# Update and install required software +RUN yum -y update +RUN yum -y install epel-release +RUN yum -y install git curl bind-utils wget which nginx +RUN yum -y install ftp vsftpd +RUN yum -y install openssh-server +RUN yum -y install glibc-locale-source glibc-langpack-en # for en_US.UTF-8 support + +# Set locale +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +WORKDIR /root +RUN mkdir -p /etc/nginx/pki/private +COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf +COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf + +# Setup ftp +ENV VSFTPD_CONF=/etc/vsftpd/vsftpd.conf +ENV FTP_PASSIVE_DEFAULT=true +COPY test/test-config/vsftpd.conf /etc/vsftpd/vsftpd.conf +RUN adduser ftpuser +RUN echo 'ftpuser:ftpuser' | chpasswd +RUN adduser www-data +RUN usermod -G www-data ftpuser +RUN usermod -G www-data root +RUN mkdir -p /var/www/.well-known/acme-challenge +RUN chown -R www-data.www-data /var/www +RUN chmod g+w -R /var/www + +# BATS (Bash Automated Testings) +RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 +RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support +RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert +RUN /bats-core/install.sh /usr/local diff --git a/test/restart-ftpd b/test/restart-ftpd index f87d9d8..8087437 100755 --- a/test/restart-ftpd +++ b/test/restart-ftpd @@ -2,7 +2,7 @@ if [ "$GETSSL_OS" = "alpine" ]; then killall -HUP vsftpd >&3- -elif [[ "$GETSSL_OS" == "centos"[78] ]]; then +elif [[ "$GETSSL_OS" == "centos"[78] || "$GETSSL_OS" == "rockylinux"* ]]; then pgrep vsftpd | head -1 | xargs kill -HUP else service vsftpd restart >/dev/null >&3- diff --git a/test/restart-nginx b/test/restart-nginx index 4dc8af0..48ea7ac 100755 --- a/test/restart-nginx +++ b/test/restart-nginx @@ -3,7 +3,7 @@ if [ "$GETSSL_OS" = "alpine" ]; then killall -HUP nginx >&3- sleep 5 -elif [[ "$GETSSL_OS" == "centos"[78] ]]; then +elif [[ "$GETSSL_OS" == "centos"[78] || "$GETSSL_OS" == "rockylinux"* ]]; then pgrep nginx | head -1 | xargs kill -HUP sleep 5 else diff --git a/test/test_helper.bash b/test/test_helper.bash index 5745332..dedd3ae 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -80,7 +80,7 @@ if [[ -f /usr/bin/supervisord && -f /etc/supervisord.conf ]]; then # Give supervisord time to start sleep 1 fi -elif [[ "$GETSSL_OS" == "centos"[78] ]]; then +elif [[ "$GETSSL_OS" == "centos"[78] || "$GETSSL_OS" == "rockylinux"* ]]; then if [ -z "$(pgrep nginx)" ]; then nginx >&3- fi From 84a3cf26408bcf8b70fa495e53da2c2198f93cd9 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 18 Jul 2021 22:07:49 +0100 Subject: [PATCH 252/308] Fix check to see if dig supports +noidnout (only broke on debian) --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index bb48e09..52e5fc3 100755 --- a/getssl +++ b/getssl @@ -1167,11 +1167,12 @@ find_dns_utils() { HAS_DIG_OR_DRILL="dig" fi - if [[ $(${HAS_DIG_OR_DRILL} +noidnout >/dev/null 2>&1) ]]; then + if [[ -z $(dig +noidnout >/dev/null 2>&1) ]]; then DIG_SUPPORTS_NOIDNOUT=true fi debug "HAS DIG_OR_DRILL=$HAS_DIG_OR_DRILL" + debug "DIG_SUPPORTS_NOIDNOUT=$DIG_SUPPORTS_NOIDNOUT" fi if [[ -n "$(command -v host 2>/dev/null)" ]]; then From ce61e500abed4910b426485e8e3487e8261267f0 Mon Sep 17 00:00:00 2001 From: Robin KERDILES Date: Mon, 19 Jul 2021 13:30:18 +0200 Subject: [PATCH 253/308] Support environment variables when using DNS challenges with OVH --- dns_scripts/dns_add_ovh | 6 +++--- dns_scripts/dns_del_ovh | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dns_scripts/dns_add_ovh b/dns_scripts/dns_add_ovh index 6c062a7..9791ed9 100755 --- a/dns_scripts/dns_add_ovh +++ b/dns_scripts/dns_add_ovh @@ -5,9 +5,9 @@ challenge="$2" # Please, do not forget to ask for your credentials at https://eu.api.ovh.com/createToken/ # permissions needed are /domain/zone/* in GET,POST,DELETE -applicationKey="YourAK" -applicationSecret="YourAS" -consumerKey="YourCK" +applicationKey=${OVH_APPLICATION_KEY:-''} +applicationSecret=${OVH_APPLICATION_SECRET:-''} +consumerKey=${OVH_CONSUMER_KEY:-''} topDomain=${domains[2]} subDomain=${domains[1]%%.} diff --git a/dns_scripts/dns_del_ovh b/dns_scripts/dns_del_ovh index bf7fe09..78fedf6 100755 --- a/dns_scripts/dns_del_ovh +++ b/dns_scripts/dns_del_ovh @@ -5,9 +5,9 @@ domains=($(echo "$1"|sed -e 's/^\(\([a-zA-Z0-9.-]*\?\)\.\)*\([a-zA-Z0-9-]\+\.[a- # Please, do not forget to ask for your credentials at https://eu.api.ovh.com/createToken/ # permissions needed are /domain/zone/* in GET,POST,DELETE -applicationKey="YourAK" -applicationSecret="YourAS" -consumerKey="YourCK" +applicationKey=${OVH_APPLICATION_KEY:-''} +applicationSecret=${OVH_APPLICATION_SECRET:-''} +consumerKey=${OVH_CONSUMER_KEY:-''} topDomain=${domains[2]} subDomain=${domains[1]%%.} From 5d69191f3d134ccba8b16d995ea2553b498b0b21 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 19 Jul 2021 15:21:54 +0100 Subject: [PATCH 254/308] Correct fix for +idnnoout check and dig -r check --- getssl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 52e5fc3..d0f02a2 100755 --- a/getssl +++ b/getssl @@ -1160,14 +1160,14 @@ find_dns_utils() { debug "HAS DIG_OR_DRILL=drill" HAS_DIG_OR_DRILL="drill" elif [[ -n "$(command -v dig 2>/dev/null)" ]] && dig >/dev/null 2>&1; then - if [[ $(dig -r >/dev/null 2>&1) ]]; then + if dig -r >/dev/null 2>&1; then # use dig -r so ~/.digrc is not used HAS_DIG_OR_DRILL="dig -r" else HAS_DIG_OR_DRILL="dig" fi - if [[ -z $(dig +noidnout >/dev/null 2>&1) ]]; then + if dig +noidnout >/dev/null 2>&1; then DIG_SUPPORTS_NOIDNOUT=true fi From 25d29bbff5d3270b9f986504c9602a32514da375 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 20 Jul 2021 16:09:13 +0100 Subject: [PATCH 255/308] Use setup_file so setup code only runs once --- test/2-simple-dns01-dig.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index f8f0cb4..a0d70a2 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -5,7 +5,7 @@ load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' -setup() { +setup_file() { if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi @@ -18,7 +18,7 @@ setup() { } -teardown() { +teardown_file() { if [ -f /usr/bin/host.getssl.bak ]; then mv /usr/bin/host.getssl.bak /usr/bin/host fi From 278988b76d27afa97429669f581a5f1d079037cd Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 20 Jul 2021 16:09:38 +0100 Subject: [PATCH 256/308] Enable the stale issue workflow --- .github/workflows/stale2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale2.yml b/.github/workflows/stale2.yml index 9d5511b..94d3686 100644 --- a/.github/workflows/stale2.yml +++ b/.github/workflows/stale2.yml @@ -13,4 +13,4 @@ jobs: days-before-stale: 60 days-before-close: 30 any-of-labels: 'needs more information' - debug-only: true + debug-only: false From 622b4b32376d91d427639dffd63a8e9c72564b7b Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Tue, 20 Jul 2021 16:10:44 +0100 Subject: [PATCH 257/308] Update version and change log --- getssl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/getssl b/getssl index 6069ed6..81fe187 100755 --- a/getssl +++ b/getssl @@ -260,7 +260,9 @@ # 2021-02-18 Add FULL_CHAIN_INCLUDE_ROOT # 2021-03-25 Fix DNS challenge completion check if CNAMEs on different NS are used (sideeffect42)(2.35) # 2021-05-08 Merge from tlhackque/getssl: GoDaddy, split-view, tempfile permissions fixes, --version(2.36) +# 2021-07-07 Request new certificate if SANs have changed (#669)(#673) # 2021-07-12 Do not redirect outputs on remote commands when the debug option is used (atisne) +# 2021-07-20 Use +noidnout to enable certificates for IDN domains (#679)(2.37) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -269,16 +271,16 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.36" +VERSION="2.37" # defaults ACCOUNT_KEY_LENGTH=4096 ACCOUNT_KEY_TYPE="rsa" -CA="https://acme-staging-v02.api.letsencrypt.org/directory" CA_CERT_LOCATION="" +CA="https://acme-staging-v02.api.letsencrypt.org/directory" CHALLENGE_CHECK_TYPE="http" -CHECK_REMOTE="true" CHECK_REMOTE_WAIT=0 +CHECK_REMOTE="true" CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" CSR_SUBJECT="/" CURL_USERAGENT="${PROGNAME}/${VERSION}" @@ -291,6 +293,7 @@ FULL_CHAIN_INCLUDE_ROOT="false" GETSSL_IGNORE_CP_PRESERVE="false" HTTP_TOKEN_CHECK_WAIT=0 IGNORE_DIRECTORY_DOMAIN="false" +OCSP_MUST_STAPLE="false" ORIG_UMASK=$(umask) PREFERRED_CHAIN="" # Set this to use an alternative root certificate PREVIOUSLY_VALIDATED="true" @@ -301,7 +304,6 @@ REUSE_PRIVATE_KEY="true" SERVER_TYPE="https" SKIP_HTTP_TOKEN_CHECK="false" SSLCONF="$(openssl version -d 2>/dev/null| cut -d\" -f2)/openssl.cnf" -OCSP_MUST_STAPLE="false" TEMP_UPGRADE_FILE="" TOKEN_USER_ID="" USE_SINGLE_ACL="false" From ee249abef2abe66c36ef9144f1078d342e5140be Mon Sep 17 00:00:00 2001 From: Robert Spencer Date: Tue, 20 Jul 2021 20:49:11 +0200 Subject: [PATCH 258/308] Fix leading whitespace in heredoc so it's uniform --- getssl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/getssl b/getssl index 6069ed6..7291c13 100755 --- a/getssl +++ b/getssl @@ -893,8 +893,8 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. fi $FTP_COMMAND <<- _EOF open $ftphost - user $ftpuser $ftppass - $FTP_OPTIONS + user $ftpuser $ftppass + $FTP_OPTIONS cd $ftpdirn lcd $fromdir put ./$fromfile @@ -1802,7 +1802,7 @@ help_message() { # print out the help message -U, --nocheck Do not check if a more recent version is available -v --version Display current version of $PROGNAME -w working_dir "Working directory" - --preferred-chain "chain" Use an alternate chain for the certificate + --preferred-chain "chain" Use an alternate chain for the certificate _EOF_ } @@ -2450,7 +2450,7 @@ write_domain_template() { # write out a template file for a domain. # where "/path/to/your/website/folder/" is the path, on your web server, to the web root for your domain. # You can also user WebDAV over HTTPS as transport mechanism. To do so, start with davs: followed by username, # password, host, port (explicitly needed even if using default port 443) and path on the server. - # Multiple locations can be defined for a file by separating the locations with a semi-colon. + # Multiple locations can be defined for a file by separating the locations with a semi-colon. #ACL=('/var/www/${DOMAIN}/web/.well-known/acme-challenge' # 'ssh:server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' @@ -2560,18 +2560,18 @@ write_getssl_template() { # write out the main template file #DNS_ADD_COMMAND= #DNS_DEL_COMMAND= - # Unusual configurations (especially split views) may require these. - # If you have a mixture, these can go in the per-domain getssl.cfg. - # - # If you must use an external DNS Server (e.g. due to split views) - # Specify it here. Otherwise, the default is to find the zone master. - # The default will usually work. - # PUBLIC_DNS_SERVER="8.8.8.8" - - # If getssl is unable to determine the authoritative nameserver for a domain - # it will as you to enter AUTH_DNS_SERVER. This is a server that - # can answer queries for the zone - a master or a slave, not a recursive server. - # AUTH_DNS_SERVER="10.0.0.14" + # Unusual configurations (especially split views) may require these. + # If you have a mixture, these can go in the per-domain getssl.cfg. + # + # If you must use an external DNS Server (e.g. due to split views) + # Specify it here. Otherwise, the default is to find the zone master. + # The default will usually work. + # PUBLIC_DNS_SERVER="8.8.8.8" + + # If getssl is unable to determine the authoritative nameserver for a domain + # it will as you to enter AUTH_DNS_SERVER. This is a server that + # can answer queries for the zone - a master or a slave, not a recursive server. + # AUTH_DNS_SERVER="10.0.0.14" _EOF_getssl_ } From b1e1c44119caa087173d274389fde976fd2d5122 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 22 Jul 2021 22:28:50 +0100 Subject: [PATCH 259/308] Check if drill supports +noidnout Only pass +noidnout param to dig/drill --- getssl | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/getssl b/getssl index f64d01c..bf1fb15 100755 --- a/getssl +++ b/getssl @@ -693,28 +693,27 @@ check_config() { # check the config files for all obvious errors # check domain exists using all DNS utilities. DNS_CHECK_OPTIONS may bind IP address or provide TSIG - # add +noidnout if idn-domain so search for domain in results works - if [[ "${d}" == xn--* || "${d}" == *".xn--"* ]]; then - if [[ "$HAS_DIG_OR_DRILL" != "dig" || "$DIG_SUPPORTS_NOIDNOUT" == "true" ]]; then - DNS_CHECK_OPTIONS="$DNS_CHECK_OPTIONS +noidnout" - fi - fi - found_ip=false if [[ -n "$HAS_DIG_OR_DRILL" ]]; then - debug "DNS lookup using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS ${d}" + # add +noidnout if idn-domain so search for domain in results works + DIG_CHECK_OPTIONS="$DNS_CHECK_OPTIONS" + if [[ ("${d}" == xn--* || "${d}" == *".xn--"* ) && "$DIG_SUPPORTS_NOIDNOUT" == "true" ]]; then + DIG_CHECK_OPTIONS="$DNS_CHECK_OPTIONS +noidnout" + fi + + debug "DNS lookup using $HAS_DIG_OR_DRILL $DIG_CHECK_OPTIONS ${d}" # shellcheck disable=SC2086 - if [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t SOA "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then + if [[ "$($HAS_DIG_OR_DRILL $DIG_CHECK_OPTIONS -t SOA "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then found_ip=true - elif [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t A "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then + elif [[ "$($HAS_DIG_OR_DRILL $DIG_CHECK_OPTIONS -t A "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then found_ip=true - elif [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t AAAA "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then + elif [[ "$($HAS_DIG_OR_DRILL $DIG_CHECK_OPTIONS -t AAAA "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then found_ip=true fi fi if [[ "$HAS_HOST" == "true" ]]; then - debug "DNS lookup using host ${d}" + debug "DNS lookup using host $DNS_CHECK_OPTIONS ${d}" # shellcheck disable=SC2086 if [[ "$(host $DNS_CHECK_OPTIONS "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then found_ip=true @@ -722,7 +721,7 @@ check_config() { # check the config files for all obvious errors fi if [[ "$HAS_NSLOOKUP" == "true" ]]; then - debug "DNS lookup using nslookup -query AAAA ${d}" + debug "DNS lookup using nslookup $DNS_CHECK_OPTIONS -query AAAA ${d}" # shellcheck disable=SC2086 if [[ "$(nslookup $DNS_CHECK_OPTIONS -query=AAAA "${d}"|grep -c -i "^${d}.*has AAAA address")" -ge 1 ]]; then debug "found IPv6 record for ${d}" @@ -1161,7 +1160,6 @@ find_dns_utils() { fi if [[ -n "$(command -v drill 2>/dev/null)" ]]; then - debug "HAS DIG_OR_DRILL=drill" HAS_DIG_OR_DRILL="drill" elif [[ -n "$(command -v dig 2>/dev/null)" ]] && dig >/dev/null 2>&1; then if dig -r >/dev/null 2>&1; then @@ -1170,8 +1168,10 @@ find_dns_utils() { else HAS_DIG_OR_DRILL="dig" fi + fi - if dig +noidnout >/dev/null 2>&1; then + if [[ -n "$HAS_DIG_OR_DRILL" ]]; then + if $HAS_DIG_OR_DRILL +noidnout >/dev/null 2>&1; then DIG_SUPPORTS_NOIDNOUT=true fi From 0855b908eaf4388a3eeb644e57b4f5f6a81439f3 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 22 Jul 2021 22:30:26 +0100 Subject: [PATCH 260/308] Add GETSSL_IDN_HOST instead of hardcoding idn test domain --- test/37-idn.bats | 7 +++---- test/run-test.cmd | 5 +++-- test/run-test.sh | 5 +++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/test/37-idn.bats b/test/37-idn.bats index 7b91827..be624de 100644 --- a/test/37-idn.bats +++ b/test/37-idn.bats @@ -7,14 +7,13 @@ load '/getssl/test/test_helper.bash' setup_file() { if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt - GETSSL_CMD_HOST=${GETSSL_HOST/getssl/xn--t-r1a81lydm69gz81r} - curl --silent -X POST -d '{"host":"'$GETSSL_CMD_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + curl --silent -X POST -d '{"host":"'$GETSSL_IDN_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a fi } # This is run for every test setup() { - GETSSL_CMD_HOST=${GETSSL_HOST/getssl/xn--t-r1a81lydm69gz81r} + GETSSL_CMD_HOST=${GETSSL_IDN_HOST} # use the test description to move tools we don't want to test out of the way DNS_TOOL=${BATS_TEST_DESCRIPTION##*:} @@ -39,7 +38,7 @@ teardown() { teardown_file() { if [ -z "$STAGING" ]; then - curl --silent -X POST -d '{"host":"'$GETSSL_CMD_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + curl --silent -X POST -d '{"host":"'$GETSSL_IDN_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a fi } diff --git a/test/run-test.cmd b/test/run-test.cmd index 88e692d..44c46be 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -8,11 +8,11 @@ SET COMMAND=%2 %3 :CheckAlias REM check if OS *contains* staging +SET GETSSL_IDN_HOST=%OS%.xn--t-r1a81lydm69gz81r.test IF NOT x%OS:duck=%==x%OS% GOTO duckdns IF NOT x%OS:dynu=%==x%OS% GOTO dynu IF NOT x%OS:bash=%==x%OS% GOTO bash SET ALIAS=%OS%.getssl.test -SET IDN=%OS%.xn--t-r1a81lydm69gz81r.test SET STAGING= SET GETSSL_OS=%OS% GOTO Run @@ -51,12 +51,13 @@ IF %ErrorLevel% EQU 1 GOTO End @echo on docker run -it ^ --env GETSSL_HOST=%ALIAS% %STAGING% ^ + --env GETSSL_IDN_HOST=%GETSSL_IDN_HOST% ^ --env GETSSL_OS=%GETSSL_OS% ^ -v %cd%:/getssl ^ --rm ^ --network %CurrDirName%_acmenet ^ --network-alias %ALIAS% ^ - --network-alias %IDN% ^ + --network-alias %GETSSL_IDN_HOST% ^ --network-alias a.%OS%.getssl.test ^ --network-alias b.%OS%.getssl.test ^ --network-alias c.%OS%.getssl.test ^ diff --git a/test/run-test.sh b/test/run-test.sh index 8f405e1..c3852ef 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -15,7 +15,7 @@ else fi ALIAS="$OS.getssl.test" -IDN="$OS.xn--t-r1a81lydm69gz81r.test" +GETSSL_IDN_HOST="$OS.xn--t-r1a81lydm69gz81r.test" STAGING="" GETSSL_OS=$OS @@ -35,12 +35,13 @@ docker build --rm -f "test/Dockerfile-$OS" -t "getssl-$OS" . # shellcheck disable=SC2086 docker run \ --env GETSSL_HOST=$ALIAS $STAGING \ + --env GETSSL_IDN_HOST=$GETSSL_IDN_HOST \ --env GETSSL_OS=$GETSSL_OS \ -v "$(pwd)":/getssl \ --rm \ --network ${PWD##*/}_acmenet \ --network-alias $ALIAS \ - --network-alias $IDN \ + --network-alias $GETSSL_IDN_HOST \ --network-alias "a.$OS.getssl.test" \ --network-alias "b.$OS.getssl.test" \ --network-alias "c.$OS.getssl.test" \ From 9d023115b01e978b4d66a1a38be1295ad705b968 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 22 Jul 2021 22:31:09 +0100 Subject: [PATCH 261/308] Test that host/nslookup are not called with +noidnout --- test/38-idn-http01-check-noidnout.bats | 44 ++++++++++++++++++++++++++ test/test_helper.bash | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 test/38-idn-http01-check-noidnout.bats diff --git a/test/38-idn-http01-check-noidnout.bats b/test/38-idn-http01-check-noidnout.bats new file mode 100644 index 0000000..fde4fe6 --- /dev/null +++ b/test/38-idn-http01-check-noidnout.bats @@ -0,0 +1,44 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + +setup_file() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + curl --silent -X POST -d '{"host":"'$GETSSL_IDN_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + fi +} + +setup() { + GETSSL_CMD_HOST=$GETSSL_IDN_HOST +} + +teardown_file() { + if [ -z "$STAGING" ]; then + curl --silent -X POST -d '{"host":"'$GETSSL_IDN_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + + fi +} + +@test "Ensure noidnout in check_config isn't passed to host and nslookup (HTTP-01)" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +SANS="${GETSSL_HOST}" +USE_SINGLE_ACL="true" +EOF + + create_certificate -d --check-config + + assert_success + refute_output --partial "DNS lookup using host +noidnout" + refute_output --partial "DNS lookup using nslookup +noidnout" + refute_output --partial "+noidnout $GETSSL_HOST" + check_output_for_errors +} diff --git a/test/test_helper.bash b/test/test_helper.bash index dedd3ae..ea71967 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -47,7 +47,7 @@ create_certificate() { # Create certificate cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" # shellcheck disable=SC2086 - run ${CODE_DIR}/getssl $1 "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl "$@" "$GETSSL_CMD_HOST" } init_getssl() { From 2f518618d34f8d844d26b060ef9e553cf16dd6e2 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 23 Jul 2021 15:10:06 +0100 Subject: [PATCH 262/308] Update version and change log --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index bf1fb15..fecbc7c 100755 --- a/getssl +++ b/getssl @@ -263,6 +263,7 @@ # 2021-07-07 Request new certificate if SANs have changed (#669)(#673) # 2021-07-12 Do not redirect outputs on remote commands when the debug option is used (atisne) # 2021-07-20 Use +noidnout to enable certificates for IDN domains (#679)(2.37) +# 2021-07-22 Only pass +noidnout param to dig/drill(#682)(2.38) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -271,7 +272,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.37" +VERSION="2.38" # defaults ACCOUNT_KEY_LENGTH=4096 From 6aacf4b3ca8f4ce6b0bcf1e39a871d212dcc8aa3 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Sun, 25 Jul 2021 09:12:13 -0400 Subject: [PATCH 263/308] Fix copy_file_to_location failures with ssh When a suffix is applied to a filename lacking an extension, a '.' in the host name is treated as the extension, and the extension is inserted there instead of being appended to the filename. Inspect the basename of the destination, and append only the suffix if no extension is present. Thus ssh:host.example.net:/etc/ssl/private/foo will now be copied to host.example.net/etc/ssl/private/foo.suffix instead of host.example.suffix.net/etc./ssl/private/foo (which usually would fail). Note that a local file, such as /etc/ssl/private/foo will be copied to /etc/ssl/private/foo.suffix. (Not /etc/ssl/private/foo.suffix. as before, which was incorrect). --- getssl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index fecbc7c..3061415 100755 --- a/getssl +++ b/getssl @@ -264,6 +264,7 @@ # 2021-07-12 Do not redirect outputs on remote commands when the debug option is used (atisne) # 2021-07-20 Use +noidnout to enable certificates for IDN domains (#679)(2.37) # 2021-07-22 Only pass +noidnout param to dig/drill(#682)(2.38) +# 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension (2.39) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -272,7 +273,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.38" +VERSION="2.39" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -850,7 +851,12 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. IFS=\; read -r -a copy_locations <<<"$3" for to in "${copy_locations[@]}"; do if [[ -n "$suffix" ]]; then - to="${to%.*}.${suffix}.${to##*.}" + bname="`basename $to`" + if [[ "${bname##*.}" == "$bname" ]]; then + to="${to}.${suffix}" + else + to="${to%.*}.${suffix}.${to##*.}" + fi fi info "copying $cert to $to" if [[ "${to:0:4}" == "ssh:" ]] ; then From e21fd2e08772767e2d7be086198e96a30bd9522b Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Sun, 25 Jul 2021 09:25:15 -0400 Subject: [PATCH 264/308] Fix lint --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 3061415..e09af56 100755 --- a/getssl +++ b/getssl @@ -851,7 +851,7 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. IFS=\; read -r -a copy_locations <<<"$3" for to in "${copy_locations[@]}"; do if [[ -n "$suffix" ]]; then - bname="`basename $to`" + bname="$(basename "$to")" if [[ "${bname##*.}" == "$bname" ]]; then to="${to}.${suffix}" else From bf9403fb9c7a5db5128981a08b75f0552af0144f Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Tue, 27 Jul 2021 11:17:01 -0400 Subject: [PATCH 265/308] Provide ftps:// copy which verifies remote TLS certificates ftses:// uses --insecure, which is, well, insecure. --- getssl | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index e09af56..e86a1d3 100755 --- a/getssl +++ b/getssl @@ -264,7 +264,8 @@ # 2021-07-12 Do not redirect outputs on remote commands when the debug option is used (atisne) # 2021-07-20 Use +noidnout to enable certificates for IDN domains (#679)(2.37) # 2021-07-22 Only pass +noidnout param to dig/drill(#682)(2.38) -# 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension (2.39) +# 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension +# 2021-07-27 Provide ftps:// copy which verifies remote TLS certificates (vs. ftpes:// which is insecure) (2.39) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -940,7 +941,7 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. debug "davs user=$davsuser - pass=$davspass - host=$davshost port=$davsport dir=$davsdirn file=$davsfile" debug "from dir=$fromdir file=$fromfile" curl -u "${davsuser}:${davspass}" -T "${fromdir}/${fromfile}" "https://${davshost}:${davsport}${davsdirn}${davsfile}" - elif [[ "${to:0:6}" == "ftpes:" ]] ; then + elif [[ "${to:0:6}" == "ftpes:" ]] || [[ "${to:0:5}" == "ftps:" ]] ; then debug "using ftp to copy the file from $from" ftpuser=$(echo "$to"| awk -F: '{print $2}') ftppass=$(echo "$to"| awk -F: '{print $3}') @@ -952,7 +953,11 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. fromfile=$(basename "$from") debug "ftp user=$ftpuser - pass=$ftppass - host=$ftphost dir=$ftpdirn file=$ftpfile" debug "from dir=$fromdir file=$fromfile" - curl --insecure --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" + if [[ "${to:0:5}" == "ftps:" ]] ; then + curl --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" + else + curl --insecure --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" + fi else if ! mkdir -p "$(dirname "$to")" ; then error_exit "cannot create ACL directory $(basename "$to")" @@ -2454,9 +2459,11 @@ write_domain_template() { # write out a template file for a domain. # 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:/ftpes: then the next variables are ftpuserid:ftppassword:servername:ACL_location + # If these start with ftp:/ftpes:/ftps: 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. + # ftp: uses regular ftp; ftpes: uses ftp over TLS but DOES NOT verify the remote certificates; ftps: uses ftp over TLS. + # ftpes: is less secure than ftps: and should only be used for hosts with self-signed certificates. # You can also user WebDAV over HTTPS as transport mechanism. To do so, start with davs: followed by username, # password, host, port (explicitly needed even if using default port 443) and path on the server. # Multiple locations can be defined for a file by separating the locations with a semi-colon. @@ -2465,7 +2472,7 @@ write_domain_template() { # write out a template file for a domain. # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' # 'ftp:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge' # 'davs:davsuserid:davspassword:{DOMAIN}:443:/web/.well-known/acme-challenge' - # 'ftpes:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge') + # 'ftps:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge') # Specify SSH options, e.g. non standard port in SSH_OPTS # (Can also use SCP_OPTS and SFTP_OPTS) From 8070d45ad402037f5945dff375af19b031155463 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Tue, 27 Jul 2021 19:01:35 -0400 Subject: [PATCH 266/308] Apply suggestions Co-authored-by: Tim Kimber --- getssl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/getssl b/getssl index e86a1d3..7c034c4 100755 --- a/getssl +++ b/getssl @@ -264,8 +264,8 @@ # 2021-07-12 Do not redirect outputs on remote commands when the debug option is used (atisne) # 2021-07-20 Use +noidnout to enable certificates for IDN domains (#679)(2.37) # 2021-07-22 Only pass +noidnout param to dig/drill(#682)(2.38) -# 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension -# 2021-07-27 Provide ftps:// copy which verifies remote TLS certificates (vs. ftpes:// which is insecure) (2.39) +# 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension (tlhackque)(#686) +# 2021-07-27 Support ftps://, FTPS_OPTIONS, remove default --insecure parameter to ftpes (tlhackque)(#687)(2.39) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -956,7 +956,8 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. if [[ "${to:0:5}" == "ftps:" ]] ; then curl --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" else - curl --insecure --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" + # shellcheck disable=SC2086 + curl $FTPS_OPTIONS --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" fi else if ! mkdir -p "$(dirname "$to")" ; then @@ -2462,8 +2463,8 @@ write_domain_template() { # write out a template file for a domain. # If these start with ftp:/ftpes:/ftps: 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. - # ftp: uses regular ftp; ftpes: uses ftp over TLS but DOES NOT verify the remote certificates; ftps: uses ftp over TLS. - # ftpes: is less secure than ftps: and should only be used for hosts with self-signed certificates. + # ftp: uses regular ftp; ftpes: ftp over explicit TLS (port 21); ftps: ftp over implicit TLS (port 990). + # ftps/ftpes support FTPS_OPTIONS, e.g. to add "--insecure" to the curl command for hosts with self-signed certificates. # You can also user WebDAV over HTTPS as transport mechanism. To do so, start with davs: followed by username, # password, host, port (explicitly needed even if using default port 443) and path on the server. # Multiple locations can be defined for a file by separating the locations with a semi-colon. @@ -2472,7 +2473,8 @@ write_domain_template() { # write out a template file for a domain. # 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge' # 'ftp:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge' # 'davs:davsuserid:davspassword:{DOMAIN}:443:/web/.well-known/acme-challenge' - # 'ftps:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge') + # 'ftps:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge' + # 'ftpes:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge') # Specify SSH options, e.g. non standard port in SSH_OPTS # (Can also use SCP_OPTS and SFTP_OPTS) From b8f943b88bf8c4967b22605b88ec49dc755d3705 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Tue, 27 Jul 2021 19:05:29 -0400 Subject: [PATCH 267/308] Missed part of suggested change in batch Co-authored-by: Tim Kimber --- getssl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 7c034c4..01638fe 100755 --- a/getssl +++ b/getssl @@ -954,7 +954,8 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. debug "ftp user=$ftpuser - pass=$ftppass - host=$ftphost dir=$ftpdirn file=$ftpfile" debug "from dir=$fromdir file=$fromfile" if [[ "${to:0:5}" == "ftps:" ]] ; then - curl --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" + # shellcheck disable=SC2086 + curl $FTPS_OPTIONS --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}:990/" else # shellcheck disable=SC2086 curl $FTPS_OPTIONS --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" From 830148e419564d5fd394af0b87cec660ee6415c0 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Tue, 27 Jul 2021 19:08:07 -0400 Subject: [PATCH 268/308] Ensure that ftpes: and ftps: use TLS Prevent fallback to insecure when a secure protocol is requested. --- getssl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 01638fe..2002d91 100755 --- a/getssl +++ b/getssl @@ -955,10 +955,10 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. debug "from dir=$fromdir file=$fromfile" if [[ "${to:0:5}" == "ftps:" ]] ; then # shellcheck disable=SC2086 - curl $FTPS_OPTIONS --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}:990/" + curl $FTPS_OPTIONS --ftp-ssl --ftp-ssl-reqd -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}:990/" else # shellcheck disable=SC2086 - curl $FTPS_OPTIONS --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" + curl $FTPS_OPTIONS --ftp-ssl --ftp-ssl-reqd -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" fi else if ! mkdir -p "$(dirname "$to")" ; then From 3bc4a80a8939cb4ba09969fa1fd43a1f821e0b5a Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Tue, 27 Jul 2021 19:14:23 -0400 Subject: [PATCH 269/308] Lint: FTPS_OPTIONS not defined in revised FTP update --- getssl | 1 + 1 file changed, 1 insertion(+) diff --git a/getssl b/getssl index 2002d91..9f8486f 100755 --- a/getssl +++ b/getssl @@ -292,6 +292,7 @@ DEFAULT_REVOKE_CA="https://acme-v02.api.letsencrypt.org" DOMAIN_KEY_LENGTH=4096 DUAL_RSA_ECDSA="false" FTP_OPTIONS="" +FTPS_OPTIONS="" FULL_CHAIN_INCLUDE_ROOT="false" GETSSL_IGNORE_CP_PRESERVE="false" HTTP_TOKEN_CHECK_WAIT=0 From f245e9a5f5f47ceed309c5ca100e621a4703b00e Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 28 Jul 2021 05:26:24 -0400 Subject: [PATCH 270/308] Document use of --insecure when verifying HTTP-01 tokens --insecure is almost always a bad idea. In this case, it is required for compatibility with Let's Encrypt. Replace the less obvious '-k' with '--insecure' in the cURL command, and document why it is used in the comments, --- getssl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 9f8486f..a83fe77 100755 --- a/getssl +++ b/getssl @@ -1371,7 +1371,10 @@ for d in "${alldomains[@]}"; do else sleep "$HTTP_TOKEN_CHECK_WAIT" # check that we can reach the challenge ourselves, if not, then error - if [[ ! "$(curl --user-agent "$CURL_USERAGENT" -k --silent --location "$wellknown_url")" == "$keyauthorization" ]]; then + # ACME only allows port 80 (http), but redirects may use https. --insecure is used in case + # those certificates are being renewed. Let's Encrypt does the same. In this case, we verify + # that the correct data is returned, so this is safe. + if [[ ! "$(curl --user-agent "$CURL_USERAGENT" --insecure --silent --location "$wellknown_url")" == "$keyauthorization" ]]; then error_exit "for some reason could not reach $wellknown_url - please check it manually" fi fi From 519aafdce5883bc8d30bd7aec476a25a4a2f6030 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 28 Jul 2021 05:47:59 -0400 Subject: [PATCH 271/308] Report caller of error_exit in debug and test modes debug() does this, but the automated tests aren't run with -d. This also ensures that there is a breadcrumb if error_exit is called without a preceding debug(). It's really hard to follow the breadcrumbs for debug when there aren't any. --- getssl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index a83fe77..1a1cbea 100755 --- a/getssl +++ b/getssl @@ -265,7 +265,7 @@ # 2021-07-20 Use +noidnout to enable certificates for IDN domains (#679)(2.37) # 2021-07-22 Only pass +noidnout param to dig/drill(#682)(2.38) # 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension (tlhackque)(#686) -# 2021-07-27 Support ftps://, FTPS_OPTIONS, remove default --insecure parameter to ftpes (tlhackque)(#687)(2.39) +# 2021-07-27 Support ftps://, FTPS_OPTIONS, remove default --insecure parameter to ftpes. Report caller of error_exit in debug and test modes (tlhackque)(#687)(2.39) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -1160,6 +1160,9 @@ test_output() { # write out debug output for testing error_exit() { # give error message on error exit echo -e "${PROGNAME}: ${1:-"Unknown Error"}" >&2 + if [[ ${_RUNNING_TEST} -eq 1 ]] || [[ ${_USE_DEBUG} -eq 1 ]] ; then + echo " from ${FUNCNAME[1]}:${BASH_LINENO[1]}" >&2 + fi clean_up exit 1 } From 23b670d50ac90cb4fd601a5c5bddfc2b1cf828b8 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 28 Jul 2021 11:58:45 -0400 Subject: [PATCH 272/308] Provide traceback on error exit when debugging or running tests More breadcrumbs. --- getssl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 1a1cbea..6343655 100755 --- a/getssl +++ b/getssl @@ -265,7 +265,7 @@ # 2021-07-20 Use +noidnout to enable certificates for IDN domains (#679)(2.37) # 2021-07-22 Only pass +noidnout param to dig/drill(#682)(2.38) # 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension (tlhackque)(#686) -# 2021-07-27 Support ftps://, FTPS_OPTIONS, remove default --insecure parameter to ftpes. Report caller of error_exit in debug and test modes (tlhackque)(#687)(2.39) +# 2021-07-27 Support ftps://, FTPS_OPTIONS, remove default --insecure parameter to ftpes. Report caller(s) of error_exit in debug and test modes (tlhackque)(#687)(2.39) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -1161,7 +1161,7 @@ test_output() { # write out debug output for testing error_exit() { # give error message on error exit echo -e "${PROGNAME}: ${1:-"Unknown Error"}" >&2 if [[ ${_RUNNING_TEST} -eq 1 ]] || [[ ${_USE_DEBUG} -eq 1 ]] ; then - echo " from ${FUNCNAME[1]}:${BASH_LINENO[1]}" >&2 + traceback fi clean_up exit 1 @@ -2413,6 +2413,16 @@ signal_exit() { # Handle trapped signals esac } +traceback() { # Print function traceback + local i d=1 lbl=" called" + echo "Traceback" >&2 + for ((i=$((${#FUNCNAME[@]}-1)); i>0; i--)); do + if [[ ${i} -eq 1 ]] ; then lbl=" called traceback" ; fi + printf "%*s%s() line %d%s\n" "$d" '' "${FUNCNAME[$i]}" "${BASH_LINENO[$((i-1))]}" "$lbl" >&2 + ((d++)) + done +} + urlbase64() { # urlbase64: base64 encoded string with '+' replaced with '-' and '/' replaced with '_' openssl base64 -e | tr -d '\n\r' | os_esed -e 's:=*$::g' -e 'y:+/:-_:' } From 5a6f3e318d5413e62a75659a1587216d23806dc2 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Fri, 30 Jul 2021 05:38:42 -0400 Subject: [PATCH 273/308] Prefer API V2 when both offered in a single directory This doesn't happen with Let'sEncrypt, but it does with at least one other CA. The ACME spec allows it. --- getssl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/getssl b/getssl index 6343655..b77cf07 100755 --- a/getssl +++ b/getssl @@ -266,6 +266,7 @@ # 2021-07-22 Only pass +noidnout param to dig/drill(#682)(2.38) # 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension (tlhackque)(#686) # 2021-07-27 Support ftps://, FTPS_OPTIONS, remove default --insecure parameter to ftpes. Report caller(s) of error_exit in debug and test modes (tlhackque)(#687)(2.39) +# 2021-07-30 Prefer API V2 when both offered (tlhackque) (#690) (2.40) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -274,7 +275,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.39" +VERSION="2.40" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -2072,10 +2073,11 @@ obtain_ca_resource_locations() fi done - if [[ -n "$URL_new_reg" ]]; then - API=1 - elif [[ -n "$URL_newAccount" ]]; then + # If a directory offers both versions, select V2. + if [[ -n "$URL_newAccount" ]]; then API=2 + elif [[ -n "$URL_new_reg" ]]; then + API=1 else error_exit "unknown API version" fi From 4447f4ec47c01fd7a83b387f11f2a6621fbcff08 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Sat, 31 Jul 2021 07:00:37 -0400 Subject: [PATCH 274/308] Run tests in debug mode, use fork's repo for upgraded The test harness will suppress output unless an error occurs. Upgrade testing was failing in forked repos CI because the source repo was hard-coded. Use the CI environment to use the fork's repo. --- getssl | 35 +++++++++++++++++++++++++---------- test/32-test-upgrade.bats | 7 ++++++- test/run-test.sh | 1 + test/test_helper.bash | 6 +++--- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/getssl b/getssl index b77cf07..f0a289c 100755 --- a/getssl +++ b/getssl @@ -267,6 +267,7 @@ # 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension (tlhackque)(#686) # 2021-07-27 Support ftps://, FTPS_OPTIONS, remove default --insecure parameter to ftpes. Report caller(s) of error_exit in debug and test modes (tlhackque)(#687)(2.39) # 2021-07-30 Prefer API V2 when both offered (tlhackque) (#690) (2.40) +# 2021-07-30 Run tests with -d to catch intermittent failures, Use fork's repo for upgrade tests. (tlhackque) (#692) (2.41) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -275,7 +276,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.40" +VERSION="2.41" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -285,7 +286,11 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" CHALLENGE_CHECK_TYPE="http" CHECK_REMOTE_WAIT=0 CHECK_REMOTE="true" -CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" +if [[ -n "${GITHUB_REPOSITORY}" ]] ; then + CODE_LOCATION="https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/master/getssl" +else + CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" +fi CSR_SUBJECT="/" CURL_USERAGENT="${PROGNAME}/${VERSION}" DEACTIVATE_AUTH="false" @@ -1798,7 +1803,7 @@ get_signing_params() { # get signing parameters from key } graceful_exit() { # normal exit function. - exit_code=$1 + exit_code="${1-0}" clean_up # shellcheck disable=SC2086 exit $exit_code @@ -2415,14 +2420,18 @@ signal_exit() { # Handle trapped signals esac } +test_setup() { # setup for running test + _USE_DEBUG=1 +} + traceback() { # Print function traceback - local i d=1 lbl=" called" - echo "Traceback" >&2 - for ((i=$((${#FUNCNAME[@]}-1)); i>0; i--)); do - if [[ ${i} -eq 1 ]] ; then lbl=" called traceback" ; fi - printf "%*s%s() line %d%s\n" "$d" '' "${FUNCNAME[$i]}" "${BASH_LINENO[$((i-1))]}" "$lbl" >&2 - ((d++)) - done + local i d=1 lbl=" called" + debug "Traceback" + for ((i=$((${#FUNCNAME[@]}-1)); i>0; i--)); do + if [[ ${i} -eq 1 ]] ; then lbl=" called traceback" ; fi + debug "$(printf "%*s%s() line %d%s\n" "$d" '' "${FUNCNAME[$i]}" "${BASH_LINENO[$((i-1))]}" "$lbl")" + ((d++)) + done } urlbase64() { # urlbase64: base64 encoded string with '+' replaced with '-' and '/' replaced with '_' @@ -2627,6 +2636,12 @@ write_openssl_conf() { # write out a minimal openssl conf trap "signal_exit TERM" TERM HUP trap "signal_exit INT" INT +# When running tests, use debug mode to capture intermittent faults +# Test harness will Save output in a temporary file, which is displayed if an error occurs +if [[ ${_RUNNING_TEST} -eq 1 ]] ; then + test_setup +fi + # Parse command-line while [[ -n ${1+defined} ]]; do case $1 in diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index f8fc68a..48edf85 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -11,7 +11,12 @@ setup() { # Turn off warning about detached head git config --global advice.detachedHead false - run git clone https://github.com/srvrco/getssl.git "$INSTALL_DIR/upgrade-getssl" + if [[ -n "${GITHUB_REPOSITORY}" ]] ; then + _REPO="https://github.com/${GITHUB_REPOSITORY}.git" + else + _REPO="https://github.com/srvrco/getssl.git" + fi + run git clone "${_REPO}" "$INSTALL_DIR/upgrade-getssl" # Don't do version arithmetics any longer, look what was the previous version by getting the last # line (starting with v) and the one before that from the list of tags. diff --git a/test/run-test.sh b/test/run-test.sh index c3852ef..76a7555 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -37,6 +37,7 @@ docker run \ --env GETSSL_HOST=$ALIAS $STAGING \ --env GETSSL_IDN_HOST=$GETSSL_IDN_HOST \ --env GETSSL_OS=$GETSSL_OS \ + --env GITHUB_REPOSITORY="${GITHUB_REPOSITORY}" \ -v "$(pwd)":/getssl \ --rm \ --network ${PWD##*/}_acmenet \ diff --git a/test/test_helper.bash b/test/test_helper.bash index ea71967..0827adf 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -25,7 +25,7 @@ check_nginx() { check_output_for_errors() { refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' # less strict tests if running with debug output - if [ -n "$1" ]; then + if [ -n "X$1" ]; then # don't fail for :error:badNonce refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' # don't check for "Warnings:" as there might be a warning message if nslookup doesn't support -debug (alpine/ubuntu) @@ -47,12 +47,12 @@ create_certificate() { # Create certificate cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" # shellcheck disable=SC2086 - run ${CODE_DIR}/getssl "$@" "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -d "$@" "$GETSSL_CMD_HOST" } init_getssl() { # Run initialisation (create account key, etc) - run ${CODE_DIR}/getssl -c "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -d -c "$GETSSL_CMD_HOST" assert_success [ -d "$INSTALL_DIR/.getssl" ] } From ea831390aa9740b7c0813456301eff36e54dd679 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Sat, 31 Jul 2021 08:22:59 -0400 Subject: [PATCH 275/308] Skip all tests after first failure From https://github.com/sstephenson/bats/issues/135 via @timkimber --- test/1-simple-http01-dig.bats | 2 ++ test/1-simple-http01-nslookup.bats | 2 ++ test/1-simple-http01-two-acl.bats | 5 +++ test/1-simple-http01.bats | 5 +++ test/10-mixed-case.bats | 5 +++ test/11-test--install.bats | 5 +++ test/11-test-no-domain-storage.bats | 7 ++++ test/12-auto-upgrade-v1.bats | 35 +++++++++++++++++++ test/13-notify-valid.bats | 5 +++ test/14-test-revoke.bats | 5 +++ test/15-test-revoke-no-suffix.bats | 5 +++ test/16-test-bad-acl.bats | 5 +++ test/17-test-spaces-in-sans-dns01.bats | 5 +++ test/17-test-spaces-in-sans-http01.bats | 5 +++ test/18-retry-dns-add.bats | 5 +++ test/19-test-add-to-sans.bats | 2 ++ test/2-simple-dns01-dig.bats | 14 ++++++++ test/2-simple-dns01-nslookup.bats | 2 ++ test/20-wildcard-simple.bats | 5 +++ test/21-wildcard-dual-rsa.bats | 5 +++ ...dcard-dual-rsa-ecdsa-copy-2-locations.bats | 5 +++ test/23-wildcard-check-globbing.bats | 5 +++ test/24-wildcard-sans.bats | 2 ++ test/25-wildcard-all.bats | 5 +++ test/26-wildcard-revoke.bats | 5 +++ test/27-wildcard-existing-cert.bats | 5 +++ test/28-wildcard-error-http01-validation.bats | 5 +++ test/29-check-mktemp-failure.bats | 5 +++ test/3-dual-rsa-ecdsa.bats | 5 +++ test/30-handle-dig-failure.bats | 2 ++ test/31-test-posix-error.bats | 5 +++ test/32-test-upgrade.bats | 2 ++ test/33-ftp.bats | 2 ++ test/34-ftp-passive.bats | 2 ++ test/35-preferred-chain.bats | 5 +++ test/36-full-chain-inc-root.bats | 5 +++ test/37-idn.bats | 2 ++ test/38-idn-http01-check-noidnout.bats | 5 +++ test/4-more-than-10-hosts.bats | 5 +++ test/5-secp384-http01.bats | 5 +++ test/6-dual-rsa-ecdsa-copy-2-locations.bats | 2 ++ test/7-test-renewal.bats | 2 ++ test/8-staging-ecdsa.bats | 28 +++++++++++++++ test/9-multiple-domains-dns01.bats | 5 +++ test/9-test--all.bats | 5 +++ test/u1-test-get_auth_dns-dig.bats | 2 ++ test/u2-test-get_auth_dns-drill.bats | 2 ++ test/u3-mktemp-template.bats | 7 ++++ test/u4-create-csr-and-ifs.bats | 5 +++ .../u5-test-get_auth_dns-no-root-servers.bats | 2 ++ 50 files changed, 271 insertions(+) diff --git a/test/1-simple-http01-dig.bats b/test/1-simple-http01-dig.bats index be01f27..b3c36cc 100644 --- a/test/1-simple-http01-dig.bats +++ b/test/1-simple-http01-dig.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -f /usr/bin/host ]; then mv /usr/bin/host /usr/bin/host.getssl.bak @@ -18,6 +19,7 @@ setup() { teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -f /usr/bin/host.getssl.bak ]; then mv /usr/bin/host.getssl.bak /usr/bin/host fi diff --git a/test/1-simple-http01-nslookup.bats b/test/1-simple-http01-nslookup.bats index 78d175a..65c3669 100644 --- a/test/1-simple-http01-nslookup.bats +++ b/test/1-simple-http01-nslookup.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -f /usr/bin/dig ]; then mv /usr/bin/dig /usr/bin/dig.getssl.bak @@ -18,6 +19,7 @@ setup() { teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -f /usr/bin/dig.getssl.bak ]; then mv /usr/bin/dig.getssl.bak /usr/bin/dig fi diff --git a/test/1-simple-http01-two-acl.bats b/test/1-simple-http01-two-acl.bats index 0169bd0..5a09f60 100644 --- a/test/1-simple-http01-two-acl.bats +++ b/test/1-simple-http01-two-acl.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/1-simple-http01.bats b/test/1-simple-http01.bats index a57010b..543d29b 100644 --- a/test/1-simple-http01.bats +++ b/test/1-simple-http01.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/10-mixed-case.bats b/test/10-mixed-case.bats index 974f669..9ec0e35 100644 --- a/test/10-mixed-case.bats +++ b/test/10-mixed-case.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/11-test--install.bats b/test/11-test--install.bats index e034326..0d015ee 100644 --- a/test/11-test--install.bats +++ b/test/11-test--install.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/11-test-no-domain-storage.bats b/test/11-test-no-domain-storage.bats index 3be0be5..92cade4 100644 --- a/test/11-test-no-domain-storage.bats +++ b/test/11-test-no-domain-storage.bats @@ -5,6 +5,13 @@ load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Check that if domain storage isn't set getssl doesn't try to delete /tmp" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" diff --git a/test/12-auto-upgrade-v1.bats b/test/12-auto-upgrade-v1.bats index 4165cd3..b63acfb 100644 --- a/test/12-auto-upgrade-v1.bats +++ b/test/12-auto-upgrade-v1.bats @@ -5,6 +5,13 @@ load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Check that auto upgrade to v2 doesn't change pebble url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -19,6 +26,13 @@ load '/getssl/test/test_helper.bash' } +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Check that auto upgrade to v2 doesn't change v2 staging url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -33,6 +47,13 @@ load '/getssl/test/test_helper.bash' } +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Check that auto upgrade to v2 doesn't change v2 prod url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -47,6 +68,13 @@ load '/getssl/test/test_helper.bash' } +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Check that auto upgrade to v2 changes v1 staging to v2 staging url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -61,6 +89,13 @@ load '/getssl/test/test_helper.bash' } +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Check that auto upgrade to v2 changes v1 prod to v2 prod url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" diff --git a/test/13-notify-valid.bats b/test/13-notify-valid.bats index ac1a50c..199f165 100644 --- a/test/13-notify-valid.bats +++ b/test/13-notify-valid.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats index d31e832..86be2e2 100644 --- a/test/14-test-revoke.bats +++ b/test/14-test-revoke.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index 30802d8..d2272fc 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/16-test-bad-acl.bats b/test/16-test-bad-acl.bats index d953951..abf365c 100644 --- a/test/16-test-bad-acl.bats +++ b/test/16-test-bad-acl.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/17-test-spaces-in-sans-dns01.bats b/test/17-test-spaces-in-sans-dns01.bats index 9d425af..9eb2c32 100644 --- a/test/17-test-spaces-in-sans-dns01.bats +++ b/test/17-test-spaces-in-sans-dns01.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/17-test-spaces-in-sans-http01.bats b/test/17-test-spaces-in-sans-http01.bats index 1730e99..5fc4eb4 100644 --- a/test/17-test-spaces-in-sans-http01.bats +++ b/test/17-test-spaces-in-sans-http01.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/18-retry-dns-add.bats b/test/18-retry-dns-add.bats index 25318de..68e508f 100644 --- a/test/18-retry-dns-add.bats +++ b/test/18-retry-dns-add.bats @@ -5,7 +5,12 @@ load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats index a0a6d71..7f96929 100644 --- a/test/19-test-add-to-sans.bats +++ b/test/19-test-add-to-sans.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -14,6 +15,7 @@ setup() { } teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a fi diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index a0d70a2..e62e903 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -28,6 +28,13 @@ teardown_file() { } +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Create new certificate using DNS-01 verification (dig)" { CONFIG_FILE="getssl-dns01.cfg" @@ -40,6 +47,13 @@ teardown_file() { } +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Force renewal of certificate using DNS-01 (dig)" { run ${CODE_DIR}/getssl -d -f $GETSSL_HOST assert_success diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index f97b5dc..8ff465d 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi @@ -20,6 +21,7 @@ setup() { teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -f /usr/bin/dig.getssl.bak ]; then mv /usr/bin/dig.getssl.bak /usr/bin/dig fi diff --git a/test/20-wildcard-simple.bats b/test/20-wildcard-simple.bats index b56a876..e68810b 100644 --- a/test/20-wildcard-simple.bats +++ b/test/20-wildcard-simple.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/21-wildcard-dual-rsa.bats b/test/21-wildcard-dual-rsa.bats index 550bbe0..16a8d97 100644 --- a/test/21-wildcard-dual-rsa.bats +++ b/test/21-wildcard-dual-rsa.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats index b005af5..e397ac8 100644 --- a/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # These are run for every test, not once per file +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/23-wildcard-check-globbing.bats b/test/23-wildcard-check-globbing.bats index 1c812b1..8566b88 100644 --- a/test/23-wildcard-check-globbing.bats +++ b/test/23-wildcard-check-globbing.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/24-wildcard-sans.bats b/test/24-wildcard-sans.bats index a9ca2a5..74a1e5e 100644 --- a/test/24-wildcard-sans.bats +++ b/test/24-wildcard-sans.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"wild-'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -15,6 +16,7 @@ setup() { teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"wild-'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a fi diff --git a/test/25-wildcard-all.bats b/test/25-wildcard-all.bats index 8e428ab..a9b0380 100644 --- a/test/25-wildcard-all.bats +++ b/test/25-wildcard-all.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/26-wildcard-revoke.bats b/test/26-wildcard-revoke.bats index 37f8f10..3be9bcd 100644 --- a/test/26-wildcard-revoke.bats +++ b/test/26-wildcard-revoke.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/27-wildcard-existing-cert.bats b/test/27-wildcard-existing-cert.bats index 76f2aa7..0c69389 100644 --- a/test/27-wildcard-existing-cert.bats +++ b/test/27-wildcard-existing-cert.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/28-wildcard-error-http01-validation.bats b/test/28-wildcard-error-http01-validation.bats index dbb64b7..bf8a7f2 100644 --- a/test/28-wildcard-error-http01-validation.bats +++ b/test/28-wildcard-error-http01-validation.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/29-check-mktemp-failure.bats b/test/29-check-mktemp-failure.bats index 782dc64..9fcd710 100644 --- a/test/29-check-mktemp-failure.bats +++ b/test/29-check-mktemp-failure.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/3-dual-rsa-ecdsa.bats b/test/3-dual-rsa-ecdsa.bats index 87527c2..c4c06e8 100644 --- a/test/3-dual-rsa-ecdsa.bats +++ b/test/3-dual-rsa-ecdsa.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/30-handle-dig-failure.bats b/test/30-handle-dig-failure.bats index 1102745..6ea5803 100644 --- a/test/30-handle-dig-failure.bats +++ b/test/30-handle-dig-failure.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -f /usr/bin/drill ]; then mv /usr/bin/drill /usr/bin/drill.getssl.bak @@ -18,6 +19,7 @@ setup() { teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -f /usr/bin/drill.getssl.bak ]; then mv /usr/bin/drill.getssl.bak /usr/bin/drill fi diff --git a/test/31-test-posix-error.bats b/test/31-test-posix-error.bats index e9950fd..37d7074 100644 --- a/test/31-test-posix-error.bats +++ b/test/31-test-posix-error.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index 48edf85..77ad362 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt # Turn off warning about detached head @@ -32,6 +33,7 @@ setup() { teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip rm -r "$INSTALL_DIR/upgrade-getssl" } diff --git a/test/33-ftp.bats b/test/33-ftp.bats index 9c2e387..1131967 100644 --- a/test/33-ftp.bats +++ b/test/33-ftp.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -n "${VSFTPD_CONF}" ]; then cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl @@ -23,6 +24,7 @@ _FTP teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -n "${VSFTPD_CONF}" ]; then cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF ${CODE_DIR}/test/restart-ftpd diff --git a/test/34-ftp-passive.bats b/test/34-ftp-passive.bats index 0d16574..b53223d 100644 --- a/test/34-ftp-passive.bats +++ b/test/34-ftp-passive.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -n "${VSFTPD_CONF}" ]; then cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl @@ -26,6 +27,7 @@ _FTP teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -n "${VSFTPD_CONF}" ]; then cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF ${CODE_DIR}/test/restart-ftpd diff --git a/test/35-preferred-chain.bats b/test/35-preferred-chain.bats index 9c3fc6b..6995925 100644 --- a/test/35-preferred-chain.bats +++ b/test/35-preferred-chain.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/36-full-chain-inc-root.bats b/test/36-full-chain-inc-root.bats index 5b29d0b..1fed1ba 100644 --- a/test/36-full-chain-inc-root.bats +++ b/test/36-full-chain-inc-root.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/37-idn.bats b/test/37-idn.bats index be624de..04e26fd 100644 --- a/test/37-idn.bats +++ b/test/37-idn.bats @@ -13,6 +13,7 @@ setup_file() { # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" GETSSL_CMD_HOST=${GETSSL_IDN_HOST} # use the test description to move tools we don't want to test out of the way @@ -26,6 +27,7 @@ setup() { } teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip # use the test description to move tools we didn't want to test back DNS_TOOL=${BATS_TEST_DESCRIPTION##*-} for tool in dig drill host nslookup diff --git a/test/38-idn-http01-check-noidnout.bats b/test/38-idn-http01-check-noidnout.bats index fde4fe6..032bc2d 100644 --- a/test/38-idn-http01-check-noidnout.bats +++ b/test/38-idn-http01-check-noidnout.bats @@ -11,7 +11,12 @@ setup_file() { fi } +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" GETSSL_CMD_HOST=$GETSSL_IDN_HOST } diff --git a/test/4-more-than-10-hosts.bats b/test/4-more-than-10-hosts.bats index f4eb95c..2343cc4 100644 --- a/test/4-more-than-10-hosts.bats +++ b/test/4-more-than-10-hosts.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/5-secp384-http01.bats b/test/5-secp384-http01.bats index 3d05159..7e478dc 100644 --- a/test/5-secp384-http01.bats +++ b/test/5-secp384-http01.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/6-dual-rsa-ecdsa-copy-2-locations.bats b/test/6-dual-rsa-ecdsa-copy-2-locations.bats index 6f75f25..93c3349 100644 --- a/test/6-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/6-dual-rsa-ecdsa-copy-2-locations.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # These are run for every test, not once per file setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -15,6 +16,7 @@ setup() { teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a fi diff --git a/test/7-test-renewal.bats b/test/7-test-renewal.bats index 074f882..ceb2966 100644 --- a/test/7-test-renewal.bats +++ b/test/7-test-renewal.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -15,6 +16,7 @@ setup() { } teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a diff --git a/test/8-staging-ecdsa.bats b/test/8-staging-ecdsa.bats index 6aebd60..f3cf611 100644 --- a/test/8-staging-ecdsa.bats +++ b/test/8-staging-ecdsa.bats @@ -7,6 +7,13 @@ load '/getssl/test/test_helper.bash' +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Create new certificate using staging server and prime256v1" { if [ -z "$STAGING" ]; then skip "Running external tests, skipping internal testing" @@ -22,6 +29,13 @@ load '/getssl/test/test_helper.bash' } +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Force renewal of certificate using staging server and prime256v1" { if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" @@ -33,6 +47,13 @@ load '/getssl/test/test_helper.bash' } +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Create new certificate using staging server and secp384r1" { if [ -z "$STAGING" ]; then skip "Running external tests, skipping internal testing" @@ -48,6 +69,13 @@ load '/getssl/test/test_helper.bash' } +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Force renewal of certificate using staging server and secp384r1" { if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" diff --git a/test/9-multiple-domains-dns01.bats b/test/9-multiple-domains-dns01.bats index 65eab09..af6e059 100644 --- a/test/9-multiple-domains-dns01.bats +++ b/test/9-multiple-domains-dns01.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/9-test--all.bats b/test/9-test--all.bats index cb043a5..f3520c0 100644 --- a/test/9-test--all.bats +++ b/test/9-test--all.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt export PATH=$PATH:/getssl } diff --git a/test/u1-test-get_auth_dns-dig.bats b/test/u1-test-get_auth_dns-dig.bats index ac11c1d..05ec0b7 100644 --- a/test/u1-test-get_auth_dns-dig.bats +++ b/test/u1-test-get_auth_dns-dig.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" for app in drill host nslookup do if [ -f /usr/bin/${app} ]; then @@ -22,6 +23,7 @@ setup() { teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip for app in drill host nslookup do if [ -f /usr/bin/${app}.getssl.bak ]; then diff --git a/test/u2-test-get_auth_dns-drill.bats b/test/u2-test-get_auth_dns-drill.bats index d20079c..ce0fe88 100644 --- a/test/u2-test-get_auth_dns-drill.bats +++ b/test/u2-test-get_auth_dns-drill.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" for app in dig host nslookup do if [ -f /usr/bin/${app} ]; then @@ -22,6 +23,7 @@ setup() { teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip for app in dig host nslookup do if [ -f /usr/bin/${app}.getssl.bak ]; then diff --git a/test/u3-mktemp-template.bats b/test/u3-mktemp-template.bats index 2cb8040..968e0db 100644 --- a/test/u3-mktemp-template.bats +++ b/test/u3-mktemp-template.bats @@ -5,6 +5,13 @@ load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' +setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" +} +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + @test "Check mktemp -t getssl.XXXXXX works on all platforms" { run mktemp -t getssl.XXXXXX assert_success diff --git a/test/u4-create-csr-and-ifs.bats b/test/u4-create-csr-and-ifs.bats index 344a536..528394d 100644 --- a/test/u4-create-csr-and-ifs.bats +++ b/test/u4-create-csr-and-ifs.bats @@ -6,7 +6,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip +} + setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" . /getssl/getssl --source find_dns_utils _RUNNING_TEST=1 diff --git a/test/u5-test-get_auth_dns-no-root-servers.bats b/test/u5-test-get_auth_dns-no-root-servers.bats index d218eb9..ab0f846 100644 --- a/test/u5-test-get_auth_dns-no-root-servers.bats +++ b/test/u5-test-get_auth_dns-no-root-servers.bats @@ -7,6 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { + [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" cp /etc/resolv.conf /etc/resolv.conf.getssl cat <<- EOF > /etc/resolv.conf nameserver 8.8.8.8 @@ -28,6 +29,7 @@ EOF teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip cat /etc/resolv.conf.getssl > /etc/resolv.conf for app in drill host nslookup do From d91516735fe412f0bfd32a07178d7c90ccf0c8fe Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Sat, 31 Jul 2021 09:52:32 -0400 Subject: [PATCH 276/308] Make first fail global & improve diagnostics The first fail logic seems scoped to a single test file. Set the flag globally. Since the tests run in a container, cleanup is automagic. Various test tweaks to allow for skipping tests & null strings. --- getssl | 54 +++++++++++-------- test/1-simple-http01-dig.bats | 4 +- test/1-simple-http01-nslookup.bats | 4 +- test/1-simple-http01-two-acl.bats | 4 +- test/1-simple-http01.bats | 4 +- test/10-mixed-case.bats | 4 +- test/11-test--install.bats | 4 +- test/11-test-no-domain-storage.bats | 4 +- test/12-auto-upgrade-v1.bats | 20 +++---- test/13-notify-valid.bats | 4 +- test/14-test-revoke.bats | 4 +- test/15-test-revoke-no-suffix.bats | 4 +- test/16-test-bad-acl.bats | 4 +- test/17-test-spaces-in-sans-dns01.bats | 4 +- test/17-test-spaces-in-sans-http01.bats | 5 +- test/18-retry-dns-add.bats | 4 +- test/19-test-add-to-sans.bats | 4 +- test/2-simple-dns01-dig.bats | 8 +-- test/2-simple-dns01-nslookup.bats | 4 +- test/20-wildcard-simple.bats | 4 +- test/21-wildcard-dual-rsa.bats | 4 +- ...dcard-dual-rsa-ecdsa-copy-2-locations.bats | 4 +- test/23-wildcard-check-globbing.bats | 4 +- test/24-wildcard-sans.bats | 4 +- test/25-wildcard-all.bats | 4 +- test/26-wildcard-revoke.bats | 4 +- test/27-wildcard-existing-cert.bats | 4 +- test/28-wildcard-error-http01-validation.bats | 4 +- test/29-check-mktemp-failure.bats | 4 +- test/3-dual-rsa-ecdsa.bats | 4 +- test/30-handle-dig-failure.bats | 4 +- test/31-test-posix-error.bats | 4 +- test/32-test-upgrade.bats | 7 +-- test/33-ftp.bats | 4 +- test/34-ftp-passive.bats | 4 +- test/35-preferred-chain.bats | 4 +- test/36-full-chain-inc-root.bats | 4 +- test/37-idn.bats | 4 +- test/38-idn-http01-check-noidnout.bats | 4 +- test/4-more-than-10-hosts.bats | 4 +- test/5-secp384-http01.bats | 4 +- test/6-dual-rsa-ecdsa-copy-2-locations.bats | 4 +- test/7-test-renewal.bats | 4 +- test/8-staging-ecdsa.bats | 16 +++--- test/9-multiple-domains-dns01.bats | 4 +- test/9-test--all.bats | 4 +- test/dns_add_fail | 2 +- test/u1-test-get_auth_dns-dig.bats | 4 +- test/u2-test-get_auth_dns-drill.bats | 4 +- test/u3-mktemp-template.bats | 4 +- test/u4-create-csr-and-ifs.bats | 4 +- .../u5-test-get_auth_dns-no-root-servers.bats | 4 +- 52 files changed, 151 insertions(+), 141 deletions(-) diff --git a/getssl b/getssl index f0a289c..3576591 100755 --- a/getssl +++ b/getssl @@ -340,6 +340,7 @@ _FORCE_RENEW=0 _KEEP_VERSIONS="" _MUTE=0 _NOTIFY_VALID=0 +_NOMETER="" _QUIET=0 _RECREATE_CSR=0 _REDIRECT_OUTPUT="1>/dev/null 2>&1" @@ -568,7 +569,7 @@ check_challenge_completion_dns() { # perform validation via DNS challenge check_result=$($DNS_CHECK_FUNC $DNS_CHECK_OPTIONS TXT "${rr}" "@${ns}" \ | grep -i "^${rr}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') - debug "check_result=$check_result" + debug "check_result=\"$check_result\"" if [[ -z "$check_result" ]]; then # shellcheck disable=SC2086 debug "$DNS_CHECK_FUNC" $DNS_CHECK_OPTIONS ANY "${rr}" "@${ns}" @@ -576,7 +577,7 @@ check_challenge_completion_dns() { # perform validation via DNS challenge check_result=$($DNS_CHECK_FUNC $DNS_CHECK_OPTIONS ANY "${rr}" "@${ns}" \ | grep -i "^${rr}" \ | grep 'IN\WTXT'|awk -F'"' '{ print $2}') - debug "check_result=$check_result" + debug "check_result=\"$check_result\"" fi elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then check_result=$($DNS_CHECK_FUNC -t TXT "${rr}" "${ns}" \ @@ -589,8 +590,8 @@ check_challenge_completion_dns() { # perform validation via DNS challenge | grep 'text ='|awk -F'"' '{ print $2}') fi fi - debug "expecting $auth_key" - debug "${ns} gave ... $check_result" + debug "expecting \"$auth_key\"" + debug "${ns} gave ... \"$check_result\"" if [[ "$check_result" == *"$auth_key"* ]]; then check_dns="success" @@ -612,7 +613,7 @@ check_challenge_completion_dns() { # perform validation via DNS challenge debug "dns check failed - removing existing value" del_dns_rr "${d}" "${auth_key}" - error_exit "checking ${rr} gave $check_result not $auth_key" + error_exit "checking \"${rr}\" gave \"$check_result\" not \"$auth_key\"" fi fi done @@ -764,7 +765,7 @@ check_getssl_upgrade() { # check if a more recent version of code is available a if [ "$TEMP_UPGRADE_FILE" == "" ]; then error_exit "mktemp failed" fi - curl --user-agent "$CURL_USERAGENT" --silent "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" + curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" errcode=$? if [[ $errcode -eq 60 ]]; then error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" @@ -947,7 +948,7 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. fromfile=$(basename "$from") debug "davs user=$davsuser - pass=$davspass - host=$davshost port=$davsport dir=$davsdirn file=$davsfile" debug "from dir=$fromdir file=$fromfile" - curl -u "${davsuser}:${davspass}" -T "${fromdir}/${fromfile}" "https://${davshost}:${davsport}${davsdirn}${davsfile}" + curl ${_NOMETER} -u "${davsuser}:${davspass}" -T "${fromdir}/${fromfile}" "https://${davshost}:${davsport}${davsdirn}${davsfile}" elif [[ "${to:0:6}" == "ftpes:" ]] || [[ "${to:0:5}" == "ftps:" ]] ; then debug "using ftp to copy the file from $from" ftpuser=$(echo "$to"| awk -F: '{print $2}') @@ -962,10 +963,10 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. debug "from dir=$fromdir file=$fromfile" if [[ "${to:0:5}" == "ftps:" ]] ; then # shellcheck disable=SC2086 - curl $FTPS_OPTIONS --ftp-ssl --ftp-ssl-reqd -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}:990/" + curl ${_NOMETER} $FTPS_OPTIONS --ftp-ssl --ftp-ssl-reqd -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}:990/" else # shellcheck disable=SC2086 - curl $FTPS_OPTIONS --ftp-ssl --ftp-ssl-reqd -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" + curl ${_NOMETER} $FTPS_OPTIONS --ftp-ssl --ftp-ssl-reqd -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/" fi else if ! mkdir -p "$(dirname "$to")" ; then @@ -1383,7 +1384,7 @@ for d in "${alldomains[@]}"; do # ACME only allows port 80 (http), but redirects may use https. --insecure is used in case # those certificates are being renewed. Let's Encrypt does the same. In this case, we verify # that the correct data is returned, so this is safe. - if [[ ! "$(curl --user-agent "$CURL_USERAGENT" --insecure --silent --location "$wellknown_url")" == "$keyauthorization" ]]; then + if [[ ! "$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --insecure --silent --location "$wellknown_url")" == "$keyauthorization" ]]; then error_exit "for some reason could not reach $wellknown_url - please check it manually" fi fi @@ -1627,7 +1628,7 @@ get_certificate() { # get certificate for csr, if all domains validated. CertData=$(awk ' $1 ~ "^Location" {print $2}' "$CURL_HEADER" |tr -d '\r') if [[ "$CertData" ]] ; then echo -----BEGIN CERTIFICATE----- > "$gc_certfile" - curl --user-agent "$CURL_USERAGENT" --silent "$CertData" | openssl base64 -e >> "$gc_certfile" + curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$CertData" | openssl base64 -e >> "$gc_certfile" echo -----END CERTIFICATE----- >> "$gc_certfile" info "Certificate saved in $CERT_FILE" fi @@ -1647,7 +1648,7 @@ get_certificate() { # get certificate for csr, if all domains validated. | sed 's/>//g') if [[ "$IssuerData" ]] ; then echo -----BEGIN CERTIFICATE----- > "$gc_cafile" - curl --user-agent "$CURL_USERAGENT" --silent "$IssuerData" | openssl base64 -e >> "$gc_cafile" + curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$IssuerData" | openssl base64 -e >> "$gc_cafile" echo -----END CERTIFICATE----- >> "$gc_cafile" info "The intermediate CA cert is in $gc_cafile" fi @@ -1705,7 +1706,7 @@ get_certificate() { # get certificate for csr, if all domains validated. cp "$gc_certfile" "$gc_fullchain" while [[ -n "$issuer_url" ]]; do debug Fetching certificate issuer from "$issuer_url" - issuer_cert=$(curl --user-agent "$CURL_USERAGENT" --silent "$issuer_url" | openssl x509 -inform der -outform pem) + issuer_cert=$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$issuer_url" | openssl x509 -inform der -outform pem) debug Fetched issuer certificate "$(echo "$issuer_cert" | openssl x509 -inform pem -noout -text | awk 'BEGIN {FS="Subject: "} NF==2 {print $2; exit}')" echo "$issuer_cert" >> "$gc_fullchain" @@ -1720,7 +1721,7 @@ get_certificate() { # get certificate for csr, if all domains validated. get_cr() { # get curl response url="$1" debug url "$url" - response=$(curl --user-agent "$CURL_USERAGENT" --silent "$url") + response=$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$url") ret=$? debug response "${response//[$'\t\r\n']}" code=$(json_get "$response" status) @@ -2061,7 +2062,7 @@ obtain_ca_resource_locations() for suffix in "" "/directory" "/dir"; do # Obtain CA resource locations - ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}${suffix}" 2>/dev/null) + ca_all_loc=$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" "${CA}${suffix}" 2>/dev/null) debug "ca_all_loc from ${CA}${suffix} gives $ca_all_loc" # APIv1 URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') @@ -2243,9 +2244,9 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p CURL_HEADER="$TEMP_DIR/curl.header" dp="$TEMP_DIR/curl.dump" - CURL="curl " + CURL="curl ${_NOMETER} " # shellcheck disable=SC2072 - if [[ "$($CURL -V | head -1 | cut -d' ' -f2 )" > "7.33" ]]; then + if [[ ! "$($CURL -V | head -1 | cut -d' ' -f2 )" < "7.33" ]]; then CURL="$CURL --http1.1 " fi @@ -2321,7 +2322,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p fi if [[ $errcode -gt 0 || ( "$response" == "" && $url != *"revoke"* ) ]]; then - error_exit "ERROR curl \"$url\" failed with $errcode and returned $response" + error_exit "ERROR curl \"$url\" failed with $errcode and returned \"$response\"" fi responseHeaders=$(cat "$CURL_HEADER") @@ -2420,10 +2421,6 @@ signal_exit() { # Handle trapped signals esac } -test_setup() { # setup for running test - _USE_DEBUG=1 -} - traceback() { # Print function traceback local i d=1 lbl=" called" debug "Traceback" @@ -2432,6 +2429,7 @@ traceback() { # Print function traceback debug "$(printf "%*s%s() line %d%s\n" "$d" '' "${FUNCNAME[$i]}" "${BASH_LINENO[$((i-1))]}" "$lbl")" ((d++)) done + return 0 } urlbase64() { # urlbase64: base64 encoded string with '+' replaced with '-' and '/' replaced with '_' @@ -2639,7 +2637,7 @@ trap "signal_exit INT" INT # When running tests, use debug mode to capture intermittent faults # Test harness will Save output in a temporary file, which is displayed if an error occurs if [[ ${_RUNNING_TEST} -eq 1 ]] ; then - test_setup + _USE_DEBUG=1 fi # Parse command-line @@ -2737,6 +2735,16 @@ requires sed requires sort requires mktemp +# Make sure cURL doesn't display a progress meter (if it's new enough) +# --silent also does this, but suppresses warnings and informational messages too. +# TODO: see where --silent can be removed (if _NOMETER defaults to --silent for old versions?) +# This would help with debugging transfer errors. + +# shellcheck disable=SC2072 +if [[ ! "$(curl -V | head -1 | cut -d' ' -f2 )" < "7.67" ]]; then + _NOMETER="--no-progress-meter" +fi + # Check if upgrades are available (unless they have specified -U to ignore Upgrade checks) if [[ $_UPGRADE_CHECK -eq 1 ]]; then check_getssl_upgrade diff --git a/test/1-simple-http01-dig.bats b/test/1-simple-http01-dig.bats index b3c36cc..6c29ec6 100644 --- a/test/1-simple-http01-dig.bats +++ b/test/1-simple-http01-dig.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -f /usr/bin/host ]; then mv /usr/bin/host /usr/bin/host.getssl.bak @@ -19,7 +19,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -f /usr/bin/host.getssl.bak ]; then mv /usr/bin/host.getssl.bak /usr/bin/host fi diff --git a/test/1-simple-http01-nslookup.bats b/test/1-simple-http01-nslookup.bats index 65c3669..aa71e1c 100644 --- a/test/1-simple-http01-nslookup.bats +++ b/test/1-simple-http01-nslookup.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -f /usr/bin/dig ]; then mv /usr/bin/dig /usr/bin/dig.getssl.bak @@ -19,7 +19,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -f /usr/bin/dig.getssl.bak ]; then mv /usr/bin/dig.getssl.bak /usr/bin/dig fi diff --git a/test/1-simple-http01-two-acl.bats b/test/1-simple-http01-two-acl.bats index 5a09f60..b4bb3f1 100644 --- a/test/1-simple-http01-two-acl.bats +++ b/test/1-simple-http01-two-acl.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/1-simple-http01.bats b/test/1-simple-http01.bats index 543d29b..518f734 100644 --- a/test/1-simple-http01.bats +++ b/test/1-simple-http01.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/10-mixed-case.bats b/test/10-mixed-case.bats index 9ec0e35..382f19a 100644 --- a/test/10-mixed-case.bats +++ b/test/10-mixed-case.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/11-test--install.bats b/test/11-test--install.bats index 0d015ee..1ab1ca4 100644 --- a/test/11-test--install.bats +++ b/test/11-test--install.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/11-test-no-domain-storage.bats b/test/11-test-no-domain-storage.bats index 92cade4..9ad4aa4 100644 --- a/test/11-test-no-domain-storage.bats +++ b/test/11-test-no-domain-storage.bats @@ -6,10 +6,10 @@ load '/getssl/test/test_helper.bash' setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Check that if domain storage isn't set getssl doesn't try to delete /tmp" { diff --git a/test/12-auto-upgrade-v1.bats b/test/12-auto-upgrade-v1.bats index b63acfb..7554561 100644 --- a/test/12-auto-upgrade-v1.bats +++ b/test/12-auto-upgrade-v1.bats @@ -6,10 +6,10 @@ load '/getssl/test/test_helper.bash' setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Check that auto upgrade to v2 doesn't change pebble url" { @@ -27,10 +27,10 @@ teardown() { setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Check that auto upgrade to v2 doesn't change v2 staging url" { @@ -48,10 +48,10 @@ teardown() { setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Check that auto upgrade to v2 doesn't change v2 prod url" { @@ -69,10 +69,10 @@ teardown() { setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Check that auto upgrade to v2 changes v1 staging to v2 staging url" { @@ -90,10 +90,10 @@ teardown() { setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Check that auto upgrade to v2 changes v1 prod to v2 prod url" { diff --git a/test/13-notify-valid.bats b/test/13-notify-valid.bats index 199f165..6b66927 100644 --- a/test/13-notify-valid.bats +++ b/test/13-notify-valid.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats index 86be2e2..fffe300 100644 --- a/test/14-test-revoke.bats +++ b/test/14-test-revoke.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index d2272fc..3eb273c 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/16-test-bad-acl.bats b/test/16-test-bad-acl.bats index abf365c..e2feec5 100644 --- a/test/16-test-bad-acl.bats +++ b/test/16-test-bad-acl.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/17-test-spaces-in-sans-dns01.bats b/test/17-test-spaces-in-sans-dns01.bats index 9eb2c32..574866d 100644 --- a/test/17-test-spaces-in-sans-dns01.bats +++ b/test/17-test-spaces-in-sans-dns01.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/17-test-spaces-in-sans-http01.bats b/test/17-test-spaces-in-sans-http01.bats index 5fc4eb4..0947e06 100644 --- a/test/17-test-spaces-in-sans-http01.bats +++ b/test/17-test-spaces-in-sans-http01.bats @@ -7,11 +7,12 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/18-retry-dns-add.bats b/test/18-retry-dns-add.bats index 68e508f..80244aa 100644 --- a/test/18-retry-dns-add.bats +++ b/test/18-retry-dns-add.bats @@ -6,11 +6,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats index 7f96929..945432a 100644 --- a/test/19-test-add-to-sans.bats +++ b/test/19-test-add-to-sans.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -15,7 +15,7 @@ setup() { } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a fi diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index e62e903..c0edf7b 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -29,10 +29,10 @@ teardown_file() { setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Create new certificate using DNS-01 verification (dig)" { @@ -48,10 +48,10 @@ teardown() { setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Force renewal of certificate using DNS-01 (dig)" { diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index 8ff465d..c0b7383 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi @@ -21,7 +21,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -f /usr/bin/dig.getssl.bak ]; then mv /usr/bin/dig.getssl.bak /usr/bin/dig fi diff --git a/test/20-wildcard-simple.bats b/test/20-wildcard-simple.bats index e68810b..eb0544f 100644 --- a/test/20-wildcard-simple.bats +++ b/test/20-wildcard-simple.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/21-wildcard-dual-rsa.bats b/test/21-wildcard-dual-rsa.bats index 16a8d97..97e23cb 100644 --- a/test/21-wildcard-dual-rsa.bats +++ b/test/21-wildcard-dual-rsa.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats index e397ac8..4d6e115 100644 --- a/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # These are run for every test, not once per file teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/23-wildcard-check-globbing.bats b/test/23-wildcard-check-globbing.bats index 8566b88..bf74230 100644 --- a/test/23-wildcard-check-globbing.bats +++ b/test/23-wildcard-check-globbing.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/24-wildcard-sans.bats b/test/24-wildcard-sans.bats index 74a1e5e..500acd4 100644 --- a/test/24-wildcard-sans.bats +++ b/test/24-wildcard-sans.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"wild-'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -16,7 +16,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"wild-'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a fi diff --git a/test/25-wildcard-all.bats b/test/25-wildcard-all.bats index a9b0380..4a74912 100644 --- a/test/25-wildcard-all.bats +++ b/test/25-wildcard-all.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/26-wildcard-revoke.bats b/test/26-wildcard-revoke.bats index 3be9bcd..e613c1e 100644 --- a/test/26-wildcard-revoke.bats +++ b/test/26-wildcard-revoke.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/27-wildcard-existing-cert.bats b/test/27-wildcard-existing-cert.bats index 0c69389..a9e83be 100644 --- a/test/27-wildcard-existing-cert.bats +++ b/test/27-wildcard-existing-cert.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/28-wildcard-error-http01-validation.bats b/test/28-wildcard-error-http01-validation.bats index bf8a7f2..3c08e72 100644 --- a/test/28-wildcard-error-http01-validation.bats +++ b/test/28-wildcard-error-http01-validation.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/29-check-mktemp-failure.bats b/test/29-check-mktemp-failure.bats index 9fcd710..81b9ae4 100644 --- a/test/29-check-mktemp-failure.bats +++ b/test/29-check-mktemp-failure.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/3-dual-rsa-ecdsa.bats b/test/3-dual-rsa-ecdsa.bats index c4c06e8..df8a8fc 100644 --- a/test/3-dual-rsa-ecdsa.bats +++ b/test/3-dual-rsa-ecdsa.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/30-handle-dig-failure.bats b/test/30-handle-dig-failure.bats index 6ea5803..898ac4d 100644 --- a/test/30-handle-dig-failure.bats +++ b/test/30-handle-dig-failure.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -f /usr/bin/drill ]; then mv /usr/bin/drill /usr/bin/drill.getssl.bak @@ -19,7 +19,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -f /usr/bin/drill.getssl.bak ]; then mv /usr/bin/drill.getssl.bak /usr/bin/drill fi diff --git a/test/31-test-posix-error.bats b/test/31-test-posix-error.bats index 37d7074..7623cae 100644 --- a/test/31-test-posix-error.bats +++ b/test/31-test-posix-error.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index 77ad362..1a311d7 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt # Turn off warning about detached head @@ -33,8 +33,9 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip - rm -r "$INSTALL_DIR/upgrade-getssl" + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -d "$INSTALL_DIR/upgrade-getssl" ] && rm -r "$INSTALL_DIR/upgrade-getssl" + true } diff --git a/test/33-ftp.bats b/test/33-ftp.bats index 1131967..086636a 100644 --- a/test/33-ftp.bats +++ b/test/33-ftp.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -n "${VSFTPD_CONF}" ]; then cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl @@ -24,7 +24,7 @@ _FTP teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -n "${VSFTPD_CONF}" ]; then cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF ${CODE_DIR}/test/restart-ftpd diff --git a/test/34-ftp-passive.bats b/test/34-ftp-passive.bats index b53223d..ac6e222 100644 --- a/test/34-ftp-passive.bats +++ b/test/34-ftp-passive.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -n "${VSFTPD_CONF}" ]; then cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl @@ -27,7 +27,7 @@ _FTP teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -n "${VSFTPD_CONF}" ]; then cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF ${CODE_DIR}/test/restart-ftpd diff --git a/test/35-preferred-chain.bats b/test/35-preferred-chain.bats index 6995925..0ffe71e 100644 --- a/test/35-preferred-chain.bats +++ b/test/35-preferred-chain.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/36-full-chain-inc-root.bats b/test/36-full-chain-inc-root.bats index 1fed1ba..4655075 100644 --- a/test/36-full-chain-inc-root.bats +++ b/test/36-full-chain-inc-root.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/37-idn.bats b/test/37-idn.bats index 04e26fd..a3cf43a 100644 --- a/test/37-idn.bats +++ b/test/37-idn.bats @@ -13,7 +13,7 @@ setup_file() { # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" GETSSL_CMD_HOST=${GETSSL_IDN_HOST} # use the test description to move tools we don't want to test out of the way @@ -27,7 +27,7 @@ setup() { } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip # use the test description to move tools we didn't want to test back DNS_TOOL=${BATS_TEST_DESCRIPTION##*-} for tool in dig drill host nslookup diff --git a/test/38-idn-http01-check-noidnout.bats b/test/38-idn-http01-check-noidnout.bats index 032bc2d..6ba8d14 100644 --- a/test/38-idn-http01-check-noidnout.bats +++ b/test/38-idn-http01-check-noidnout.bats @@ -12,11 +12,11 @@ setup_file() { } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" GETSSL_CMD_HOST=$GETSSL_IDN_HOST } diff --git a/test/4-more-than-10-hosts.bats b/test/4-more-than-10-hosts.bats index 2343cc4..f62d2e6 100644 --- a/test/4-more-than-10-hosts.bats +++ b/test/4-more-than-10-hosts.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/5-secp384-http01.bats b/test/5-secp384-http01.bats index 7e478dc..5ddf0d6 100644 --- a/test/5-secp384-http01.bats +++ b/test/5-secp384-http01.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/6-dual-rsa-ecdsa-copy-2-locations.bats b/test/6-dual-rsa-ecdsa-copy-2-locations.bats index 93c3349..16ca162 100644 --- a/test/6-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/6-dual-rsa-ecdsa-copy-2-locations.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # These are run for every test, not once per file setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -16,7 +16,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a fi diff --git a/test/7-test-renewal.bats b/test/7-test-renewal.bats index ceb2966..a2e9e0c 100644 --- a/test/7-test-renewal.bats +++ b/test/7-test-renewal.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -16,7 +16,7 @@ setup() { } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a diff --git a/test/8-staging-ecdsa.bats b/test/8-staging-ecdsa.bats index f3cf611..67e657a 100644 --- a/test/8-staging-ecdsa.bats +++ b/test/8-staging-ecdsa.bats @@ -8,10 +8,10 @@ load '/getssl/test/test_helper.bash' setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Create new certificate using staging server and prime256v1" { @@ -30,10 +30,10 @@ teardown() { setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Force renewal of certificate using staging server and prime256v1" { @@ -48,10 +48,10 @@ teardown() { setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Create new certificate using staging server and secp384r1" { @@ -70,10 +70,10 @@ teardown() { setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Force renewal of certificate using staging server and secp384r1" { diff --git a/test/9-multiple-domains-dns01.bats b/test/9-multiple-domains-dns01.bats index af6e059..12bb2e1 100644 --- a/test/9-multiple-domains-dns01.bats +++ b/test/9-multiple-domains-dns01.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/9-test--all.bats b/test/9-test--all.bats index f3520c0..35697fd 100644 --- a/test/9-test--all.bats +++ b/test/9-test--all.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt export PATH=$PATH:/getssl } diff --git a/test/dns_add_fail b/test/dns_add_fail index c39a89a..b8aa2b8 100755 --- a/test/dns_add_fail +++ b/test/dns_add_fail @@ -2,5 +2,5 @@ # Special test script which will always fail to update dns -echo "This is a test script to check retry works if DNS isn't updated" +echo "dns_add_fail: This is a test script to check retry works if DNS isn't updated" exit 0 diff --git a/test/u1-test-get_auth_dns-dig.bats b/test/u1-test-get_auth_dns-dig.bats index 05ec0b7..24ab088 100644 --- a/test/u1-test-get_auth_dns-dig.bats +++ b/test/u1-test-get_auth_dns-dig.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" for app in drill host nslookup do if [ -f /usr/bin/${app} ]; then @@ -23,7 +23,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip for app in drill host nslookup do if [ -f /usr/bin/${app}.getssl.bak ]; then diff --git a/test/u2-test-get_auth_dns-drill.bats b/test/u2-test-get_auth_dns-drill.bats index ce0fe88..b63cf1b 100644 --- a/test/u2-test-get_auth_dns-drill.bats +++ b/test/u2-test-get_auth_dns-drill.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" for app in dig host nslookup do if [ -f /usr/bin/${app} ]; then @@ -23,7 +23,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip for app in dig host nslookup do if [ -f /usr/bin/${app}.getssl.bak ]; then diff --git a/test/u3-mktemp-template.bats b/test/u3-mktemp-template.bats index 968e0db..e28208c 100644 --- a/test/u3-mktemp-template.bats +++ b/test/u3-mktemp-template.bats @@ -6,10 +6,10 @@ load '/getssl/test/test_helper.bash' setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } @test "Check mktemp -t getssl.XXXXXX works on all platforms" { diff --git a/test/u4-create-csr-and-ifs.bats b/test/u4-create-csr-and-ifs.bats index 528394d..7871445 100644 --- a/test/u4-create-csr-and-ifs.bats +++ b/test/u4-create-csr-and-ifs.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip } setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" . /getssl/getssl --source find_dns_utils _RUNNING_TEST=1 diff --git a/test/u5-test-get_auth_dns-no-root-servers.bats b/test/u5-test-get_auth_dns-no-root-servers.bats index ab0f846..7dcbdc9 100644 --- a/test/u5-test-get_auth_dns-no-root-servers.bats +++ b/test/u5-test-get_auth_dns-no-root-servers.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests" + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" cp /etc/resolv.conf /etc/resolv.conf.getssl cat <<- EOF > /etc/resolv.conf nameserver 8.8.8.8 @@ -29,7 +29,7 @@ EOF teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip cat /etc/resolv.conf.getssl > /etc/resolv.conf for app in drill host nslookup do From 2f55c41fb5cc33182b61ff4d4b89fcc7a3332533 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 4 Aug 2021 09:18:36 -0400 Subject: [PATCH 277/308] Optimize cURL version checks Only run cURL once to determine it's version. --- getssl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 3576591..3bb6272 100755 --- a/getssl +++ b/getssl @@ -336,6 +336,7 @@ DNS_WAIT_RETRY_ADD="false" # Try the dns_add_command again if the DNS recor # Private variables _CHECK_ALL=0 _CREATE_CONFIG=0 +_CURL_VERSION="" _FORCE_RENEW=0 _KEEP_VERSIONS="" _MUTE=0 @@ -2246,7 +2247,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p CURL="curl ${_NOMETER} " # shellcheck disable=SC2072 - if [[ ! "$($CURL -V | head -1 | cut -d' ' -f2 )" < "7.33" ]]; then + if [[ ! "${_CURL_VERSION}" < "7.33" ]]; then CURL="$CURL --http1.1 " fi @@ -2740,8 +2741,9 @@ requires mktemp # TODO: see where --silent can be removed (if _NOMETER defaults to --silent for old versions?) # This would help with debugging transfer errors. +_CURL_VERSION="$(curl -V | head -1 | cut -d' ' -f2 )" # shellcheck disable=SC2072 -if [[ ! "$(curl -V | head -1 | cut -d' ' -f2 )" < "7.67" ]]; then +if [[ ! "${_CURL_VERSION}" < "7.67" ]]; then _NOMETER="--no-progress-meter" fi From d7e30393084b99a697d18bc0e9640235b36637af Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Tue, 10 Aug 2021 08:15:15 -0400 Subject: [PATCH 278/308] Add a test for unified directories Verify that a unified directory, API V2 is selected. --- test/u6-test-combined-directory.bats | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test/u6-test-combined-directory.bats diff --git a/test/u6-test-combined-directory.bats b/test/u6-test-combined-directory.bats new file mode 100644 index 0000000..4ef0d1f --- /dev/null +++ b/test/u6-test-combined-directory.bats @@ -0,0 +1,34 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + +# CA with a unified directory (both ACME V1 and V2 at the same URI) +CA="https://api.test4.buypass.no/acme" + +# This is run for every test +setup() { + [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + + . /getssl/getssl --source + + requires curl + _NOMETER="--silent" + + _RUNNING_TEST=1 + _USE_DEBUG=1 +} + + +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip +} + + +@test "Check that API V2 is selected in a unified ACME directory." { + obtain_ca_resource_locations + + [ "$API" -eq 2 ] +} + From a83240400cfe4ce5f90dd71b2ba0c0f20a79b1db Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 25 Aug 2021 15:36:29 -0400 Subject: [PATCH 279/308] Use GitHub secrets for dynamic dns test credentials Note: To add the secrets to your repository on GitHub Goto Actions -> Settings -> Secrets New Repository Secret Add DUCKDNS_TOKEN Add DYNU_API_KEY --- .github/workflows/run-tests-staging-duckdns.yml | 2 ++ .github/workflows/run-tests-staging-dynu.yml | 2 ++ test/Dockerfile-centos7-duckdns | 2 +- test/Dockerfile-centos7-dynu | 2 +- test/Dockerfile-ubuntu-duckdns | 2 +- test/Dockerfile-ubuntu-dynu | 2 +- test/run-test.sh | 2 ++ 7 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/run-tests-staging-duckdns.yml b/.github/workflows/run-tests-staging-duckdns.yml index a6348bc..7647afe 100644 --- a/.github/workflows/run-tests-staging-duckdns.yml +++ b/.github/workflows/run-tests-staging-duckdns.yml @@ -8,6 +8,8 @@ on: pull_request: branches: - master +env: + DUCKDNS_TOKEN: ${{ secrets.DUCKDNS_TOKEN }} jobs: test-centos7-duckdns: runs-on: ubuntu-latest diff --git a/.github/workflows/run-tests-staging-dynu.yml b/.github/workflows/run-tests-staging-dynu.yml index 1f55bae..294faf5 100644 --- a/.github/workflows/run-tests-staging-dynu.yml +++ b/.github/workflows/run-tests-staging-dynu.yml @@ -8,6 +8,8 @@ on: pull_request: branches: - master +env: + DYNU_API_KEY: ${{ secrets.DYNU_API_KEY }} jobs: test-centos7-dynu: runs-on: ubuntu-latest diff --git a/test/Dockerfile-centos7-duckdns b/test/Dockerfile-centos7-duckdns index be26c79..96a5fab 100644 --- a/test/Dockerfile-centos7-duckdns +++ b/test/Dockerfile-centos7-duckdns @@ -14,7 +14,7 @@ ENV LC_ALL en_US.UTF-8 ENV staging "true" ENV dynamic_dns "dynu" -ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb +#ENV DUCKDNS_TOKEN WORKDIR /root RUN mkdir -p /etc/nginx/pki/private diff --git a/test/Dockerfile-centos7-dynu b/test/Dockerfile-centos7-dynu index 65c8051..09a1534 100644 --- a/test/Dockerfile-centos7-dynu +++ b/test/Dockerfile-centos7-dynu @@ -14,7 +14,7 @@ ENV LC_ALL en_US.UTF-8 ENV staging "true" ENV dynamic_dns "duckdns" -ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 +#ENV DYNU_API_KEY WORKDIR /root RUN mkdir /etc/nginx/pki diff --git a/test/Dockerfile-ubuntu-duckdns b/test/Dockerfile-ubuntu-duckdns index f0f2edd..c4fdc6a 100644 --- a/test/Dockerfile-ubuntu-duckdns +++ b/test/Dockerfile-ubuntu-duckdns @@ -8,7 +8,7 @@ ENV DEBIAN_FRONTEND noninteractive # Ensure tests in this image use the staging server ENV staging "true" ENV dynamic_dns "duckdns" -ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb +#ENV DUCKDNS_TOKEN # Update and install required software RUN apt-get update --fix-missing diff --git a/test/Dockerfile-ubuntu-dynu b/test/Dockerfile-ubuntu-dynu index b010293..68f5c06 100644 --- a/test/Dockerfile-ubuntu-dynu +++ b/test/Dockerfile-ubuntu-dynu @@ -8,7 +8,7 @@ ENV DEBIAN_FRONTEND noninteractive # Ensure tests in this image use the staging server ENV staging "true" ENV dynamic_dns "dynu" -ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 +#ENV DYNU_API_KEY # Update and install required software RUN apt-get update --fix-missing diff --git a/test/run-test.sh b/test/run-test.sh index 76a7555..d6156fb 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -38,6 +38,8 @@ docker run \ --env GETSSL_IDN_HOST=$GETSSL_IDN_HOST \ --env GETSSL_OS=$GETSSL_OS \ --env GITHUB_REPOSITORY="${GITHUB_REPOSITORY}" \ + --env DUCKDNS_TOKEN="${DUCKDNS_TOKEN}" \ + --env DYNU_API_KEY="${DYNU_API_KEY}" \ -v "$(pwd)":/getssl \ --rm \ --network ${PWD##*/}_acmenet \ From 0a94644a7fa426ea8cdace8ce43261d9a515ff3e Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 25 Aug 2021 16:31:54 -0400 Subject: [PATCH 280/308] Fix "directory exists" test failures when setting up nginx Some versions of nginx create directories, so use -p with mkdir. --- test/Dockerfile-bash4-0 | 6 +++--- test/Dockerfile-bash4-2 | 6 +++--- test/Dockerfile-bash5-0 | 6 +++--- test/Dockerfile-centos7-dynu | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/Dockerfile-bash4-0 b/test/Dockerfile-bash4-0 index 9b1f790..0dae149 100644 --- a/test/Dockerfile-bash4-0 +++ b/test/Dockerfile-bash4-0 @@ -7,9 +7,9 @@ RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx l WORKDIR /root # Create nginx directories in standard places -RUN mkdir /run/nginx -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /run/nginx +RUN mkdir -p /etc/nginx/pki +RUN mkdir -p /etc/nginx/pki/private # Setup ftp ENV VSFTPD_CONF=/etc/vsftpd.conf diff --git a/test/Dockerfile-bash4-2 b/test/Dockerfile-bash4-2 index d9386f6..dd1cb11 100644 --- a/test/Dockerfile-bash4-2 +++ b/test/Dockerfile-bash4-2 @@ -7,9 +7,9 @@ RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx l WORKDIR /root # Create nginx directories in standard places -RUN mkdir /run/nginx -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /run/nginx +RUN mkdir -p /etc/nginx/pki +RUN mkdir -p /etc/nginx/pki/private # Setup ftp ENV VSFTPD_CONF=/etc/vsftpd.conf diff --git a/test/Dockerfile-bash5-0 b/test/Dockerfile-bash5-0 index 2d776eb..260290d 100644 --- a/test/Dockerfile-bash5-0 +++ b/test/Dockerfile-bash5-0 @@ -7,9 +7,9 @@ RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx l WORKDIR /root # Create nginx directories in standard places -RUN mkdir /run/nginx -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /run/nginx +RUN mkdir -p /etc/nginx/pki +RUN mkdir -p /etc/nginx/pki/private # Setup ftp ENV VSFTPD_CONF=/etc/vsftpd.conf diff --git a/test/Dockerfile-centos7-dynu b/test/Dockerfile-centos7-dynu index 09a1534..cabd7eb 100644 --- a/test/Dockerfile-centos7-dynu +++ b/test/Dockerfile-centos7-dynu @@ -17,8 +17,8 @@ ENV dynamic_dns "duckdns" #ENV DYNU_API_KEY WORKDIR /root -RUN mkdir /etc/nginx/pki -RUN mkdir /etc/nginx/pki/private +RUN mkdir -p /etc/nginx/pki +RUN mkdir -p /etc/nginx/pki/private COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf From 1511bc6f652c21feb2c631862b8e566c017d98cc Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 25 Aug 2021 16:53:54 -0400 Subject: [PATCH 281/308] Include repository name in dynamic DNS test domains For now, srvrco is excluded. The domain name will be --getssl. Must be added to accounts on these services. --- test/run-test.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/run-test.sh b/test/run-test.sh index d6156fb..e9aab38 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -14,17 +14,27 @@ else COMMAND="bats /getssl/test --timing" fi +REPO="" +if [ -n "$GITHUB_REPOSITORY" ] ; then + REPO="$(echo "$GITHUB_REPOSITORY" | cut -d/ -f1)" + if [[ "$REPO" == "srvrco" ]] ; then + REPO="" + else + REPO="${REPO}-" + fi +fi + ALIAS="$OS.getssl.test" GETSSL_IDN_HOST="$OS.xn--t-r1a81lydm69gz81r.test" STAGING="" GETSSL_OS=$OS if [[ "$OS" == *"duckdns"* ]]; then - ALIAS="${OS%-duckdns}-getssl.duckdns.org" + ALIAS="${REPO}${OS%-duckdns}-getssl.duckdns.org" STAGING="--env STAGING=true --env dynamic_dns=duckdns" GETSSL_OS="${OS%-duckdns}" elif [[ "$OS" == *"dynu"* ]]; then - ALIAS="${OS%-dynu}-getssl.freeddns.org" + ALIAS="${REPO}${OS%-dynu}-getssl.freeddns.org" STAGING="--env STAGING=true --env dynamic_dns=dynu" GETSSL_OS="${OS%-dynu}" elif [[ "$OS" == "bash"* ]]; then From b2e4d73e9d3540de47e3d8451632b5e7d0b8b1a3 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 25 Aug 2021 17:39:38 -0400 Subject: [PATCH 282/308] Allow tests to run manually Avoids having to push, e.g. when adding a tag or updating credentials. --- .github/workflows/run-tests-pebble.yml | 3 +++ .github/workflows/run-tests-staging-duckdns.yml | 3 +++ .github/workflows/run-tests-staging-dynu.yml | 3 +++ .github/workflows/shellcheck.yml | 3 +++ 4 files changed, 12 insertions(+) diff --git a/.github/workflows/run-tests-pebble.yml b/.github/workflows/run-tests-pebble.yml index fe82ad6..65fed1c 100644 --- a/.github/workflows/run-tests-pebble.yml +++ b/.github/workflows/run-tests-pebble.yml @@ -8,6 +8,9 @@ on: pull_request: branches: - master + workflow_dispatch: + branches: + - master jobs: test-alpine: runs-on: ubuntu-latest diff --git a/.github/workflows/run-tests-staging-duckdns.yml b/.github/workflows/run-tests-staging-duckdns.yml index 7647afe..3a8efea 100644 --- a/.github/workflows/run-tests-staging-duckdns.yml +++ b/.github/workflows/run-tests-staging-duckdns.yml @@ -8,6 +8,9 @@ on: pull_request: branches: - master + workflow_dispatch: + branches: + - master env: DUCKDNS_TOKEN: ${{ secrets.DUCKDNS_TOKEN }} jobs: diff --git a/.github/workflows/run-tests-staging-dynu.yml b/.github/workflows/run-tests-staging-dynu.yml index 294faf5..2f9ec4f 100644 --- a/.github/workflows/run-tests-staging-dynu.yml +++ b/.github/workflows/run-tests-staging-dynu.yml @@ -8,6 +8,9 @@ on: pull_request: branches: - master + workflow_dispatch: + branches: + - master env: DYNU_API_KEY: ${{ secrets.DYNU_API_KEY }} jobs: diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index baf6603..52873f6 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -7,6 +7,9 @@ on: branches: [ master ] pull_request: branches: [ master ] + workflow_dispatch: + branches: + - master jobs: lint: From 8747f91c2f0c451ac4b40e09edbc006b1af1972d Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 25 Aug 2021 18:36:45 -0400 Subject: [PATCH 283/308] Update test documentation with GitHub secrets Document the accounts and repo-specific domain names required to run the dynamic DNS tests. Also document the GitHub "secrets" that must be stored for CI testing to work. --- test/README-Testing.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/README-Testing.md b/test/README-Testing.md index d713914..5d67977 100644 --- a/test/README-Testing.md +++ b/test/README-Testing.md @@ -10,6 +10,23 @@ For continuous integration testing we have the following: 2. Then runs the `bats` test scripts (all the files with a ".bats" extension) for each OS (alpine, centos6, debian, ubuntu) 3. Runs the `bats` test script against the staging server (using ubuntu docker image and duckdns.org) +Tests can also be triggered manually from the GitHub website. + +For dynamic DNS tests, you need accounts on duckdns.org and dynu.com, and need to create 4 domain names in each account. + +For duckdns.org: +- Add DUCKDNS_TOKEN to your repository's environment secrets. The value is your account's token +- Add domains -centos7-getssl.duckdns.org, wild--centos7.duckdns.org, -ubuntu-getssl.duckdns.org, and wild--ubuntu-getssl.duckdns.org + +For dynu.com: + - Add DYNU_API_KEY to your repository's environment secrets. The value is your account's API Key. + - Add domains -centos7-getssl.freedns.org, wild--centos7.freedns.org, -ubuntu-getssl.freedns.org, and wild--ubuntu-getssl.freedns.org + +To run dynamic DNS tests outside the CI environment, you need accounts without in the domain names. Export the environment variable corresponding to the secrets (with the same values). + +For individual accounts, is your github account name. + + ## To run all the tests on a single OS 1. Start `pebble` and `challtestsrv` using ```docker-compose up -d --build``` From 6da313cedf4a9c003068d80b6c6856e8dc599f20 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Thu, 26 Aug 2021 14:00:50 -0400 Subject: [PATCH 284/308] Improve upgrades - use releases, do full install Use the GitHub release data to decide if an upgrade is available. Only download the release if a newer stable release is published. Install the full release - including the DNS scripts (requires "make") Don't check for upgrades when restarting. Remove --keep logic - only 1 old version is kept, only if make isn't available. Old versions are availablel from the repo; if you have local changes, --upgrade doesn't make sense. Can upgrade (or downgrade) to any tagged release with --experimental vx.yy Note that GitHub API requests are rate-limited; this shouldn't be an issue unless getssl is run more than ~60 times/hr. If the limit is exceeded, getssl will sleep until the limit is reset. The limit is per-IP address. The tests have been modified to only check for updates in the tests that verify the check for updates logic. This has the side effect of not doing MANY pointless checks for updates in the tests... --- README.md | 4 +- getssl | 241 +++++++++++++++++------- test/1-simple-http01.bats | 2 +- test/11-test--install.bats | 4 +- test/11-test-no-domain-storage.bats | 2 +- test/12-auto-upgrade-v1.bats | 10 +- test/13-notify-valid.bats | 4 +- test/14-test-revoke.bats | 2 +- test/15-test-revoke-no-suffix.bats | 2 +- test/17-test-spaces-in-sans-dns01.bats | 4 +- test/17-test-spaces-in-sans-http01.bats | 4 +- test/2-simple-dns01-dig.bats | 2 +- test/20-wildcard-simple.bats | 6 +- test/23-wildcard-check-globbing.bats | 2 +- test/25-wildcard-all.bats | 4 +- test/26-wildcard-revoke.bats | 2 +- test/27-wildcard-existing-cert.bats | 2 +- test/29-check-mktemp-failure.bats | 2 +- test/3-dual-rsa-ecdsa.bats | 6 +- test/31-test-posix-error.bats | 2 +- test/32-test-upgrade.bats | 63 +++++-- test/4-more-than-10-hosts.bats | 2 +- test/5-secp384-http01.bats | 4 +- test/8-staging-ecdsa.bats | 8 +- test/9-multiple-domains-dns01.bats | 2 +- test/9-test--all.bats | 2 +- test/Dockerfile-alpine | 2 +- test/Dockerfile-bash4-0 | 2 +- test/Dockerfile-bash4-2 | 2 +- test/Dockerfile-bash5-0 | 2 +- test/Dockerfile-centos6 | 2 +- test/Dockerfile-centos7 | 2 +- test/Dockerfile-centos7-duckdns | 2 +- test/Dockerfile-centos7-dynu | 2 +- test/Dockerfile-centos8 | 2 +- test/Dockerfile-debian | 2 +- test/Dockerfile-rockylinux8 | 2 +- test/Dockerfile-ubuntu | 2 +- test/Dockerfile-ubuntu-duckdns | 2 +- test/Dockerfile-ubuntu-dynu | 2 +- test/Dockerfile-ubuntu16 | 2 +- test/Dockerfile-ubuntu18 | 2 +- test/debug-test.sh | 4 +- test/test_helper.bash | 4 +- 44 files changed, 291 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index 454a388..42dd5a9 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ sftp or ftp access to the remote server). getssl ver. 2.36 Obtain SSL certificates from the letsencrypt.org ACME server -Usage: getssl [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet] [-Q|--mute] [-u|--upgrade] [-k|--keep #] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir] [--preferred-chain chain] domain +Usage: getssl [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet] [-Q|--mute] [-u|--upgrade] [-X|--experimental tag] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir] [--preferred-chain chain] domain Options: -a, --all Check all certificates @@ -105,7 +105,7 @@ Options: -Q, --mute Like -q, but also mute notification about successful upgrade -r, --revoke "cert" "key" [CA_server] Revoke a certificate (the cert and key are required) -u, --upgrade Upgrade getssl if a more recent version is available - can be used with or without domain(s) - -k, --keep "#" Maximum number of old getssl versions to keep when upgrading + -X --experimental tag Allow upgrade to a specified version of getssl -U, --nocheck Do not check if a more recent version is available -v --version Display current version of getssl -w working_dir "Working directory" diff --git a/getssl b/getssl index 3bb6272..f7a58b9 100755 --- a/getssl +++ b/getssl @@ -268,6 +268,7 @@ # 2021-07-27 Support ftps://, FTPS_OPTIONS, remove default --insecure parameter to ftpes. Report caller(s) of error_exit in debug and test modes (tlhackque)(#687)(2.39) # 2021-07-30 Prefer API V2 when both offered (tlhackque) (#690) (2.40) # 2021-07-30 Run tests with -d to catch intermittent failures, Use fork's repo for upgrade tests. (tlhackque) (#692) (2.41) +# 2021-08-26 Improve upgrade check & make upgrade do a full install when possible (tlhackque) (#694) (2.42) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -276,7 +277,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.41" +VERSION="2.42" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -286,10 +287,11 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" CHALLENGE_CHECK_TYPE="http" CHECK_REMOTE_WAIT=0 CHECK_REMOTE="true" +LIMIT_API="https://api.github.com/rate_limit" if [[ -n "${GITHUB_REPOSITORY}" ]] ; then - CODE_LOCATION="https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/master/getssl" + RELEASE_API="https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/latest" else - CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" + RELEASE_API="https://api.github.com/repos/srvrco/getssl/releases/latest" fi CSR_SUBJECT="/" CURL_USERAGENT="${PROGNAME}/${VERSION}" @@ -314,7 +316,7 @@ REUSE_PRIVATE_KEY="true" SERVER_TYPE="https" SKIP_HTTP_TOKEN_CHECK="false" SSLCONF="$(openssl version -d 2>/dev/null| cut -d\" -f2)/openssl.cnf" -TEMP_UPGRADE_FILE="" +TEMP_UPGRADE_DIR="" TOKEN_USER_ID="" USE_SINGLE_ACL="false" WORKING_DIR_CANDIDATES=("/etc/getssl" "${PROGDIR}/conf" "${PROGDIR}/.getssl" "${HOME}/.getssl") @@ -338,7 +340,6 @@ _CHECK_ALL=0 _CREATE_CONFIG=0 _CURL_VERSION="" _FORCE_RENEW=0 -_KEEP_VERSIONS="" _MUTE=0 _NOTIFY_VALID=0 _NOMETER="" @@ -351,6 +352,7 @@ _TEST_SKIP_CNAME_CALL=0 _TEST_SKIP_SOA_CALL=0 _UPGRADE=0 _UPGRADE_CHECK=1 +_UPGRADE_TO_TAG="" _USE_DEBUG=0 _ONLY_CHECK_CONFIG=0 config_errors="false" @@ -761,71 +763,165 @@ check_config() { # check the config files for all obvious errors debug "${DOMAIN}: check_config completed - all OK" } -check_getssl_upgrade() { # check if a more recent version of code is available available - TEMP_UPGRADE_FILE="$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX)" - if [ "$TEMP_UPGRADE_FILE" == "" ]; then - error_exit "mktemp failed" - fi - curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" +# Quota generally shouldn't be an issue - except for tests +# Rate limits are per-IP address +check_github_quota() { + local need remaining reset limits now + need="$1" + while true ; do + limits="$(curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" -H 'Accept: application/vnd.github.v3+json' "$LIMIT_API" | sed -e's/\("[^:]*": *\("[^""]*",\|[^,]*[,}]\)\)/\r\n\1/g' | sed -ne'/"core":/,/}/p')" + errcode=$? + if [[ $errcode -eq 60 ]]; then + error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" + elif [[ $errcode -gt 0 ]]; then + error_exit "curl error checking releases: $errcode" + fi + limits="$(sed -e's/^ *//g' <<<"${limits}")" + remaining="$(sed -e'/^"remaining": *[0-9]/!d;s/^"remaining": *\([0-9][0-9]*\).*$/\1/' <<<"${limits}")" + reset="$(sed -e'/^"reset": *[0-9]/!d;s/^"reset": *\([0-9][0-9]*\).*$/\1/' <<<"${limits}")" + if [[ "$remaining" -ge "$need" ]] ; then return 0 ; fi + limit="$(sed -e'/^"limit": *[0-9]/!d;s/^"limit": *\([0-9][0-9]*\).*$/\1/' <<<"${limits}")" + if [[ "$limit" -lt "$need" ]] ; then + error_exit "GitHub API request $need exceeds limit $limit" + fi + now="$(date +%s)" + while [[ "$now" -lt "$reset" ]] ; do + info "sleeping $(( "$reset" - "$now" )) seconds for GitHub quota" + sleep "$(( "$reset" - "$now" ))" + now="$(date +%s)" + done + done +} +check_getssl_upgrade() { # check if a more recent release is available + check_github_quota 2 + # Check GitHub for latest stable release, or a specified tag + if [[ -n "$_UPGRADE_TO_TAG" ]]; then + RELEASE_API="$RELEASE_API/tags/$_UPGRADE_TO_TAG" + fi + local release_data release_tag release_ver local_ver release_desc release_url release_tar NEWCMD + debug "Checking for releases at $RELEASE_API" + # Sometimes the json is pretty-printed, sometimes not. Loosely tied to --user-agent, but not + # always. Normalize it enough to get the 3 elements necessary. Oh, for jq... + release_data="$(curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" -H 'Accept: application/vnd.github.v3+json' "$RELEASE_API" | sed -e's/\("[^:]*": *\("[^""]*",\|[^,]*[,}]\)\)/\r\n\1/g')" errcode=$? if [[ $errcode -eq 60 ]]; then error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" elif [[ $errcode -gt 0 ]]; then - error_exit "curl error : $errcode" + error_exit "curl error checking releases: $errcode" + fi + debug "$release_data" + release_data="$(sed -e's/^ *//g' <<<"${release_data}")" + release_tag="$(sed -e'/^"tag_name": *"/!d;s/^"tag_name": *"\([^""]*\).*$/\1/' <<<"${release_data}")" + if [[ "${release_tag:0:1}" != 'v' ]] ; then + if [[ ${_MUTE} -eq 0 ]]; then + info "The current repository has no releases or is improperly tagged; can't check for upgrades: '$release_tag'" + fi + return 0 fi - latestversion=$(awk -F '"' '$1 == "VERSION=" {print $2}' "$TEMP_UPGRADE_FILE") - latestvdec=$(echo "$latestversion"| tr -d '.') - localvdec=$(echo "$VERSION"| tr -d '.' ) + release_ver="$( tr -d '.v' <<<"${release_tag}")" + local_ver="$( tr -d '.' <<<"${VERSION}")" debug "current code is version ${VERSION}" - debug "Most recent version is ${latestversion}" - # use a default of 0 for cases where the latest code has not been obtained. - if [[ "${latestvdec:-0}" -gt "$localvdec" ]]; then - if [[ ${_UPGRADE} -eq 1 ]]; then - if ! install "$0" "${0}.v${VERSION}"; then - error_exit "problem renaming old version while updating, check permissions" - fi - if ! install -m 700 "$TEMP_UPGRADE_FILE" "$0"; then - error_exit "problem installing new version while updating, check permissions" - fi - if [[ ${_MUTE} -eq 0 ]]; then - echo "Updated getssl from v${VERSION} to v${latestversion}" - echo "These update notifications can be turned off using the -Q option" - echo "" - echo "Updates are;" - awk "/\(${VERSION}\)$/ {s=1} s; /\(${latestversion}\)$/ || /^# ----/ {s=0}" "$TEMP_UPGRADE_FILE" | awk '{if(NR>1)print}' - echo "" - fi - if [[ -n "$_KEEP_VERSIONS" ]] && [[ "$_KEEP_VERSIONS" =~ ^[0-9]+$ ]]; then - # Obtain all locally stored old versions in getssl_versions - declare -a getssl_versions - shopt -s nullglob - for getssl_version in "$0".v*; do - getssl_versions[${#getssl_versions[@]}]="$getssl_version" - done - shopt -u nullglob - # Explicitly sort the getssl_versions array to make sure - shopt -s -o noglob - # shellcheck disable=SC2207 - IFS=$'\n' getssl_versions=($(sort <<< "${getssl_versions[*]}")) - shopt -u -o noglob - # Remove entries until given number of old versions to keep is reached - while [[ ${#getssl_versions[@]} -gt $_KEEP_VERSIONS ]]; do - debug "removing old version ${getssl_versions[0]}" - rm "${getssl_versions[0]}" - getssl_versions=("${getssl_versions[@]:1}") - done - fi - if ! eval "$ORIGCMD"; then - error_exit "Running upgraded getssl failed" - fi - graceful_exit - else + debug "Most recent version is ${release_tag:1}" + if [[ -z "$_UPGRADE_TO_TAG" ]] ; then + if [[ "$local_ver" -ge "$release_ver" ]] ; then return 0; fi + else + if [[ "$local_ver" -eq "$release_ver" ]] ; then return 0; fi + fi + if [[ ${_UPGRADE} -ne 1 ]]; then + if [[ ${_MUTE} -eq 0 ]]; then + release_desc="$(sed -e'/^"body": *"/!d;s/^"body": *"\([^""]*\).*$/\1/;s/\\r/\r/g;s/\\n/\n/g' <<<"$release_data")" info "" - info "A more recent version (v${latestversion}) of getssl is available, please update" + info "A more recent version (${release_tag}) than $VERSION of getssl is available, please update" info "The easiest way is to use the -u or --upgrade flag" info "" + info "Release ${release_tag} summary" + info "$release_desc" + info "" fi + return 0; + fi + # Find, download, and unpack the tarball containing the selected release + release_url="$(sed -e'/^"tarball_url": *"/!d;s/^"tarball_url": *"\([^""]*\).*$/\1/' <<<"${release_data}")" + debug "Release url '$release_url'" + requires tar + TEMP_UPGRADE_DIR="$(mktemp -d 2>/dev/null || mktemp -d -t getssl.XXXXXXXX)" + if [ "$TEMP_UPGRADE_DIR" == "" ]; then + error_exit "mktemp failed" + fi + release_tar="$TEMP_UPGRADE_DIR/getssl-${release_tag}.tgz" + debug "Downloading release to $release_tar" + check_github_quota 1 + curl ${_NOMETER:---silent} -L --user-agent "$CURL_USERAGENT" -H 'Accept: application/vnd.github.v3+json' "$release_url" --output "$release_tar" + errcode=$? + if [[ $errcode -eq 60 ]]; then + error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" + elif [[ $errcode -gt 0 ]]; then + error_exit "curl error downloading release: $errcode" + fi + if ! tar -C "${TEMP_UPGRADE_DIR}" --strip-components 1 -xzf "$release_tar" ; then + error_exit "failed to unpack release: $?" fi + # Inhibit check for upgrades when running the new version + NEWCMD="$(sed -e's/ -\(u\|-upgrade\|U\|-nocheck\)//g;s/^\([^ ]* \)/\1--nocheck /' <<<"$ORIGCMD")" + # Install everything with make - if it's available + if [ -n "$(command -v 'make' 2>/dev/null)" ]; then + if [[ "${0%/usr/bin/getssl}" != "$0" ]] ; then + export DESTDIR="${0%/usr/bin/getssl}" + fi + if [[ ${_MUTE} -eq 0 ]]; then + if ! make -C "${TEMP_UPGRADE_DIR}" "install" ; then + error_exit "Installation failed: $?" + fi + else + if ! make -s -C "${TEMP_UPGRADE_DIR}" "install" >/dev/null ; then + error_exit "Installation failed: $?" + fi + fi + clean_up + if [[ ${_MUTE} -eq 0 ]]; then + info "Installed $release_tag, restarting with $NEWCMD" + fi + if ! eval "$NEWCMD"; then + error_exit "Running upgraded getssl failed" + fi + graceful_exit + fi + # Fall back to 'install' and just the main script. + if [[ ${_MUTE} -eq 0 ]]; then + info "'make' is not available. getssl will be installed, but support scripts will not be upgraded" + info "To stay completely up-to-date, please install make" + fi + if ! install "$0" "${0}.v${VERSION}"; then + error_exit "problem renaming old version while updating, check permissions" + fi + if ! install -m 700 "$TEMP_UPGRADE_DIR/getssl" "$0"; then + error_exit "problem installing new version while updating, check permissions" + fi + if [[ ${_MUTE} -eq 0 ]]; then + echo "Updated getssl from v${VERSION} to $release_tag" + echo "The old version remains as ${0}.v${VERSION} and should be removed" + echo "" + fi + # This version can't be removed since disappearing can confuse bash. + declare -a getssl_versions + shopt -s nullglob + for getssl_version in "$0".v*; do + if [[ "$getssl_version" != "${0}.v${VERSION}" ]] ; then + getssl_versions[${#getssl_versions[@]}]="$getssl_version" + fi + done + shopt -u nullglob + if [[ -n "${getssl_versions[*]}" ]] ; then + rm "${getssl_versions[@]}" + fi + clean_up + if [[ ${_MUTE} -eq 0 ]]; then + info "Installed $release_tag, restarting with $NEWCMD" + fi + if ! eval "$NEWCMD"; then + error_exit "Running upgraded getssl failed" + fi + graceful_exit } clean_up() { # Perform pre-exit housekeeping @@ -848,8 +944,12 @@ clean_up() { # Perform pre-exit housekeeping rm -rf "${TEMP_DIR:?}" fi fi - if [[ -n "$TEMP_UPGRADE_FILE" ]] && [[ -f "$TEMP_UPGRADE_FILE" ]]; then - rm -f "$TEMP_UPGRADE_FILE" + if [[ -n "$TEMP_UPGRADE_DIR" ]] && [[ -d "$TEMP_UPGRADE_DIR" ]]; then + if [ "${TEMP_UPGRADE_DIR}" -ef "/tmp" ]; then + info "Not going to delete TEMP_UPGRADE_DIR ${TEMP_UPGRADE_DIR} as it appears to be /tmp" + else + rm -rf "${TEMP_UPGRADE_DIR:?}" + fi fi } @@ -1829,7 +1929,7 @@ help_message() { # print out the help message -Q, --mute Like -q, but also mute notification about successful upgrade -r, --revoke "cert" "key" [CA_server] Revoke a certificate (the cert and key are required) -u, --upgrade Upgrade getssl if a more recent version is available - can be used with or without domain(s) - -k, --keep "#" Maximum number of old getssl versions to keep when upgrading + -X, --experimental tag Upgrade to experimental releases, specified by tag (e.g. v9.43) -U, --nocheck Do not check if a more recent version is available -v --version Display current version of $PROGNAME -w working_dir "Working directory" @@ -2451,7 +2551,7 @@ urlbase64_decode() { usage() { # echos out the program usage echo "Usage: $PROGNAME [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet]"\ - "[-Q|--mute] [-u|--upgrade] [-k|--keep #] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir]"\ + "[-Q|--mute] [-u|--upgrade] [-X|--experimental tag] [-U|--nocheck] [-r|--revoke cert key] [-w working_dir]"\ "[--preferred-chain chain] domain" } @@ -2660,7 +2760,8 @@ while [[ -n ${1+defined} ]]; do -a | --all) _CHECK_ALL=1 ;; -k | --keep) - shift; _KEEP_VERSIONS="$1";; + shift; + echo "--keep has no effect" ;; -q | --quiet) _QUIET=1 ;; -Q | --mute) @@ -2678,6 +2779,9 @@ while [[ -n ${1+defined} ]]; do REVOKE_REASON=0 ;; -u | --upgrade) _UPGRADE=1 ;; + -X | --experimental) + _UPGRADE_TO_TAG="$1" + shift ;; -U | --nocheck) _UPGRADE_CHECK=0 ;; -i | --install) @@ -2747,6 +2851,15 @@ if [[ ! "${_CURL_VERSION}" < "7.67" ]]; then _NOMETER="--no-progress-meter" fi +# Make sure mktemp works before going too far +MKDIR_TEST_FILE="$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX)" +if [ "$MKDIR_TEST_FILE" == "" ]; then + error_exit "mktemp failed" +else + rm "$MKDIR_TEST_FILE" +fi +unset MKDIR_TEST_FILE + # Check if upgrades are available (unless they have specified -U to ignore Upgrade checks) if [[ $_UPGRADE_CHECK -eq 1 ]]; then check_getssl_upgrade diff --git a/test/1-simple-http01.bats b/test/1-simple-http01.bats index 518f734..15205e1 100644 --- a/test/1-simple-http01.bats +++ b/test/1-simple-http01.bats @@ -33,7 +33,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors cleanup_environment diff --git a/test/11-test--install.bats b/test/11-test--install.bats index 1ab1ca4..186e8c6 100644 --- a/test/11-test--install.bats +++ b/test/11-test--install.bats @@ -34,7 +34,7 @@ setup() { cp "${CODE_DIR}/test/test-config/getssl-etc-template.cfg" "/etc/getssl/getssl.cfg" # Run getssl - run ${CODE_DIR}/getssl "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d "$GETSSL_CMD_HOST" assert_success check_output_for_errors @@ -53,7 +53,7 @@ setup() { CONFIG_FILE="getssl-http01.cfg" # Run getssl - run ${CODE_DIR}/getssl --install "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d --install "$GETSSL_CMD_HOST" assert_success check_output_for_errors diff --git a/test/11-test-no-domain-storage.bats b/test/11-test-no-domain-storage.bats index 9ad4aa4..f61db28 100644 --- a/test/11-test-no-domain-storage.bats +++ b/test/11-test-no-domain-storage.bats @@ -20,7 +20,7 @@ teardown() { setup_environment mkdir ${INSTALL_DIR}/.getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" - run ${CODE_DIR}/getssl -a + run ${CODE_DIR}/getssl -U -d -a assert_success check_output_for_errors assert_line 'Not going to delete TEMP_DIR ///tmp as it appears to be /tmp' diff --git a/test/12-auto-upgrade-v1.bats b/test/12-auto-upgrade-v1.bats index 7554561..1dc5139 100644 --- a/test/12-auto-upgrade-v1.bats +++ b/test/12-auto-upgrade-v1.bats @@ -20,7 +20,7 @@ teardown() { setup_environment mkdir ${INSTALL_DIR}/.getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" - run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success assert_line 'Using certificate issuer: https://pebble:14000/dir' } @@ -41,7 +41,7 @@ teardown() { setup_environment mkdir ${INSTALL_DIR}/.getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" - run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success assert_line 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' } @@ -62,7 +62,7 @@ teardown() { setup_environment mkdir ${INSTALL_DIR}/.getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" - run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success assert_line 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' } @@ -83,7 +83,7 @@ teardown() { setup_environment mkdir ${INSTALL_DIR}/.getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" - run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success assert_line 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' } @@ -104,7 +104,7 @@ teardown() { setup_environment mkdir ${INSTALL_DIR}/.getssl cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" - run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success assert_line 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' } diff --git a/test/13-notify-valid.bats b/test/13-notify-valid.bats index 6b66927..6c06123 100644 --- a/test/13-notify-valid.bats +++ b/test/13-notify-valid.bats @@ -33,7 +33,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d $GETSSL_HOST assert_success check_output_for_errors } @@ -43,7 +43,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl --notify-valid $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d --notify-valid $GETSSL_HOST assert [ $status == 2 ] check_output_for_errors cleanup_environment diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats index fffe300..abc33cd 100644 --- a/test/14-test-revoke.bats +++ b/test/14-test-revoke.bats @@ -43,7 +43,7 @@ setup() { CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key - run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA + run ${CODE_DIR}/getssl -U -d --revoke $CERT $KEY $CA assert_success check_output_for_errors "debug" } diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index 3eb273c..1eaa060 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -49,7 +49,7 @@ setup() { CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key - run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA + run ${CODE_DIR}/getssl -U -d --revoke $CERT $KEY $CA assert_success check_output_for_errors "debug" } diff --git a/test/17-test-spaces-in-sans-dns01.bats b/test/17-test-spaces-in-sans-dns01.bats index 574866d..cc9efc7 100644 --- a/test/17-test-spaces-in-sans-dns01.bats +++ b/test/17-test-spaces-in-sans-dns01.bats @@ -41,7 +41,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors cleanup_environment @@ -66,7 +66,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors cleanup_environment diff --git a/test/17-test-spaces-in-sans-http01.bats b/test/17-test-spaces-in-sans-http01.bats index 0947e06..86df5dc 100644 --- a/test/17-test-spaces-in-sans-http01.bats +++ b/test/17-test-spaces-in-sans-http01.bats @@ -42,7 +42,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors cleanup_environment @@ -67,7 +67,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors cleanup_environment diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index c0edf7b..2e8199e 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -55,7 +55,7 @@ teardown() { } @test "Force renewal of certificate using DNS-01 (dig)" { - run ${CODE_DIR}/getssl -d -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success assert_output --partial "dig" check_output_for_errors "debug" diff --git a/test/20-wildcard-simple.bats b/test/20-wildcard-simple.bats index eb0544f..7b69f1f 100644 --- a/test/20-wildcard-simple.bats +++ b/test/20-wildcard-simple.bats @@ -35,7 +35,7 @@ setup() { skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl "*.$GETSSL_HOST" + run ${CODE_DIR}/getssl -U -d "*.$GETSSL_HOST" assert_success assert_line --partial "certificate is valid for more than" check_output_for_errors @@ -47,7 +47,7 @@ setup() { skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f "*.$GETSSL_HOST" + run ${CODE_DIR}/getssl -U -d -f "*.$GETSSL_HOST" assert_success refute_line --partial "certificate is valid for more than" check_output_for_errors @@ -61,7 +61,7 @@ setup() { echo "RENEW_ALLOW=2000" >> "${INSTALL_DIR}/.getssl/*.${GETSSL_HOST}/getssl.cfg" - run ${CODE_DIR}/getssl "*.$GETSSL_HOST" + run ${CODE_DIR}/getssl -U -d "*.$GETSSL_HOST" assert_success refute_line --partial "certificate is valid for more than" check_output_for_errors diff --git a/test/23-wildcard-check-globbing.bats b/test/23-wildcard-check-globbing.bats index bf74230..a075f5d 100644 --- a/test/23-wildcard-check-globbing.bats +++ b/test/23-wildcard-check-globbing.bats @@ -44,7 +44,7 @@ setup() { skip "Not trying on staging server yet" fi - run ${CODE_DIR}/getssl -f "*.$GETSSL_HOST" + run ${CODE_DIR}/getssl -U -d -f "*.$GETSSL_HOST" assert_success refute_line --partial "certificate is valid for more than" check_output_for_errors diff --git a/test/25-wildcard-all.bats b/test/25-wildcard-all.bats index 4a74912..a5e1c13 100644 --- a/test/25-wildcard-all.bats +++ b/test/25-wildcard-all.bats @@ -32,13 +32,13 @@ setup() { cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/*.${GETSSL_HOST}/getssl.cfg" # create another domain in the .getssl directory - run ${CODE_DIR}/getssl -c "a.${GETSSL_HOST}" + run ${CODE_DIR}/getssl -U -d -c "a.${GETSSL_HOST}" cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/a.${GETSSL_HOST}/getssl.cfg" # Create a directory in /root which looks like a domain so that if glob expansion is performed the wildcard certificate won't be created mkdir -p "${INSTALL_DIR}/a.${GETSSL_HOST}" - run ${CODE_DIR}/getssl --all + run ${CODE_DIR}/getssl -U -d --all assert_success assert_line --partial "Certificate saved in /root/.getssl/*.${GETSSL_HOST}/*.${GETSSL_HOST}" diff --git a/test/26-wildcard-revoke.bats b/test/26-wildcard-revoke.bats index e613c1e..5709cc7 100644 --- a/test/26-wildcard-revoke.bats +++ b/test/26-wildcard-revoke.bats @@ -39,7 +39,7 @@ setup() { CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key - run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA + run ${CODE_DIR}/getssl -U -d --revoke $CERT $KEY $CA assert_line "certificate revoked" assert_success check_output_for_errors "debug" diff --git a/test/27-wildcard-existing-cert.bats b/test/27-wildcard-existing-cert.bats index a9e83be..98c97e4 100644 --- a/test/27-wildcard-existing-cert.bats +++ b/test/27-wildcard-existing-cert.bats @@ -40,7 +40,7 @@ setup() { rm -r ${INSTALL_DIR}/.getssl # Create configuration - run ${CODE_DIR}/getssl -c "${GETSSL_CMD_HOST}" + run ${CODE_DIR}/getssl -U -d -c "${GETSSL_CMD_HOST}" # Assert that the newly created configuration contains the additional domain in SANS # if this fails then error in tests will be "grep failed" - this means SANS did not hold the expected value diff --git a/test/29-check-mktemp-failure.bats b/test/29-check-mktemp-failure.bats index 81b9ae4..1a00929 100644 --- a/test/29-check-mktemp-failure.bats +++ b/test/29-check-mktemp-failure.bats @@ -28,7 +28,7 @@ setup() { # set TMPDIR to an invalid directory and check for failure export TMPDIR=/getssl.invalid.directory setup_environment - run ${CODE_DIR}/getssl -c "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d -c "$GETSSL_CMD_HOST" assert_failure assert_line --partial "mktemp failed" } diff --git a/test/3-dual-rsa-ecdsa.bats b/test/3-dual-rsa-ecdsa.bats index df8a8fc..5babf8f 100644 --- a/test/3-dual-rsa-ecdsa.bats +++ b/test/3-dual-rsa-ecdsa.bats @@ -45,7 +45,7 @@ setup() { skip "Using staging server, skipping internal test" fi check_nginx - run ${CODE_DIR}/getssl -d $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d $GETSSL_HOST if [ "$OLD_NGINX" = "false" ]; then assert_line "certificate on server is same as the local cert" @@ -60,7 +60,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -f $GETSSL_HOST assert_success check_output_for_errors } @@ -94,7 +94,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -f $GETSSL_HOST assert_success check_output_for_errors cleanup_environment diff --git a/test/31-test-posix-error.bats b/test/31-test-posix-error.bats index 7623cae..87879b5 100644 --- a/test/31-test-posix-error.bats +++ b/test/31-test-posix-error.bats @@ -23,7 +23,7 @@ setup() { skip "Using staging server, skipping internal test" fi - run bash --posix "${CODE_DIR}/getssl" + run bash --posix "${CODE_DIR}/getssl" -U -d assert_failure assert_line "getssl: Running with POSIX mode enabled is not supported" check_output_for_errors diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index 1a311d7..fa000bb 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -5,9 +5,52 @@ load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' +setup_file() { + if [ -f $BATS_TMPDIR/failed.skip ]; then + echo "# Skipping setup due to previous test failure" >&3 + return 0 + fi + local n + # Not every tag reflects a stable release. Ask GitHub for the releases & identify the last two. + # This is sorted by creation date of the release tag, not the publication date. This matches + # GitHub's releases/latest, which is how getssl determines what's available. + # This is expensive, so do it only once + + . "${CODE_DIR}/getssl" -U --source + check_github_quota 1 + export RELEASES="$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX)" + if [ -z "$RELEASES" ]; then + echo "# mktemp failed" >&3 + return 1 + fi + if ! curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" \ + -H 'Accept: application/vnd.github.v3+json' "${RELEASE_API%/latest}" | \ + jq 'map(select((.draft or .prerelease)|not))|sort_by(.created_at)|reverse' >"$RELEASES" ; then + errcode="$?" + echo "# Failed to download release information from ${RELEASE_API%/latest} $errcode" >&3 + return "$errcode" + fi + n="$(jq '.|length' <$RELEASES)" + if [[ "$n" < 2 ]]; then + echo "# Fewer than 2 ($n) stable releases detected in ${RELEASE_API%/latest}, can not run upgrade tests" >&3 + return 0 + fi + CURRENT_TAG="$(jq -r '.[0].tag_name' <"$RELEASES")" + export CURRENT_TAG="${CURRENT_TAG:1}" + PREVIOUS_TAG="$(jq -r '.[1].tag_name' <"$RELEASES")" + export PREVIOUS_TAG="${PREVIOUS_TAG:1}" +} + +teardown_file() { + [ -n "$RELEASES" ] && rm -f "$RELEASES" + true +} + # This is run for every test setup() { [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ -z "$PREVIOUS_TAG" ] && skip "Skipping upgrade test because no previous release detected" + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt # Turn off warning about detached head @@ -19,13 +62,9 @@ setup() { fi run git clone "${_REPO}" "$INSTALL_DIR/upgrade-getssl" - # Don't do version arithmetics any longer, look what was the previous version by getting the last - # line (starting with v) and the one before that from the list of tags. + cd "$INSTALL_DIR/upgrade-getssl" - # This sets CURRENT_TAG and PREVIOUS_TAG bash variables - eval $(git tag -l | awk 'BEGIN {cur="?.??"};/^v/{prv=cur;cur=substr($1,2)};END{ printf("CURRENT_TAG=\"%s\";PREVIOUS_TAG=\"%s\"\n",cur,prv)}') - # The version in the file, which we will overwrite FILE_VERSION=$(awk -F'"' '/^VERSION=/{print $2}' "$CODE_DIR/getssl") # If FILE_VERSION > CURRENT_TAG then either we are testing a push to master or the last version wasn't released @@ -57,11 +96,11 @@ teardown() { cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_TAG}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" - run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config ${GETSSL_CMD_HOST} + run "$INSTALL_DIR/upgrade-getssl/getssl" -d --check-config ${GETSSL_CMD_HOST} assert_success # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) - assert_line --regexp "A more recent version \(v(${CURRENT_TAG}|${FILE_VERSION})\) of getssl is available, please update" + assert_line --regexp "A more recent version \(v(${CURRENT_TAG}|${FILE_VERSION})\) than .* of getssl is available, please update" check_output_for_errors } @@ -84,15 +123,17 @@ teardown() { cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_TAG}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" - run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config --upgrade ${GETSSL_CMD_HOST} + run "$INSTALL_DIR/upgrade-getssl/getssl" -d --check-config --upgrade ${GETSSL_CMD_HOST} assert_success # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) - assert_line --regexp "Updated getssl from v${PREVIOUS_TAG} to v(${CURRENT_TAG}|${FILE_VERSION})" + assert_line --regexp "Installed v(${CURRENT_TAG}|${FILE_VERSION}), restarting" } @test "Test that we can upgrade to the newer version when invoking as \"bash ./getssl\"" { + skip "Makefile doesn't support bash ./getssl" + # Note that `bash getssl` will fail if the CWD isn't in the PATH and an upgrade occurs if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -111,9 +152,9 @@ teardown() { cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_TAG}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" - run bash ./getssl --check-config --upgrade ${GETSSL_CMD_HOST} + run bash ./getssl -d --check-config --upgrade ${GETSSL_CMD_HOST} assert_success # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) - assert_line --regexp "Updated getssl from v${PREVIOUS_TAG} to v(${CURRENT_TAG}|${FILE_VERSION})" + assert_line --regexp "Installed v(${CURRENT_TAG}|${FILE_VERSION}), restarting" } diff --git a/test/4-more-than-10-hosts.bats b/test/4-more-than-10-hosts.bats index f62d2e6..143afb4 100644 --- a/test/4-more-than-10-hosts.bats +++ b/test/4-more-than-10-hosts.bats @@ -39,7 +39,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors # Remove all the dns aliases diff --git a/test/5-secp384-http01.bats b/test/5-secp384-http01.bats index 5ddf0d6..a108c27 100644 --- a/test/5-secp384-http01.bats +++ b/test/5-secp384-http01.bats @@ -33,7 +33,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors } @@ -56,7 +56,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors } diff --git a/test/8-staging-ecdsa.bats b/test/8-staging-ecdsa.bats index 67e657a..797ce04 100644 --- a/test/8-staging-ecdsa.bats +++ b/test/8-staging-ecdsa.bats @@ -23,7 +23,7 @@ teardown() { setup_environment init_getssl sed -e 's/rsa/prime256v1/g' < "${CODE_DIR}/test/test-config/${CONFIG_FILE}" > "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" - run ${CODE_DIR}/getssl -d "$GETSSL_HOST" + run ${CODE_DIR}/getssl -U -d "$GETSSL_HOST" assert_success check_output_for_errors "debug" } @@ -40,7 +40,7 @@ teardown() { if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi - run ${CODE_DIR}/getssl -d -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors "debug" cleanup_environment @@ -63,7 +63,7 @@ teardown() { setup_environment init_getssl sed -e 's/rsa/secp384r1/g' < "${CODE_DIR}/test/test-config/${CONFIG_FILE}" > "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" - run ${CODE_DIR}/getssl -d "$GETSSL_HOST" + run ${CODE_DIR}/getssl -U -d "$GETSSL_HOST" assert_success check_output_for_errors "debug" } @@ -80,7 +80,7 @@ teardown() { if [ -z "$STAGING" ]; then skip "Running internal tests, skipping external test" fi - run ${CODE_DIR}/getssl -d -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors "debug" cleanup_environment diff --git a/test/9-multiple-domains-dns01.bats b/test/9-multiple-domains-dns01.bats index 12bb2e1..c540d9a 100644 --- a/test/9-multiple-domains-dns01.bats +++ b/test/9-multiple-domains-dns01.bats @@ -39,7 +39,7 @@ setup() { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" fi - run ${CODE_DIR}/getssl -f $GETSSL_HOST + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors # Remove all the dns aliases diff --git a/test/9-test--all.bats b/test/9-test--all.bats index 35697fd..bab1ced 100644 --- a/test/9-test--all.bats +++ b/test/9-test--all.bats @@ -29,7 +29,7 @@ setup() { cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" # Run test - run ${CODE_DIR}/getssl --all + run ${CODE_DIR}/getssl -U -d --all # Check success conditions assert_success diff --git a/test/Dockerfile-alpine b/test/Dockerfile-alpine index b0a0ae1..667512e 100644 --- a/test/Dockerfile-alpine +++ b/test/Dockerfile-alpine @@ -2,7 +2,7 @@ FROM alpine:latest # Note this image uses busybox awk instead of gawk -RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash lftp vsftpd openssh-server +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash lftp vsftpd openssh-server jq WORKDIR /root diff --git a/test/Dockerfile-bash4-0 b/test/Dockerfile-bash4-0 index 0dae149..8c92f8e 100644 --- a/test/Dockerfile-bash4-0 +++ b/test/Dockerfile-bash4-0 @@ -2,7 +2,7 @@ FROM bash:4.0 # https://hub.docker.com/_/bash -RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server jq WORKDIR /root diff --git a/test/Dockerfile-bash4-2 b/test/Dockerfile-bash4-2 index dd1cb11..1f0f7f3 100644 --- a/test/Dockerfile-bash4-2 +++ b/test/Dockerfile-bash4-2 @@ -2,7 +2,7 @@ FROM bash:4.2 # https://hub.docker.com/_/bash -RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server jq WORKDIR /root diff --git a/test/Dockerfile-bash5-0 b/test/Dockerfile-bash5-0 index 260290d..a437388 100644 --- a/test/Dockerfile-bash5-0 +++ b/test/Dockerfile-bash5-0 @@ -2,7 +2,7 @@ FROM bash:5.0 # https://hub.docker.com/_/bash -RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server +RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server jq WORKDIR /root diff --git a/test/Dockerfile-centos6 b/test/Dockerfile-centos6 index e16388f..f8d08b2 100644 --- a/test/Dockerfile-centos6 +++ b/test/Dockerfile-centos6 @@ -12,7 +12,7 @@ RUN sed -i 's/enabled=1/enabled=0/g' /etc/yum/pluginconf.d/fastestmirror.conf && # Update and install required software RUN yum -y install epel-release -RUN yum -y install git curl dnsutils ldns wget nginx +RUN yum -y install git curl dnsutils ldns wget nginx jq RUN yum -y install ftp vsftpd RUN yum -y install openssh-server diff --git a/test/Dockerfile-centos7 b/test/Dockerfile-centos7 index 56dff7d..400dcea 100644 --- a/test/Dockerfile-centos7 +++ b/test/Dockerfile-centos7 @@ -3,7 +3,7 @@ FROM centos:centos7 # Update and install required software RUN yum -y update RUN yum -y install epel-release -RUN yum -y install git curl ldns bind-utils wget which nginx +RUN yum -y install git curl ldns bind-utils wget which nginx jq RUN yum -y install ftp vsftpd RUN yum -y install openssh-server diff --git a/test/Dockerfile-centos7-duckdns b/test/Dockerfile-centos7-duckdns index 96a5fab..46bd254 100644 --- a/test/Dockerfile-centos7-duckdns +++ b/test/Dockerfile-centos7-duckdns @@ -5,7 +5,7 @@ FROM centos:centos7 # Update and install required software RUN yum -y update RUN yum -y install epel-release -RUN yum -y install git curl bind-utils ldns wget which nginx +RUN yum -y install git curl bind-utils ldns wget which nginx jq # Set locale ENV LANG en_US.UTF-8 diff --git a/test/Dockerfile-centos7-dynu b/test/Dockerfile-centos7-dynu index cabd7eb..f196c5d 100644 --- a/test/Dockerfile-centos7-dynu +++ b/test/Dockerfile-centos7-dynu @@ -5,7 +5,7 @@ FROM centos:centos7 # Update and install required software RUN yum -y update RUN yum -y install epel-release -RUN yum -y install git curl bind-utils ldns wget which nginx +RUN yum -y install git curl bind-utils ldns wget which nginx jq # Set locale ENV LANG en_US.UTF-8 diff --git a/test/Dockerfile-centos8 b/test/Dockerfile-centos8 index 4ac3114..552e1d9 100644 --- a/test/Dockerfile-centos8 +++ b/test/Dockerfile-centos8 @@ -5,7 +5,7 @@ FROM centos:centos8 # Update and install required software RUN yum -y update RUN yum -y install epel-release -RUN yum -y install git curl bind-utils wget which nginx +RUN yum -y install git curl bind-utils wget which nginx jq RUN yum -y install ftp vsftpd RUN yum -y install openssh-server diff --git a/test/Dockerfile-debian b/test/Dockerfile-debian index 1a57107..0deedff 100644 --- a/test/Dockerfile-debian +++ b/test/Dockerfile-debian @@ -4,7 +4,7 @@ FROM debian:latest # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light jq RUN apt-get install -y ftp vsftpd RUN apt-get install -y openssh-server RUN apt-get install -y locales # for idn testing diff --git a/test/Dockerfile-rockylinux8 b/test/Dockerfile-rockylinux8 index 4b7a135..37bff04 100644 --- a/test/Dockerfile-rockylinux8 +++ b/test/Dockerfile-rockylinux8 @@ -3,7 +3,7 @@ FROM rockylinux/rockylinux:8 # Update and install required software RUN yum -y update RUN yum -y install epel-release -RUN yum -y install git curl bind-utils wget which nginx +RUN yum -y install git curl bind-utils wget which nginx jq RUN yum -y install ftp vsftpd RUN yum -y install openssh-server RUN yum -y install glibc-locale-source glibc-langpack-en # for en_US.UTF-8 support diff --git a/test/Dockerfile-ubuntu b/test/Dockerfile-ubuntu index 5dee554..9ee83c6 100644 --- a/test/Dockerfile-ubuntu +++ b/test/Dockerfile-ubuntu @@ -7,7 +7,7 @@ ENV DEBIAN_FRONTEND noninteractive # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light jq RUN apt-get install -y vim dos2unix # for debugging RUN apt-get install -y ftp vsftpd RUN apt-get install -y openssh-server diff --git a/test/Dockerfile-ubuntu-duckdns b/test/Dockerfile-ubuntu-duckdns index c4fdc6a..783a151 100644 --- a/test/Dockerfile-ubuntu-duckdns +++ b/test/Dockerfile-ubuntu-duckdns @@ -12,7 +12,7 @@ ENV dynamic_dns "duckdns" # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light jq RUN apt-get install -y vim dos2unix # for debugging RUN apt-get install -y locales # for idn testing diff --git a/test/Dockerfile-ubuntu-dynu b/test/Dockerfile-ubuntu-dynu index 68f5c06..a84dc08 100644 --- a/test/Dockerfile-ubuntu-dynu +++ b/test/Dockerfile-ubuntu-dynu @@ -12,7 +12,7 @@ ENV dynamic_dns "dynu" # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light jq RUN apt-get install -y vim dos2unix # for debugging RUN apt-get install -y locales # for idn testing diff --git a/test/Dockerfile-ubuntu16 b/test/Dockerfile-ubuntu16 index 8e4ecae..396d13d 100644 --- a/test/Dockerfile-ubuntu16 +++ b/test/Dockerfile-ubuntu16 @@ -5,7 +5,7 @@ FROM ubuntu:xenial # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light jq RUN apt-get install -y ftp vsftpd RUN apt-get install -y openssh-server RUN apt-get install -y locales # for idn testing diff --git a/test/Dockerfile-ubuntu18 b/test/Dockerfile-ubuntu18 index 98b62d5..76ce362 100644 --- a/test/Dockerfile-ubuntu18 +++ b/test/Dockerfile-ubuntu18 @@ -5,7 +5,7 @@ FROM ubuntu:bionic # Update and install required software RUN apt-get update --fix-missing -RUN apt-get install -y git curl dnsutils ldnsutils wget gawk nginx-light +RUN apt-get install -y git curl dnsutils ldnsutils wget gawk nginx-light jq RUN apt-get install -y ftp vsftpd RUN apt-get install -y openssh-server RUN apt-get install -y locales # for idn testing diff --git a/test/debug-test.sh b/test/debug-test.sh index ac94b53..07e6cd6 100755 --- a/test/debug-test.sh +++ b/test/debug-test.sh @@ -24,7 +24,7 @@ if grep -q pebble "${CONFIG_FILE}"; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi -"${CODE_DIR}/getssl" -c "$GETSSL_HOST" 3>&1 +"${CODE_DIR}/getssl" -U -c "$GETSSL_HOST" 3>&1 cp "${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" # shellcheck disable=SC2086 -"${CODE_DIR}/getssl" ${DEBUG} -f "$GETSSL_HOST" 3>&1 +"${CODE_DIR}/getssl" -U ${DEBUG} -f "$GETSSL_HOST" 3>&1 diff --git a/test/test_helper.bash b/test/test_helper.bash index 0827adf..37f77cd 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -47,12 +47,12 @@ create_certificate() { # Create certificate cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" # shellcheck disable=SC2086 - run ${CODE_DIR}/getssl -d "$@" "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d "$@" "$GETSSL_CMD_HOST" } init_getssl() { # Run initialisation (create account key, etc) - run ${CODE_DIR}/getssl -d -c "$GETSSL_CMD_HOST" + run ${CODE_DIR}/getssl -U -d -c "$GETSSL_CMD_HOST" assert_success [ -d "$INSTALL_DIR/.getssl" ] } From fa97be6a38174fca92fb3de69059de4ac28356b9 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Fri, 27 Aug 2021 11:14:40 -0400 Subject: [PATCH 285/308] Provide default credentials for srvrco (temporary) Use hard-coded default credentials for srvrco when GitHub secrets are not installed. This is a security issue for srvrco, but a fix seems to be difficult. --- .github/workflows/run-tests-staging-duckdns.yml | 2 +- .github/workflows/run-tests-staging-dynu.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests-staging-duckdns.yml b/.github/workflows/run-tests-staging-duckdns.yml index 3a8efea..87da158 100644 --- a/.github/workflows/run-tests-staging-duckdns.yml +++ b/.github/workflows/run-tests-staging-duckdns.yml @@ -12,7 +12,7 @@ on: branches: - master env: - DUCKDNS_TOKEN: ${{ secrets.DUCKDNS_TOKEN }} + DUCKDNS_TOKEN: ${{ secrets.DUCKDNS_TOKEN == '' && '1d616aa9-b8e4-4bb4-b312-3289de82badb' || secrets.DUCKDNS_TOKEN }} jobs: test-centos7-duckdns: runs-on: ubuntu-latest diff --git a/.github/workflows/run-tests-staging-dynu.yml b/.github/workflows/run-tests-staging-dynu.yml index 2f9ec4f..fde2ba2 100644 --- a/.github/workflows/run-tests-staging-dynu.yml +++ b/.github/workflows/run-tests-staging-dynu.yml @@ -12,7 +12,7 @@ on: branches: - master env: - DYNU_API_KEY: ${{ secrets.DYNU_API_KEY }} + DYNU_API_KEY: ${{ secrets.DYNU_API_KEY == '' && '65cXefd35XbYf36546eg5dYcZT6X52Y2' || secrets.DYNU_API_KEY }} jobs: test-centos7-dynu: runs-on: ubuntu-latest From 2f4523642317f73527d926c55f61e35c02fbf252 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Fri, 27 Aug 2021 14:18:00 -0400 Subject: [PATCH 286/308] Suppress test failure when release description contains "error" Upgrade test checks for "error" in output. But release descriptions can have "fix error in ..." Don't run this check. Checking that a new version is detected suffices. --- test/32-test-upgrade.bats | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index fa000bb..823ec96 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -101,7 +101,8 @@ teardown() { # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) assert_line --regexp "A more recent version \(v(${CURRENT_TAG}|${FILE_VERSION})\) than .* of getssl is available, please update" - check_output_for_errors + # output can contain "error" in release description + # check_output_for_errors } From 01e3728d8430d0713421f8efbbe574ae13b1c381 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Thu, 2 Sep 2021 10:01:44 -0400 Subject: [PATCH 287/308] Compare version numbers properly getssl uses cURL's version to determine what command options are valid. The previous shortcuts will fail when curl V8.10 is released. (8.9 is greater than 8.10). V8 is planned for release, in part to avoid a minor version of 100, which also would fail. check_version() will compare full or partial version strings by component, and is true if $1 is at least $2. --- getssl | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index f7a58b9..c8dfde7 100755 --- a/getssl +++ b/getssl @@ -269,6 +269,7 @@ # 2021-07-30 Prefer API V2 when both offered (tlhackque) (#690) (2.40) # 2021-07-30 Run tests with -d to catch intermittent failures, Use fork's repo for upgrade tests. (tlhackque) (#692) (2.41) # 2021-08-26 Improve upgrade check & make upgrade do a full install when possible (tlhackque) (#694) (2.42) +# 2021-09-02 Fix version compare - cURL v8 may have single digit minor numbers. (tlhackque) (2.43) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -277,7 +278,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.42" +VERSION="2.43" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -924,6 +925,27 @@ check_getssl_upgrade() { # check if a more recent release is available graceful_exit } +check_version() { # true if version string $1 >= $2 + local v1 v2 i n1 n2 n + # $1 and $2 can be different lengths, but all parts must be numeric + if [[ "$1" == "$2" ]] ; then return 0; fi + local IFS='.' + # shellcheck disable=SC2206 + v1=($1) + # shellcheck disable=SC2206 + v2=($2) + n1="${#v1[@]}" + n2="${#v2[@]}" + if [[ "$n1" -ge "$n2" ]] ; then n="$n1" ; else n="$n2" ; fi + for ((i=0; i Date: Sun, 26 Sep 2021 21:44:35 +0200 Subject: [PATCH 288/308] delete key file when key alg has changed --- getssl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/getssl b/getssl index 3bb6272..4f71639 100755 --- a/getssl +++ b/getssl @@ -3135,6 +3135,21 @@ if [[ "$REUSE_PRIVATE_KEY" != "true" ]]; then rm -f "$DOMAIN_DIR/${DOMAIN}.ec.key" fi fi + +# check if private key alg has changed from RSA to EC (or vice versa) +if [[ "$DUAL_RSA_ECDSA" == "false" ]] && [[ -s "$DOMAIN_DIR/${DOMAIN}.key" ]]; then + case "${PRIVATE_KEY_ALG}" in + rsa) + if grep --silent -- "-----BEGIN EC PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then + rm -f "$DOMAIN_DIR/${DOMAIN}.key" + fi ;; + prime256v1|secp384r1|secp521r1) + if grep --silent -- "-----BEGIN RSA PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then + rm -f "$DOMAIN_DIR/${DOMAIN}.key" + fi ;; + esac +fi + # create new domain keys if they don't already exist if [[ "$DUAL_RSA_ECDSA" == "false" ]]; then create_key "${PRIVATE_KEY_ALG}" "$DOMAIN_DIR/${DOMAIN}.key" "$DOMAIN_KEY_LENGTH" From b013c9abb3f700562d671f3f61656cf48e41fc03 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 27 Sep 2021 21:19:31 +0100 Subject: [PATCH 289/308] Temporarily revert changes to upgrade using `make` Reduce test noise --- getssl | 178 ++++++------------ test/1-simple-http01-dig.bats | 4 +- test/1-simple-http01-nslookup.bats | 4 +- test/1-simple-http01-two-acl.bats | 8 +- test/1-simple-http01.bats | 4 +- test/10-mixed-case.bats | 4 +- test/11-test--install.bats | 12 +- test/11-test-no-domain-storage.bats | 6 +- test/12-auto-upgrade-v1.bats | 45 +---- test/13-notify-valid.bats | 4 +- test/14-test-revoke.bats | 6 +- test/15-test-revoke-no-suffix.bats | 6 +- test/16-test-bad-acl.bats | 4 +- test/17-test-spaces-in-sans-dns01.bats | 33 ++-- test/17-test-spaces-in-sans-http01.bats | 32 ++-- test/18-retry-dns-add.bats | 5 +- test/19-test-add-to-sans.bats | 14 +- test/2-simple-dns01-dig.bats | 20 +- test/2-simple-dns01-nslookup.bats | 6 +- test/20-wildcard-simple.bats | 4 +- test/21-wildcard-dual-rsa.bats | 4 +- ...dcard-dual-rsa-ecdsa-copy-2-locations.bats | 4 +- test/23-wildcard-check-globbing.bats | 4 +- test/24-wildcard-sans.bats | 14 +- test/25-wildcard-all.bats | 4 +- test/26-wildcard-revoke.bats | 8 +- test/27-wildcard-existing-cert.bats | 4 +- test/28-wildcard-error-http01-validation.bats | 4 +- test/29-check-mktemp-failure.bats | 4 +- test/3-dual-rsa-ecdsa.bats | 6 +- test/30-handle-dig-failure.bats | 8 +- test/31-test-posix-error.bats | 6 +- test/32-test-upgrade.bats | 47 ++++- test/33-ftp.bats | 4 +- test/34-ftp-passive.bats | 4 +- test/35-preferred-chain.bats | 4 +- test/36-full-chain-inc-root.bats | 4 +- test/37-idn.bats | 26 +-- test/38-idn-http01-check-noidnout.bats | 20 +- test/4-more-than-10-hosts.bats | 36 ++-- test/5-secp384-http01.bats | 4 +- test/6-dual-rsa-ecdsa-copy-2-locations.bats | 14 +- test/7-test-renewal.bats | 15 +- test/8-staging-ecdsa.bats | 46 ++--- test/9-multiple-domains-dns01.bats | 32 ++-- test/9-test--all.bats | 4 +- test/restart-ftpd | 2 + test/restart-nginx | 2 + test/run-test.cmd | 4 +- test/test-config/getssl-dns01.cfg | 3 - test/test-config/getssl-http01.cfg | 3 - test/test_helper.bash | 16 +- test/u1-test-get_auth_dns-dig.bats | 7 +- test/u2-test-get_auth_dns-drill.bats | 7 +- test/u3-mktemp-template.bats | 4 +- test/u4-create-csr-and-ifs.bats | 7 +- .../u5-test-get_auth_dns-no-root-servers.bats | 7 +- test/u6-test-combined-directory.bats | 8 +- 58 files changed, 382 insertions(+), 417 deletions(-) diff --git a/getssl b/getssl index c8dfde7..aeb3244 100755 --- a/getssl +++ b/getssl @@ -288,10 +288,11 @@ CA="https://acme-staging-v02.api.letsencrypt.org/directory" CHALLENGE_CHECK_TYPE="http" CHECK_REMOTE_WAIT=0 CHECK_REMOTE="true" -LIMIT_API="https://api.github.com/rate_limit" if [[ -n "${GITHUB_REPOSITORY}" ]] ; then + CODE_LOCATION="https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/getssl/master/getssl" RELEASE_API="https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/latest" else + CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" RELEASE_API="https://api.github.com/repos/srvrco/getssl/releases/latest" fi CSR_SUBJECT="/" @@ -317,7 +318,6 @@ REUSE_PRIVATE_KEY="true" SERVER_TYPE="https" SKIP_HTTP_TOKEN_CHECK="false" SSLCONF="$(openssl version -d 2>/dev/null| cut -d\" -f2)/openssl.cnf" -TEMP_UPGRADE_DIR="" TOKEN_USER_ID="" USE_SINGLE_ACL="false" WORKING_DIR_CANDIDATES=("/etc/getssl" "${PROGDIR}/conf" "${PROGDIR}/.getssl" "${HOME}/.getssl") @@ -348,7 +348,6 @@ _QUIET=0 _RECREATE_CSR=0 _REDIRECT_OUTPUT="1>/dev/null 2>&1" _REVOKE=0 -_RUNNING_TEST=0 _TEST_SKIP_CNAME_CALL=0 _TEST_SKIP_SOA_CALL=0 _UPGRADE=0 @@ -552,7 +551,7 @@ check_challenge_completion_dns() { # perform validation via DNS challenge # add +noidnout if idn-domain so search for domain in results works if [[ "${d}" == xn--* || "${d}" == *".xn--"* ]]; then if [[ "$DNS_CHECK_FUNC" == "nslookup" || "$DNS_CHECK_FUNC" == "host" || ("$DNS_CHECK_FUNC" == "dig" && "$DIG_SUPPORTS_NOIDNOUT" == "false") ]]; then - info "Warning: idn domain but $DNS_CHECK_FUNC doesn't support +noidnout" + info "Info: idn domain but $DNS_CHECK_FUNC doesn't support +noidnout" else debug "adding +noidnout to DNS_CHECK_OPTIONS" DNS_CHECK_OPTIONS="$DNS_CHECK_OPTIONS +noidnout" @@ -604,9 +603,9 @@ check_challenge_completion_dns() { # perform validation via DNS challenge ntries=$(( ntries + 1 )) if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 )) == 0 ]]; then - test_output "Deleting DNS RR via command: ${DNS_DEL_COMMAND}" + debug "Deleting DNS via command: ${DNS_DEL_COMMAND}" del_dns_rr "${d}" "${auth_key}" - test_output "Retrying adding DNS via command: ${DNS_ADD_COMMAND}" + debug "Retrying adding DNS via command: ${DNS_ADD_COMMAND}" add_dns_rr "${d}" "${auth_key}" \ || error_exit "DNS_ADD_COMMAND failed for domain ${d}" fi @@ -764,45 +763,16 @@ check_config() { # check the config files for all obvious errors debug "${DOMAIN}: check_config completed - all OK" } -# Quota generally shouldn't be an issue - except for tests -# Rate limits are per-IP address -check_github_quota() { - local need remaining reset limits now - need="$1" - while true ; do - limits="$(curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" -H 'Accept: application/vnd.github.v3+json' "$LIMIT_API" | sed -e's/\("[^:]*": *\("[^""]*",\|[^,]*[,}]\)\)/\r\n\1/g' | sed -ne'/"core":/,/}/p')" - errcode=$? - if [[ $errcode -eq 60 ]]; then - error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" - elif [[ $errcode -gt 0 ]]; then - error_exit "curl error checking releases: $errcode" - fi - limits="$(sed -e's/^ *//g' <<<"${limits}")" - remaining="$(sed -e'/^"remaining": *[0-9]/!d;s/^"remaining": *\([0-9][0-9]*\).*$/\1/' <<<"${limits}")" - reset="$(sed -e'/^"reset": *[0-9]/!d;s/^"reset": *\([0-9][0-9]*\).*$/\1/' <<<"${limits}")" - if [[ "$remaining" -ge "$need" ]] ; then return 0 ; fi - limit="$(sed -e'/^"limit": *[0-9]/!d;s/^"limit": *\([0-9][0-9]*\).*$/\1/' <<<"${limits}")" - if [[ "$limit" -lt "$need" ]] ; then - error_exit "GitHub API request $need exceeds limit $limit" - fi - now="$(date +%s)" - while [[ "$now" -lt "$reset" ]] ; do - info "sleeping $(( "$reset" - "$now" )) seconds for GitHub quota" - sleep "$(( "$reset" - "$now" ))" - now="$(date +%s)" - done - done -} check_getssl_upgrade() { # check if a more recent release is available - check_github_quota 2 # Check GitHub for latest stable release, or a specified tag if [[ -n "$_UPGRADE_TO_TAG" ]]; then RELEASE_API="$RELEASE_API/tags/$_UPGRADE_TO_TAG" fi - local release_data release_tag release_ver local_ver release_desc release_url release_tar NEWCMD + local release_data release_tag release_ver local_ver release_desc NEWCMD debug "Checking for releases at $RELEASE_API" # Sometimes the json is pretty-printed, sometimes not. Loosely tied to --user-agent, but not # always. Normalize it enough to get the 3 elements necessary. Oh, for jq... + # shellcheck disable=SC2086 release_data="$(curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" -H 'Accept: application/vnd.github.v3+json' "$RELEASE_API" | sed -e's/\("[^:]*": *\("[^""]*",\|[^,]*[,}]\)\)/\r\n\1/g')" errcode=$? if [[ $errcode -eq 60 ]]; then @@ -810,7 +780,8 @@ check_getssl_upgrade() { # check if a more recent release is available elif [[ $errcode -gt 0 ]]; then error_exit "curl error checking releases: $errcode" fi - debug "$release_data" + # Replace error in release description with _error (which is ignored by check_output_for_errors() in the tests) + debug "${release_data//error/_error}" release_data="$(sed -e's/^ *//g' <<<"${release_data}")" release_tag="$(sed -e'/^"tag_name": *"/!d;s/^"tag_name": *"\([^""]*\).*$/\1/' <<<"${release_data}")" if [[ "${release_tag:0:1}" != 'v' ]] ; then @@ -836,74 +807,47 @@ check_getssl_upgrade() { # check if a more recent release is available info "The easiest way is to use the -u or --upgrade flag" info "" info "Release ${release_tag} summary" - info "$release_desc" + # Replace error in release description with _error (which is ignored by check_output_for_errors() in the tests) + info "${release_desc//error/_error}" info "" fi return 0; fi - # Find, download, and unpack the tarball containing the selected release - release_url="$(sed -e'/^"tarball_url": *"/!d;s/^"tarball_url": *"\([^""]*\).*$/\1/' <<<"${release_data}")" - debug "Release url '$release_url'" - requires tar - TEMP_UPGRADE_DIR="$(mktemp -d 2>/dev/null || mktemp -d -t getssl.XXXXXXXX)" - if [ "$TEMP_UPGRADE_DIR" == "" ]; then + + # Download the latest tag + TEMP_UPGRADE_FILE="$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX)" + if [ "$TEMP_UPGRADE_FILE" == "" ]; then error_exit "mktemp failed" fi - release_tar="$TEMP_UPGRADE_DIR/getssl-${release_tag}.tgz" - debug "Downloading release to $release_tar" - check_github_quota 1 - curl ${_NOMETER:---silent} -L --user-agent "$CURL_USERAGENT" -H 'Accept: application/vnd.github.v3+json' "$release_url" --output "$release_tar" + CODE_LOCATION=$(sed -e"s/master/${release_tag}/" <<<"$CODE_LOCATION") + # shellcheck disable=SC2086 + curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" + errcode=$? if [[ $errcode -eq 60 ]]; then error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" elif [[ $errcode -gt 0 ]]; then error_exit "curl error downloading release: $errcode" fi - if ! tar -C "${TEMP_UPGRADE_DIR}" --strip-components 1 -xzf "$release_tar" ; then - error_exit "failed to unpack release: $?" - fi - # Inhibit check for upgrades when running the new version - NEWCMD="$(sed -e's/ -\(u\|-upgrade\|U\|-nocheck\)//g;s/^\([^ ]* \)/\1--nocheck /' <<<"$ORIGCMD")" - # Install everything with make - if it's available - if [ -n "$(command -v 'make' 2>/dev/null)" ]; then - if [[ "${0%/usr/bin/getssl}" != "$0" ]] ; then - export DESTDIR="${0%/usr/bin/getssl}" - fi - if [[ ${_MUTE} -eq 0 ]]; then - if ! make -C "${TEMP_UPGRADE_DIR}" "install" ; then - error_exit "Installation failed: $?" - fi - else - if ! make -s -C "${TEMP_UPGRADE_DIR}" "install" >/dev/null ; then - error_exit "Installation failed: $?" - fi - fi - clean_up - if [[ ${_MUTE} -eq 0 ]]; then - info "Installed $release_tag, restarting with $NEWCMD" - fi - if ! eval "$NEWCMD"; then - error_exit "Running upgraded getssl failed" - fi - graceful_exit - fi - # Fall back to 'install' and just the main script. - if [[ ${_MUTE} -eq 0 ]]; then - info "'make' is not available. getssl will be installed, but support scripts will not be upgraded" - info "To stay completely up-to-date, please install make" - fi + if ! install "$0" "${0}.v${VERSION}"; then error_exit "problem renaming old version while updating, check permissions" fi - if ! install -m 700 "$TEMP_UPGRADE_DIR/getssl" "$0"; then + if ! install -m 700 "$TEMP_UPGRADE_FILE" "$0"; then error_exit "problem installing new version while updating, check permissions" fi + if [[ ${_MUTE} -eq 0 ]]; then - echo "Updated getssl from v${VERSION} to $release_tag" + echo "Updated getssl from v${VERSION} to v${release_tag}" echo "The old version remains as ${0}.v${VERSION} and should be removed" + echo "These update notifications can be turned off using the -Q option" + echo "" + echo "Updates are;" + awk "/\(${VERSION}\)$/ {s=1} s; /\(${release_tag}\)$/ || /^# ----/ {s=0}" "$TEMP_UPGRADE_FILE" | awk '{if(NR>1)print}' echo "" fi - # This version can't be removed since disappearing can confuse bash. + + # Delete old versions, but not the version just upgraded (which can't be removed since disappearing can confuse bash) declare -a getssl_versions shopt -s nullglob for getssl_version in "$0".v*; do @@ -915,6 +859,9 @@ check_getssl_upgrade() { # check if a more recent release is available if [[ -n "${getssl_versions[*]}" ]] ; then rm "${getssl_versions[@]}" fi + + # Inhibit check for upgrades when running the new version + NEWCMD="$(sed -e's/ -\(u\|-upgrade\|U\|-nocheck\)//g;s/^\([^ ]* \)/\1--nocheck /' <<<"$ORIGCMD")" clean_up if [[ ${_MUTE} -eq 0 ]]; then info "Installed $release_tag, restarting with $NEWCMD" @@ -922,6 +869,7 @@ check_getssl_upgrade() { # check if a more recent release is available if ! eval "$NEWCMD"; then error_exit "Running upgraded getssl failed" fi + graceful_exit } @@ -966,13 +914,6 @@ clean_up() { # Perform pre-exit housekeeping rm -rf "${TEMP_DIR:?}" fi fi - if [[ -n "$TEMP_UPGRADE_DIR" ]] && [[ -d "$TEMP_UPGRADE_DIR" ]]; then - if [ "${TEMP_UPGRADE_DIR}" -ef "/tmp" ]; then - info "Not going to delete TEMP_UPGRADE_DIR ${TEMP_UPGRADE_DIR} as it appears to be /tmp" - else - rm -rf "${TEMP_UPGRADE_DIR:?}" - fi - fi } copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. @@ -1071,6 +1012,7 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required. fromfile=$(basename "$from") debug "davs user=$davsuser - pass=$davspass - host=$davshost port=$davsport dir=$davsdirn file=$davsfile" debug "from dir=$fromdir file=$fromfile" + # shellcheck disable=SC2086 curl ${_NOMETER} -u "${davsuser}:${davspass}" -T "${fromdir}/${fromfile}" "https://${davshost}:${davsport}${davsdirn}${davsfile}" elif [[ "${to:0:6}" == "ftpes:" ]] || [[ "${to:0:5}" == "ftps:" ]] ; then debug "using ftp to copy the file from $from" @@ -1139,7 +1081,7 @@ create_csr() { # create a csr using a given key (if it doesn't already exist) info "existing csr at $csr_file does not have the same domains as the config - re-create-csr" _RECREATE_CSR=1 else - test_output "Existing csr at $csr_file contains same domains as the config" + debug "Existing csr at $csr_file contains same domains as the config" fi fi # end of ... check if domain csr exists - if not then create it @@ -1272,9 +1214,9 @@ date_renew() { # calculates the renewal time in epoch debug() { # write out debug info if the debug flag has been set if [[ ${_USE_DEBUG} -eq 1 ]]; then - # If running tests then output in TAP format (for debugging tests) - if [[ ${_RUNNING_TEST} -eq 1 ]]; then - echo "# $(date "+%b %d %T") ${FUNCNAME[1]}:${BASH_LINENO[1]}" "$@" >&3 + # If running tests then verbose output (for debugging tests) + if [[ -n ${BATS_RUN_TMPDIR} ]]; then + echo "$(date "+%b %d %T") ${FUNCNAME[1]}:${BASH_LINENO[1]}" "$@" else echo " " echo "$@" @@ -1282,15 +1224,9 @@ debug() { # write out debug info if the debug flag has been set fi } -test_output() { # write out debug output for testing - if [[ ${_RUNNING_TEST} -eq 1 ]]; then - echo "#" "$@" - fi -} - error_exit() { # give error message on error exit echo -e "${PROGNAME}: ${1:-"Unknown Error"}" >&2 - if [[ ${_RUNNING_TEST} -eq 1 ]] || [[ ${_USE_DEBUG} -eq 1 ]] ; then + if [[ ${_USE_DEBUG} -eq 1 ]]; then traceback fi clean_up @@ -1507,6 +1443,7 @@ for d in "${alldomains[@]}"; do # ACME only allows port 80 (http), but redirects may use https. --insecure is used in case # those certificates are being renewed. Let's Encrypt does the same. In this case, we verify # that the correct data is returned, so this is safe. + # shellcheck disable=SC2086 if [[ ! "$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --insecure --silent --location "$wellknown_url")" == "$keyauthorization" ]]; then error_exit "for some reason could not reach $wellknown_url - please check it manually" fi @@ -1577,11 +1514,8 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n gad_s="@$gad_s" fi - # Check if domain is a CNAME, first - test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME" - # Two options here; either dig CNAME will return the CNAME and the NS or just the CNAME - debug Checking for CNAME using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME $gad_d $gad_s" + debug "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME $gad_d $gad_s" # shellcheck disable=SC2086 res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME "$gad_d" $gad_s| grep "^$gad_d") cname=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') @@ -1604,19 +1538,16 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n if [[ -z "$res" ]] && [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then # shellcheck disable=SC2086 if [[ "$HAS_DIG_OR_DRILL" == "drill" ]]; then - debug Using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -T $gad_d $gad_s" to find primary nameserver - test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS SOA" + debug Using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -T SOA $gad_d $gad_s" to find primary nameserver res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -T SOA "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W") else debug Using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS SOA +trace +nocomments $gad_d $gad_s" to find primary nameserver - test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS SOA" res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS SOA +trace +nocomments "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W") fi fi # Query for NS records if [[ -z "$res" ]]; then - test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS NS" debug Using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS NS $gad_d $gad_s" to find primary nameserver # shellcheck disable=SC2086 res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS NS "$gad_d" $gad_s | grep -E "IN\W(NS|SOA)\W") @@ -1646,7 +1577,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n primary_ns="$primary_ns $PUBLIC_DNS_SERVER" fi - test_output set primary_ns ="$primary_ns" + debug set primary_ns ="$primary_ns" return fi @@ -1751,6 +1682,7 @@ get_certificate() { # get certificate for csr, if all domains validated. CertData=$(awk ' $1 ~ "^Location" {print $2}' "$CURL_HEADER" |tr -d '\r') if [[ "$CertData" ]] ; then echo -----BEGIN CERTIFICATE----- > "$gc_certfile" + # shellcheck disable=SC2086 curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$CertData" | openssl base64 -e >> "$gc_certfile" echo -----END CERTIFICATE----- >> "$gc_certfile" info "Certificate saved in $CERT_FILE" @@ -1771,6 +1703,7 @@ get_certificate() { # get certificate for csr, if all domains validated. | sed 's/>//g') if [[ "$IssuerData" ]] ; then echo -----BEGIN CERTIFICATE----- > "$gc_cafile" + # shellcheck disable=SC2086 curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$IssuerData" | openssl base64 -e >> "$gc_cafile" echo -----END CERTIFICATE----- >> "$gc_cafile" info "The intermediate CA cert is in $gc_cafile" @@ -1829,6 +1762,7 @@ get_certificate() { # get certificate for csr, if all domains validated. cp "$gc_certfile" "$gc_fullchain" while [[ -n "$issuer_url" ]]; do debug Fetching certificate issuer from "$issuer_url" + # shellcheck disable=SC2086 issuer_cert=$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$issuer_url" | openssl x509 -inform der -outform pem) debug Fetched issuer certificate "$(echo "$issuer_cert" | openssl x509 -inform pem -noout -text | awk 'BEGIN {FS="Subject: "} NF==2 {print $2; exit}')" echo "$issuer_cert" >> "$gc_fullchain" @@ -1844,6 +1778,7 @@ get_certificate() { # get certificate for csr, if all domains validated. get_cr() { # get curl response url="$1" debug url "$url" + # shellcheck disable=SC2086 response=$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" --silent "$url") ret=$? debug response "${response//[$'\t\r\n']}" @@ -1967,12 +1902,12 @@ hex2bin() { # Remove spaces, add leading zero, escape as hex string ensuring no info() { # write out info as long as the quiet flag has not been set. if [[ ${_QUIET} -eq 0 ]]; then - # If running tests then output in TAP format as well (for debugging tests) - if [[ ${_RUNNING_TEST} -eq 1 ]]; then - echo "# $(date "+%b %d %T") ${FUNCNAME[1]}:${BASH_LINENO[1]}" "$@" >&3 + # If running tests then verbose output (for debugging tests) + if [[ -n ${BATS_RUN_TMPDIR} ]]; then + echo "$(date "+%b %d %T") ${FUNCNAME[1]}:${BASH_LINENO[1]}" "$@" + else + echo "$@" fi - - echo "$@" fi } @@ -2185,6 +2120,7 @@ obtain_ca_resource_locations() for suffix in "" "/directory" "/dir"; do # Obtain CA resource locations + # shellcheck disable=SC2086 ca_all_loc=$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" "${CA}${suffix}" 2>/dev/null) debug "ca_all_loc from ${CA}${suffix} gives $ca_all_loc" # APIv1 @@ -2756,12 +2692,6 @@ write_openssl_conf() { # write out a minimal openssl conf trap "signal_exit TERM" TERM HUP trap "signal_exit INT" INT -# When running tests, use debug mode to capture intermittent faults -# Test harness will Save output in a temporary file, which is displayed if an error occurs -if [[ ${_RUNNING_TEST} -eq 1 ]] ; then - _USE_DEBUG=1 -fi - # Parse command-line while [[ -n ${1+defined} ]]; do case $1 in @@ -2781,7 +2711,7 @@ while [[ -n ${1+defined} ]]; do -a | --all) _CHECK_ALL=1 ;; -k | --keep) - shift; + shift; echo "--keep has no effect" ;; -q | --quiet) _QUIET=1 ;; diff --git a/test/1-simple-http01-dig.bats b/test/1-simple-http01-dig.bats index 6c29ec6..1aab990 100644 --- a/test/1-simple-http01-dig.bats +++ b/test/1-simple-http01-dig.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -f /usr/bin/host ]; then mv /usr/bin/host /usr/bin/host.getssl.bak @@ -19,7 +19,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip if [ -f /usr/bin/host.getssl.bak ]; then mv /usr/bin/host.getssl.bak /usr/bin/host fi diff --git a/test/1-simple-http01-nslookup.bats b/test/1-simple-http01-nslookup.bats index aa71e1c..447b466 100644 --- a/test/1-simple-http01-nslookup.bats +++ b/test/1-simple-http01-nslookup.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -f /usr/bin/dig ]; then mv /usr/bin/dig /usr/bin/dig.getssl.bak @@ -19,7 +19,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip if [ -f /usr/bin/dig.getssl.bak ]; then mv /usr/bin/dig.getssl.bak /usr/bin/dig fi diff --git a/test/1-simple-http01-two-acl.bats b/test/1-simple-http01-two-acl.bats index b4bb3f1..1f3c7e8 100644 --- a/test/1-simple-http01-two-acl.bats +++ b/test/1-simple-http01-two-acl.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } @@ -23,9 +23,9 @@ setup() { CONFIG_FILE="getssl-http01-two-acl.cfg" setup_environment init_getssl - create_certificate -d + create_certificate assert_success assert_output --partial "to /var/www/html/.well-known/acme-challenge" assert_output --partial "to /var/webroot/html/.well-known/acme-challenge" - check_output_for_errors "debug" + check_output_for_errors } diff --git a/test/1-simple-http01.bats b/test/1-simple-http01.bats index 15205e1..6e5360d 100644 --- a/test/1-simple-http01.bats +++ b/test/1-simple-http01.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/10-mixed-case.bats b/test/10-mixed-case.bats index 382f19a..d55cf8a 100644 --- a/test/10-mixed-case.bats +++ b/test/10-mixed-case.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/11-test--install.bats b/test/11-test--install.bats index 186e8c6..e69cd4c 100644 --- a/test/11-test--install.bats +++ b/test/11-test--install.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } @@ -38,8 +38,8 @@ setup() { assert_success check_output_for_errors - assert_line 'Verification completed, obtaining certificate.' - assert_line 'Requesting certificate' + assert_line --partial 'Verification completed, obtaining certificate.' + assert_line --partial 'Requesting certificate' refute [ -d '$HOME/.getssl' ] } @@ -57,8 +57,8 @@ setup() { assert_success check_output_for_errors - refute_line 'Verification completed, obtaining certificate.' - refute_line 'Requesting certificate' + refute_line --partial 'Verification completed, obtaining certificate.' + refute_line --partial 'Requesting certificate' assert_line --partial 'copying domain certificate to' assert_line --partial 'copying private key to' assert_line --partial 'copying CA certificate to' diff --git a/test/11-test-no-domain-storage.bats b/test/11-test-no-domain-storage.bats index f61db28..c2c1179 100644 --- a/test/11-test-no-domain-storage.bats +++ b/test/11-test-no-domain-storage.bats @@ -6,10 +6,10 @@ load '/getssl/test/test_helper.bash' setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } @test "Check that if domain storage isn't set getssl doesn't try to delete /tmp" { @@ -23,5 +23,5 @@ teardown() { run ${CODE_DIR}/getssl -U -d -a assert_success check_output_for_errors - assert_line 'Not going to delete TEMP_DIR ///tmp as it appears to be /tmp' + assert_line --partial 'Not going to delete TEMP_DIR ///tmp as it appears to be /tmp' } diff --git a/test/12-auto-upgrade-v1.bats b/test/12-auto-upgrade-v1.bats index 1dc5139..a7cdb91 100644 --- a/test/12-auto-upgrade-v1.bats +++ b/test/12-auto-upgrade-v1.bats @@ -6,12 +6,15 @@ load '/getssl/test/test_helper.bash' setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } + + teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } + @test "Check that auto upgrade to v2 doesn't change pebble url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -22,17 +25,10 @@ teardown() { cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success - assert_line 'Using certificate issuer: https://pebble:14000/dir' + assert_line --partial 'Using certificate issuer: https://pebble:14000/dir' } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" -} -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip -} - @test "Check that auto upgrade to v2 doesn't change v2 staging url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -43,17 +39,10 @@ teardown() { cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success - assert_line 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' + assert_line --partial 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" -} -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip -} - @test "Check that auto upgrade to v2 doesn't change v2 prod url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -64,17 +53,10 @@ teardown() { cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success - assert_line 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' + assert_line --partial 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" -} -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip -} - @test "Check that auto upgrade to v2 changes v1 staging to v2 staging url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -85,17 +67,10 @@ teardown() { cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success - assert_line 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' + assert_line --partial 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" -} -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip -} - @test "Check that auto upgrade to v2 changes v1 prod to v2 prod url" { if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" @@ -106,5 +81,5 @@ teardown() { cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" run ${CODE_DIR}/getssl -U -d --check-config "$GETSSL_CMD_HOST" assert_success - assert_line 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' + assert_line --partial 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' } diff --git a/test/13-notify-valid.bats b/test/13-notify-valid.bats index 6c06123..f389744 100644 --- a/test/13-notify-valid.bats +++ b/test/13-notify-valid.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats index abc33cd..b9ad81b 100644 --- a/test/14-test-revoke.bats +++ b/test/14-test-revoke.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi @@ -45,5 +45,5 @@ setup() { run ${CODE_DIR}/getssl -U -d --revoke $CERT $KEY $CA assert_success - check_output_for_errors "debug" + check_output_for_errors } diff --git a/test/15-test-revoke-no-suffix.bats b/test/15-test-revoke-no-suffix.bats index 1eaa060..20cfbc9 100644 --- a/test/15-test-revoke-no-suffix.bats +++ b/test/15-test-revoke-no-suffix.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi @@ -51,5 +51,5 @@ setup() { run ${CODE_DIR}/getssl -U -d --revoke $CERT $KEY $CA assert_success - check_output_for_errors "debug" + check_output_for_errors } diff --git a/test/16-test-bad-acl.bats b/test/16-test-bad-acl.bats index e2feec5..8c7bc9c 100644 --- a/test/16-test-bad-acl.bats +++ b/test/16-test-bad-acl.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/17-test-spaces-in-sans-dns01.bats b/test/17-test-spaces-in-sans-dns01.bats index cc9efc7..f1bf718 100644 --- a/test/17-test-spaces-in-sans-dns01.bats +++ b/test/17-test-spaces-in-sans-dns01.bats @@ -6,14 +6,32 @@ load '/getssl/test/test_helper.bash' # This is run for every test +setup() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + + teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + +setup_file() { + # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + for prefix in a b c; do + curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + done + fi +} + + +teardown_file() { + if [ -z "$STAGING" ]; then + for prefix in a b c; do + curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a + done fi } @@ -25,11 +43,6 @@ setup() { CONFIG_FILE="getssl-dns01-spaces-sans.cfg" setup_environment - # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) - for prefix in a b c; do - curl --silent -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 @@ -85,8 +98,4 @@ setup() { assert_success check_output_for_errors cleanup_environment - - for prefix in a b c; do - curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a - done } diff --git a/test/17-test-spaces-in-sans-http01.bats b/test/17-test-spaces-in-sans-http01.bats index 86df5dc..b785546 100644 --- a/test/17-test-spaces-in-sans-http01.bats +++ b/test/17-test-spaces-in-sans-http01.bats @@ -6,15 +6,32 @@ load '/getssl/test/test_helper.bash' # This is run for every test +setup() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + + teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +setup_file() { + # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + for prefix in a b c; do + curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + done + fi +} + + +teardown_file() { + if [ -z "$STAGING" ]; then + for prefix in a b c; do + curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a + done fi } @@ -26,11 +43,6 @@ setup() { CONFIG_FILE="getssl-http01-spaces-sans.cfg" setup_environment - # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) - for prefix in a b c; do - curl --silent -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 @@ -86,8 +98,4 @@ setup() { assert_success check_output_for_errors cleanup_environment - - for prefix in a b c; do - curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a - done } diff --git a/test/18-retry-dns-add.bats b/test/18-retry-dns-add.bats index 80244aa..11ca7f3 100644 --- a/test/18-retry-dns-add.bats +++ b/test/18-retry-dns-add.bats @@ -6,11 +6,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } @@ -35,7 +35,6 @@ DNS_EXTRA_WAIT=0 CHECK_ALL_AUTH_DNS="false" CHECK_PUBLIC_DNS_SERVER="false" DNS_WAIT_RETRY_ADD="true" -_RUNNING_TEST=1 EOF create_certificate assert_failure diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats index 945432a..ea9650c 100644 --- a/test/19-test-add-to-sans.bats +++ b/test/19-test-add-to-sans.bats @@ -7,15 +7,23 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip +} + + +setup_file() { if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a fi } -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + +teardown_file() { if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a fi diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index 2e8199e..c5bc854 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -29,35 +29,31 @@ teardown_file() { setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } + + teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } + @test "Create new certificate using DNS-01 verification (dig)" { CONFIG_FILE="getssl-dns01.cfg" setup_environment init_getssl - create_certificate -d + create_certificate assert_success assert_output --partial "dig" - check_output_for_errors "debug" + check_output_for_errors } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" -} -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip -} - @test "Force renewal of certificate using DNS-01 (dig)" { run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success assert_output --partial "dig" - check_output_for_errors "debug" + check_output_for_errors cleanup_environment } diff --git a/test/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index c0b7383..37fa121 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi @@ -21,7 +21,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip if [ -f /usr/bin/dig.getssl.bak ]; then mv /usr/bin/dig.getssl.bak /usr/bin/dig fi @@ -36,7 +36,7 @@ teardown() { setup_environment init_getssl - create_certificate -d + create_certificate assert_success assert_output --partial "nslookup" check_output_for_errors "debug" diff --git a/test/20-wildcard-simple.bats b/test/20-wildcard-simple.bats index 7b69f1f..c99fda5 100644 --- a/test/20-wildcard-simple.bats +++ b/test/20-wildcard-simple.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/21-wildcard-dual-rsa.bats b/test/21-wildcard-dual-rsa.bats index 97e23cb..395de22 100644 --- a/test/21-wildcard-dual-rsa.bats +++ b/test/21-wildcard-dual-rsa.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats index 4d6e115..51d966b 100644 --- a/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/22-wildcard-dual-rsa-ecdsa-copy-2-locations.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # These are run for every test, not once per file teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/23-wildcard-check-globbing.bats b/test/23-wildcard-check-globbing.bats index a075f5d..636bd33 100644 --- a/test/23-wildcard-check-globbing.bats +++ b/test/23-wildcard-check-globbing.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/24-wildcard-sans.bats b/test/24-wildcard-sans.bats index 500acd4..1ce09c2 100644 --- a/test/24-wildcard-sans.bats +++ b/test/24-wildcard-sans.bats @@ -7,7 +7,16 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + + +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip +} + + +setup_file() { if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"wild-'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -15,8 +24,7 @@ setup() { } -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip +teardown_file() { if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"wild-'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a fi diff --git a/test/25-wildcard-all.bats b/test/25-wildcard-all.bats index a5e1c13..64b6c6d 100644 --- a/test/25-wildcard-all.bats +++ b/test/25-wildcard-all.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/26-wildcard-revoke.bats b/test/26-wildcard-revoke.bats index 5709cc7..5b61e00 100644 --- a/test/26-wildcard-revoke.bats +++ b/test/26-wildcard-revoke.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi @@ -40,7 +40,7 @@ setup() { KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key run ${CODE_DIR}/getssl -U -d --revoke $CERT $KEY $CA - assert_line "certificate revoked" + assert_line --partial "certificate revoked" assert_success - check_output_for_errors "debug" + check_output_for_errors } diff --git a/test/27-wildcard-existing-cert.bats b/test/27-wildcard-existing-cert.bats index 98c97e4..dcb74e6 100644 --- a/test/27-wildcard-existing-cert.bats +++ b/test/27-wildcard-existing-cert.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/28-wildcard-error-http01-validation.bats b/test/28-wildcard-error-http01-validation.bats index 3c08e72..e90db22 100644 --- a/test/28-wildcard-error-http01-validation.bats +++ b/test/28-wildcard-error-http01-validation.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/29-check-mktemp-failure.bats b/test/29-check-mktemp-failure.bats index 1a00929..566c7a5 100644 --- a/test/29-check-mktemp-failure.bats +++ b/test/29-check-mktemp-failure.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/3-dual-rsa-ecdsa.bats b/test/3-dual-rsa-ecdsa.bats index 5babf8f..d230ab4 100644 --- a/test/3-dual-rsa-ecdsa.bats +++ b/test/3-dual-rsa-ecdsa.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } @@ -48,7 +48,7 @@ setup() { run ${CODE_DIR}/getssl -U -d $GETSSL_HOST if [ "$OLD_NGINX" = "false" ]; then - assert_line "certificate on server is same as the local cert" + assert_line --partial "certificate on server is same as the local cert" else assert_line --partial "certificate is valid for more than 30 days" fi diff --git a/test/30-handle-dig-failure.bats b/test/30-handle-dig-failure.bats index 898ac4d..5b7edb1 100644 --- a/test/30-handle-dig-failure.bats +++ b/test/30-handle-dig-failure.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -f /usr/bin/drill ]; then mv /usr/bin/drill /usr/bin/drill.getssl.bak @@ -19,7 +19,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip if [ -f /usr/bin/drill.getssl.bak ]; then mv /usr/bin/drill.getssl.bak /usr/bin/drill fi @@ -39,8 +39,8 @@ teardown() { CONFIG_FILE="getssl-http01.cfg" setup_environment init_getssl - create_certificate -d + create_certificate assert_success refute_line --partial "HAS DIG_OR_DRILL=dig" - check_output_for_errors "debug" + check_output_for_errors } diff --git a/test/31-test-posix-error.bats b/test/31-test-posix-error.bats index 87879b5..fece7ff 100644 --- a/test/31-test-posix-error.bats +++ b/test/31-test-posix-error.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } @@ -25,6 +25,6 @@ setup() { run bash --posix "${CODE_DIR}/getssl" -U -d assert_failure - assert_line "getssl: Running with POSIX mode enabled is not supported" + assert_line --partial "getssl: Running with POSIX mode enabled is not supported" check_output_for_errors } diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index 823ec96..2bce33c 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -4,9 +4,41 @@ load '/bats-support/load.bash' load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' +LIMIT_API="https://api.github.com/rate_limit" + +# Quota generally shouldn't be an issue - except for tests +# Rate limits are per-IP address +check_github_quota() { + local need remaining reset limits now + need="$1" + while true ; do + limits="$(curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" -H 'Accept: application/vnd.github.v3+json' "$LIMIT_API" | sed -e's/\("[^:]*": *\("[^""]*",\|[^,]*[,}]\)\)/\r\n\1/g' | sed -ne'/"core":/,/}/p')" + errcode=$? + if [[ $errcode -eq 60 ]]; then + error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" + elif [[ $errcode -gt 0 ]]; then + error_exit "curl error checking releases: $errcode" + fi + limits="$(sed -e's/^ *//g' <<<"${limits}")" + remaining="$(sed -e'/^"remaining": *[0-9]/!d;s/^"remaining": *\([0-9][0-9]*\).*$/\1/' <<<"${limits}")" + reset="$(sed -e'/^"reset": *[0-9]/!d;s/^"reset": *\([0-9][0-9]*\).*$/\1/' <<<"${limits}")" + if [[ "$remaining" -ge "$need" ]] ; then return 0 ; fi + limit="$(sed -e'/^"limit": *[0-9]/!d;s/^"limit": *\([0-9][0-9]*\).*$/\1/' <<<"${limits}")" + if [[ "$limit" -lt "$need" ]] ; then + error_exit "GitHub API request $need exceeds limit $limit" + fi + now="$(date +%s)" + while [[ "$now" -lt "$reset" ]] ; do + info "sleeping $(( "$reset" - "$now" )) seconds for GitHub quota" + sleep "$(( "$reset" - "$now" ))" + now="$(date +%s)" + done + done +} + setup_file() { - if [ -f $BATS_TMPDIR/failed.skip ]; then + if [ -f $BATS_RUN_TMPDIR/failed.skip ]; then echo "# Skipping setup due to previous test failure" >&3 return 0 fi @@ -17,7 +49,7 @@ setup_file() { # This is expensive, so do it only once . "${CODE_DIR}/getssl" -U --source - check_github_quota 1 + check_github_quota 7 export RELEASES="$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX)" if [ -z "$RELEASES" ]; then echo "# mktemp failed" >&3 @@ -48,7 +80,7 @@ teardown_file() { # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" [ -z "$PREVIOUS_TAG" ] && skip "Skipping upgrade test because no previous release detected" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt @@ -62,7 +94,7 @@ setup() { fi run git clone "${_REPO}" "$INSTALL_DIR/upgrade-getssl" - + cd "$INSTALL_DIR/upgrade-getssl" # The version in the file, which we will overwrite @@ -72,7 +104,7 @@ setup() { teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip [ -d "$INSTALL_DIR/upgrade-getssl" ] && rm -r "$INSTALL_DIR/upgrade-getssl" true } @@ -102,7 +134,7 @@ teardown() { # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) assert_line --regexp "A more recent version \(v(${CURRENT_TAG}|${FILE_VERSION})\) than .* of getssl is available, please update" # output can contain "error" in release description - # check_output_for_errors + check_output_for_errors } @@ -129,12 +161,11 @@ teardown() { # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) assert_line --regexp "Installed v(${CURRENT_TAG}|${FILE_VERSION}), restarting" + assert_line "Configuration check successful" } @test "Test that we can upgrade to the newer version when invoking as \"bash ./getssl\"" { - skip "Makefile doesn't support bash ./getssl" - # Note that `bash getssl` will fail if the CWD isn't in the PATH and an upgrade occurs if [ -n "$STAGING" ]; then skip "Using staging server, skipping internal test" diff --git a/test/33-ftp.bats b/test/33-ftp.bats index 086636a..7c35f96 100644 --- a/test/33-ftp.bats +++ b/test/33-ftp.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -n "${VSFTPD_CONF}" ]; then cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl @@ -24,7 +24,7 @@ _FTP teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip if [ -n "${VSFTPD_CONF}" ]; then cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF ${CODE_DIR}/test/restart-ftpd diff --git a/test/34-ftp-passive.bats b/test/34-ftp-passive.bats index ac6e222..5648771 100644 --- a/test/34-ftp-passive.bats +++ b/test/34-ftp-passive.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt if [ -n "${VSFTPD_CONF}" ]; then cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl @@ -27,7 +27,7 @@ _FTP teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip if [ -n "${VSFTPD_CONF}" ]; then cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF ${CODE_DIR}/test/restart-ftpd diff --git a/test/35-preferred-chain.bats b/test/35-preferred-chain.bats index 0ffe71e..ad94caf 100644 --- a/test/35-preferred-chain.bats +++ b/test/35-preferred-chain.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/36-full-chain-inc-root.bats b/test/36-full-chain-inc-root.bats index 4655075..6f06190 100644 --- a/test/36-full-chain-inc-root.bats +++ b/test/36-full-chain-inc-root.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt fi diff --git a/test/37-idn.bats b/test/37-idn.bats index a3cf43a..27f82e0 100644 --- a/test/37-idn.bats +++ b/test/37-idn.bats @@ -4,16 +4,9 @@ load '/bats-support/load.bash' load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' -setup_file() { - if [ -z "$STAGING" ]; then - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt - curl --silent -X POST -d '{"host":"'$GETSSL_IDN_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a - fi -} - # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" GETSSL_CMD_HOST=${GETSSL_IDN_HOST} # use the test description to move tools we don't want to test out of the way @@ -27,7 +20,7 @@ setup() { } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip # use the test description to move tools we didn't want to test back DNS_TOOL=${BATS_TEST_DESCRIPTION##*-} for tool in dig drill host nslookup @@ -38,6 +31,13 @@ teardown() { done } +setup_file() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + curl --silent -X POST -d '{"host":"'$GETSSL_IDN_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + fi +} + teardown_file() { if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"'$GETSSL_IDN_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a @@ -53,11 +53,11 @@ teardown_file() { setup_environment init_getssl - create_certificate -d + create_certificate assert_success assert_output --partial "dig" - check_output_for_errors "debug" + check_output_for_errors } @test "Check that DNS-01 verification works if the domain is idn:drill" { @@ -73,9 +73,9 @@ teardown_file() { setup_environment init_getssl - create_certificate -d + create_certificate assert_success assert_output --partial "drill" - check_output_for_errors "debug" + check_output_for_errors } diff --git a/test/38-idn-http01-check-noidnout.bats b/test/38-idn-http01-check-noidnout.bats index 6ba8d14..01b7542 100644 --- a/test/38-idn-http01-check-noidnout.bats +++ b/test/38-idn-http01-check-noidnout.bats @@ -4,20 +4,20 @@ load '/bats-support/load.bash' load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' -setup_file() { - if [ -z "$STAGING" ]; then - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt - curl --silent -X POST -d '{"host":"'$GETSSL_IDN_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a - fi +setup() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + GETSSL_CMD_HOST=$GETSSL_IDN_HOST } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" - GETSSL_CMD_HOST=$GETSSL_IDN_HOST +setup_file() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + curl --silent -X POST -d '{"host":"'$GETSSL_IDN_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + fi } teardown_file() { @@ -39,7 +39,7 @@ SANS="${GETSSL_HOST}" USE_SINGLE_ACL="true" EOF - create_certificate -d --check-config + create_certificate --check-config assert_success refute_output --partial "DNS lookup using host +noidnout" diff --git a/test/4-more-than-10-hosts.bats b/test/4-more-than-10-hosts.bats index 143afb4..efa1ea0 100644 --- a/test/4-more-than-10-hosts.bats +++ b/test/4-more-than-10-hosts.bats @@ -7,12 +7,33 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } + setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + + +setup_file() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + # 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 --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + done + fi +} + + +teardown_file() { + # Remove all the dns aliases + if [ -n "$STAGING" ]; then + for prefix in a b c d e f g h i j k; do + curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a + done + fi } @@ -23,11 +44,6 @@ setup() { 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 --silent -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 @@ -42,9 +58,5 @@ setup() { run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors - # Remove all the dns aliases cleanup_environment - for prefix in a b c d e f g h i j k; do - curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a - done } diff --git a/test/5-secp384-http01.bats b/test/5-secp384-http01.bats index a108c27..8a1de37 100644 --- a/test/5-secp384-http01.bats +++ b/test/5-secp384-http01.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt } diff --git a/test/6-dual-rsa-ecdsa-copy-2-locations.bats b/test/6-dual-rsa-ecdsa-copy-2-locations.bats index 16ca162..1ad73f4 100644 --- a/test/6-dual-rsa-ecdsa-copy-2-locations.bats +++ b/test/6-dual-rsa-ecdsa-copy-2-locations.bats @@ -7,7 +7,16 @@ load '/getssl/test/test_helper.bash' # These are run for every test, not once per file setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + + +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip +} + + +setup_file() { if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -15,8 +24,7 @@ setup() { } -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip +teardown_file() { if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a fi diff --git a/test/7-test-renewal.bats b/test/7-test-renewal.bats index a2e9e0c..30a5472 100644 --- a/test/7-test-renewal.bats +++ b/test/7-test-renewal.bats @@ -7,7 +7,16 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + + +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip +} + + +setup_file() { if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a @@ -15,8 +24,8 @@ setup() { fi } -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + +teardown_file() { if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a diff --git a/test/8-staging-ecdsa.bats b/test/8-staging-ecdsa.bats index 797ce04..c486ea7 100644 --- a/test/8-staging-ecdsa.bats +++ b/test/8-staging-ecdsa.bats @@ -5,18 +5,19 @@ load '/bats-assert/load.bash' load '/getssl/test/test_helper.bash' - - setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } + + teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } + @test "Create new certificate using staging server and prime256v1" { if [ -z "$STAGING" ]; then - skip "Running external tests, skipping internal testing" + skip "Running local tests this is a staging server test" fi CONFIG_FILE="getssl-dns01.cfg" @@ -25,38 +26,24 @@ teardown() { sed -e 's/rsa/prime256v1/g' < "${CODE_DIR}/test/test-config/${CONFIG_FILE}" > "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" run ${CODE_DIR}/getssl -U -d "$GETSSL_HOST" assert_success - check_output_for_errors "debug" + check_output_for_errors } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" -} -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip -} - @test "Force renewal of certificate using staging server and prime256v1" { if [ -z "$STAGING" ]; then - skip "Running internal tests, skipping external test" + skip "Running local tests this is a staging server test" fi run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success - check_output_for_errors "debug" + check_output_for_errors cleanup_environment } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" -} -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip -} - @test "Create new certificate using staging server and secp384r1" { if [ -z "$STAGING" ]; then - skip "Running external tests, skipping internal testing" + skip "Running local tests this is a staging server test" fi CONFIG_FILE="getssl-dns01.cfg" @@ -65,24 +52,17 @@ teardown() { sed -e 's/rsa/secp384r1/g' < "${CODE_DIR}/test/test-config/${CONFIG_FILE}" > "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg" run ${CODE_DIR}/getssl -U -d "$GETSSL_HOST" assert_success - check_output_for_errors "debug" + check_output_for_errors } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" -} -teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip -} - @test "Force renewal of certificate using staging server and secp384r1" { if [ -z "$STAGING" ]; then - skip "Running internal tests, skipping external test" + skip "Running local tests this is a staging server test" fi run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success - check_output_for_errors "debug" + check_output_for_errors cleanup_environment } diff --git a/test/9-multiple-domains-dns01.bats b/test/9-multiple-domains-dns01.bats index c540d9a..e693c3e 100644 --- a/test/9-multiple-domains-dns01.bats +++ b/test/9-multiple-domains-dns01.bats @@ -6,13 +6,28 @@ load '/getssl/test/test_helper.bash' # This is run for every test +setup() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } -setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" - export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + +setup_file() { + # Add top level domain from SANS to DNS + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + curl --silent -X POST -d '{"host":"getssl.test", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + fi +} + + +teardown_file() { + if [ -z "$STAGING" ]; then + curl --silent -X POST -d '{"host":"getssl.tst"}' http://10.30.50.3:8055/clear-a + fi } @@ -24,9 +39,6 @@ setup() { CONFIG_FILE="getssl-dns01-multiple-domains.cfg" setup_environment - # Add top level domain from SANS to DNS - curl --silent -X POST -d '{"host":"getssl.test", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a - init_getssl create_certificate assert_success @@ -42,11 +54,10 @@ setup() { run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST assert_success check_output_for_errors - # Remove all the dns aliases cleanup_environment - curl --silent -X POST -d '{"host":"getssl.tst"}' http://10.30.50.3:8055/clear-a } + @test "Test IGNORE_DIRECTORY_DOMAIN using DNS-01 verification" { # This tests we can create a certificate for getssl.test and .getssl.test (*both* in SANS) if [ -n "$STAGING" ]; then @@ -55,9 +66,6 @@ setup() { CONFIG_FILE="getssl-dns01-ignore-directory-domain.cfg" setup_environment - # Add top level domain from SANS to DNS - curl --silent -X POST -d '{"host":"getssl.test", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a - init_getssl create_certificate assert_success diff --git a/test/9-test--all.bats b/test/9-test--all.bats index bab1ced..7e317cc 100644 --- a/test/9-test--all.bats +++ b/test/9-test--all.bats @@ -7,11 +7,11 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt export PATH=$PATH:/getssl } diff --git a/test/restart-ftpd b/test/restart-ftpd index 8087437..5bdc3cd 100755 --- a/test/restart-ftpd +++ b/test/restart-ftpd @@ -4,6 +4,8 @@ if [ "$GETSSL_OS" = "alpine" ]; then killall -HUP vsftpd >&3- elif [[ "$GETSSL_OS" == "centos"[78] || "$GETSSL_OS" == "rockylinux"* ]]; then pgrep vsftpd | head -1 | xargs kill -HUP +elif [[ "$GETSSL_OS" == "centos6" ]]; then + service vsftpd restart >&3- >/dev/null else service vsftpd restart >/dev/null >&3- fi diff --git a/test/restart-nginx b/test/restart-nginx index 48ea7ac..ca402f3 100755 --- a/test/restart-nginx +++ b/test/restart-nginx @@ -6,6 +6,8 @@ if [ "$GETSSL_OS" = "alpine" ]; then elif [[ "$GETSSL_OS" == "centos"[78] || "$GETSSL_OS" == "rockylinux"* ]]; then pgrep nginx | head -1 | xargs kill -HUP sleep 5 +elif [[ "$GETSSL_OS" == "centos6" ]]; then + service nginx restart >&3- >/dev/null else service nginx restart >/dev/null >&3- fi diff --git a/test/run-test.cmd b/test/run-test.cmd index 44c46be..9d51875 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -28,13 +28,13 @@ GOTO CheckAlias :duckdns SET ALIAS=%OS:-duckdns=%-getssl.duckdns.org -SET STAGING=--env STAGING=true --env dynamic_dns=duckdns +SET STAGING=--env STAGING=true --env dynamic_dns=duckdns --env DUCKDNS_TOKEN=1d616aa9-b8e4-4bb4-b312-3289de82badb SET GETSSL_OS=%OS:-duckdns=% GOTO Run :dynu SET ALIAS=%OS:-dynu=%-getssl.freeddns.org -SET STAGING=--env STAGING=true --env dynamic_dns=dynu +SET STAGING=--env STAGING=true --env dynamic_dns=dynu --env DYNU_API_KEY=65cXefd35XbYf36546eg5dYcZT6X52Y2 SET GETSSL_OS=%OS:-dynu=% GOTO Run diff --git a/test/test-config/getssl-dns01.cfg b/test/test-config/getssl-dns01.cfg index bd02c50..f71d19f 100644 --- a/test/test-config/getssl-dns01.cfg +++ b/test/test-config/getssl-dns01.cfg @@ -51,9 +51,6 @@ RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /get SERVER_TYPE="https" CHECK_REMOTE="true" -#_USE_DEBUG=1 -#_RUNNING_TEST=1 - if [[ -s "$DOMAIN_DIR/getssl_test_specific.cfg" ]]; then . $DOMAIN_DIR/getssl_test_specific.cfg fi diff --git a/test/test-config/getssl-http01.cfg b/test/test-config/getssl-http01.cfg index 9a713bc..8183b16 100644 --- a/test/test-config/getssl-http01.cfg +++ b/test/test-config/getssl-http01.cfg @@ -31,6 +31,3 @@ CHECK_REMOTE="true" if [[ -s "$DOMAIN_DIR/getssl_test_specific.cfg" ]]; then . $DOMAIN_DIR/getssl_test_specific.cfg fi - -#_USE_DEBUG=1 -#_RUNNING_TEST=1 diff --git a/test/test_helper.bash b/test/test_helper.bash index 37f77cd..efc52fa 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -16,24 +16,16 @@ check_nginx() { if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then export OLD_NGINX="false" else - echo "INFO: Running nginx version $currentver which doesn't support dual certificates" >&3 - echo "INFO: not checking that certificate is installed correctly" >&3 + echo "# INFO: Running nginx version $currentver which doesn't support dual certificates" + echo "# INFO: not checking that certificate is installed correctly" export OLD_NGINX="true" fi } check_output_for_errors() { refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]' - # less strict tests if running with debug output - if [ -n "X$1" ]; then - # don't fail for :error:badNonce - refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]' - # don't check for "Warnings:" as there might be a warning message if nslookup doesn't support -debug (alpine/ubuntu) - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]' - else - refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]' - refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' - fi + refute_output --regexp '[^_][Ee][Rr][Rr][Oo][Rr][^:nonce]' + refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]' refute_line --partial 'command not found' } diff --git a/test/u1-test-get_auth_dns-dig.bats b/test/u1-test-get_auth_dns-dig.bats index 24ab088..17ead16 100644 --- a/test/u1-test-get_auth_dns-dig.bats +++ b/test/u1-test-get_auth_dns-dig.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" for app in drill host nslookup do if [ -f /usr/bin/${app} ]; then @@ -17,13 +17,12 @@ setup() { . /getssl/getssl --source find_dns_utils - _RUNNING_TEST=1 - _USE_DEBUG=0 + _USE_DEBUG=1 } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip for app in drill host nslookup do if [ -f /usr/bin/${app}.getssl.bak ]; then diff --git a/test/u2-test-get_auth_dns-drill.bats b/test/u2-test-get_auth_dns-drill.bats index b63cf1b..4884a60 100644 --- a/test/u2-test-get_auth_dns-drill.bats +++ b/test/u2-test-get_auth_dns-drill.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" for app in dig host nslookup do if [ -f /usr/bin/${app} ]; then @@ -17,13 +17,12 @@ setup() { . /getssl/getssl --source find_dns_utils - _RUNNING_TEST=1 - _USE_DEBUG=0 + _USE_DEBUG=1 } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip for app in dig host nslookup do if [ -f /usr/bin/${app}.getssl.bak ]; then diff --git a/test/u3-mktemp-template.bats b/test/u3-mktemp-template.bats index e28208c..c42c0b5 100644 --- a/test/u3-mktemp-template.bats +++ b/test/u3-mktemp-template.bats @@ -6,10 +6,10 @@ load '/getssl/test/test_helper.bash' setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } @test "Check mktemp -t getssl.XXXXXX works on all platforms" { diff --git a/test/u4-create-csr-and-ifs.bats b/test/u4-create-csr-and-ifs.bats index 7871445..4e5280e 100644 --- a/test/u4-create-csr-and-ifs.bats +++ b/test/u4-create-csr-and-ifs.bats @@ -7,15 +7,14 @@ load '/getssl/test/test_helper.bash' # This is run for every test teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" . /getssl/getssl --source find_dns_utils - _RUNNING_TEST=1 - _USE_DEBUG=0 + _USE_DEBUG=1 } diff --git a/test/u5-test-get_auth_dns-no-root-servers.bats b/test/u5-test-get_auth_dns-no-root-servers.bats index 7dcbdc9..5fd743f 100644 --- a/test/u5-test-get_auth_dns-no-root-servers.bats +++ b/test/u5-test-get_auth_dns-no-root-servers.bats @@ -7,7 +7,7 @@ load '/getssl/test/test_helper.bash' # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" cp /etc/resolv.conf /etc/resolv.conf.getssl cat <<- EOF > /etc/resolv.conf nameserver 8.8.8.8 @@ -23,13 +23,12 @@ EOF . /getssl/getssl --source find_dns_utils - _RUNNING_TEST=1 - _USE_DEBUG=0 + _USE_DEBUG=1 } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip cat /etc/resolv.conf.getssl > /etc/resolv.conf for app in drill host nslookup do diff --git a/test/u6-test-combined-directory.bats b/test/u6-test-combined-directory.bats index 4ef0d1f..0bafe13 100644 --- a/test/u6-test-combined-directory.bats +++ b/test/u6-test-combined-directory.bats @@ -9,26 +9,24 @@ CA="https://api.test4.buypass.no/acme" # This is run for every test setup() { - [ ! -f $BATS_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" . /getssl/getssl --source requires curl _NOMETER="--silent" - _RUNNING_TEST=1 _USE_DEBUG=1 } teardown() { - [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_TMPDIR/failed.skip + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip } @test "Check that API V2 is selected in a unified ACME directory." { obtain_ca_resource_locations - + [ "$API" -eq 2 ] } - From d013dc5f6498d5e5d3ad537764c8c3f0a5ec21af Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 27 Sep 2021 21:53:59 +0100 Subject: [PATCH 290/308] Add glibc-all-langpacks to fix locale error --- test/Dockerfile-centos8 | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Dockerfile-centos8 b/test/Dockerfile-centos8 index 552e1d9..dc6853b 100644 --- a/test/Dockerfile-centos8 +++ b/test/Dockerfile-centos8 @@ -4,6 +4,7 @@ FROM centos:centos8 # Update and install required software RUN yum -y update +RUN yum -y install glibc-all-langpacks RUN yum -y install epel-release RUN yum -y install git curl bind-utils wget which nginx jq RUN yum -y install ftp vsftpd From 966f618349d83be94c0b4093597953f8b35e48ef Mon Sep 17 00:00:00 2001 From: Owen Griffin Date: Tue, 28 Sep 2021 08:58:32 +0000 Subject: [PATCH 291/308] dns_scripts for Azure CLI --- dns_scripts/Azure-README.txt | 21 +++++++++++++++++++++ dns_scripts/dns_add_azure | 22 ++++++++++++++++++++++ dns_scripts/dns_del_azure | 20 ++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 dns_scripts/Azure-README.txt create mode 100755 dns_scripts/dns_add_azure create mode 100755 dns_scripts/dns_del_azure diff --git a/dns_scripts/Azure-README.txt b/dns_scripts/Azure-README.txt new file mode 100644 index 0000000..d314463 --- /dev/null +++ b/dns_scripts/Azure-README.txt @@ -0,0 +1,21 @@ +Using Azure for LetsEncrypt domain verification + +Guide for using Azure for LetsEncrypt domain verification. + +Prerequisites: +- Azure CLI tools installed - see https://docs.microsoft.com/en-us/cli/azure/install-azure-cli +- Logged in with azure-cli - i.e. azure login + +The dns_add_azure and dns_del_azure scripts assume that the following +environment variables are added to the configuration file: + +- AZURE_RESOURCE_GROUP - the name of the resource group that contains the DNS zone +- AZURE_ZONE_ID - the name of the DNS zone +- AZURE_SUBSCRIPTION_ID - the name or ID of the subscription that AZURE_RESOURCE_GROUP is part of + +Each of these variables can be included in the .getssl.cfg, e.g: + +export AZURE_RESOURCE_GROUP=my-resource-group +export AZURE_ZONE_ID=example.com +export AZURE_SUBSCRIPTION_ID=my-azure-subscriptin + diff --git a/dns_scripts/dns_add_azure b/dns_scripts/dns_add_azure new file mode 100755 index 0000000..bf2263d --- /dev/null +++ b/dns_scripts/dns_add_azure @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Set the TXT DNS record with azure-cli +fulldomain="${1}" +token="${2}" + +if [[ -z "$AZURE_RESOURCE_GROUP" ]]; then + echo "AZURE_RESOURCE_GROUP is not set. Unable to set TXT records." + exit 2 +fi +if [[ -z "$AZURE_ZONE_ID" ]]; then + echo "AZURE_ZONE_ID is not set. Unable to set TXT records." + exit 2 +fi +if [[ -z "$AZURE_SUBSCRIPTION_ID" ]]; then + echo "AZURE_SUBSCRIPTION_ID is not set. Unable to set TXT records." + exit 2 +fi + +az account set --subscription "$AZURE_SUBSCRIPTION_ID" +recordset="_acme-challenge.${fulldomain/.$AZURE_ZONE_ID/}" +[[ "$recordset" == "_acme-challenge.$fulldomain" ]] && recordset="_acme-challenge" +az network dns record-set txt add-record -g "$AZURE_RESOURCE_GROUP" -z "$AZURE_ZONE_ID" -n "$recordset" -v "$token" diff --git a/dns_scripts/dns_del_azure b/dns_scripts/dns_del_azure new file mode 100755 index 0000000..5e103c9 --- /dev/null +++ b/dns_scripts/dns_del_azure @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# Remove the TXT DNS record with azure-cli +fulldomain="${1}" +if [[ -z "$AZURE_RESOURCE_GROUP" ]]; then + echo "AZURE_RESOURCE_GROUP is not set. Unable to set TXT records." + exit 2 +fi +if [[ -z "$AZURE_ZONE_ID" ]]; then + echo "AZURE_ZONE_ID is not set. Unable to set TXT records." + exit 2 +fi +if [[ -z "$AZURE_SUBSCRIPTION_ID" ]]; then + echo "AZURE_SUBSCRIPTION_ID is not set. Unable to set TXT records." + exit 2 +fi + +az account set --subscription "$AZURE_SUBSCRIPTION_ID" +recordset="_acme-challenge.${fulldomain/.$AZURE_ZONE_ID/}" +[[ "$recordset" == "_acme-challenge.$fulldomain" ]] && recordset="_acme-challenge" +az network dns record-set txt delete --yes -g "$AZURE_RESOURCE_GROUP" -z "$AZURE_ZONE_ID" -n "$recordset" From 31b51a0e60489d294bd66e1cec70e79e8963fc4e Mon Sep 17 00:00:00 2001 From: Owen Griffin Date: Tue, 28 Sep 2021 10:43:02 +0000 Subject: [PATCH 292/308] Allow multiple zone_ids to be used with Azure DNS --- dns_scripts/Azure-README.txt | 13 +++++++++---- dns_scripts/dns_add_azure | 22 ++++++++++++++++++++-- dns_scripts/dns_del_azure | 22 ++++++++++++++++++++-- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/dns_scripts/Azure-README.txt b/dns_scripts/Azure-README.txt index d314463..a0dbdc4 100644 --- a/dns_scripts/Azure-README.txt +++ b/dns_scripts/Azure-README.txt @@ -6,16 +6,21 @@ Prerequisites: - Azure CLI tools installed - see https://docs.microsoft.com/en-us/cli/azure/install-azure-cli - Logged in with azure-cli - i.e. azure login -The dns_add_azure and dns_del_azure scripts assume that the following -environment variables are added to the configuration file: +Ensure dns_add_azure and dns_del_azure scripts are called when the DNS is validated by modifying the .getssl.cfg: + +VALIDATE_VIA_DNS=true +DNS_ADD_COMMAND=dns_scripts/dns_add_azure # n.b use valid path +DNS_DEL_COMMAND=dns_scripts/dns_del_azure + +The dns_add_azure and dns_del_azure scripts assume that the following environment variables are added to the configuration file: - AZURE_RESOURCE_GROUP - the name of the resource group that contains the DNS zone -- AZURE_ZONE_ID - the name of the DNS zone +- AZURE_ZONE_ID - a comma-separated list of valid DNS zones. this allows the same certificate to be used across multiple top-level domains - AZURE_SUBSCRIPTION_ID - the name or ID of the subscription that AZURE_RESOURCE_GROUP is part of Each of these variables can be included in the .getssl.cfg, e.g: export AZURE_RESOURCE_GROUP=my-resource-group -export AZURE_ZONE_ID=example.com +export AZURE_ZONE_ID=example.com,anotherdomain.com export AZURE_SUBSCRIPTION_ID=my-azure-subscriptin diff --git a/dns_scripts/dns_add_azure b/dns_scripts/dns_add_azure index bf2263d..3f0f666 100755 --- a/dns_scripts/dns_add_azure +++ b/dns_scripts/dns_add_azure @@ -16,7 +16,25 @@ if [[ -z "$AZURE_SUBSCRIPTION_ID" ]]; then exit 2 fi +# Determine which zone ID to use from AZURE_ZONE_IDs +# Convert the comma-separated list of AZURE_ZONE_IDs into an array and loop +IFS=',' read -ra zone_ids <<< "$AZURE_ZONE_ID" +for item in "${zone_ids[@]}"; do + # If the full domain ends with the current zone ID + [[ "$fulldomain" =~ .*"${item}"$ ]] && zone_id="$item" +done + +if [ -z "$zone_id" ]; then + echo "${fulldomain} does not match any of the zone IDs specified by ${AZURE_ZONE_ID[@]}" + exit 2 +fi + az account set --subscription "$AZURE_SUBSCRIPTION_ID" -recordset="_acme-challenge.${fulldomain/.$AZURE_ZONE_ID/}" +# Determine the recordset by removing the zone_id from the full domain and prefixing +# with _acme-challenge. +recordset="_acme-challenge.${fulldomain/.$zone_id/}" +# The fulldomain should not be included in the recordset. It is used for subdomains. +# E.g. domain = *.sub.example.com the recordset is _acme-challenge.sub +# domain = example.com the record set is _acme-challenge [[ "$recordset" == "_acme-challenge.$fulldomain" ]] && recordset="_acme-challenge" -az network dns record-set txt add-record -g "$AZURE_RESOURCE_GROUP" -z "$AZURE_ZONE_ID" -n "$recordset" -v "$token" +az network dns record-set txt add-record -g "$AZURE_RESOURCE_GROUP" -z "$zone_id" -n "$recordset" -v "$token" diff --git a/dns_scripts/dns_del_azure b/dns_scripts/dns_del_azure index 5e103c9..45518c3 100755 --- a/dns_scripts/dns_del_azure +++ b/dns_scripts/dns_del_azure @@ -14,7 +14,25 @@ if [[ -z "$AZURE_SUBSCRIPTION_ID" ]]; then exit 2 fi +# Determine which zone ID to use from AZURE_ZONE_IDs +# Convert the comma-separated list of AZURE_ZONE_IDs into an array and loop +IFS=',' read -ra zone_ids <<< "$AZURE_ZONE_ID" +for item in "${zone_ids[@]}"; do + # If the full domain ends with the current zone ID + [[ "$fulldomain" =~ .*"${item}"$ ]] && zone_id="$item" +done + +if [ -z "$zone_id" ]; then + echo "${fulldomain} does not match any of the zone IDs specified by ${AZURE_ZONE_ID[@]}" + exit 2 +fi + az account set --subscription "$AZURE_SUBSCRIPTION_ID" -recordset="_acme-challenge.${fulldomain/.$AZURE_ZONE_ID/}" +# Determine the recordset by removing the zone_id from the full domain and prefixing +# with _acme-challenge. +recordset="_acme-challenge.${fulldomain/.$zone_id/}" +# The fulldomain should not be included in the recordset. It is used for subdomains. +# E.g. domain = *.sub.example.com the recordset is _acme-challenge.sub +# domain = example.com the record set is _acme-challenge [[ "$recordset" == "_acme-challenge.$fulldomain" ]] && recordset="_acme-challenge" -az network dns record-set txt delete --yes -g "$AZURE_RESOURCE_GROUP" -z "$AZURE_ZONE_ID" -n "$recordset" +az network dns record-set txt delete --yes -g "$AZURE_RESOURCE_GROUP" -z "$zone_id" -n "$recordset" From f9d166e10f12edfcadb6bc1f373f62329f4db0d7 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 30 Sep 2021 18:10:06 +0100 Subject: [PATCH 293/308] Add test for delete key file with key alg changes (#706) Force new certificate if key alg changes (fixes #276) --- getssl | 33 ++++++----- test/39-private-key-alg-changed.bats | 88 ++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 15 deletions(-) create mode 100644 test/39-private-key-alg-changed.bats diff --git a/getssl b/getssl index 473f3e6..a688ca9 100755 --- a/getssl +++ b/getssl @@ -270,6 +270,7 @@ # 2021-07-30 Run tests with -d to catch intermittent failures, Use fork's repo for upgrade tests. (tlhackque) (#692) (2.41) # 2021-08-26 Improve upgrade check & make upgrade do a full install when possible (tlhackque) (#694) (2.42) # 2021-09-02 Fix version compare - cURL v8 may have single digit minor numbers. (tlhackque) (2.43) +# 2021-09-26 Delete key file when key algorithm has changed (makuhama) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -838,7 +839,7 @@ check_getssl_upgrade() { # check if a more recent release is available fi if [[ ${_MUTE} -eq 0 ]]; then - echo "Updated getssl from v${VERSION} to v${release_tag}" + echo "Updated getssl from v${VERSION} to ${release_tag}" echo "The old version remains as ${0}.v${VERSION} and should be removed" echo "These update notifications can be turned off using the -Q option" echo "" @@ -3146,6 +3147,22 @@ else fi debug "created SAN list = $SANLIST" +# check if private key alg has changed from RSA to EC (or vice versa) +if [[ "$DUAL_RSA_ECDSA" == "false" ]] && [[ -s "$DOMAIN_DIR/${DOMAIN}.key" ]]; then + case "${PRIVATE_KEY_ALG}" in + rsa) + if grep --silent -- "-----BEGIN EC PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then + rm -f "$DOMAIN_DIR/${DOMAIN}.key" + _FORCE_RENEW=1 + fi ;; + prime256v1|secp384r1|secp521r1) + if grep --silent -- "-----BEGIN RSA PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then + rm -f "$DOMAIN_DIR/${DOMAIN}.key" + _FORCE_RENEW=1 + fi ;; + esac +fi + # if there is an existing certificate file, check details. if [[ -s "$CERT_FILE" ]]; then debug "certificate $CERT_FILE exists" @@ -3199,20 +3216,6 @@ if [[ "$REUSE_PRIVATE_KEY" != "true" ]]; then fi fi -# check if private key alg has changed from RSA to EC (or vice versa) -if [[ "$DUAL_RSA_ECDSA" == "false" ]] && [[ -s "$DOMAIN_DIR/${DOMAIN}.key" ]]; then - case "${PRIVATE_KEY_ALG}" in - rsa) - if grep --silent -- "-----BEGIN EC PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then - rm -f "$DOMAIN_DIR/${DOMAIN}.key" - fi ;; - prime256v1|secp384r1|secp521r1) - if grep --silent -- "-----BEGIN RSA PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then - rm -f "$DOMAIN_DIR/${DOMAIN}.key" - fi ;; - esac -fi - # create new domain keys if they don't already exist if [[ "$DUAL_RSA_ECDSA" == "false" ]]; then create_key "${PRIVATE_KEY_ALG}" "$DOMAIN_DIR/${DOMAIN}.key" "$DOMAIN_KEY_LENGTH" diff --git a/test/39-private-key-alg-changed.bats b/test/39-private-key-alg-changed.bats new file mode 100644 index 0000000..a8b0e43 --- /dev/null +++ b/test/39-private-key-alg-changed.bats @@ -0,0 +1,88 @@ +#! /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 +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip +} + +setup() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt +} + +teardown_file() { + cleanup_environment +} + +@test "Create new certificate to create a private key" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors + # save a coy of the private key + cp "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key.orig" +} + +@test "Renew certificate (not force) and check nothing happens and key doesn't change" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + ORIG_KEY_HASH="$(cat ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | sha256sum)" + + run ${CODE_DIR}/getssl -U -d $GETSSL_HOST + assert_success + assert_line --partial "certificate is valid for more than 30 days" + check_output_for_errors + + NEW_KEY_HASH="$(cat ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | sha256sum)" + + assert [ "$NEW_KEY_HASH" == "$ORIG_KEY_HASH" ] +} + +@test "Force renewal and check key hasn't changed" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + ORIG_KEY_HASH="$(cat ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | sha256sum)" + + run ${CODE_DIR}/getssl -U -d -f $GETSSL_HOST + assert_success + check_output_for_errors + + NEW_KEY_HASH="$(cat ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | sha256sum)" + + assert [ "$NEW_KEY_HASH" == "$ORIG_KEY_HASH" ] +} + +@test "Change key algorithm, force renewal, and check key has changed" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + + ORIG_KEY_HASH="$(cat ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | sha256sum)" + + cat <<- 'EOF' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +PRIVATE_KEY_ALG="prime256v1" +EOF + + run ${CODE_DIR}/getssl -U -d $GETSSL_HOST + assert_success + refute_line --partial "certificate is valid for more than 30 days" + + check_output_for_errors + + NEW_KEY_HASH="$(cat ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | sha256sum)" + + assert [ "$NEW_KEY_HASH" != "$ORIG_KEY_HASH" ] +} From 99c285491960c2a337b8160ee298b01b5bec6468 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 30 Sep 2021 18:33:24 +0100 Subject: [PATCH 294/308] Show curl error if obtain_ca_resource_location fails --- getssl | 13 ++++++++++++- test/0-test-curl-error.bats | 29 +++++++++++++++++++++++++++++ test/32-test-upgrade.bats | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 test/0-test-curl-error.bats diff --git a/getssl b/getssl index a688ca9..0365c83 100755 --- a/getssl +++ b/getssl @@ -2118,11 +2118,22 @@ json_get() { # get values from json obtain_ca_resource_locations() { + CURL_RESPONSE_FILE="$(mktemp 2>/dev/null || mktemp -t getssl.XXXXXX)" + for suffix in "" "/directory" "/dir"; do # Obtain CA resource locations # shellcheck disable=SC2086 - ca_all_loc=$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" "${CA}${suffix}" 2>/dev/null) + ca_all_loc=$(curl ${_NOMETER} --user-agent "$CURL_USERAGENT" "${CA}${suffix}" 2> $CURL_RESPONSE_FILE) + errcode=$? + if [[ $errcode -ne 0 ]]; then + response=$(cat "$CURL_RESPONSE_FILE") + rm "$CURL_RESPONSE_FILE" + error_exit "ERROR curl \"$CA$suffix\" failed with $errcode and returned:\n$response" + else + rm "$CURL_RESPONSE_FILE" + fi + debug "ca_all_loc from ${CA}${suffix} gives $ca_all_loc" # APIv1 URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') diff --git a/test/0-test-curl-error.bats b/test/0-test-curl-error.bats new file mode 100644 index 0000000..1e9e2b7 --- /dev/null +++ b/test/0-test-curl-error.bats @@ -0,0 +1,29 @@ +#! /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 +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip +} + +setup() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + #export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt +} + + +@test "Run getssl without pebble certificates to check the error message" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate + refute_line "getssl: unknown API version" + assert_failure +} diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index 2bce33c..e698fc5 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -161,7 +161,7 @@ teardown() { # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) assert_line --regexp "Installed v(${CURRENT_TAG}|${FILE_VERSION}), restarting" - assert_line "Configuration check successful" + assert_line --partial "Configuration check successful" } From 544240d1f3ae8d818195d6a72039a9fc01b91b09 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 30 Sep 2021 20:17:34 +0100 Subject: [PATCH 295/308] Fix grep --silent on alpine Add debug statement to investigate failures when running in github actions --- getssl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/getssl b/getssl index 0365c83..ab3afce 100755 --- a/getssl +++ b/getssl @@ -822,9 +822,11 @@ check_getssl_upgrade() { # check if a more recent release is available fi CODE_LOCATION=$(sed -e"s/master/${release_tag}/" <<<"$CODE_LOCATION") # shellcheck disable=SC2086 + debug curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" + # shellcheck disable=SC2086 curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" - errcode=$? + if [[ $errcode -eq 60 ]]; then error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" elif [[ $errcode -gt 0 ]]; then @@ -843,7 +845,7 @@ check_getssl_upgrade() { # check if a more recent release is available echo "The old version remains as ${0}.v${VERSION} and should be removed" echo "These update notifications can be turned off using the -Q option" echo "" - echo "Updates are;" + echo "Updates are:" awk "/\(${VERSION}\)$/ {s=1} s; /\(${release_tag}\)$/ || /^# ----/ {s=0}" "$TEMP_UPGRADE_FILE" | awk '{if(NR>1)print}' echo "" fi @@ -3162,12 +3164,12 @@ debug "created SAN list = $SANLIST" if [[ "$DUAL_RSA_ECDSA" == "false" ]] && [[ -s "$DOMAIN_DIR/${DOMAIN}.key" ]]; then case "${PRIVATE_KEY_ALG}" in rsa) - if grep --silent -- "-----BEGIN EC PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then + if grep -q -- "-----BEGIN EC PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then rm -f "$DOMAIN_DIR/${DOMAIN}.key" _FORCE_RENEW=1 fi ;; prime256v1|secp384r1|secp521r1) - if grep --silent -- "-----BEGIN RSA PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then + if grep -q -- "-----BEGIN RSA PRIVATE KEY-----" "$DOMAIN_DIR/${DOMAIN}.key"; then rm -f "$DOMAIN_DIR/${DOMAIN}.key" _FORCE_RENEW=1 fi ;; From f6d48acc72fdfc109ea39ae8b1c09a306c177102 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 30 Sep 2021 20:42:52 +0100 Subject: [PATCH 296/308] Fix code location --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index ab3afce..5cf32f9 100755 --- a/getssl +++ b/getssl @@ -820,7 +820,7 @@ check_getssl_upgrade() { # check if a more recent release is available if [ "$TEMP_UPGRADE_FILE" == "" ]; then error_exit "mktemp failed" fi - CODE_LOCATION=$(sed -e"s/master/${release_tag}/" <<<"$CODE_LOCATION") + CODE_LOCATION=$(sed -e"s/getssl\/master/${release_tag}/" <<<"$CODE_LOCATION") # shellcheck disable=SC2086 debug curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" # shellcheck disable=SC2086 From 96201d441f08a20cf9052eb2cf5078f8773a83cd Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 1 Oct 2021 18:02:57 +0100 Subject: [PATCH 297/308] Fix -preferred-chain arg (#712) Show help if no domain specified (#705) --- getssl | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/getssl b/getssl index 5cf32f9..6a4aedb 100755 --- a/getssl +++ b/getssl @@ -271,6 +271,9 @@ # 2021-08-26 Improve upgrade check & make upgrade do a full install when possible (tlhackque) (#694) (2.42) # 2021-09-02 Fix version compare - cURL v8 may have single digit minor numbers. (tlhackque) (2.43) # 2021-09-26 Delete key file when key algorithm has changed (makuhama) +# 2021-09-30 better error if curl returns 60 (#709) +# 2021-10-01 Fix -preferred-chain argument (#712) +# 2021-10-01 Show help if no domain specified (#705)(2.44) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -279,7 +282,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.43" +VERSION="2.44" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -290,7 +293,7 @@ CHALLENGE_CHECK_TYPE="http" CHECK_REMOTE_WAIT=0 CHECK_REMOTE="true" if [[ -n "${GITHUB_REPOSITORY}" ]] ; then - CODE_LOCATION="https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/getssl/master/getssl" + CODE_LOCATION="https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/master/getssl" RELEASE_API="https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/latest" else CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" @@ -820,7 +823,7 @@ check_getssl_upgrade() { # check if a more recent release is available if [ "$TEMP_UPGRADE_FILE" == "" ]; then error_exit "mktemp failed" fi - CODE_LOCATION=$(sed -e"s/getssl\/master/${release_tag}/" <<<"$CODE_LOCATION") + CODE_LOCATION=$(sed -e"s/master/${release_tag}/" <<<"$CODE_LOCATION") # shellcheck disable=SC2086 debug curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" # shellcheck disable=SC2086 @@ -2755,7 +2758,7 @@ while [[ -n ${1+defined} ]]; do _ONLY_CHECK_CONFIG=1 ;; -w) shift; WORKING_DIR="$1" ;; - -preferred-chain) + -preferred-chain | --preferred-chain) shift; PREFERRED_CHAIN="$1" ;; --source) return ;; @@ -2830,6 +2833,10 @@ if [[ $_UPGRADE_CHECK -eq 1 ]]; then # if nothing in command line and no revocation and not only config check, # then exit after upgrade if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]] && [[ ${_REVOKE} -ne 1 ]] && [ "${_ONLY_CHECK_CONFIG}" -ne 1 ]; then + # if nothing in command line, print help before exit. + if [[ -z "$DOMAIN" ]] && [[ ${_CHECK_ALL} -ne 1 ]]; then + help_message + fi graceful_exit fi fi From 0462542f7d3a7d494ee4f31eb58ab38892284cd5 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 6 Oct 2021 17:47:39 +0100 Subject: [PATCH 298/308] Fixes for centos6 automated test hanging --- test/33-ftp.bats | 4 ++-- test/34-ftp-passive.bats | 4 ++-- test/restart-ftpd | 8 +++++++- test/restart-nginx | 3 ++- test/test_helper.bash | 4 ++-- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/test/33-ftp.bats b/test/33-ftp.bats index 7c35f96..59297c0 100644 --- a/test/33-ftp.bats +++ b/test/33-ftp.bats @@ -18,7 +18,7 @@ setup() { pasv_enable=NO _FTP - ${CODE_DIR}/test/restart-ftpd + ${CODE_DIR}/test/restart-ftpd start fi } @@ -27,7 +27,7 @@ teardown() { [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip if [ -n "${VSFTPD_CONF}" ]; then cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF - ${CODE_DIR}/test/restart-ftpd + ${CODE_DIR}/test/restart-ftpd stop fi } diff --git a/test/34-ftp-passive.bats b/test/34-ftp-passive.bats index 5648771..71e6ed0 100644 --- a/test/34-ftp-passive.bats +++ b/test/34-ftp-passive.bats @@ -21,7 +21,7 @@ pasv_min_port=10090 connect_from_port_20=NO _FTP - ${CODE_DIR}/test/restart-ftpd + ${CODE_DIR}/test/restart-ftpd start fi } @@ -30,7 +30,7 @@ teardown() { [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip if [ -n "${VSFTPD_CONF}" ]; then cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF - ${CODE_DIR}/test/restart-ftpd + ${CODE_DIR}/test/restart-ftpd stop fi } diff --git a/test/restart-ftpd b/test/restart-ftpd index 5bdc3cd..6bb780c 100755 --- a/test/restart-ftpd +++ b/test/restart-ftpd @@ -1,11 +1,17 @@ #!/usr/bin/env bash +if [ -z "$1" ]; then + arg="restart" +else + arg=$1 +fi + if [ "$GETSSL_OS" = "alpine" ]; then killall -HUP vsftpd >&3- elif [[ "$GETSSL_OS" == "centos"[78] || "$GETSSL_OS" == "rockylinux"* ]]; then pgrep vsftpd | head -1 | xargs kill -HUP elif [[ "$GETSSL_OS" == "centos6" ]]; then - service vsftpd restart >&3- >/dev/null + service vsftpd "$arg" else service vsftpd restart >/dev/null >&3- fi diff --git a/test/restart-nginx b/test/restart-nginx index ca402f3..ee49af4 100755 --- a/test/restart-nginx +++ b/test/restart-nginx @@ -7,7 +7,8 @@ elif [[ "$GETSSL_OS" == "centos"[78] || "$GETSSL_OS" == "rockylinux"* ]]; then pgrep nginx | head -1 | xargs kill -HUP sleep 5 elif [[ "$GETSSL_OS" == "centos6" ]]; then - service nginx restart >&3- >/dev/null + service nginx restart 3>&- + # service nginx restart else service nginx restart >/dev/null >&3- fi diff --git a/test/test_helper.bash b/test/test_helper.bash index efc52fa..e8d68b0 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -74,10 +74,10 @@ if [[ -f /usr/bin/supervisord && -f /etc/supervisord.conf ]]; then fi elif [[ "$GETSSL_OS" == "centos"[78] || "$GETSSL_OS" == "rockylinux"* ]]; then if [ -z "$(pgrep nginx)" ]; then - nginx >&3- + nginx 3>&- fi if [ -z "$(pgrep vsftpd)" ] && [ "$(command -v vsftpd)" ]; then - vsftpd >&3- + vsftpd 3>&- fi fi From 9e7e8fa77741d8d2846496fd6f0c6dc1d2eb8c79 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 6 Oct 2021 18:27:05 +0100 Subject: [PATCH 299/308] Don't assume release_data has carriage returns (fixes #717) --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index 6a4aedb..cee82b7 100755 --- a/getssl +++ b/getssl @@ -787,7 +787,7 @@ check_getssl_upgrade() { # check if a more recent release is available # Replace error in release description with _error (which is ignored by check_output_for_errors() in the tests) debug "${release_data//error/_error}" release_data="$(sed -e's/^ *//g' <<<"${release_data}")" - release_tag="$(sed -e'/^"tag_name": *"/!d;s/^"tag_name": *"\([^""]*\).*$/\1/' <<<"${release_data}")" + release_tag="$(sed -e'/"tag_name": *"/!d;s/"tag_name": *"\([^""]*\).*$/\1/' <<<"${release_data}")" if [[ "${release_tag:0:1}" != 'v' ]] ; then if [[ ${_MUTE} -eq 0 ]]; then info "The current repository has no releases or is improperly tagged; can't check for upgrades: '$release_tag'" From 34417121c3f75c576d3c8e1758af64d84d0f9ec8 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 6 Oct 2021 18:30:55 +0100 Subject: [PATCH 300/308] Tweak info message to avoid automated test failure --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index cee82b7..c4712e8 100755 --- a/getssl +++ b/getssl @@ -2430,7 +2430,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p fi debug "response status = $response_status" if [[ "$code" -eq 500 ]]; then - info "error on acme server - trying again ...." + info "_error on acme server - trying again ...." debug "loop_limit = $loop_limit" sleep 5 loop_limit=$((loop_limit - 1)) From 758d00c5598f25d52fa9347620006a351696afec Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 6 Oct 2021 22:10:14 +0100 Subject: [PATCH 301/308] Update README.md Use `latest` tag instead of `master` in installation instructions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42dd5a9..dbe46c3 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Since the script is only one file, you can use the following command for a quick installation of GetSSL only: ```sh -curl --silent https://raw.githubusercontent.com/srvrco/getssl/master/getssl > getssl ; chmod 700 getssl +curl --silent https://raw.githubusercontent.com/srvrco/getssl/latest/getssl > getssl ; chmod 700 getssl ``` This will copy the getssl Bash script to the current location and change From 0cb0241b880ab0026d5cbf860232849efdc27ab6 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Fri, 8 Oct 2021 16:39:10 +0100 Subject: [PATCH 302/308] Extract release tag from release api using awk (fix BSD issues) --- getssl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/getssl b/getssl index c4712e8..254ca16 100755 --- a/getssl +++ b/getssl @@ -774,10 +774,8 @@ check_getssl_upgrade() { # check if a more recent release is available fi local release_data release_tag release_ver local_ver release_desc NEWCMD debug "Checking for releases at $RELEASE_API" - # Sometimes the json is pretty-printed, sometimes not. Loosely tied to --user-agent, but not - # always. Normalize it enough to get the 3 elements necessary. Oh, for jq... # shellcheck disable=SC2086 - release_data="$(curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" -H 'Accept: application/vnd.github.v3+json' "$RELEASE_API" | sed -e's/\("[^:]*": *\("[^""]*",\|[^,]*[,}]\)\)/\r\n\1/g')" + release_data="$(curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" -H 'Accept: application/vnd.github.v3+json' "$RELEASE_API")" errcode=$? if [[ $errcode -eq 60 ]]; then error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" @@ -786,8 +784,8 @@ check_getssl_upgrade() { # check if a more recent release is available fi # Replace error in release description with _error (which is ignored by check_output_for_errors() in the tests) debug "${release_data//error/_error}" - release_data="$(sed -e's/^ *//g' <<<"${release_data}")" - release_tag="$(sed -e'/"tag_name": *"/!d;s/"tag_name": *"\([^""]*\).*$/\1/' <<<"${release_data}")" + # awk from https://stackoverflow.com/questions/1761341/awk-print-next-record-following-matched-record + release_tag=$(awk -F'"' '/tag_name/ {f=NR} f&&NR-1==f' RS=":|," <<<"${release_data}" | sed -e's/"//g') if [[ "${release_tag:0:1}" != 'v' ]] ; then if [[ ${_MUTE} -eq 0 ]]; then info "The current repository has no releases or is improperly tagged; can't check for upgrades: '$release_tag'" From 07b5b6e4da964a25b9d0787e1da06ce89585e63f Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 11 Oct 2021 10:18:15 +0100 Subject: [PATCH 303/308] Fix broken upgrade url Add pre and post upgrade sanity checks Fixes #718 --- getssl | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/getssl b/getssl index 254ca16..fc61831 100755 --- a/getssl +++ b/getssl @@ -274,6 +274,8 @@ # 2021-09-30 better error if curl returns 60 (#709) # 2021-10-01 Fix -preferred-chain argument (#712) # 2021-10-01 Show help if no domain specified (#705)(2.44) +# 2021-10-08 Extract release tag from release api using awk (fix BSD issues) +# 2021-10-11 Fix broken upgrade url (#718)(2.45) # ---------------------------------------------------------------------------------------- case :$SHELLOPTS: in @@ -282,7 +284,7 @@ esac PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.44" +VERSION="2.45" # defaults ACCOUNT_KEY_LENGTH=4096 @@ -825,8 +827,9 @@ check_getssl_upgrade() { # check if a more recent release is available # shellcheck disable=SC2086 debug curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" # shellcheck disable=SC2086 - curl ${_NOMETER:---silent} --user-agent "$CURL_USERAGENT" "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE" + status=$(curl ${_NOMETER:---silent} -w "%{http_code}" --user-agent "$CURL_USERAGENT" "$CODE_LOCATION" --output "$TEMP_UPGRADE_FILE") errcode=$? +debug errcode=$errcode if [[ $errcode -eq 60 ]]; then error_exit "curl needs updating, your version does not support SNI (multiple SSL domains on a single IP)" @@ -834,6 +837,10 @@ check_getssl_upgrade() { # check if a more recent release is available error_exit "curl error downloading release: $errcode" fi + if [[ $status -ne 200 ]]; then + error_exit "curl didn't find the updated version of getssl at $CODE_LOCATION" + fi + if ! install "$0" "${0}.v${VERSION}"; then error_exit "problem renaming old version while updating, check permissions" fi @@ -841,6 +848,17 @@ check_getssl_upgrade() { # check if a more recent release is available error_exit "problem installing new version while updating, check permissions" fi + check=$(bash "$0" -U -v) + release_tag_upper=$(echo "$release_tag" | tr "[:lower:]" "[:upper:]") + if [[ "$check" != "getssl ${release_tag_upper}" ]]; then + info "problem running new version, rolling back to old version" + if ! install "${0}.v${VERSION}" "$0"; then + error_exit "problem rolling back, you'll need to manually check $0 and $0.${VERSION}" + fi + error_exit "problem calling new version; output of $TEMP_UPGRADE_FILE -v was \"$check\", expected \"getssl ${release_tag_upper}\"" + fi + + if [[ ${_MUTE} -eq 0 ]]; then echo "Updated getssl from v${VERSION} to ${release_tag}" echo "The old version remains as ${0}.v${VERSION} and should be removed" From f960ac9843a0138118ce99609f32e33984a2968a Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 11 Oct 2021 11:49:12 +0100 Subject: [PATCH 304/308] Don't run centos and ubuntu tests at same time --- .github/workflows/run-tests-staging-duckdns.yml | 2 ++ .github/workflows/run-tests-staging-dynu.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/run-tests-staging-duckdns.yml b/.github/workflows/run-tests-staging-duckdns.yml index 87da158..02805fa 100644 --- a/.github/workflows/run-tests-staging-duckdns.yml +++ b/.github/workflows/run-tests-staging-duckdns.yml @@ -24,6 +24,8 @@ jobs: run: test/run-test.sh centos7-duckdns test-ubuntu-duckdns: runs-on: ubuntu-latest + if: always() + needs: test-centos7-duckdns steps: - uses: actions/checkout@v2 - name: Build the docker-compose stack diff --git a/.github/workflows/run-tests-staging-dynu.yml b/.github/workflows/run-tests-staging-dynu.yml index fde2ba2..cf38bd7 100644 --- a/.github/workflows/run-tests-staging-dynu.yml +++ b/.github/workflows/run-tests-staging-dynu.yml @@ -24,6 +24,8 @@ jobs: run: test/run-test.sh centos7-dynu test-ubuntu-dynu: runs-on: ubuntu-latest + if: always() + needs: test-centos7-dynu steps: - uses: actions/checkout@v2 - name: Build the docker-compose stack From 8103b10e39c40f31ac5cf7abd9bc3e9fbb6ae26d Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Mon, 11 Oct 2021 16:42:25 +0100 Subject: [PATCH 305/308] Update README.md Add manual upgrade instructions for v2.43 --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index dbe46c3..1af7ab0 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,11 @@ for automating the process on remote servers. - [Include Root certificate in full chain](#include-root-certificate-in-full-chain) - [Issues / problems / help](#issues--problems--help) +## Upgrade broken in v2.43 + +The automatic upgrade in v2.43 is broken as the url is incorrect. If you have this version installed you'll need to manually upgrade using: +```curl --silent --user-agent getssl/manual https://raw.githubusercontent.com/srvrco/getssl/latest/getssl --output getssl``` + ## Features * **Bash** - It runs on virtually all unix machines, including BSD, most From 742efc1114a2350e98edc4abe66983e465cf0fc6 Mon Sep 17 00:00:00 2001 From: amartin-git <70332648+amartin-git@users.noreply.github.com> Date: Fri, 22 Oct 2021 10:30:33 -0400 Subject: [PATCH 306/308] Fix DOMAIN_CHAIN_LOCATION to copy correct file When FULL_CHAIN_INCLUDE_ROOT is set, DOMAIN_CHAIN_LOCATION was sending just the intermediate and server cert. Copying $FULL_CHAIN instead of $CERT_FILE+$CA_CERT fixes this. --- getssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getssl b/getssl index fc61831..66f6a36 100755 --- a/getssl +++ b/getssl @@ -438,7 +438,7 @@ cert_install() { # copy certs to the correct location (creating concatenated fi else to_location="${DOMAIN_CHAIN_LOCATION}" fi - cat "$CERT_FILE" "$CA_CERT" > "$TEMP_DIR/${DOMAIN}_chain.pem" + cat "$FULL_CHAIN" > "$TEMP_DIR/${DOMAIN}_chain.pem" copy_file_to_location "full chain" "$TEMP_DIR/${DOMAIN}_chain.pem" "$to_location" if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then cat "${CERT_FILE%.*}.ec.crt" "${CA_CERT%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}_chain.pem.ec" From a67fd6fa5b3ff851e988976a070c1d5edb03ea26 Mon Sep 17 00:00:00 2001 From: Thomas Mieslinger Date: Wed, 10 Nov 2021 15:05:43 +0100 Subject: [PATCH 307/308] detect Solaris derivates and add /usr/gnu/bin to PATH --- getssl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/getssl b/getssl index fc61831..8aac6ba 100755 --- a/getssl +++ b/getssl @@ -1824,6 +1824,14 @@ get_os() { # function to get the current Operating System os="cygwin" elif [[ ${uname_res:0:5} == "MINGW" ]]; then os="mingw" + elif [[ ${uname_res} == "SunOS" ]]; then + os="solaris" + if [ -d /usr/gnu/bin ]; then + export PATH=/usr/gnu/bin:$PATH + else + echo "Path with required GNU commands not found, please install /usr/gnu/bin" + exit 1 + fi else os="unknown" fi From 63d8206794a3b775da1ca42769b9bc8a24b03424 Mon Sep 17 00:00:00 2001 From: Thomas Mieslinger Date: Wed, 10 Nov 2021 15:36:10 +0100 Subject: [PATCH 308/308] add scripts to use IONOS DNS API --- dns_scripts/DNS_IONOS.md | 9 +++++++ dns_scripts/dns_add_ionos | 54 +++++++++++++++++++++++++++++++++++++++ dns_scripts/dns_del_ionos | 23 +++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 dns_scripts/DNS_IONOS.md create mode 100755 dns_scripts/dns_add_ionos create mode 100755 dns_scripts/dns_del_ionos diff --git a/dns_scripts/DNS_IONOS.md b/dns_scripts/DNS_IONOS.md new file mode 100644 index 0000000..d3a685e --- /dev/null +++ b/dns_scripts/DNS_IONOS.md @@ -0,0 +1,9 @@ +# Do DNS-01 verification using IONOS DNS API + +The getting started guide explains how to obtain API Keys https://developer.hosting.ionos.de/docs/getstarted + +All API Documentation can be found here https://developer.hosting.ionos.de/docs/dns + +JSON processing in bash is ... hard. So I choose `jq` to do the heavylifting. Other authors choose python so if +you think I did a bad decision feel free to implement this whith python/perl/ruby... + diff --git a/dns_scripts/dns_add_ionos b/dns_scripts/dns_add_ionos new file mode 100755 index 0000000..e4354bf --- /dev/null +++ b/dns_scripts/dns_add_ionos @@ -0,0 +1,54 @@ +#!/usr/bin/bash +# +# Called as +# +# eval "${DNS_ADD_COMMAND}" "${lower_d}" "${auth_key}" +# + +# See https://developer.hosting.ionos.de/docs/getstarted how to generate +# an API Key consisting of prefix and key +# +# see DNS API Doc here https://developer.hosting.ionos.de/docs/dns +# + +API_KEY="X-API-Key: ." +API_URL="https://api.hosting.ionos.com/dns/v1" + +# TODO: check $1,$2 not empty + +DNS_RR=$1 +DNS_SECRET=$2 + + +# get zone id: +curl -s -X GET "$API_URL/zones" -H "accept: application/json" -H "Content-Type: application/json" -H "$API_KEY" \ + | jq -r 'map([.name, .id] | join (";")) | .[]' >/tmp/$$.zones + +ZONE=$DNS_RR + +do=true +while $do; do + ZONE_ID=$(awk -F\; '/^'"$ZONE"';/{print $2}'