diff --git a/.github/workflows/run-tests-staging-acmedns.yml b/.github/workflows/run-tests-staging-acmedns.yml new file mode 100644 index 0000000..bfcf7a4 --- /dev/null +++ b/.github/workflows/run-tests-staging-acmedns.yml @@ -0,0 +1,25 @@ +name: Run all tests using Dynu and acmedns +on: + push: + paths-ignore: + - '.github/workflows/*' + branches: + - master + pull_request: + branches: + - master + workflow_dispatch: + branches: + - master +env: + DYNU_API_KEY: ${{ secrets.DYNU_API_KEY == '' && '65cXefd35XbYf36546eg5dYcZT6X52Y2' || secrets.DYNU_API_KEY }} +jobs: + test-ubuntu-acmedns: + runs-on: ubuntu-latest + if: always() + steps: + - 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 acmedns + run: test/run-test.sh ubuntu-acmedns diff --git a/.gitignore b/.gitignore index 8317ebf..397dd03 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ *.tar.gz *.orig JSON.sh +.vscode/settings.json diff --git a/dns_scripts/dns_add_acmedns b/dns_scripts/dns_add_acmedns new file mode 100644 index 0000000..a8c3073 --- /dev/null +++ b/dns_scripts/dns_add_acmedns @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Need to add your API user and key below or set as env variable +apiuser=${ACMEDNS_API_USER:-''} +apikey=${ACMEDNS_API_KEY:-''} +apisubdomain=${ACMEDNS_SUBDOMAIN:-''} + +# This script adds a token to acme-dns.io DNS for the ACME challenge +# usage dns_add_acme-dns "domain name" "token" +# return codes are; +# 0 - success +# 1 - error returned from server + +fulldomain="${1}" +token="${2}" + +API='https://auth.acme-dns.io/update' + +# 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 "X-Api-Key: $apikey" + -H "X-Api-User: $apiuser" + -H 'Content-Type: application/json' +) + +generate_post_data() +{ + cat <]" '{print $2}') - deactivate_url_list="$deactivate_url_list $deactivate_url" - debug "adding url to deactivate list - $deactivate_url" - fi } check_challenge_completion_dns() { # perform validation via DNS challenge @@ -575,10 +572,19 @@ check_challenge_completion_dns() { # perform validation via DNS challenge # 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}') + check_output=$($DNS_CHECK_FUNC $DNS_CHECK_OPTIONS TXT "${rr}" "@${ns}") + check_result=$(grep -i "^${rr}"<<<"${check_output}"|grep 'IN\WTXT'|awk -F'"' '{ print $2}') debug "check_result=\"$check_result\"" + + # Check if rr is a CNAME + if [[ -z "$check_result" ]]; then + rr_cname=$(grep -i "^${rr}"<<<"${check_output}"|grep 'IN\WCNAME'|awk '{ print $5}') + debug "cname check=\"$rr_cname\"" + if [[ -n "$rr_cname" ]]; then + check_result=$(grep -i "^${rr_cname}"<<<"${check_output}"|grep 'IN\WTXT'|awk -F'"' '{ print $2}' | uniq) + fi + fi + if [[ -z "$check_result" ]]; then # shellcheck disable=SC2086 debug "$DNS_CHECK_FUNC" $DNS_CHECK_OPTIONS ANY "${rr}" "@${ns}" @@ -589,14 +595,20 @@ check_challenge_completion_dns() { # perform validation via DNS challenge debug "check_result=\"$check_result\"" fi elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then + debug "$DNS_CHECK_FUNC" -t TXT "${rr}" "${ns}" check_result=$($DNS_CHECK_FUNC -t TXT "${rr}" "${ns}" \ | grep 'descriptive text'|awk -F'"' '{ print $2}') + debug "check_result=\"$check_result\"" else + debug "$DNS_CHECK_FUNC" -type=txt "${rr}" "${ns}" check_result=$(nslookup -type=txt "${rr}" "${ns}" \ | grep 'text ='|awk -F'"' '{ print $2}') + debug "check_result=\"$check_result\"" if [[ -z "$check_result" ]]; then + debug "$DNS_CHECK_FUNC" -type=any "${rr}" "${ns}" check_result=$(nslookup -type=any "${rr}" "${ns}" \ | grep 'text ='|awk -F'"' '{ print $2}') + debug "check_result=\"$check_result\"" fi fi debug "expecting \"$auth_key\"" @@ -1201,6 +1213,11 @@ create_order() { fi ((dn++)) done + if [[ "$DEACTIVATE_AUTH" == "true" ]]; then + deactivate_url_list+=" $l " + debug "url added to deactivate list ${l}" + debug "deactivate list is now $deactivate_url_list" + fi done fi } @@ -1352,12 +1369,6 @@ for d in "${alldomains[@]}"; do if [[ $response_status == "valid" ]]; then info "$d is already validated" - if [[ "$DEACTIVATE_AUTH" == "true" ]]; then - deactivate_url="$(echo "$responseHeaders" | awk ' $1 ~ "^Location" {print $2}' | tr -d "\r")" - deactivate_url_list+=" $deactivate_url " - debug "url added to deactivate list ${deactivate_url}" - debug "deactivate list is now $deactivate_url_list" - fi # increment domain-counter ((dn++)) else @@ -1554,6 +1565,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n # domain is a CNAME: resolve it and continue with that debug Domain is a CNAME, actual domain is "$cname" gad_d=${cname} + res= fi # Use SOA +trace to find the name server @@ -1629,6 +1641,7 @@ 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" return fi fi @@ -1639,26 +1652,48 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n # shellcheck disable=SC2086 res=$(nslookup $DNS_CHECK_OPTIONS -debug -type=soa -type=ns "$gad_d" ${gad_s}) + # check for CNAME (assumes gad_d is _acme-challenge.{host}) + if [[ "$(grep -c "NXDOMAIN"<<<"$res")" -gt 0 ]]; then + debug "Cannot find nameserver record for $gad_d, using parent domain ${gad_d#*.}" + gad_d="${gad_d#*.}" + debug "nslookup $DNS_CHECK_OPTIONS -debug -type=soa -type=ns $gad_d ${gad_s}" + # shellcheck disable=SC2086 + res=$(nslookup $DNS_CHECK_OPTIONS -debug -type=soa -type=ns "$gad_d" ${gad_s}) + fi + if [[ "$(echo "$res" | grep -c "Non-authoritative")" -gt 0 ]]; then # this is a Non-authoritative server, need to check for an authoritative one. + debug "Response from non-authoritative server looking for authoritative server" + 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 the previous line fails to find the nameserver, use the original + if [[ -z "$gad_s" ]]; then + gad_s="$orig_gad_s" + fi + + if [[ "$(echo "$res" | grep -c "canonical name")" -gt 0 ]]; then + debug "$gad_d" appears to be a CNAME + gad_d=$(echo "$res" | awk ' $2 ~ "canonical" {print $5; exit }' |sed 's/\.$//g') + debug "Using $gad_d instead" + elif [[ "$(echo "$res" | grep -c "an't find")" -gt 0 ]]; then # if domain name doesn't exist, then find auth servers for next level up + debug "Couldn't find NS or SOA for domain name, using nslookup $DNS_CHECK_OPTIONS -debug ${gad_d#*.} ${orig_gad_s}" + # shellcheck disable=SC2086 + res=$(nslookup $DNS_CHECK_OPTIONS -debug "${gad_d#*.}" ${orig_gad_s}) 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" + gad_d="${orig_gad_d}" fi fi + debug "Using nslookup $DNS_CHECK_OPTIONS -debug -type=soa -type=ns $gad_d ${gad_s}" # shellcheck disable=SC2086 res=$(nslookup $DNS_CHECK_OPTIONS -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 + if [[ "$(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 @@ -1680,6 +1715,11 @@ 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" return fi fi diff --git a/test/2-simple-dns01-dig.bats b/test/2-simple-dns01-dig.bats index c5bc854..cfac9e9 100644 --- a/test/2-simple-dns01-dig.bats +++ b/test/2-simple-dns01-dig.bats @@ -6,6 +6,7 @@ load '/getssl/test/test_helper.bash' setup_file() { + [ ! -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/2-simple-dns01-nslookup.bats b/test/2-simple-dns01-nslookup.bats index 37fa121..513d856 100644 --- a/test/2-simple-dns01-nslookup.bats +++ b/test/2-simple-dns01-nslookup.bats @@ -14,6 +14,9 @@ setup() { if [ -f /usr/bin/dig ]; then mv /usr/bin/dig /usr/bin/dig.getssl.bak fi + if [ -f /usr/bin/drill ]; then + mv /usr/bin/drill /usr/bin/drill.getssl.bak + fi if [ -f /usr/bin/host ]; then mv /usr/bin/host /usr/bin/host.getssl.bak fi @@ -25,6 +28,9 @@ teardown() { if [ -f /usr/bin/dig.getssl.bak ]; then mv /usr/bin/dig.getssl.bak /usr/bin/dig fi + if [ -f /usr/bin/drill.getssl.bak ]; then + mv /usr/bin/drill.getssl.bak /usr/bin/drill + fi if [ -f /usr/bin/host.getssl.bak ]; then mv /usr/bin/host.getssl.bak /usr/bin/host fi diff --git a/test/32-test-upgrade.bats b/test/32-test-upgrade.bats index e698fc5..c0b68de 100644 --- a/test/32-test-upgrade.bats +++ b/test/32-test-upgrade.bats @@ -38,6 +38,10 @@ check_github_quota() { setup_file() { + if [ -n "$STAGING" ]; then + echo "Using staging server, skipping internal test" >&3 + return 0 + fi if [ -f $BATS_RUN_TMPDIR/failed.skip ]; then echo "# Skipping setup due to previous test failure" >&3 return 0 diff --git a/test/40-cname-dns01-dig.bats b/test/40-cname-dns01-dig.bats new file mode 100644 index 0000000..db445fa --- /dev/null +++ b/test/40-cname-dns01-dig.bats @@ -0,0 +1,60 @@ +#! /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 + fi + 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_file() { + 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 +} + + +setup() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + + +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip +} + + +@test "Check CNAME _acme-challenge works if AUTH_DNS specified (dig)" { + if [ -z "$STAGING" ]; then + skip "Running local tests this is a staging server test" + fi + CONFIG_FILE="getssl-dns01.cfg" + + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +PUBLIC_DNS_SERVER= +AUTH_DNS_SERVER="8.8.8.8" +CHECK_ALL_AUTH_DNS="false" +CHECK_PUBLIC_DNS_SERVER="false" +EOF + create_certificate + assert_success + assert_output --partial "dig" + check_output_for_errors +} diff --git a/test/40-cname-dns01-nslookup.bats b/test/40-cname-dns01-nslookup.bats new file mode 100644 index 0000000..1222fb1 --- /dev/null +++ b/test/40-cname-dns01-nslookup.bats @@ -0,0 +1,111 @@ +#! /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 + fi + if [ -f /usr/bin/dig ]; then + mv /usr/bin/dig /usr/bin/dig.getssl.bak + fi + if [ -f /usr/bin/drill ]; then + mv /usr/bin/drill /usr/bin/drill.getssl.bak + fi + if [ -f /usr/bin/host ]; then + mv /usr/bin/host /usr/bin/host.getssl.bak + fi +} + + +teardown_file() { + if [ -f /usr/bin/dig.getssl.bak ]; then + mv /usr/bin/dig.getssl.bak /usr/bin/dig + fi + if [ -f /usr/bin/drill.getssl.bak ]; then + mv /usr/bin/drill.getssl.bak /usr/bin/drill + fi + if [ -f /usr/bin/host.getssl.bak ]; then + mv /usr/bin/host.getssl.bak /usr/bin/host + fi +} + + +setup() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" +} + + +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip +} + + +@test "Check CNAME _acme-challenge works with default DNS values (nslookup)" { + if [ -z "$STAGING" ]; then + skip "Running local tests this is a staging server test" + fi + + CONFIG_FILE="getssl-dns01.cfg" + + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +PUBLIC_DNS_SERVER= +AUTH_DNS_SERVER= +CHECK_ALL_AUTH_DNS="false" +CHECK_PUBLIC_DNS_SERVER="false" +EOF + create_certificate + assert_success + assert_output --partial "nslookup -type=txt" + check_output_for_errors +} + + +@test "Check CNAME _acme-challenge works if PUBLIC_DNS specified (nslookup)" { + if [ -z "$STAGING" ]; then + skip "Running local tests this is a staging server test" + fi + CONFIG_FILE="getssl-dns01.cfg" + + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +PUBLIC_DNS_SERVER="8.8.8.8" +AUTH_DNS_SERVER= +CHECK_ALL_AUTH_DNS="false" +CHECK_PUBLIC_DNS_SERVER="false" +EOF + create_certificate + assert_success + assert_output --partial "nslookup -type=txt" + check_output_for_errors +} + + +@test "Check CNAME _acme-challenge works if AUTH_DNS specified (nslookup)" { + if [ -z "$STAGING" ]; then + skip "Running local tests this is a staging server test" + fi + CONFIG_FILE="getssl-dns01.cfg" + + setup_environment + init_getssl + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +PUBLIC_DNS_SERVER= +AUTH_DNS_SERVER="8.8.8.8" +CHECK_ALL_AUTH_DNS="false" +CHECK_PUBLIC_DNS_SERVER="false" +EOF + create_certificate + assert_success + assert_output --partial "nslookup -type=txt" + check_output_for_errors +} diff --git a/test/Dockerfile-ubuntu-acmedns b/test/Dockerfile-ubuntu-acmedns new file mode 100644 index 0000000..2061c38 --- /dev/null +++ b/test/Dockerfile-ubuntu-acmedns @@ -0,0 +1,39 @@ +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" +# 2016ENV dynamic_dns "acme-dns" +ENV ACMEDNS_API_USER 49ac5f6d-74cd-4aca-acfe-f9457af7894c +ENV ACMEDNS_API_KEY 2NPGF8cH7PeTrHZWXImi1prhTsQGz2pdCC7Za5zE +ENV ACMEDNS_SUBDOMAIN 7268181b-7075-4dce-be51-9c20c205cf6e + +# 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 +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 + +# 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 9d51875..dccf1a0 100644 --- a/test/run-test.cmd +++ b/test/run-test.cmd @@ -11,6 +11,7 @@ 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:acmedns=%==x%OS% GOTO acmedns IF NOT x%OS:bash=%==x%OS% GOTO bash SET ALIAS=%OS%.getssl.test SET STAGING= @@ -38,6 +39,12 @@ SET STAGING=--env STAGING=true --env dynamic_dns=dynu --env DYNU_API_KEY=65cXefd SET GETSSL_OS=%OS:-dynu=% GOTO Run +:acmedns +SET ALIAS=%OS%-getssl.freeddns.org +SET STAGING=--env STAGING=true --env dynamic_dns=acmedns +SET GETSSL_OS=%OS:-acmedns=% +GOTO Run + :bash SET ALIAS=%OS%.getssl.test SET STAGING= diff --git a/test/run-test.sh b/test/run-test.sh index e9aab38..9abe864 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -37,13 +37,17 @@ elif [[ "$OS" == *"dynu"* ]]; then ALIAS="${REPO}${OS%-dynu}-getssl.freeddns.org" STAGING="--env STAGING=true --env dynamic_dns=dynu" GETSSL_OS="${OS%-dynu}" +elif [[ "$OS" == *"acmedns"* ]]; then + ALIAS="${REPO}${OS}-getssl.freeddns.org" + STAGING="--env STAGING=true --env dynamic_dns=acmedns" + GETSSL_OS="${OS%-acmedns}" elif [[ "$OS" == "bash"* ]]; then GETSSL_OS="alpine" fi docker build --rm -f "test/Dockerfile-$OS" -t "getssl-$OS" . # shellcheck disable=SC2086 -docker run \ +docker run -it \ --env GETSSL_HOST=$ALIAS $STAGING \ --env GETSSL_IDN_HOST=$GETSSL_IDN_HOST \ --env GETSSL_OS=$GETSSL_OS \ diff --git a/test/test-config/getssl-dns01.cfg b/test/test-config/getssl-dns01.cfg index f71d19f..af4d5dc 100644 --- a/test/test-config/getssl-dns01.cfg +++ b/test/test-config/getssl-dns01.cfg @@ -1,6 +1,11 @@ # Test that the script works with dns VALIDATE_VIA_DNS=true +# 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" @@ -8,30 +13,29 @@ if [ -z "$STAGING" ]; then 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" + # Re-use the account key when calling the staging server (otherwise hit limits) + ACCOUNT_KEY="${HOME}/account.key" + DEACTIVATE_AUTH="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" + PUBLIC_DNS_SERVER="8.8.8.8" # resolver1.infoserve.de" if [[ "${dynamic_dns}" == "dynu" ]]; then AUTH_DNS_SERVER=ns1.dynu.com - else + elif [[ "${dynamic_dns}" != "acmedns" ]]; then 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" + if [[ "${dynamic_dns}" != "acmedns" ]]; then + DNS_WAIT=30 + DNS_WAIT_COUNT=20 + DNS_EXTRA_WAIT=120 + fi fi # Additional domains - this could be multiple domains / subdomains in a comma separated list SANS="" diff --git a/test/u1-test-get_auth_dns-dig.bats b/test/u1-test-get_auth_dns-dig.bats index 17ead16..03f70cd 100644 --- a/test/u1-test-get_auth_dns-dig.bats +++ b/test/u1-test-get_auth_dns-dig.bats @@ -139,41 +139,3 @@ teardown() { run get_auth_dns www.duckdns.org assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.net 1\.0\.0\.1' } - - -@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_PUBLIC_DNS_SERVER=false - 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-9]+\.duckdns\.org' - - # Assert that we found a CNAME but didn't use 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 - run get_auth_dns www.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 4884a60..57b913f 100644 --- a/test/u2-test-get_auth_dns-drill.bats +++ b/test/u2-test-get_auth_dns-drill.bats @@ -155,49 +155,3 @@ teardown() { run get_auth_dns www.duckdns.org assert_output --regexp 'set primary_ns = ns.*\.awsdns.*\.net 1\.0\.0\.1' } - - -@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_PUBLIC_DNS_SERVER=false - 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-9]+\.duckdns\.org' - - # Assert that we found a CNAME but didn't use 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 - run get_auth_dns www.duckdns.org - assert_output --regexp 'set primary_ns = (ns[1-9]+\.duckdns\.org )+' -} diff --git a/test/u7-test-get_auth_dns-nslookup.bats b/test/u7-test-get_auth_dns-nslookup.bats new file mode 100644 index 0000000..597a652 --- /dev/null +++ b/test/u7-test-get_auth_dns-nslookup.bats @@ -0,0 +1,148 @@ +#! /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() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + for app in dig drill host + do + if [ -f /usr/bin/${app} ]; then + mv /usr/bin/${app} /usr/bin/${app}.getssl.bak + fi + done + + . /getssl/getssl --source + _USE_DEBUG=1 + find_dns_utils + + NSLOOKUP_VERSION=$(echo "" | nslookup -version 2>/dev/null | awk -F"[ -]" '{ print $2 }') + # Version 9.11.3 on Ubuntu -debug doesn't work inside docker in my test env, version 9.16.1 does + if [[ "${NSLOOKUP_VERSION}" != "Invalid" ]] && check_version "${NSLOOKUP_VERSION}" "9.11.4" ; then + DNS_CHECK_OPTIONS="$DNS_CHECK_OPTIONS -debug" + else + skip "This version of nslookup either doesn't support -debug or it doesn't work in local docker" + fi +} + + +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip + for app in dig drill host + 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 using nslookup 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_PUBLIC_DNS_SERVER=false + 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-9]+\.duckdns\.org' + # Assert that we had to use dig NS + #assert_line --regexp 'Using nslookup.* NS' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=true + run get_auth_dns _acme-challenge.ubuntu-getssl.duckdns.org + assert_output --regexp 'set primary_ns=(ns[1-9]+\.duckdns\.org )+' +} + + +@test "Check get_auth_dns using nslookup 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_PUBLIC_DNS_SERVER=false + CHECK_ALL_AUTH_DNS=false + + run get_auth_dns _acme-challenge.ubuntu-getssl.duckdns.org + + # Assert that we've found the primary_ns server + assert_output --regexp 'set primary_ns=ns[1-9]+\.duckdns\.org' + + # Assert that we had to use nslookup NS + assert_line --regexp 'Using nslookup.*-type=soa' + assert_line --regexp 'Using nslookup.*-type=ns' + + # Check all Authoritive DNS servers are returned if requested + CHECK_ALL_AUTH_DNS=true + run get_auth_dns _acme-challenge.ubuntu-getssl.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 _acme-challenge.ubuntu-getssl.duckdns.org + assert_output --regexp 'set primary_ns=(ns[1-9]+\.duckdns\.org )+ 1\.0\.0\.1' +} + + +@test "Check get_auth_dns using nslookup 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_PUBLIC_DNS_SERVER=false + 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.*\.org' + + # Assert that we found a CNAME + assert_line --partial 'appears to be a CNAME' + + # 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.*\.org )+' + + # 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.* )+ 1\.0\.0\.1' +} diff --git a/test/u8-test-get_auth_dns-cname-nslookup.bats b/test/u8-test-get_auth_dns-cname-nslookup.bats new file mode 100644 index 0000000..9a25503 --- /dev/null +++ b/test/u8-test-get_auth_dns-cname-nslookup.bats @@ -0,0 +1,62 @@ +#! /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() { + [ ! -f $BATS_RUN_TMPDIR/failed.skip ] || skip "skipping tests after first failure" + for app in dig drill host + do + if [ -f /usr/bin/${app} ]; then + mv /usr/bin/${app} /usr/bin/${app}.getssl.bak + fi + done + + . /getssl/getssl --source + find_dns_utils + _USE_DEBUG=1 + + NSLOOKUP_VERSION=$(echo "" | nslookup -version 2>/dev/null | awk -F"[ -]" '{ print $2 }') + # Version 9.11.3 on Ubuntu -debug doesn't work inside docker in my test env, version 9.16.1 does + if [[ "${NSLOOKUP_VERSION}" != "Invalid" ]] && check_version "${NSLOOKUP_VERSION}" "9.11.4" ; then + DNS_CHECK_OPTIONS="$DNS_CHECK_OPTIONS -debug" + else + skip "This version of nslookup either doesn't support -debug or it doesn't work in local docker" + fi +} + + +teardown() { + [ -n "$BATS_TEST_COMPLETED" ] || touch $BATS_RUN_TMPDIR/failed.skip + for app in dig drill host + 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 for a CNAME using system DNS and nslookup" { + PUBLIC_DNS_SERVER= + AUTH_DNS_SERVER= + CHECK_ALL_AUTH_DNS="false" + CHECK_PUBLIC_DNS_SERVER="false" + + # This is a CNAME, but the later `nslookup -type=txt ` call will fail if set to the remote ns + run get_auth_dns _acme-challenge.ubuntu-acmedns-getssl.freeddns.org + assert_output --regexp 'set primary_ns=ns[0-9].dynu.com' +} + +@test "Check get_auth_dns for a CNAME using public DNS and nslookup" { + PUBLIC_DNS_SERVER=1.0.0.1 + AUTH_DNS_SERVER= + CHECK_ALL_AUTH_DNS="false" + CHECK_PUBLIC_DNS_SERVER="false" + + run get_auth_dns _acme-challenge.ubuntu-acmedns-getssl.freeddns.org + assert_output --regexp 'set primary_ns=ns[0-9].dynu.com' +}