Docker Security – part 3(Engine access)

This is the third part of my Docker security series. In this blog, we will cover ways to securely access Docker engine. Following are the other parts (1, 2, 4)

Docker engine access:

Docker engine runs as a daemon and by default listens on the Unix socket, “unix:///var/
run/docker.sock”. In Ubuntu distributions, Docker start options are specified in “/etc/default/docker”. To allow Docker API and client to access Docker engine remotely, we need to expose Docker daemon using http socket. This can be done by:

DOCKER_OPTS="-D -H unix:///var/run/docker.sock -H
tcp://192.168.56.101:2376" -> add this to /etc/default/docker
Sudo service docker restart -> Restart Docker daemon

Exposing Docker daemon using http is not a good practice and it is needed to secure the connection using https. Similar to the way web browsers trust the web server using https and TLS, Docker client can establish a secure connection to Docker engine that provides confidentiality, authentication as well as integrity. There are two options: first option is for client to verify server identity and in second option both client and server verify each other’s identity. Certificates establish the identity of a server. For commercial purposes, Certificates can be purchased from third-party sources like Verisign. For testing purposes, we can generate certificates using Openssl as described below. The procedure below is based on the steps detailed here.

Server side authentication:

We need to generate the following using Openssl first:

  • server side – server certificate which has server public key and digest, server private key
  • client side – CA public key

Following are the steps:

  • Sign server certificate with CA private key.
  • Client receives the certificate and verifies it using CA’s public key that has already been distributed.
  • Client encrypts random message using server’s public key and sends it
  • Server decrypts encrypted random message using server’s private key and sends it back to client
  • Client verifies message is correct and server authentication is complete

Server and client authentication:

In this case, other than client authenticating the server, server needs to authenticate the client.
We need to generate the following using Openssl first:

  • Server side – server certificate which has server public key and digest, server private key, CA public key
  • Client side – client certificate which has client public key and digest, client private key, CA public key

Following are the steps for client authentication. The previously described steps for server authentication is still done.

  • Sign client certificate with CA private key
  • Server receives the certificate and verifies it using CA’s public key that has already been distributed.
  • Server encrypts random message using client’s public key and sends it
  • Client decrypts encrypted random message using client’s private key and sends it back to server
  • Server verifies message is correct and client authentication is complete

Following command starts Docker daemon enabling TLS:

sudo docker daemon --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem   -H=172.17.8.110:2376

Following command executes Docker command connecting securely to remote Docker engine:

docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=172.17.8.110:2376 version

Authorization plugin:

This feature is added newly in Docker 1.10. Authorization plugin can provide granular access to the Docker daemon based on userid, groupid, command executed, command arguments, time of day etc. In a multi-tenant scenario, this feature becomes very useful. Following are some details on this:

  • Authorization feature is implemented as a plugin so that different implementations can co-exist and the user can choose the suitable scheme for their environment.
  • Authorization plugin informs Docker daemon if the specific command can be allowed or not based on the policy and the command executed.
  • Twistlock authz broker is one of the first plugins that is currently available.
  • In Twistlock case, policy is created as a JSON file and is given as argument to Docker daemon. When policy is changed, it is not necessary to restart Docker daemon, the new policy is automatically picked up.
  • User identity support is not available and will be added in Docker 1.11 release. For now, we need to specify a “null” user in the policy.

Installation and Usage:

Twistlock authz broker can be installed as an application or as a Container. Following steps can be used to build twistlock Container.

export GOPATH=$HOME/workspace
export PATH=$PATH:$GOPATH/bin
cd workspace/
go get github.com/twistlock/authz
go get github.com/tools/godep
cd src/github.com/twistlock/authz
godep restore
make all

Following output shows the built twistlock Container image:

$ docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
twistlock/authz-broker   latest              701438e4f3d1        40 seconds ago      13.72 MB

Following command shows how to start Docker daemon with twistlock authz plugin enabled:

docker run -d  --restart=always -v /var/lib/authz-broker/policy.json:/var/lib/authz-broker/policy.json -v /run/docker/plugins/:/run/docker/plugins twistlock/authz-broker

To test authz plugin, I created a read-only Container policy as shown below in “/var/lib/authz-broker/policy.json”:

{"name":"policy_1","users":[""],"actions":["container"] , "readonly":true}

When I tried to run the Container, I got following error since I had a read-only policy and I am trying to create a new Container:

$ docker run -d nginx
ERRO[0016] AuthZRequest for POST /v1.22/containers/create returned error: authorization denied by plugin authz-broker: action 'container_create' not allowed for user '' by readonly policy 'policy_1' 
docker: Error response from daemon: authorization denied by plugin authz-broker: action 'container_create' not allowed for user '' by readonly policy 'policy_1'.

I had some issues in getting the Twistlock working. Mostly, these were operator issues from my side. Twistlock team was kind enough to help and the discussion with them is captured here.

References:

3 thoughts on “Docker Security – part 3(Engine access)

Leave a comment