CoreOS Configuration Docker API TLS Certification

Keywords: Docker socket OpenSSL sudo

We often use Portainer to manage the docker environment, Jenkins to build and deploy the docker automatically, and the Docker API is used for remote management. Usually we just open a 2375 (usually) port without security protection, which is dangerous and can lead to remote hijacking attacks.Then we need to configure the TLS certified 2376 (usually) port.

Here we configure the CoreOS system:

1. Use the openssl that comes with the system to generate the corresponding server and client certificates

We use scripts to generate them automatically, which is very convenient. The scripts (auto-tls-certs.sh) are as follows:

#!/bin/bash
# 
# -------------------------------------------------------------
# Automatically create Docker TLS certificates
# -------------------------------------------------------------

# Here is the configuration information
# --[BEGIN]------------------------------

CODE="dp"
IP="docker The server ip"
PASSWORD="Certificate Password"
COUNTRY="CN"
STATE="BEIJING"
CITY="BEIJING"
ORGANIZATION="company"
ORGANIZATIONAL_UNIT="Dev"
COMMON_NAME="$IP"
EMAIL="mailbox"

# --[END]--

# Generate CA key
openssl genrsa -aes256 -passout "pass:$PASSWORD" -out "ca-key-$CODE.pem" 4096
# Generate CA
openssl req -new -x509 -days 365 -key "ca-key-$CODE.pem" -sha256 -out "ca-$CODE.pem" -passin "pass:$PASSWORD" -subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"
# Generate Server key
openssl genrsa -out "server-key-$CODE.pem" 4096

# Generate Server Certs.
openssl req -subj "/CN=$COMMON_NAME" -sha256 -new -key "server-key-$CODE.pem" -out server.csr

echo "subjectAltName = IP:$IP,IP:127.0.0.1" >> extfile.cnf
echo "extendedKeyUsage = serverAuth" >> extfile.cnf

openssl x509 -req -days 365 -sha256 -in server.csr -passin "pass:$PASSWORD" -CA "ca-$CODE.pem" -CAkey "ca-key-$CODE.pem" -CAcreateserial -out "server-cert-$CODE.pem" -extfile extfile.cnf


# Generate Client Certs.
rm -f extfile.cnf

openssl genrsa -out "key-$CODE.pem" 4096
openssl req -subj '/CN=client' -new -key "key-$CODE.pem" -out client.csr
echo extendedKeyUsage = clientAuth >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -passin "pass:$PASSWORD" -CA "ca-$CODE.pem" -CAkey "ca-key-$CODE.pem" -CAcreateserial -out "cert-$CODE.pem" -extfile extfile.cnf

rm -vf client.csr server.csr

chmod -v 0400 "ca-key-$CODE.pem" "key-$CODE.pem" "server-key-$CODE.pem"
chmod -v 0444 "ca-$CODE.pem" "server-cert-$CODE.pem" "cert-$CODE.pem"

# Packaging client certificates
mkdir -p "tls-client-certs-$CODE"
cp -f "ca-$CODE.pem" "cert-$CODE.pem" "key-$CODE.pem" "tls-client-certs-$CODE/"
cd "tls-client-certs-$CODE"
tar zcf "tls-client-certs-$CODE.tar.gz" *
mv "tls-client-certs-$CODE.tar.gz" ../
cd ..
rm -rf "tls-client-certs-$CODE"

# Copy server-side certificate
mkdir -p /etc/docker/certs.d
cp "ca-$CODE.pem" "server-cert-$CODE.pem" "server-key-$CODE.pem" /etc/docker/certs.d/

When the variables in the script are modified and run, a tls certificate is automatically created, and the server's certificate is in the / etc/docker/certs.d/directory:

The client's certificate is conveniently located in the directory where the script is run and a package of.tar.gz is automatically typed.

2. Configuring Docker services (official instructions)

Note that the certificate path is modified.

Enable the secure remote API on a new socket

Create a file called /etc/systemd/system/docker-tls-tcp.socket to make Docker available on a secured TCP socket on port 2376.

[Unit]
Description=Docker Secured Socket for the API

[Socket]
ListenStream=2376
BindIPv6Only=both
Service=docker.service

[Install]
WantedBy=sockets.target

Then enable this new socket:

systemctl enable docker-tls-tcp.socket
systemctl stop docker
systemctl start docker-tls-tcp.socket

Drop-in configuration

Create /etc/systemd/system/docker.service.d/10-tls-verify.conf drop-in for systemd Docker service:

[Service]
Environment="DOCKER_OPTS=--tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server.pem --tlskey=/etc/docker/server-key.pem"

Reload systemd config files and restart docker service:

sudo systemctl daemon-reload
sudo systemctl restart docker.service

Configure Portainer Remote TLS Connection

Certificate Correspondence Selection:

  1. ca.pem
  2. cert.pem
  3. key.pem

That's it.Note that if you have previously opened an unauthenticated port 2375, close and disable it and restart the docker service.

# Stop unsafe port 2375
systemctl stop docker-tcp.socket

# Disable this port
systemctl disable docker-tcp.socket

# Restart docker service
systemctl restart docker.service

Posted by krotkruton on Wed, 22 Jan 2020 08:29:43 -0800