Browse Source

Merge pull request #731 from srvrco/acme-dns

Fix CNAME issues and support acme-dns (fixes #722, #308, #646, #600, #585)
pull/749/head
Tim Kimber 4 years ago
committed by GitHub
parent
commit
734940d8ca
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 723 additions and 126 deletions
  1. +8
    -0
      .github/workflows/run-tests-pebble.yml
  2. +25
    -0
      .github/workflows/run-tests-staging-acmedns.yml
  3. +1
    -0
      .gitignore
  4. +55
    -0
      dns_scripts/dns_add_acmedns
  5. +0
    -0
      dns_scripts/dns_add_cpanel
  6. +0
    -0
      dns_scripts/dns_add_del_aliyun.sh
  7. +55
    -0
      dns_scripts/dns_del_acmedns
  8. +0
    -0
      dns_scripts/dns_del_cpanel
  9. +60
    -20
      getssl
  10. +6
    -0
      test/2-simple-dns01-nslookup.bats
  11. +4
    -0
      test/32-test-upgrade.bats
  12. +60
    -0
      test/40-cname-dns01-dig.bats
  13. +111
    -0
      test/40-cname-dns01-nslookup.bats
  14. +7
    -6
      test/Dockerfile-rockylinux8
  15. +39
    -0
      test/Dockerfile-ubuntu-acmedns
  16. +45
    -0
      test/Dockerfile-ubuntu14
  17. +7
    -0
      test/run-test.cmd
  18. +11
    -1
      test/run-test.sh
  19. +16
    -12
      test/test-config/getssl-dns01.cfg
  20. +3
    -3
      test/test-config/vsftpd.initd
  21. +0
    -38
      test/u1-test-get_auth_dns-dig.bats
  22. +0
    -46
      test/u2-test-get_auth_dns-drill.bats
  23. +148
    -0
      test/u7-test-get_auth_dns-nslookup.bats
  24. +62
    -0
      test/u8-test-get_auth_dns-cname-nslookup.bats

+ 8
- 0
.github/workflows/run-tests-pebble.yml View File

@ -92,6 +92,14 @@ jobs:
run: docker-compose up -d --build
- name: Run test suite on Ubuntu
run: test/run-test.sh ubuntu
test-ubuntu14:
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 Ubuntu14
run: test/run-test.sh ubuntu14
test-ubuntu16:
runs-on: ubuntu-latest
steps:


+ 25
- 0
.github/workflows/run-tests-staging-acmedns.yml View File

@ -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

+ 1
- 0
.gitignore View File

@ -7,3 +7,4 @@
*.tar.gz
*.orig
JSON.sh
.vscode/settings.json

+ 55
- 0
dns_scripts/dns_add_acmedns View File

@ -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 <<EOF
{
"subdomain": "$apisubdomain",
"txt": "$token"
}
EOF
}
resp=$(curl --silent \
"${curl_params[@]}" \
-X POST "${API}" \
--data "$(generate_post_data)")
echo $resp
# If adding record failed (returned json includes "error" then print error message
if [[ "$resp" = *"\"error\""* ]]; then
echo "Error: DNS challenge not added: unknown error - ${resp}"
exit 1
fi

+ 0
- 0
dns_scripts/dns_add_cpanel View File


+ 0
- 0
dns_scripts/dns_add_del_aliyun.sh View File


+ 55
- 0
dns_scripts/dns_del_acmedns View File

@ -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 <<EOF
{
"subdomain": "$apisubdomain",
"txt": "$token"
}
EOF
}
resp=$(curl --silent \
"${curl_params[@]}" \
-X POST "${API}" \
--data "$(generate_post_data)")
echo $resp
# If adding record failed (returned json includes "error" then print error message
if [[ "$resp" = *"\"error\""* ]]; then
echo "Error: DNS challenge not added: unknown error - ${resp}"
exit 1
fi

+ 0
- 0
dns_scripts/dns_del_cpanel View File


+ 60
- 20
getssl View File

