Make the ACME developements testing easier

* ADD docker-compose and shell script to allow developers to get ACME environment easily
This commit is contained in:
NicoMen 2017-07-07 11:36:32 +02:00 committed by Ludovic Fernandez
parent 8f845bac74
commit cb203f8e7e
5 changed files with 254 additions and 0 deletions

1
.gitignore vendored
View file

@ -11,3 +11,4 @@
*.log *.log
*.exe *.exe
.DS_Store .DS_Store
/example/acme/acme.json

View file

@ -0,0 +1,30 @@
# ACME Testing environment
## Objectives
In our integration ACME tests, we use a simulated Let's Encrypt container based stack named boulder.
The goal of this directory is to provide to developers a Traefik-boulder full stack environment.
This environment may be used in order to quickly test developments on ACME certificates management.
The provided Boulder stack is based on the environment used during integration tests.
## Directory content
* **compose-acme.yml** : Docker-Compose file which contains the description of Traefik and all the boulder stack containers to get,
* **acme.toml** : Traefik configuration file used by the Traefik container described above,
* **manage_acme_docker_environment.sh** Shell script which does all needed checks and manages the docker-compose environment.
## Shell script
### Description
To work fine, boulder needs a domain name, with a related IP and storage file. The shell script allows to check the environment before launching the Docker environment with the rights parameters and to managing this environment.
### Use
The script **manage_acme_docker_environment.sh** requires one argument. This argument can have 3 values :
* **--start** : Check environment and launch a new Docker environment.
* **--stop** : Stop and delete the current Docker environment.
* **--restart--** : Concatenate **--stop** and **--start** actions.

33
examples/acme/acme.toml Normal file
View file

@ -0,0 +1,33 @@
logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[acme]
email = "test@traefik.io"
storage = "/etc/traefik/conf/acme.json"
entryPoint = "https"
onDemand = false
OnHostRule = true
caServer = "http://traefik.localhost.com:4000/directory"
[web]
address = ":8080"
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "traefik.localhost.com"
watch = true
exposedbydefault = false

View file

@ -0,0 +1,89 @@
version: "2"
# IP_HOST : Docker host IP (not 127.0.0.1)
services :
boulder:
image: containous/boulder:release
environment:
FAKE_DNS: $IP_HOST
PKCS11_PROXY_SOCKET: tcp://boulder-hsm:5657
extra_hosts:
- le.wtf:127.0.0.1
- boulder:127.0.0.1
ports:
- 4000:4000 # ACME
- 4002:4002 # OCSP
- 4003:4003 # OCSP
- 4500:4500 # ct-test-srv
- 8000:8000 # debug ports
- 8001:8001
- 8002:8002
- 8003:8003
- 8004:8004
- 8055:8055 # dns-test-srv updates
- 9380:9380 # mail-test-srv
- 9381:9381 # mail-test-srv
restart: unless-stopped
depends_on:
- bhsm
- bmysql
- brabbitmq
bhsm:
image: letsencrypt/boulder-tools:2016-11-02
hostname: boulder-hsm
networks:
default:
aliases:
- boulder-hsm
environment:
PKCS11_DAEMON_SOCKET: tcp://0.0.0.0:5657
command: /usr/local/bin/pkcs11-daemon /usr/lib/softhsm/libsofthsm.so
expose:
- 5657
bmysql:
image: mariadb:10.1
hostname: boulder-mysql
networks:
default:
aliases:
- boulder-mysql
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
brabbitmq:
image: rabbitmq:3-alpine
hostname: boulder-rabbitmq
networks:
default:
aliases:
- boulder-rabbitmq
environment:
RABBITMQ_NODE_IP_ADDRESS: "0.0.0.0"
traefik:
build:
context: ../..
image: containous/traefik:latest
command: --configFile=/etc/traefik/conf/acme.toml
restart: unless-stopped
extra_hosts:
- traefik.localhost.com:$IP_HOST
volumes:
- "./acme.toml:/etc/traefik/conf/acme.toml:ro"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./acme.json:/etc/traefik/conf/acme.json:rw"
ports:
- "80:80"
- "443:443"
- "5001:443" # Needed for SNI challenge
expose:
- "8080"
labels:
- "traefik.port=8080"
- "traefik.backend=traefikception"
- "traefik.frontend.rule=Host:traefik.localhost.com"
- "traefik.enable=true"
depends_on:
- boulder

View file

@ -0,0 +1,101 @@
#! /usr/bin/env bash
# Initialize variables
readonly traefik_url="traefik.localhost.com"
readonly basedir=$(dirname $0)
readonly doc_file=$basedir"/compose-acme.yml"
# Stop and remove Docker environment
down_environment() {
echo "STOP Docker environment"
! docker-compose -f $doc_file down -v &>/dev/null && \
echo "[ERROR] Impossible to stop the Docker environment" && exit 11
}
# Create and start Docker-compose environment or subpart of its services (if services are listed)
# $@ : List of services to start (optional)
up_environment() {
echo "START Docker environment"
! docker-compose -f $doc_file up -d $@ &>/dev/null && \
echo "[ERROR] Impossible to start Docker environment" && exit 21
}
# Init the environment : get IP address and create needed files
init_environment() {
for netw in $(ip addr show | grep -v "LOOPBACK" | grep -v docker | grep -oE "^[0-9]{1}: .*:" | cut -d ':' -f2); do
ip_addr=$(ip addr show $netw | grep -E "inet " | grep -Eo "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | head -n 1)
[[ ! -z $ip_addr ]] && break
done
[[ -z $ip_addr ]] && \
echo "[ERROR] Impossible to find an IP address for the Docker host" && exit 31
# The $traefik_url entry must exist into /etc/hosts file
# It has to refer to the $ip_addr IP address
[[ $(cat /etc/hosts | grep $traefik_url | grep -vE "^#" | grep -oE "([0-9]+(\.)?){4}") != $ip_addr ]] && \
echo "[ERROR] Domain ${traefik_url} has to refer to ${ip_addr} into /etc/hosts file." && exit 32
# Export IP_HOST to use it in the DOcker COmpose file
export IP_HOST=$ip_addr
echo "CREATE empty acme.json file"
rm -f $basedir/acme.json && \
touch $basedir/acme.json && \
chmod 600 $basedir/acme.json # Needed for ACME
}
# Start all the environement
start() {
init_environment
echo "Start boulder environment"
up_environment bmysql brabbitmq bhsm boulder
waiting_counter=12
# Not start Traefik if boulder is not started
echo "WAIT for boulder..."
while [[ -z $(curl -s http://$traefik_url:4000/directory) ]]; do
sleep 5
let waiting_counter-=1
if [[ $waiting_counter -eq 0 ]]; then
echo "[ERROR] Impossible to start boulder container in the allowed time, the Docker environment will be stopped"
down_environment
exit 41
fi
done
echo "START Traefik container"
up_environment traefik
}
# Script usage
show_usage() {
echo
echo "USAGE : manage_acme_docker_environment.sh [--start|--stop|--restart]"
echo
}
# Main method
# $@ All parameters given
main() {
[[ $# -ne 1 ]] && show_usage && exit 1
case $1 in
"--start")
# Start boulder environment
start
echo "ENVIRONMENT SUCCESSFULLY STARTED"
;;
"--stop")
! down_environment
echo "ENVIRONMENT SUCCESSFULLY STOPPED"
;;
"--restart")
down_environment
start
echo "ENVIRONMENT SUCCESSFULLY STARTED"
;;
*)
show_usage && exit 2
;;
esac
}
main $@