Chapter 6. Using Docker's Built-in Security Features

In this chapter, we will take a look at working with Docker tools that can be used to secure your environment. We will be taking a look at both command-line tools as well as GUI tools that you can utilize to your advantage. We will cover the following items in this chapter:

  • Docker tools
    • Using TLS in your environments to help ensure that pieces are communicating securely
    • Using read-only containers to help protect the data in a container from being manipulated in some form
  • Docker security fundamentals
    • Kernel namespaces
    • Control groups
    • Linux kernel capabilities

Docker tools

In this section, we will cover the tools that can help you secure your Docker environment. These are options that are built into the Docker software, which you are already using. It's time to learn how to enable or utilize these such features to help give you the peace of mind in order to be sure that the communication is secure; this is where we will cover enabling TLS, which is a protocol that ensures privacy between applications. It ensures that nobody is listening in on the communication. Think of it as when you are watching a movie and people on the phone say, is this line secure? It's the same kind of idea when it comes to network communication. Then, we will look at how you can utilize the read-only containers to ensure that the data you are serving up can't be manipulated by anyone.

Using TLS

It is highly recommended to use the Docker Machine to create and manage your Docker hosts. It will automatically set up the communication to use TLS. Here's how you can verify that the default host that was created by docker-machine indeed uses TLS.

One of the important factors is knowing if you are using TLS or not and then adjusting to use TLS if you are, in fact, not using TLS. The important thing to remember is that, nowadays, almost all the Docker tools ship with the TLS enabled, or if they don't, they appear to be working towards this goal. One of the commands that you can use to check in order to see if your Docker host is utilizing the TLS is with the Docker Machine inspect command. In the following, we will take a look at a host and see if it is running with the TLS enabled:

docker-machine inspect default

{
    "ConfigVersion": 3,
    "Driver": {
      "IPAddress": "192.168.99.100",
      "MachineName": "default",
      "SSHUser": "docker",
      "SSHPort": 50858,
      "SSHKeyPath": "/Users/scottgallagher/.docker/machine/machines/default/id_rsa",
      "StorePath": "/Users/scottgallagher/.docker/machine",
      "SwarmMaster": false,
      "SwarmHost": "tcp://0.0.0.0:3376",
      "SwarmDiscovery": "",
      "VBoxManager": {},
      "CPU": 1,
      "Memory": 2048,
      "DiskSize": 204800,
      "Boot2DockerURL": "",
      "Boot2DockerImportVM": "",
      "HostDNSResolver": false,
      "HostOnlyCIDR": "192.168.99.1/24",
      "HostOnlyNicType": "82540EM",
      "HostOnlyPromiscMode": "deny",
      "NoShare": false,
      "DNSProxy": false,
      "NoVTXCheck": false
    },
    "DriverName": "virtualbox",
    "HostOptions": {
      "Driver": "",
      "Memory": 0,
      "Disk": 0,
      "EngineOptions": {
        "ArbitraryFlags": [],
        "Dns": null,
        "GraphDir": "",
        "Env": [],
        "Ipv6": false,
        "InsecureRegistry": [],
        "Labels": [],
        "LogLevel": "",
        "StorageDriver": "",
        "SelinuxEnabled": false,
        "TlsVerify": true,
        "RegistryMirror": [],
        "InstallURL": "https://get.docker.com"
      },
      "SwarmOptions": {
        "IsSwarm": false,
        "Address": "",
        "Discovery": "",
        "Master": false,
        "Host": "tcp://0.0.0.0:3376",
        "Image": "swarm:latest",
        "Strategy": "spread",
        "Heartbeat": 0,
        "Overcommit": 0,
        "ArbitraryFlags": [],
        "Env": null
      },
      "AuthOptions": {
        "CertDir": "/Users/scottgallagher/.docker/machine/certs",
        "CaCertPath": "/Users/scottgallagher/.docker/machine/certs/ca.pem",
        "CaPrivateKeyPath": "/Users/scottgallagher/.docker/machine/certs/ca-key.pem",
        "CaCertRemotePath": "",
        "ServerCertPath": "/Users/scottgallagher/.docker/machine/machines/default/server.pem",
        "ServerKeyPath": "/Users/scottgallagher/.docker/machine/machines/default/server-key.pem",
        "ClientKeyPath": "/Users/scottgallagher/.docker/machine/certs/key.pem",
        "ServerCertRemotePath": "",
        "ServerKeyRemotePath": "",
        "ClientCertPath": "/Users/scottgallagher/.docker/machine/certs/cert.pem",
        "ServerCertSANs": [],
        "StorePath": "/Users/scottgallagher/.docker/machine/machines/default"
      }
    },
    "Name": "default"
}

From the preceding output, we can focus on the following line:

    "SwarmHost": "tcp://0.0.0.0:3376",

