1
0
docker-letsencrypt-nginx-pr.../test/tests/test-functions.sh

336 lines
8.8 KiB
Bash
Raw Normal View History

2017-11-24 23:51:31 +01:00
#!/bin/bash
set -e
# Get the first domain of a comma separated list.
function get_base_domain {
2020-07-04 02:39:32 +02:00
awk -F ',' '{print $1}' <<< "${1:?}" | tr -d ' ' | sed 's/\.$//'
2017-11-24 23:51:31 +01:00
}
export -f get_base_domain
2021-04-04 22:58:22 +02:00
# Run a acme-companion container
2017-11-24 23:51:31 +01:00
function run_le_container {
local image="${1:?}"
local name="${2:?}"
shift 2
2020-10-23 23:55:50 +02:00
local -a cli_args_arr
while [[ $# -gt 0 ]]; do
local flag="$1"
case $flag in
-c|--cli-args) #only one value per flag. Multiple args = use flag multiple times
local cli_args_arr_tmp
IFS=' ' read -r -a cli_args_arr_tmp <<< "${2:?}"
cli_args_arr+=("${cli_args_arr_tmp[0]}") #Head
#shellcheck disable=SC2116
cli_args_arr+=("$(echo "${cli_args_arr_tmp[@]:1}")") #Tail
shift 2
;;
*) #Legacy Option
local cli_args_str="${1:?}"
for arg in $cli_args_str; do
cli_args_arr+=("$arg")
done
shift
;;
esac
2020-10-23 23:55:50 +02:00
done
2018-06-01 10:33:12 +02:00
if [[ "$SETUP" == '3containers' ]]; then
2020-10-23 23:55:50 +02:00
cli_args_arr+=(--env "NGINX_DOCKER_GEN_CONTAINER=$DOCKER_GEN_CONTAINER_NAME")
2018-06-01 10:33:12 +02:00
fi
if [[ "$ACME_CA" == 'boulder' ]]; then
cli_args_arr+=(--env "ACME_CA_URI=http://boulder:4001/directory")
cli_args_arr+=(--network boulder_bluenet)
elif [[ "$ACME_CA" == 'pebble' ]]; then
cli_args_arr+=(--env "ACME_CA_URI=https://pebble:14000/dir")
cli_args_arr+=(--env "CA_BUNDLE=/pebble.minica.pem")
cli_args_arr+=(--network acme_net)
cli_args_arr+=(--volume "${GITHUB_WORKSPACE}/pebble.minica.pem:/pebble.minica.pem")
else
return 1
fi
if docker run -d \
2017-11-24 23:51:31 +01:00
--name "$name" \
2020-10-09 13:04:10 +02:00
--volumes-from "$NGINX_CONTAINER_NAME" \
2017-11-24 23:51:31 +01:00
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
2020-10-23 23:55:50 +02:00
"${cli_args_arr[@]}" \
2020-12-07 00:57:22 +01:00
--env "DOCKER_GEN_WAIT=500ms:2s" \
2020-11-27 18:16:35 +01:00
--env "TEST_MODE=true" \
2020-11-08 22:30:33 +01:00
--env "DEBUG=1" \
2017-12-29 00:28:15 +01:00
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.test_suite \
"$image" > /dev/null; \
then
[[ "${DRY_RUN:-}" == 1 ]] && echo "Started letsencrypt container for test ${name%%_2*}"
else
echo "Could not start letsencrypt container for test ${name%%_2*}"
return 1
fi
return 0
2017-11-24 23:51:31 +01:00
}
export -f run_le_container
# Run an nginx container
function run_nginx_container {
local -a cli_args_arr
while [[ $# -gt 0 ]]; do
local flag="$1"
case $flag in
-h|--hosts)
local le_host="${2:?}"
local virtual_host="${le_host// /}"; virtual_host="${virtual_host//.,/,}"; virtual_host="${virtual_host%,}"
shift 2
;;
-n|--name)
local container_name="${2:?}"
shift 2
;;
-c|--cli-args)
local cli_args_str="${2:?}"
for arg in $cli_args_str; do
cli_args_arr+=("$arg")
done
shift 2
;;
*) #Unknown option
shift
;;
esac
done
if [[ "$ACME_CA" == 'boulder' ]]; then
cli_args_arr+=(--network boulder_bluenet)
elif [[ "$ACME_CA" == 'pebble' ]]; then
cli_args_arr+=(--network acme_net)
else
return 1
fi
[[ "${DRY_RUN:-}" == 1 ]] && echo "Starting $container_name nginx container, with VIRTUAL_HOST=$virtual_host, LETSENCRYPT_HOST=$le_host and the following cli arguments : ${cli_args_arr[*]}."
if docker run --rm -d \
--name "${container_name:-$virtual_host}" \
-e "VIRTUAL_HOST=$virtual_host" \
-e "LETSENCRYPT_HOST=$le_host" \
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.test_suite \
"${cli_args_arr[@]}" \
nginx:alpine > /dev/null ; \
then
[[ "${DRY_RUN:-}" == 1 ]] && echo "Started $container_name nginx container."
else
echo "Failed to start $container_name nginx container, with VIRTUAL_HOST=$virtual_host, LETSENCRYPT_HOST=$le_host and the following cli arguments : ${cli_args_arr[*]}."
return 1
fi
return 0
}
export -f run_nginx_container
2020-07-05 12:40:24 +02:00
# Wait for the /etc/nginx/conf.d/standalone-cert-$1.conf file to exist inside container $2
function wait_for_standalone_conf {
local domain="${1:?}"
local name="${2:?}"
2020-11-23 03:13:51 +01:00
local timeout
timeout="$(date +%s)"
2021-04-05 14:32:04 +02:00
timeout="$((timeout + 120))"
2020-07-05 12:40:24 +02:00
local target
until docker exec "$name" [ -f "/etc/nginx/conf.d/standalone-cert-$domain.conf" ]; do
2020-11-23 03:13:51 +01:00
if [[ "$(date +%s)" -gt "$timeout" ]]; then
2020-07-05 12:40:24 +02:00
echo "Standalone configuration file for $domain was not generated under one minute, timing out."
return 1
fi
sleep 0.1
done
}
export -f wait_for_standalone_conf
2018-03-18 18:50:47 +01:00
# Wait for the /etc/nginx/certs/$1.crt symlink to exist inside container $2
function wait_for_symlink {
2017-11-24 23:51:31 +01:00
local domain="${1:?}"
local name="${2:?}"
local expected_target="${3:-}"
2020-11-23 03:13:51 +01:00
local timeout
timeout="$(date +%s)"
2021-04-05 14:32:04 +02:00
timeout="$((timeout + 120))"
2018-03-18 18:50:47 +01:00
local target
until docker exec "$name" [ -L "/etc/nginx/certs/$domain.crt" ]; do
2020-11-23 03:13:51 +01:00
if [[ "$(date +%s)" -gt "$timeout" ]]; then
2018-11-23 03:17:31 +01:00
echo "Symlink for $domain certificate was not generated under one minute, timing out."
2017-11-24 23:51:31 +01:00
return 1
fi
2020-11-23 03:13:51 +01:00
sleep 0.1
2017-11-24 23:51:31 +01:00
done
[[ "${DRY_RUN:-}" == 1 ]] && echo "Symlink to $domain certificate has been generated."
if [[ -n "$expected_target" ]]; then
target="$(docker exec "$name" readlink "/etc/nginx/certs/$domain.crt")"
if [[ "$target" != "$expected_target" ]]; then
echo "The symlink to the $domain certificate is expected to point to $expected_target but point to $target instead."
return 1
elif [[ "${DRY_RUN:-}" == 1 ]]; then
echo "The symlink is pointing to the file $target"
fi
fi
return 0
2017-11-24 23:51:31 +01:00
}
2018-03-18 18:50:47 +01:00
export -f wait_for_symlink
2018-11-23 03:00:30 +01:00
# Wait for the /etc/nginx/certs/$1.crt symlink to be removed inside container $2
2018-03-18 18:50:47 +01:00
function wait_for_symlink_rm {
local domain="${1:?}"
local name="${2:?}"
2020-11-23 03:13:51 +01:00
local timeout
timeout="$(date +%s)"
2021-04-05 14:32:04 +02:00
timeout="$((timeout + 120))"
2018-11-23 03:00:30 +01:00
until docker exec "$name" [ ! -L "/etc/nginx/certs/$domain.crt" ]; do
2020-11-23 03:13:51 +01:00
if [[ "$(date +%s)" -gt "$timeout" ]]; then
2018-11-23 03:17:31 +01:00
echo "Certificate symlink for $domain was not removed under one minute, timing out."
2018-03-18 18:50:47 +01:00
return 1
fi
2020-11-23 03:13:51 +01:00
sleep 0.1
2018-03-18 18:50:47 +01:00
done
[[ "${DRY_RUN:-}" == 1 ]] && echo "Symlink to $domain certificate has been removed."
return 0
2018-03-18 18:50:47 +01:00
}
export -f wait_for_symlink_rm
2017-11-24 23:51:31 +01:00
# Attempt to grab the certificate from domain passed with -d/--domain
# then check if the subject either match or doesn't match the pattern
# passed with either -m/--match or -nm/--no-match
# If domain can't be reached return 1
function check_cert_subj {
while [[ $# -gt 0 ]]; do
local flag="$1"
case $flag in
-d|--domain)
local domain="${2:?}"
shift
shift
;;
-m|--match)
local re="${2:?}"
local match_rc=0
local no_match_rc=1
shift
shift
;;
-n|--no-match)
local re="${2:?}"
local match_rc=1
local no_match_rc=0
shift
shift
;;
*) #Unknown option
shift
;;
esac
done
if curl -k https://"$domain" &> /dev/null; then
local cert_subject
cert_subject="$(echo \
| openssl s_client -showcerts -servername "$domain" -connect "$domain:443" 2>/dev/null \
| openssl x509 -subject -noout)"
else
return 1
fi
if [[ "$cert_subject" =~ $re ]]; then
return $match_rc
else
return $no_match_rc
fi
}
export -f check_cert_subj
# Wait for a successful https connection to domain passed with -d/--domain then wait
# - until the served certificate isn't the default one (default behavior)
# - until the served certificate is the default one (--default-cert)
# - until the served certificate subject match a string (--subject-match)
2017-11-24 23:51:31 +01:00
function wait_for_conn {
local action
local domain
local string
while [[ $# -gt 0 ]]; do
local flag="$1"
case $flag in
-d|--domain)
domain="${2:?}"
shift
shift
;;
--default-cert)
action='--match'
shift
;;
--subject-match)
action='--match'
string="$2"
shift
shift
;;
*) #Unknown option
shift
;;
esac
done
2020-11-23 03:13:51 +01:00
local timeout
timeout="$(date +%s)"
2021-04-05 14:32:04 +02:00
timeout="$((timeout + 120))"
action="${action:---no-match}"
string="${string:-letsencrypt-nginx-proxy-companion}"
until check_cert_subj --domain "$domain" "$action" "$string"; do
2020-11-23 03:13:51 +01:00
if [[ "$(date +%s)" -gt "$timeout" ]]; then
2017-11-24 23:51:31 +01:00
echo "Could not connect to $domain using https under two minutes, timing out."
return 1
fi
2020-11-23 03:13:51 +01:00
sleep 0.1
2017-11-24 23:51:31 +01:00
done
[[ "${DRY_RUN:-}" == 1 ]] && echo "Connection to $domain using https was successful."
return 0
2017-11-24 23:51:31 +01:00
}
export -f wait_for_conn
# Get the expiration date in unix epoch of domain $1 inside container $2
function get_cert_expiration_epoch {
local domain="${1:?}"
local name="${2:?}"
local cert_expiration
cert_expiration="$(docker exec "$name" openssl x509 -noout -enddate -in "/etc/nginx/certs/$domain.crt")"
cert_expiration="$(echo "$cert_expiration" | cut -d "=" -f 2)"
if [[ "$(uname)" == 'Darwin' ]]; then
cert_expiration="$(date -j -f "%b %d %T %Y %Z" "$cert_expiration" "+%s")"
else
cert_expiration="$(date -d "$cert_expiration" "+%s")"
fi
echo "$cert_expiration"
}
export -f get_cert_expiration_epoch