Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ install:

before_script:
- git clone https://github.com/docker-library/official-images.git official-images
- test/setup/setup-nginx-proxy.sh
- test/setup/setup-boulder.sh
- test/setup/setup-nginx-proxy.sh
- docker pull nginx:alpine

script:
Expand All @@ -48,6 +48,7 @@ after_failure:
- docker logs certs_single
- docker logs certs_san
- docker logs force_renew
- docker logs permissions
- docker logs symlinks
- docker logs boulder
- if [[ $SETUP = "3containers" ]]; then docker logs $DOCKER_GEN_CONTAINER_NAME; fi
3 changes: 2 additions & 1 deletion app/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ function check_default_cert_key {
-keyout /etc/nginx/certs/default.key.new \
-out /etc/nginx/certs/default.crt.new \
&& mv /etc/nginx/certs/default.key.new /etc/nginx/certs/default.key \
&& mv /etc/nginx/certs/default.crt.new /etc/nginx/certs/default.crt
&& mv /etc/nginx/certs/default.crt.new /etc/nginx/certs/default.crt \
&& set_root_ownership_and_permissions /etc/nginx/certs/default.key
echo "Info: a default key and certificate have been created at /etc/nginx/certs/default.key and /etc/nginx/certs/default.crt."
elif [[ $DEBUG == true && "${default_cert_cn:-}" =~ $cn ]]; then
echo "Debug: the self generated default certificate is still valid for more than three months. Skipping default certificate creation."
Expand Down
21 changes: 21 additions & 0 deletions app/functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,27 @@ function reload_nginx {
fi
}

function set_root_ownership_and_permissions {
local path="${1:?}"

if [[ $(stat -c %U:%G "$path" ) != root:root ]]; then
chown root:root "$path"
[[ $DEBUG == true ]] && echo "Debug: setting $path ownership to root:root."
fi

if [[ -d "$path" ]]; then
if [[ $(stat -c %a "$path") != 700 ]]; then
chmod 700 "$path"
[[ $DEBUG == true ]] && echo "Debug: setting $path permissions to 700."
fi
elif [[ -f "$path" ]]; then
if [[ $(stat -c %a "$path") != 600 ]]; then
chmod 600 "$path"
[[ $DEBUG == true ]] && echo "Debug: setting $path permissions to 600."
fi
fi
}

# Convert argument to lowercase (bash 4 only)
function lc {
echo "${@,,}"
Expand Down
14 changes: 13 additions & 1 deletion app/letsencrypt_service
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,10 @@ function update_certs {
[[ $REUSE_PRIVATE_KEYS == true ]] && params_d_str+=" --reuse_key"
[[ "${1}" == "--force-renew" ]] && params_d_str+=" --valid_min 7776000"

# Create directory for the first domain and make it the cwd
# Create directory for the first domain,
# make it root readable only and make it the cwd
mkdir -p "$certificate_dir"
set_root_ownership_and_permissions "$certificate_dir"
pushd "$certificate_dir" || return

for domain in "${!hosts_array}"; do
Expand Down Expand Up @@ -227,6 +229,14 @@ function update_certs {

popd || return

# Make the account key and its parent folders (up to
# /etc/nginx/certs/accounts included) root readable only
account_key_perm_path="/etc/nginx/certs/accounts/${acme_ca_uri#*://}/${account_alias}.json"
until [[ "$account_key_perm_path" == /etc/nginx/certs ]]; do
set_root_ownership_and_permissions "$account_key_perm_path"
account_key_perm_path="$(dirname "$account_key_perm_path")"
done

if [[ $simp_le_return -ne 2 ]]; then
for domain in "${!hosts_array}"; do
if [[ "$acme_ca_uri" == "$le_staging_uri" ]]; then
Expand All @@ -235,6 +245,8 @@ function update_certs {
create_links "$base_domain" "$domain" && should_reload_nginx='true'
fi
done
# Make private key root readable only
set_root_ownership_and_permissions "${certificate_dir}/key.pem"
# Queue nginx reload if a certificate was issued or renewed
[[ $simp_le_return -eq 0 ]] && should_reload_nginx='true'
fi
Expand Down
1 change: 1 addition & 0 deletions test/config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ imageTests+=(
certs_single
certs_san
force_renew
permissions
symlinks
'
)
4 changes: 1 addition & 3 deletions test/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@

set -e

## Next thirteen lines were added by jrcs/docker-letsencrypt-nginx-proxy-companion
## Next eleven lines were added by jrcs/docker-letsencrypt-nginx-proxy-companion
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
self="$(basename "$0")"

Expand All @@ -207,8 +207,6 @@ if [[ -z $TRAVIS_CI ]] && [[ -f "$dir/local_test_env.sh" ]]; then
source "$dir/local_test_env.sh"
fi

BOULDER_IP="10.77.77.1" && export BOULDER_IP

# shellcheck source=./tests/test-functions.sh
source "$dir/tests/test-functions.sh"
## End of additional code
Expand Down
5 changes: 1 addition & 4 deletions test/setup/setup-boulder.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ set -e
acme_endpoint='http://boulder:4000/directory'

setup_boulder() {
# Per the boulder README:
nginx_proxy_ip="$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' "$NGINX_CONTAINER_NAME")"

export GOPATH=${TRAVIS_BUILD_DIR}/go
[[ ! -d $GOPATH/src/github.com/letsencrypt/boulder ]] \
&& git clone --depth=1 https://github.com/letsencrypt/boulder \
Expand All @@ -26,7 +23,7 @@ setup_boulder() {
docker-compose run -d \
--use-aliases \
--name boulder \
-e FAKE_DNS=${nginx_proxy_ip:?} \
-e FAKE_DNS=10.77.77.1 \
--service-ports \
boulder
popd
Expand Down
3 changes: 3 additions & 0 deletions test/setup/setup-nginx-proxy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ case $SETUP in
-v /usr/share/nginx/html \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.test_suite \
--network boulder_bluenet \
jwilder/nginx-proxy
;;

Expand All @@ -25,6 +26,7 @@ case $SETUP in
-v /etc/nginx/vhost.d \
-v /usr/share/nginx/html \
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.test_suite \
--network boulder_bluenet \
nginx:alpine

docker run -d \
Expand All @@ -33,6 +35,7 @@ case $SETUP in
-v ${TRAVIS_BUILD_DIR}/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.test_suite \
--network boulder_bluenet \
jwilder/docker-gen \
-notify-sighup $NGINX_CONTAINER_NAME -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
;;
Expand Down
1 change: 1 addition & 0 deletions test/tests/certs_san/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ for hosts in "${letsencrypt_hosts[@]}"; do
--name "$container" \
-e "VIRTUAL_HOST=${TEST_DOMAINS}" \
-e "LETSENCRYPT_HOST=${hosts}" \
--network boulder_bluenet \
nginx:alpine > /dev/null && echo "Started test web server for $hosts"

# Wait for a symlink at /etc/nginx/certs/$base_domain.crt
Expand Down
1 change: 1 addition & 0 deletions test/tests/certs_single/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ for domain in "${domains[@]}"; do
--name "$domain" \
-e "VIRTUAL_HOST=${domain}" \
-e "LETSENCRYPT_HOST=${domain}" \
--network boulder_bluenet \
nginx:alpine > /dev/null && echo "Started test web server for $domain"
done

Expand Down
2 changes: 1 addition & 1 deletion test/tests/docker_api/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ EOF
# Cleanup function with EXIT trap
function cleanup {
# Kill the Docker events listener
kill $docker_events_pid && wait $docker_events_pid 2>/dev/
kill $docker_events_pid && wait $docker_events_pid 2>/dev/null
# Remove the remaining containers silently
docker stop \
"$nginx_vol" \
Expand Down
1 change: 1 addition & 0 deletions test/tests/force_renew/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ docker run --rm -d \
--name "${domains[0]}" \
-e "VIRTUAL_HOST=${domains[0]}" \
-e "LETSENCRYPT_HOST=${domains[0]}" \
--network boulder_bluenet \
nginx:alpine > /dev/null && echo "Started test web server for ${domains[0]}"

# Wait for a symlink at /etc/nginx/certs/${domains[0]}.crt
Expand Down
4 changes: 4 additions & 0 deletions test/tests/permissions/expected-std-out.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Started letsencrypt container for test permissions
Started test web server for le1.wtf
Symlink to le1.wtf certificate has been generated.
The link is pointing to the file ./le1.wtf/fullchain.pem
61 changes: 61 additions & 0 deletions test/tests/permissions/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash

## Test for sensitive files and folders permissions

if [[ -z $TRAVIS_CI ]]; then
le_container_name="$(basename ${0%/*})_$(date "+%Y-%m-%d_%H.%M.%S")"
else
le_container_name="$(basename ${0%/*})"
fi
run_le_container ${1:?} "$le_container_name"

# Create the $domains array from comma separated domains in TEST_DOMAINS.
IFS=',' read -r -a domains <<< "$TEST_DOMAINS"

# Cleanup function with EXIT trap
function cleanup {
# Remove the ${domains[0]} Nginx container silently.
docker rm --force "${domains[0]}" > /dev/null 2>&1
# Cleanup the files created by this run of the test to avoid foiling following test(s).
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
# Stop the LE container
docker stop "$le_container_name" > /dev/null
}
trap cleanup EXIT

# Run an nginx container for ${domains[0]}.
docker run --rm -d \
--name "${domains[0]}" \
-e "VIRTUAL_HOST=${domains[0]}" \
-e "LETSENCRYPT_HOST=${domains[0]}" \
nginx:alpine > /dev/null && echo "Started test web server for ${domains[0]}"

# Wait for the cert symlink.
wait_for_symlink "${domains[0]}" "$le_container_name"

# Array of folder paths to test
folders=( \
[0]="/etc/nginx/certs/accounts" \
[1]="/etc/nginx/certs/accounts/boulder:4000" \
[2]="/etc/nginx/certs/accounts/boulder:4000/directory" \
[3]="/etc/nginx/certs/${domains[0]}" \
)

# Test folder paths
for folder in "${folders[@]}"; do
ownership_and_permissions="$(docker exec "$le_container_name" stat -c %U:%G:%a "$folder")"
[[ "$ownership_and_permissions" == root:root:700 ]] || echo "Expected root:root:700 on ${folder}, found ${ownership_and_permissions}."
done

# Array of file paths to test
files=( \
[0]="/etc/nginx/certs/default.key" \
[1]="/etc/nginx/certs/accounts/boulder:4000/directory/default.json" \
[2]="/etc/nginx/certs/${domains[0]}/key.pem" \
)

# Test file paths
for file in "${files[@]}"; do
ownership_and_permissions="$(docker exec "$le_container_name" stat -c %U:%G:%a "$file")"
[[ "$ownership_and_permissions" == root:root:600 ]] || echo "Expected root:root:600 on ${file}, found ${ownership_and_permissions}."
done
5 changes: 5 additions & 0 deletions test/tests/symlinks/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ docker run --rm -d \
--name "symlink-le1-le2" \
-e "VIRTUAL_HOST=${domains[0]},${domains[1]}" \
-e "LETSENCRYPT_HOST=${domains[0]},${domains[1]}" \
--network boulder_bluenet \
nginx:alpine > /dev/null && echo "Started test web server for ${domains[0]},${domains[1]}"

# ... plus another nginx container for the third domain.
docker run --rm -d \
--name "symlink-le3" \
-e "VIRTUAL_HOST=${domains[2]}" \
-e "LETSENCRYPT_HOST=${domains[2]}" \
--network boulder_bluenet \
nginx:alpine > /dev/null && echo "Started test web server for ${domains[2]}"

# Wait for a file at /etc/nginx/certs/$domain/cert.pem
Expand Down Expand Up @@ -74,6 +76,7 @@ docker run --rm -d \
--name "symlink-le1-le2-le3" \
-e "VIRTUAL_HOST=${domains[0]},${domains[1]},${domains[2]}" \
-e "LETSENCRYPT_HOST=${domains[0]},${domains[1]},${domains[2]}" \
--network boulder_bluenet \
nginx:alpine > /dev/null && echo "Started test web server for ${domains[0]},${domains[1]},${domains[2]}"

# Check where the symlink points (should be ./le1.wtf/fullchain.pem)
Expand All @@ -92,6 +95,7 @@ docker run --rm -d \
--name "symlink-le2" \
-e "VIRTUAL_HOST=${domains[1]}" \
-e "LETSENCRYPT_HOST=${domains[1]}" \
--network boulder_bluenet \
nginx:alpine > /dev/null && echo "Started test web server for ${domains[1]}"

# Check where the symlink points (should be ./le2.wtf/fullchain.pem)
Expand All @@ -104,6 +108,7 @@ docker run --rm -d \
--name "symlink-lim-le2" \
-e "VIRTUAL_HOST=lim.it,${domains[1]}" \
-e "LETSENCRYPT_HOST=lim.it,${domains[1]}" \
--network boulder_bluenet \
nginx:alpine > /dev/null && echo "Started test web server for lim.it,${domains[1]}"

# The symlink creation for lim.it should time out, and the ${domains[1]}
Expand Down
3 changes: 2 additions & 1 deletion test/tests/test-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ function run_le_container {
$docker_gen_arg \
--env "DHPARAM_BITS=256" \
--env "DEBUG=true" \
--env "ACME_CA_URI=http://${BOULDER_IP}:4000/directory" \
--env "ACME_CA_URI=http://boulder:4000/directory" \
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.test_suite \
--network boulder_bluenet \
"$image" > /dev/null && echo "Started letsencrypt container for test ${name%%_2*}"
}
export -f run_le_container
Expand Down