Compare commits
No commits in common. "2cb6d2686c85ac0bf26cc0e21392007d0d072849" and "b4e76559123b47e50a56dd8f83dd5e7ea883be94" have entirely different histories.
2cb6d2686c
...
b4e7655912
|
|
@ -65,7 +65,7 @@ In the above snippet, replace `<HOST>` with the hostname (output of the
|
||||||
`hostname` command) of the machine who's API you want to expose. Now we've
|
`hostname` command) of the machine who's API you want to expose. Now we've
|
||||||
created `server-key.pem` and `server.csr`.
|
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:
|
following content:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -75,87 +75,3 @@ extendedKeyUsage = serverAuth
|
||||||
|
|
||||||
Here, we once again replace `<HOST>` with the machine's hostname, and `<IP>`
|
Here, we once again replace `<HOST>` with the machine's hostname, and `<IP>`
|
||||||
with the machine's public IP.
|
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 `<DIR>` 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='<DIR>/ca.pem' --tlscert='<DIR>/server-cert.pem' --tlskey='<DIR>/server-key.pem' -H fd:// -H tcp://0.0.0.0:2376
|
|
||||||
```
|
|
||||||
|
|
||||||
Don't forget the replace `<PATH>` 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.
|
|
||||||
|
|
|
||||||
|
|
@ -10,21 +10,9 @@ days=365
|
||||||
|
|
||||||
# Displays how to use the program
|
# Displays how to use the program
|
||||||
function usage() {
|
function usage() {
|
||||||
cat << EOF
|
echo "This script generates OpenSSL certificate pairs which can be used to expose a Docker API."
|
||||||
This script generates OpenSSL certificate pairs which can be used to expose a
|
echo
|
||||||
Docker API.
|
echo "Usage: $0 [-h] [-d DAYS] HOST IP"
|
||||||
|
|
||||||
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
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,99 +25,19 @@ while getopts ':hd:' c; do
|
||||||
done
|
done
|
||||||
shift $((OPTIND - 1))
|
shift $((OPTIND - 1))
|
||||||
|
|
||||||
host="$1"
|
|
||||||
ip="$2"
|
|
||||||
certdir="$3"
|
|
||||||
|
|
||||||
# Check for correct amount of arguments
|
# Check for correct amount of arguments
|
||||||
[ $# -lt 2 ] && [ $# -gt 3 ] && usage
|
[ $# -eq 2 ] || usage
|
||||||
|
|
||||||
|
|
||||||
# =====SERVER-SIDE=====
|
|
||||||
# Generate CA key
|
# Generate CA key
|
||||||
openssl genrsa \
|
openssl genrsa -aes256 -out ca-key.pem 4096
|
||||||
-aes256 \
|
openssl req -new -x509 -days "$DAYS" -key ca-key.pem -sha256 -out ca.pem
|
||||||
-out ca-key.pem \
|
|
||||||
4096
|
|
||||||
openssl req \
|
|
||||||
-new \
|
|
||||||
-x509 \
|
|
||||||
-days "$days" \
|
|
||||||
-key ca-key.pem \
|
|
||||||
-sha256 \
|
|
||||||
-out ca.pem
|
|
||||||
|
|
||||||
# Generate server key
|
# Generate server key
|
||||||
openssl genrsa \
|
openssl genrsa -out server-key.pem 4096
|
||||||
-out server-key.pem \
|
openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
|
||||||
4096
|
|
||||||
openssl req \
|
|
||||||
-subj "/CN=$host" \
|
|
||||||
-sha256 \
|
|
||||||
-new \
|
|
||||||
-key server-key.pem \
|
|
||||||
-out server.csr
|
|
||||||
|
|
||||||
# Create extfile.cnf
|
# 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
|
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"
|
|
||||||
|
|
|
||||||
Reference in New Issue