diff --git a/content/posts/docker-tcp.md b/content/posts/docker-tcp.md index 4608cc7..7101d91 100644 --- a/content/posts/docker-tcp.md +++ b/content/posts/docker-tcp.md @@ -65,7 +65,7 @@ In the above snippet, replace `` with the hostname (output of the `hostname` command) of the machine who's API you want to expose. Now we've created `server-key.pem` and `server.csr`. -After this, we need to create a file named `extfile.cnf` with the +As a final step, we need to create a file named `extfile.cnf` with the following content: ``` @@ -75,87 +75,3 @@ extendedKeyUsage = serverAuth Here, we once again replace `` with the machine's hostname, and `` with the machine's public IP. - -This file can now be used to generate the actual signed certificate: - -```shell -openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem \ - -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf -``` - -Here, we can once again change the days argument to the value we want. After -all these steps, we're left with a signed server-side certificate. - -## Client-side - -Now we'll generate the client-side certificates. We start by creating a `csr` -file: - -```shell -openssl genrsa -out key.pem 4096 -openssl req -subj '/CN=client' -new -key key.pem -out client.csr -``` - -After this, we create another `.cnf`, this time to configure the client-side -keys. Add this to a file named `extfile-client.cnf`: - -``` -extendedKeyUsage = clientAuth -``` - -And then, we generate the client-side key: - -``` -openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey \ - ca-key.pem -CAcreateserial -out cert.pem -extfile extfile-client.cnf -``` - -Once again change the days value to whatever you want. Now we're left with all -the files we need to securely expose the API. - -## Exposing the API - -**Note**: the following steps will restart the Docker engine and all -running containers, so make sure this won't break anything. - -Start by creating a directory on the host that you're not going to delete. In -the following steps, replace `` with the absolute path to this directory. -After this, copy `ca.pem`, `server-cert.pem` and `server-key.pem` to this -directory. - -We're gonna be creating a system config file for the Docker service (this guide -assumes the use of `systemd`). In -`/etc/systemd/docker.service.d/startup_options.conf`, put the following: - -```shell -[Service] -ExecStart= -ExecStart=/usr/bin/dockerd --tlsverify --tlscacert='/ca.pem' --tlscert='/server-cert.pem' --tlskey='/server-key.pem' -H fd:// -H tcp://0.0.0.0:2376 -``` - -Don't forget the replace `` with the path to your actual directory. - -The final step is restarting the Docker engine: - -```shell -systemctl daemon-reload -systemctl restart docker.service -``` - -**Note**: these commands require root. - -After all this, you should have a Docker API that's accessible using an -encrypted connection. Let's test it by adding it to Portainer! - -## Adding engine to Portainer - -Thankfully this is the easy part. In Portainer, add a new endpoint and choose -the "Docker" type. Pick a name for your endpoint, fill in the endpoint URL -including the port number (Docker's default port number is `2376`) and enable -the "TLS" switch. We choose "TLS with server and client verification", as this -is the safest. The files to upload are `ca.pem` for the TLS CA certificate, -`cert.pem` for the TLS certificate and `key.pem` for the TLS key. If all goes -well, you should now connect to the host! - -Now, I know these steps can be quite tedious to repeat, so I've written -[a script](/scripts/docker-tcp.sh) that can automate this process for you. diff --git a/static/scripts/docker-tcp.sh b/static/scripts/docker-tcp.sh index 0b7c6e4..b1e88a2 100755 --- a/static/scripts/docker-tcp.sh +++ b/static/scripts/docker-tcp.sh @@ -10,21 +10,9 @@ days=365 # Displays how to use the program function usage() { - cat << EOF -This script generates OpenSSL certificate pairs which can be used to expose a -Docker API. - -Usage: $0 [-h] [-d DAYS] HOST IP [CERTDIR] - - HOST hostname of the machine to expose - IP public IP of the machine to expose - CERTDIR directory where the certificates will reside on the machine. If - specified, a startup_options.conf file is created for you, which - can then be copied over to the host. - - -h show this message - -d how many days the certificate will be valid; defaults to 365 -EOF + echo "This script generates OpenSSL certificate pairs which can be used to expose a Docker API." + echo + echo "Usage: $0 [-h] [-d DAYS] HOST IP" exit 1 } @@ -37,99 +25,19 @@ while getopts ':hd:' c; do done shift $((OPTIND - 1)) -host="$1" -ip="$2" -certdir="$3" - # Check for correct amount of arguments -[ $# -lt 2 ] && [ $# -gt 3 ] && usage +[ $# -eq 2 ] || usage -# =====SERVER-SIDE===== # Generate CA key -openssl genrsa \ - -aes256 \ - -out ca-key.pem \ - 4096 -openssl req \ - -new \ - -x509 \ - -days "$days" \ - -key ca-key.pem \ - -sha256 \ - -out ca.pem +openssl genrsa -aes256 -out ca-key.pem 4096 +openssl req -new -x509 -days "$DAYS" -key ca-key.pem -sha256 -out ca.pem # Generate server key -openssl genrsa \ - -out server-key.pem \ - 4096 -openssl req \ - -subj "/CN=$host" \ - -sha256 \ - -new \ - -key server-key.pem \ - -out server.csr +openssl genrsa -out server-key.pem 4096 +openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr # Create extfile.cnf -echo subjectAltName = "DNS:$host,IP:$ip,IP:127.0.0.1" > extfile.cnf + +echo subjectAltName = "DNS:$HOST,IP:$IP,IP:127.0.0.1" > extfile.cnf echo extendedKeyUsage = serverAuth >> extfile.cnf - -# Generate server-side certificate -openssl x509 \ - -req \ - -days 365 \ - -sha256 \ - -in server.csr \ - -CA ca.pem \ - -CAkey ca-key.pem \ - -CAcreateserial \ - -out server-cert.pem \ - -extfile extfile.cnf - - -# =====CLIENT-SIDE===== -# Generate key & csr -openssl genrsa \ - -out key.pem \ - 4096 -openssl req \ - -subj '/CN=client' \ - -new \ - -key key.pem \ - -out client.csr - -# Create extfile-client.cnf -echo extendedKeyUsage = clientAuth > extfile-client.cnf - -# Generate certificate -openssl x509 \ - -req \ - -days 365 \ - -sha256 \ - -in client.csr \ - -CA ca.pem \ - -CAkey ca-key.pem \ - -CAcreateserial \ - -out cert.pem \ - -extfile extfile-client.cnf - -# Create startup_options.conf -if [ -n "$certdir" ]; then - cat > startup_options.conf << EOF -[Service] -ExecStart= -ExecStart=/usr/bin/dockerd --tlsverify --tlscacert='$certdir/ca.pem' --tlscert='$certdir/server-cert.pem' --tlskey='$certdir/server-key.pem' -H fd:// -H tcp://0.0.0.0:2376 -EOF - - echo "Copy 'ca.pem', 'server-cert.pem' and 'server-key.pem' over to '$certdir' on the machine." - echo "'startup_options.conf' should be placed in '/etc/systemd/docker.service.d/startup_options.conf'." - -else - echo "Copy 'ca.pem', 'server-cert.pem' and 'server-key.pem' over to the chosen directory on the machine." - echo "Create a 'startup_options.conf' file as specified." - -fi - -echo "Now, you can restart the Docker daemon using:" -echo " systemctl daemon-reload" -echo " systemctl restart docker.service"