This shows us that if we were running Swarm, this host would be utilizing the secure 3376 port. Now, if you aren't using Docker Swarm, then you can disregard this line. However, if you are using Docker Swarm, then this line is important.

Just to take a step back, let's identify what Docker Swarm is. Docker Swarm is native clustering within Docker. It helps in turning multiple Docker hosts into an easy-to-manage single virtual host:

 "AuthOptions": {
            "CertDir": "/Users/scottgallagher/.docker/machine/certs",
            "CaCertPath": "/Users/scottgallagher/.docker/machine/certs/ca.pem",
            "CaPrivateKeyPath": "/Users/scottgallagher/.docker/machine/certs/ca-key.pem",
            "CaCertRemotePath": "",
            "ServerCertPath": "/Users/scottgallagher/.docker/machine/machines/default/server.pem",
            "ServerKeyPath": "/Users/scottgallagher/.docker/machine/machines/default/server-key.pem",
            "ClientKeyPath": "/Users/scottgallagher/.docker/machine/certs/key.pem",
            "ServerCertRemotePath": "",
            "ServerKeyRemotePath": "",
            "ClientCertPath": "/Users/scottgallagher/.docker/machine/certs/cert.pem",
            "ServerCertSANs": [],
            "StorePath": "/Users/scottgallagher/.docker/machine/machines/default"
        }

This shows us that this host is, in fact, using the certificates so we know that it is using TLS, but how do we know from just that? In the following section, we will take a look at how to tell that it is, in fact, using TLS for sure.

Docker Machine also has the option to run everything over TLS. This is the most secure way of using Docker Machine in order to manage your Docker hosts. This setup can be tricky if you start using your own certificates. By default, Docker Machine stores your certificates that it uses in /Users/<user_id>/.docker/machine/certs/. You can see the location on your machine where the certificates are stored at from the preceding output.

Let's take a look at how we can achieve the goal of viewing if our Docker host is utilize TLS:

docker-machine ls
NAME      ACTIVE   URL          STATE     URL SWARM   DOCKER   ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376  v1.9.1   

This is where we can tell that it is using TLS. The insecure port of Docker Machine hosts is the 2375 port and this host is using 2376, which is the secure TLS port for Docker Machine. Therefore, this host is, in fact, using TLS to communicate, which gives you the peace of mind in knowing that the communication is secure.

Read-only containers

With respect to the docker run command, we will mainly focus on the option that allows us to set everything inside the container as read-only. Let's take a look at an example and break down what it exactly does:

$ docker run --name mysql --read-only -v /var/lib/mysql v /tmp --e MYSQL_ROOT_PASSWORD=password -d mysql

Here, we are running a mysql container and setting the entire container as read-only, except for the /var/lib/mysql directory. What this means is that the only location the data can be written inside the container is the /var/lib/mysql directory. Any other location inside the container won't allow you to write anything in it. If you try to run the following, it would fail:

$ docker exec mysql touch /opt/filename

This can be extremely helpful if you want to control where the containers can write to or not write to. Make sure to use this wisely. Test thoroughly, as it can have consequences when the applications can't write to certain locations.

Remember the Docker volumes we looked at in the previous chapters, where we were able to set the volumes to be read-only. Similar to the previous command with docker run, where we set everything to read-only, except for a specified volume, we can now do the opposite and set a single volume (or more, if you use more -v switches) to read-only. The thing to remember about volumes is that when you use a volume and mount it in a container, it will mount as an empty volume over the top of that directory inside the container, unless you use the --volumes-from switch or add data to the container in some other way after the fact:

$ docker run -d -v /opt/uploads:/opt/uploads:/opt/uploads:ro nginx

This will mount a volume in /opt/uploads and set it to read-only. This can be useful if you don't want a running container to write to a volume in order to keep the data or configuration files intact.

The last option that we want to look at, with regards to the docker run command is the --device= switch. This switch allows us to mount a device from the Docker host into a specified location inside the container. For doing so, there are some security risks that we need to be aware of. By default, when you do this, the container will get full the access: read, write, and the mknod access to the device's location. Now, you can control these permissions by manipulating rwm at the end of the switch command.

Let's take a look at some of these and see how they work:

$ docker run --device=/dev/sdb:/dev/sdc2 -it ubuntu:latest /bin/bash

The previous command will run the latest Ubuntu image and mount the /dev/sdb device inside the container at the /dev/sdc2 location:

$ docker run --device=/dev/sdb:/dev/sdc2:r -it ubuntu:latest /bin/bash

This command will run the latest Ubuntu image and mount the /dev/sdb1 device inside the container at the /dev/sdc2 location. However, this one has the :r tag at the end of it that specifies that it's read-only and can't be written.

Read-only containers
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset