diff --git a/docker-host/README.md b/docker-host/README.md new file mode 100644 index 00000000..e7f929ca --- /dev/null +++ b/docker-host/README.md @@ -0,0 +1,35 @@ +# docker-host +- Author: Gabriel PĂ©riard-Tremblay +- Date: August 2016 + +## What docker-host Affects + +This playbook will install a docker-engine on the target host. + +## Role Variables + +These variables are needed when the docker-engine needs to be exposed. + +- docker_remote_access_enabled: True +- docker_daemon_port: 2376 +- docker_daemon_listening_ip: 0.0.0.0 + +When the docker-engine is reachable from another host, it's important +to configure TLS. Those are the basic settings for TLS and it should not be +modified. + +- docker_tls_enabled: True +- docker_tls_path: /home/docker/tls +- docker_tls_ca: ca/ca.pem +- docker_tls_ca_key: ca/ca-key.pem +- docker_tls_cert: server/cert.pem +- docker_tls_key: server/key.pem +- docker_tls_csr: server/server.csr + +## Example + +`$ ansible-playbook -i inventory docker-host.yml` + +## License + +GPLv3 diff --git a/docker-host/defaults/main.yml b/docker-host/defaults/main.yml new file mode 100644 index 00000000..40da89dd --- /dev/null +++ b/docker-host/defaults/main.yml @@ -0,0 +1,14 @@ +--- +docker_tmpdir: /home/docker/tmp + +docker_remote_access_enabled: True +docker_daemon_port: 2376 +docker_daemon_listening_ip: 0.0.0.0 + +docker_tls_enabled: True +docker_tls_path: /home/docker/tls +docker_tls_ca: ca/ca.pem +docker_tls_ca_key: ca/ca-key.pem +docker_tls_cert: server/cert.pem +docker_tls_key: server/key.pem +docker_tls_csr: server/server.csr diff --git a/docker-host/handlers/main.yml b/docker-host/handlers/main.yml new file mode 100644 index 00000000..8b484b49 --- /dev/null +++ b/docker-host/handlers/main.yml @@ -0,0 +1,9 @@ +--- +- name: reload systemd + command: systemctl daemon-reload + +- name: restart docker + service: + name: docker + state: restarted + enabled: yes diff --git a/docker-host/tasks/main.yml b/docker-host/tasks/main.yml new file mode 100644 index 00000000..37596978 --- /dev/null +++ b/docker-host/tasks/main.yml @@ -0,0 +1,69 @@ +# This role installs the docker daemon +--- +- name: Install apt-transport-https + apt: + name: apt-transport-https + state: present + update_cache: yes + +- name: Enable Docker repositories + apt_repository: + repo: 'deb https://apt.dockerproject.org/repo debian-{{ ansible_distribution_release }} main' + state: present + update_cache: no + +- name: Enable backports repository for docker-py + apt_repository: + repo: 'deb http://ftp.debian.org/debian {{ ansible_distribution_release }}-backports main' + state: present + +- name: Install Docker repo keys + apt_key: + keyserver: pgp.mit.edu + id: 58118E89F3A912897C070ADBF76221572C52609D + +- name: Install docker and docker-py + apt: + name: {{ item }} + state: latest + update_cache: yes + with_items: + - docker-engine + - python-docker + +- name: Configure docker service + template: + src: docker.service.j2 + dest: /lib/systemd/system/docker.service + notify: + - reload systemd + - restart docker + +- name: Creating Docker tmp directory + file: + path: "{{ docker_tmpdir }}" + state: directory + mode: "0644" + owner: root + +- name: Creating Docker TLS directory + file: + path: "{{ docker_tls_path }}" + state: directory + mode: "0644" + owner: root + when: "{{ docker_tls_enabled }}" + +- name: Copy shellpki utility to Docker TLS directory + template: + src: "{{ item }}.j2" + dest: "{{ docker_tls_path }}/{{ item }}" + mode: "0744" + with_items: + - shellpki.sh + - openssl.cnf + when: "{{ docker_tls_enabled }}" + +- name: Creating a CA, server key + command: "{{ docker_tls_path }}/shellpki.sh init" + when: "{{ docker_tls_enabled }}" diff --git a/docker-host/templates/docker.service.j2 b/docker-host/templates/docker.service.j2 new file mode 100644 index 00000000..02229fd8 --- /dev/null +++ b/docker-host/templates/docker.service.j2 @@ -0,0 +1,27 @@ +# {{ ansible_managed }} + +[Unit] +Description=Docker Application Container Engine +Documentation=https://docs.docker.com +After=network.target docker.socket +Requires=docker.socket + +[Service] +ExecStart=/usr/bin/docker daemon -H fd:// \ + {% if docker_tls_enabled %} + --tlsverify \ + --tlscacert={{ docker_tls_path }}/{{ docker_tls_ca }} \ + --tlscert={{ docker_tls_path }}/{{ docker_tls_cert }} \ + --tlskey={{ docker_tls_path }}/{{ docker_tls_key }} \ + {% endif %} + {% if docker_remote_access_enabled %} + -H tcp://{{ docker_daemon_listening_ip }}:{{ docker_daemon_port }} + {% endif %} +MountFlags=slave +LimitNOFILE=1048576 +LimitNPROC=1048576 +LimitCORE=infinity +Environment="TMPDIR={{ docker_tmpdir }}" + +[Install] +WantedBy=multi-user.target diff --git a/docker-host/templates/openssl.cnf.j2 b/docker-host/templates/openssl.cnf.j2 new file mode 100644 index 00000000..819c5409 --- /dev/null +++ b/docker-host/templates/openssl.cnf.j2 @@ -0,0 +1,50 @@ +# {{ ansible_managed }} + +[ ca ] +default_ca = CA_default + +[ CA_default ] +dir = {{ docker_tls_path }}/ca +certs = {{ docker_tls_path }}/certs +new_certs_dir = {{ docker_tls_path }}/ca/tmp +database = $dir/index.txt +certificate = $dir/cacert.pem +serial = $dir/serial +crl = {{ docker_tls_path }}crl.pem +private_key = $dir/private.key +RANDFILE = $dir/.rand +default_days = 365 +default_crl_days= 365 +default_md = sha256 +preserve = no +policy = policy_match + +[ policy_match ] +countryName = supplied +stateOrProvinceName = supplied +organizationName = supplied +organizationalUnitName = optional +commonName = supplied +emailAddress = supplied + +[ req ] +default_bits = 2048 +distinguished_name = req_distinguished_name + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = FR +countryName_min = 2 +countryName_max = 2 +stateOrProvinceName = State or Province +stateOrProvinceName_default = 13 +localityName = Locality Name (eg, city) +localityName_default = Marseille +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Evolix +organizationalUnitName = Organizational Unit Name (eg, section) +commonName = Common Name (eg, your name or your server\'s hostname) +commonName_max = 64 +emailAddress = Email Address +emailAddress_default = security@evolix.net +emailAddress_max = 40 diff --git a/docker-host/templates/shellpki.sh.j2 b/docker-host/templates/shellpki.sh.j2 new file mode 100644 index 00000000..21a47add --- /dev/null +++ b/docker-host/templates/shellpki.sh.j2 @@ -0,0 +1,121 @@ +#!/bin/sh +# {{ ansible_managed }} +# Simplified ShellPKI for Docker with TLS + +PREFIX={{ docker_tls_path }} +CONFFILE=$PREFIX/openssl.cnf +OPENSSL=`which openssl` + +init() { + + if [ ! -d $PREFIX/ca ]; then mkdir -p $PREFIX/ca; fi + if [ ! -d $PREFIX/ca/tmp ]; then mkdir -p $PREFIX/ca/tmp; fi + if [ ! -d $PREFIX/certs ]; then mkdir -p $PREFIX/certs; fi + if [ ! -d $PREFIX/files ]; then mkdir -p $PREFIX/files; fi + if [ ! -d $PREFIX/server ]; then mkdir -p $PREFIX/server; fi + + echo "Generating CA Key...\n" + $OPENSSL genrsa -out $PREFIX/ca/ca-key.pem 4096 + + echo "Generating CA cert...\n" + $OPENSSL req \ + -new -x509 -days 3650 -sha256 \ + -key $PREFIX/{{ docker_tls_ca_key }} \ + -out $PREFIX/{{ docker_tls_ca }} \ + -subj "/CN={{ ansible_hostname }}/C=FR" + + echo "Generating server key...\n" + $OPENSSL genrsa -out $PREFIX/{{ docker_tls_key }} 4096 + + echo "Generating server cert...\n" + $OPENSSL req \ + -new -days 3650 -sha256 \ + -key $PREFIX/{{ docker_tls_key }} \ + -out $PREFIX/{{ docker_tls_csr }} \ + -subj "/CN={{ ansible_hostname }}/C=FR" + + echo "subjectAltName = {% for ip in ansible_all_ipv4_addresses %}IP:{{ ip }},{% endfor %}IP:127.0.0.1" > $PREFIX/extfile.cnf + + echo "Signing server...\n" + $OPENSSL x509 \ + -req -sha256 -days 3650 \ + -in $PREFIX/{{ docker_tls_csr }} \ + -CA $PREFIX/{{ docker_tls_ca }} \ + -CAkey $PREFIX/{{ docker_tls_ca_key }} \ + -CAcreateserial \ + -out $PREFIX/{{ docker_tls_cert }} \ + -extfile $PREFIX/extfile.cnf + + rm $PREFIX/{{ docker_tls_csr }} +} + + +create() { + echo "Please enter your CN (Common Name)" + read cn + echo + echo "Your CN is '$cn'" + echo "Press return to continue..." + read + echo + + DIR=$PREFIX/files/$cn + mkdir $DIR + +# generate private key +$OPENSSL genrsa -out $DIR/$cn.key 4096 + +# generate csr req +$OPENSSL req \ + -new \ + -key $DIR/$cn.key \ + -config $CONFFILE \ + -out $DIR/$cn.csr \ + -subj "/CN=$cn/C=FR" + +# ca sign and generate cert + echo extendedKeyUsage = clientAuth > $DIR/extfile.cnf + $OPENSSL x509 \ + -req -sha256 \ + -in $DIR/$cn.csr \ + -CA $PREFIX/{{ docker_tls_ca }} \ + -CAkey $PREFIX/{{ docker_tls_ca_key }} \ + -CAcreateserial \ + -out $DIR/cert.pem \ + -extfile $DIR/extfile.cnf + rm $DIR/$cn.csr + cp $PREFIX/{{ docker_tls_ca }} $DIR/ +} + +revoke() { + echo "Please enter CN (Common Name) to revoke" + read cn + echo + echo "CN '$cn' will be revoked" + echo "Press return to continue..." + read + echo + +$OPENSSL ca \ + -revoke $PREFIX/certs/$cn.crt + +} + +case "$1" in + init) + init + ;; + + create) + create + ;; + + revoke) + revoke + ;; + + *) + echo "Usage: shellpki.sh {init|create|revoke}" + exit 1 + ;; +esac