2015-06-07 23:07:20 -04:00
|
|
|
<!--[metadata]>
|
|
|
|
+++
|
|
|
|
title = "Protect the Docker daemon socket"
|
|
|
|
description = "How to setup and run Docker with HTTPS"
|
|
|
|
keywords = ["docker, docs, article, example, https, daemon, tls, ca, certificate"]
|
|
|
|
[menu.main]
|
|
|
|
parent = "smn_administrate"
|
|
|
|
weight = 5
|
|
|
|
+++
|
|
|
|
<![end-metadata]-->
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2015-06-07 23:07:20 -04:00
|
|
|
# Protect the Docker daemon socket
|
2014-04-15 20:53:12 -04:00
|
|
|
|
|
|
|
By default, Docker runs via a non-networked Unix socket. It can also
|
|
|
|
optionally communicate using a HTTP socket.
|
|
|
|
|
2014-07-21 15:18:59 -04:00
|
|
|
If you need Docker to be reachable via the network in a safe manner, you can
|
|
|
|
enable TLS by specifying the `tlsverify` flag and pointing Docker's
|
|
|
|
`tlscacert` flag to a trusted CA certificate.
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2014-07-30 10:58:24 -04:00
|
|
|
In the daemon mode, it will only allow connections from clients
|
|
|
|
authenticated by a certificate signed by that CA. In the client mode,
|
|
|
|
it will only connect to servers with a certificate signed by that CA.
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2015-01-04 14:57:20 -05:00
|
|
|
> **Warning**:
|
2014-07-21 15:18:59 -04:00
|
|
|
> Using TLS and managing a CA is an advanced topic. Please familiarize yourself
|
|
|
|
> with OpenSSL, x509 and TLS before using it in production.
|
2014-07-07 15:35:05 -04:00
|
|
|
|
|
|
|
> **Warning**:
|
|
|
|
> These TLS commands will only generate a working set of certificates on Linux.
|
2015-01-04 14:57:20 -05:00
|
|
|
> Mac OS X comes with a version of OpenSSL that is incompatible with the
|
2014-07-07 15:35:05 -04:00
|
|
|
> certificates that Docker requires.
|
2014-04-15 20:53:12 -04:00
|
|
|
|
|
|
|
## Create a CA, server and client keys with OpenSSL
|
|
|
|
|
2015-01-22 15:46:01 -05:00
|
|
|
> **Note**: replace all instances of `$HOST` in the following example with the
|
2015-01-06 19:32:23 -05:00
|
|
|
> DNS name of your Docker daemon's host.
|
|
|
|
|
2015-01-04 15:49:16 -05:00
|
|
|
First generate CA private and public keys:
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2015-05-30 07:52:52 -04:00
|
|
|
$ openssl genrsa -aes256 -out ca-key.pem 4096
|
|
|
|
Generating RSA private key, 4096 bit long modulus
|
|
|
|
............................................................................................................................................................................................++
|
|
|
|
........++
|
2014-08-04 02:13:22 -04:00
|
|
|
e is 65537 (0x10001)
|
|
|
|
Enter pass phrase for ca-key.pem:
|
|
|
|
Verifying - Enter pass phrase for ca-key.pem:
|
2015-01-04 15:15:30 -05:00
|
|
|
$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
|
2014-08-04 02:13:22 -04:00
|
|
|
Enter pass phrase for ca-key.pem:
|
2015-01-07 08:08:34 -05:00
|
|
|
You are about to be asked to enter information that will be incorporated
|
|
|
|
into your certificate request.
|
|
|
|
What you are about to enter is what is called a Distinguished Name or a DN.
|
|
|
|
There are quite a few fields but you can leave some blank
|
|
|
|
For some fields there will be a default value,
|
|
|
|
If you enter '.', the field will be left blank.
|
|
|
|
-----
|
|
|
|
Country Name (2 letter code) [AU]:
|
|
|
|
State or Province Name (full name) [Some-State]:Queensland
|
|
|
|
Locality Name (eg, city) []:Brisbane
|
|
|
|
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker Inc
|
2015-08-05 12:07:11 -04:00
|
|
|
Organizational Unit Name (eg, section) []:Sales
|
2015-01-07 08:08:34 -05:00
|
|
|
Common Name (e.g. server FQDN or YOUR name) []:$HOST
|
|
|
|
Email Address []:Sven@home.org.au
|
2014-04-15 20:53:12 -04:00
|
|
|
|
|
|
|
Now that we have a CA, you can create a server key and certificate
|
2015-01-06 23:23:32 -05:00
|
|
|
signing request (CSR). Make sure that "Common Name" (i.e., server FQDN or YOUR
|
2014-07-21 15:18:59 -04:00
|
|
|
name) matches the hostname you will use to connect to Docker:
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2015-01-22 15:46:01 -05:00
|
|
|
> **Note**: replace all instances of `$HOST` in the following example with the
|
2015-01-06 19:32:23 -05:00
|
|
|
> DNS name of your Docker daemon's host.
|
|
|
|
|
2015-05-30 07:52:52 -04:00
|
|
|
$ openssl genrsa -out server-key.pem 4096
|
|
|
|
Generating RSA private key, 4096 bit long modulus
|
|
|
|
.....................................................................++
|
|
|
|
.................................................................................................++
|
2014-08-04 02:13:22 -04:00
|
|
|
e is 65537 (0x10001)
|
2015-05-30 07:52:52 -04:00
|
|
|
$ openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2015-01-07 08:08:34 -05:00
|
|
|
Next, we're going to sign the public key with our CA:
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2015-02-11 21:26:50 -05:00
|
|
|
Since TLS connections can be made via IP address as well as DNS name, they need
|
|
|
|
to be specified when creating the certificate. For example, to allow connections
|
|
|
|
using `10.10.10.20` and `127.0.0.1`:
|
2015-02-11 11:01:43 -05:00
|
|
|
|
2015-02-11 21:26:50 -05:00
|
|
|
$ echo subjectAltName = IP:10.10.10.20,IP:127.0.0.1 > extfile.cnf
|
2015-02-11 11:01:43 -05:00
|
|
|
|
2015-05-30 07:52:52 -04:00
|
|
|
$ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
|
2015-02-11 11:01:43 -05:00
|
|
|
-CAcreateserial -out server-cert.pem -extfile extfile.cnf
|
2014-08-04 02:13:22 -04:00
|
|
|
Signature ok
|
|
|
|
subject=/CN=your.host.com
|
|
|
|
Getting CA Private Key
|
|
|
|
Enter pass phrase for ca-key.pem:
|
2014-04-15 20:53:12 -04:00
|
|
|
|
|
|
|
For client authentication, create a client key and certificate signing
|
|
|
|
request:
|
|
|
|
|
2015-05-30 07:52:52 -04:00
|
|
|
$ openssl genrsa -out key.pem 4096
|
|
|
|
Generating RSA private key, 4096 bit long modulus
|
|
|
|
.........................................................++
|
|
|
|
................++
|
2014-08-04 02:13:22 -04:00
|
|
|
e is 65537 (0x10001)
|
|
|
|
$ openssl req -subj '/CN=client' -new -key key.pem -out client.csr
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2014-07-21 15:18:59 -04:00
|
|
|
To make the key suitable for client authentication, create an extensions
|
2014-04-15 20:53:12 -04:00
|
|
|
config file:
|
|
|
|
|
|
|
|
$ echo extendedKeyUsage = clientAuth > extfile.cnf
|
|
|
|
|
2015-01-07 08:08:34 -05:00
|
|
|
Now sign the public key:
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2015-05-30 07:52:52 -04:00
|
|
|
$ openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
|
2015-01-04 15:49:16 -05:00
|
|
|
-CAcreateserial -out cert.pem -extfile extfile.cnf
|
2014-08-04 02:13:22 -04:00
|
|
|
Signature ok
|
|
|
|
subject=/CN=client
|
|
|
|
Getting CA Private Key
|
|
|
|
Enter pass phrase for ca-key.pem:
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2015-01-07 08:08:34 -05:00
|
|
|
After generating `cert.pem` and `server-cert.pem` you can safely remove the
|
|
|
|
two certificate signing requests:
|
|
|
|
|
|
|
|
$ rm -v client.csr server.csr
|
|
|
|
|
2015-01-08 17:19:23 -05:00
|
|
|
With a default `umask` of 022, your secret keys will be *world-readable* and
|
2015-01-07 08:08:34 -05:00
|
|
|
writable for you and your group.
|
|
|
|
|
2015-01-08 17:19:23 -05:00
|
|
|
In order to protect your keys from accidental damage, you will want to remove their
|
2015-01-08 18:24:59 -05:00
|
|
|
write permissions. To make them only readable by you, change file modes as follows:
|
2015-01-07 08:08:34 -05:00
|
|
|
|
|
|
|
$ chmod -v 0400 ca-key.pem key.pem server-key.pem
|
|
|
|
|
|
|
|
Certificates can be world-readable, but you might want to remove write access to
|
|
|
|
prevent accidental damage:
|
|
|
|
|
|
|
|
$ chmod -v 0444 ca.pem server-cert.pem cert.pem
|
|
|
|
|
2014-04-15 20:53:12 -04:00
|
|
|
Now you can make the Docker daemon only accept connections from clients
|
|
|
|
providing a certificate trusted by our CA:
|
|
|
|
|
2015-07-22 15:37:17 -04:00
|
|
|
$ docker daemon --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem \
|
2014-07-07 15:35:05 -04:00
|
|
|
-H=0.0.0.0:2376
|
2014-04-15 20:53:12 -04:00
|
|
|
|
|
|
|
To be able to connect to Docker and validate its certificate, you now
|
|
|
|
need to provide your client keys, certificates and trusted CA:
|
|
|
|
|
2015-01-22 15:46:01 -05:00
|
|
|
> **Note**: replace all instances of `$HOST` in the following example with the
|
2015-01-06 19:32:23 -05:00
|
|
|
> DNS name of your Docker daemon's host.
|
|
|
|
|
2014-12-07 15:43:20 -05:00
|
|
|
$ docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem \
|
2015-01-06 19:32:23 -05:00
|
|
|
-H=$HOST:2376 version
|
2014-07-07 15:35:05 -04:00
|
|
|
|
|
|
|
> **Note**:
|
|
|
|
> Docker over TLS should run on TCP port 2376.
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2015-01-04 14:57:20 -05:00
|
|
|
> **Warning**:
|
2014-07-30 10:58:24 -04:00
|
|
|
> As shown in the example above, you don't have to run the `docker` client
|
|
|
|
> with `sudo` or the `docker` group when you use certificate authentication.
|
|
|
|
> That means anyone with the keys can give any instructions to your Docker
|
|
|
|
> daemon, giving them root access to the machine hosting the daemon. Guard
|
|
|
|
> these keys as you would a root password!
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2014-07-30 10:58:24 -04:00
|
|
|
## Secure by default
|
2014-07-07 15:35:05 -04:00
|
|
|
|
2015-01-04 14:57:20 -05:00
|
|
|
If you want to secure your Docker client connections by default, you can move
|
2015-01-07 08:08:34 -05:00
|
|
|
the files to the `.docker` directory in your home directory -- and set the
|
2014-10-10 11:02:04 -04:00
|
|
|
`DOCKER_HOST` and `DOCKER_TLS_VERIFY` variables as well (instead of passing
|
2015-01-30 11:20:50 -05:00
|
|
|
`-H=tcp://$HOST:2376` and `--tlsverify` on every call).
|
2014-07-07 15:35:05 -04:00
|
|
|
|
2015-01-07 08:08:34 -05:00
|
|
|
$ mkdir -pv ~/.docker
|
|
|
|
$ cp -v {ca,cert,key}.pem ~/.docker
|
2015-01-30 11:20:50 -05:00
|
|
|
$ export DOCKER_HOST=tcp://$HOST:2376 DOCKER_TLS_VERIFY=1
|
2014-07-07 15:35:05 -04:00
|
|
|
|
2014-10-10 11:02:04 -04:00
|
|
|
Docker will now connect securely by default:
|
2014-07-07 15:35:05 -04:00
|
|
|
|
2014-12-07 15:43:20 -05:00
|
|
|
$ docker ps
|
2014-07-07 15:35:05 -04:00
|
|
|
|
2014-04-15 20:53:12 -04:00
|
|
|
## Other modes
|
|
|
|
|
2014-04-23 16:48:28 -04:00
|
|
|
If you don't want to have complete two-way authentication, you can run
|
2014-04-15 20:53:12 -04:00
|
|
|
Docker in various other modes by mixing the flags.
|
|
|
|
|
|
|
|
### Daemon modes
|
|
|
|
|
2014-07-21 15:18:59 -04:00
|
|
|
- `tlsverify`, `tlscacert`, `tlscert`, `tlskey` set: Authenticate clients
|
|
|
|
- `tls`, `tlscert`, `tlskey`: Do not authenticate clients
|
2014-04-15 20:53:12 -04:00
|
|
|
|
|
|
|
### Client modes
|
|
|
|
|
2014-07-21 15:18:59 -04:00
|
|
|
- `tls`: Authenticate server based on public/default CA pool
|
|
|
|
- `tlsverify`, `tlscacert`: Authenticate server based on given CA
|
|
|
|
- `tls`, `tlscert`, `tlskey`: Authenticate with client certificate, do not
|
2014-04-23 16:48:28 -04:00
|
|
|
authenticate server based on given CA
|
2014-07-21 15:18:59 -04:00
|
|
|
- `tlsverify`, `tlscacert`, `tlscert`, `tlskey`: Authenticate with client
|
|
|
|
certificate and authenticate server based on given CA
|
2014-04-15 20:53:12 -04:00
|
|
|
|
2014-07-30 10:58:24 -04:00
|
|
|
If found, the client will send its client certificate, so you just need
|
2015-01-07 08:08:34 -05:00
|
|
|
to drop your keys into `~/.docker/{ca,cert,key}.pem`. Alternatively,
|
2014-07-30 10:58:24 -04:00
|
|
|
if you want to store your keys in another location, you can specify that
|
2014-08-04 20:17:23 -04:00
|
|
|
location using the environment variable `DOCKER_CERT_PATH`.
|
2014-07-09 13:05:16 -04:00
|
|
|
|
2015-01-07 08:08:34 -05:00
|
|
|
$ export DOCKER_CERT_PATH=~/.docker/zone1/
|
2014-12-07 15:43:20 -05:00
|
|
|
$ docker --tlsverify ps
|
2014-10-15 03:24:53 -04:00
|
|
|
|
2015-04-21 11:50:09 -04:00
|
|
|
### Connecting to the secure Docker port using `curl`
|
2014-10-15 03:24:53 -04:00
|
|
|
|
|
|
|
To use `curl` to make test API requests, you need to use three extra command line
|
|
|
|
flags:
|
|
|
|
|
2015-01-06 19:32:23 -05:00
|
|
|
$ curl https://$HOST:2376/images/json \
|
2015-01-04 19:24:33 -05:00
|
|
|
--cert ~/.docker/cert.pem \
|
|
|
|
--key ~/.docker/key.pem \
|
|
|
|
--cacert ~/.docker/ca.pem
|