@ -276,6 +276,9 @@
# 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)
# 2021-10-22 Copy fullchain to DOMAIN_CHAIN_LOCATION (amartin-git)
# 2021-11-10 Detect Solaris and use gnu tools (#701)(miesi)
# 2021-11-12 Support acme-dns and fix CNAME issues (#722)(#308)
# ----------------------------------------------------------------------------------------
case :$SHELLOPTS: in
@ -536,12 +539,6 @@ check_challenge_completion() { # checks with the ACME server if our challenge is
debug "sleep 5 secs before testing verify again"
sleep 5
done
if [[ "$DEACTIVATE_AUTH" == "true" ]]; then
deactivate_url=$(echo "$responseHeaders" | grep "^Link" | awk -F"[<>]" '{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


+ 6
- 0
test/2-simple-dns01-nslookup.bats View File

@ -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


+ 4
- 0
test/32-test-upgrade.bats View File

@ -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


+ 60
- 0
test/40-cname-dns01-dig.bats View File

@ -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
}

+ 111
- 0
test/40-cname-dns01-nslookup.bats View File

@ -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
}

+ 7
- 6
test/Dockerfile-rockylinux8 View File

@ -1,12 +1,13 @@
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 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
RUN yum -y update && \
yum -y install \
epel-release \
git curl bind-utils wget which nginx jq procps findutils \
ftp vsftpd \
openssh-server \
glibc-locale-source glibc-langpack-en # for en_US.UTF-8 support
# Set locale
ENV LANG en_US.UTF-8


+ 39
- 0
test/Dockerfile-ubuntu-acmedns View File

@ -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

+ 45
- 0
test/Dockerfile-ubuntu14 View File

@ -0,0 +1,45 @@
FROM ubuntu:trusty
# trusty = 14
# Note this image uses mawk
# Update and install required software
RUN apt-get update --fix-missing && \
apt-get install -y \
git curl dnsutils ldnsutils wget nginx-light jq \
ftp vsftpd \
openssh-server \
locales # for idn testing
# Set locale
RUN locale-gen en_US.UTF-8
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/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 mkdir -p /var/www
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
# Run eternal loop - for testing
CMD [ "tail", "-f", "/dev/null" ]

+ 7
- 0
test/run-test.cmd View File

@ -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=


+ 11
- 1
test/run-test.sh View File

@ -37,13 +37,23 @@ 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
if tty -s; then
INT="-it"
else
INT=""
fi
docker build --rm -f "test/Dockerfile-$OS" -t "getssl-$OS" .
# shellcheck disable=SC2086
docker run \
docker run $INT\
--env GETSSL_HOST=$ALIAS $STAGING \
--env GETSSL_IDN_HOST=$GETSSL_IDN_HOST \
--env GETSSL_OS=$GETSSL_OS \


+ 16
- 12
test/test-config/getssl-dns01.cfg View File

@ -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=""


+ 3
- 3
test/test-config/vsftpd.initd View File

@ -39,7 +39,7 @@ case "${1}" in
start)
log_daemon_msg "Starting FTP server" "${NAME}"
if [ -e /etc/vsftpd.conf ] && ! egrep -iq "^ *listen(_ipv6)? *= *yes" /etc/vsftpd.conf
if [ -e /etc/vsftpd.conf ] && ! grep -Eiq "^ *listen(_ipv6)? *= *yes" /etc/vsftpd.conf
then
log_warning_msg "vsftpd disabled - listen disabled in config."
exit 0
@ -51,7 +51,7 @@ case "${1}" in
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}"
if pgrep vsftpd --pidfile /var/run/vsftpd/vsftpd.pid >/dev/null
then
break
fi
@ -59,7 +59,7 @@ case "${1}" in
n=$(( $n + 1 ))
done
if ps -C vsftpd | grep -qs "${_PID}"
if ! pgrep vsftpd --pidfile /var/run/vsftpd/vsftpd.pid >/dev/null
then
log_warning_msg "vsftpd failed - probably invalid config."
exit 1


+ 0
- 38
test/u1-test-get_auth_dns-dig.bats View File

@ -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 )+'
}

+ 0
- 46
test/u2-test-get_auth_dns-drill.bats View File

@ -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 )+'
}

+ 148
- 0
test/u7-test-get_auth_dns-nslookup.bats View File

@ -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'
}

+ 62
- 0
test/u8-test-get_auth_dns-cname-nslookup.bats View File

@ -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 <domain>` 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'
}

Loading…
Cancel
Save