Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the ACME developments testing easier #1769

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -11,3 +11,4 @@
*.log
*.exe
.DS_Store
/example/acme/acme.json
30 changes: 30 additions & 0 deletions examples/acme/Docker_Acme.md
@@ -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 changes: 33 additions & 0 deletions examples/acme/acme.toml
@@ -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


89 changes: 89 additions & 0 deletions examples/acme/compose-acme.yml
@@ -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
101 changes: 101 additions & 0 deletions examples/acme/manage_acme_docker_environment.sh
@@ -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 $@