21 Days of Docker-Day 18 -Docker Security

Welcome to Day 18 of 21 Days of Docker. The topic for today is Docker Security. Today my focus is on three topics

  • Security scanning using Docker Trusted Registry
  • Managing secret in Swarm
  • Docker Content Trust
  • Encrypting Overlay Network

Security scanning using Docker Trusted Registry

Docker Trusted Registry comes along with Docker Enterprise Edition and I really like this feature called DTR scanning. Before going there what is Docker Trusted Registry?

Docker Trusted Registry is an on-premises registry that allows
enterprises to store and manage their Docker images on-premise.

DTR run a security scan on your image, you can view the results.

Managing secret in Swarm

  • In terms of Docker Swarm services, a secret is a blob of data, such as a password, SSH private key, SSL certificate, or another piece of data that should not be transmitted over a network or stored unencrypted in a Dockerfile or in your application’s source code.
  • In Docker 1.13 and higher, you can use Docker secrets to centrally manage this data and securely transmit it to only those containers that need access to it.
  • Secrets are encrypted during transit and at rest in a Docker swarm.
  • A given secret is only accessible to those services which have been granted explicit access to it, and only while those service tasks are running.
  • Step1: Create a file
 $ cat mysecret 
username: admin
pass: admin123
  • Step2: Create a secret from a file or we can even do it from STDIN.
$ docker secret create mysupersecret mysecret 
uzvrfy96205o541pql1xgym4s
  • Step3: List the secrets
$ docker secret ls
ID                          NAME                DRIVER              CREATED             UPDATED
uzvrfy96205o541pql1xgym4s   mysupersecret                           13 seconds ago      13 seconds ago
  • Step4: Secret is encrypted, so even if we try to inspect , we can’t see the secret
$ docker secret inspect uzvrfy96205o541pql1xgym4s
[
    {
        "ID": "uzvrfy96205o541pql1xgym4s",
        "Version": {
            "Index": 41
        },
        "CreatedAt": "2019-10-25T17:22:01.841559963Z",
        "UpdatedAt": "2019-10-25T17:22:01.841559963Z",
        "Spec": {
            "Name": "mysupersecret",
            "Labels": {}
        }
    }
]
  • Now let’s create a container using this secret
$ docker service create --name mynginx1 --secret mysupersecret nginx
ueugjjkuhbbvrrszya1zb5gxs
overall progress: 1 out of 1 tasks 
1/1: running   [==================================================>] 
verify: Service converged 
  • Let’s login to the container
$ docker exec -it 48a4c7e74a8e bash
root@48a4c7e74a8e:/# cd /run
root@48a4c7e74a8e:/run# ls
lock  nginx.pid  secrets  utmp
# cd secrets/
  • As you can see container has access to the secret file
# cat mysupersecret 
username: admin
pass: admin123

Docker Content Trust

  • When transferring data among networked systems, trust is a central concern. In particular, when communicating over an untrusted medium such as the internet, it is critical to ensure the integrity and the publisher of all the data a system operates on. You use the Docker Engine to push and pull images (data) to a public or private registry. Content trust gives you the ability to verify both the integrity and the publisher of all the data received from a registry over any channel.
  • Docker Content Trust (DCT) provides the ability to use digital signatures for data sent to and received from remote Docker registries. These signatures allow client-side or runtime verification of the integrity and publisher of specific image tags.
  • Through DCT, image publishers can sign their images and image consumers can ensure that the images they use are signed.
  • First, log in to Docker Hub. Enter your Docker Hub credentials when prompted.
   docker login
  • Generate a delegation key pair. 
$ docker trust key generate lakhera2014
Generating key for lakhera2014...
Enter passphrase for new lakhera2014 key with ID 8480add: 
Repeat passphrase for new lakhera2014 key with ID 8480add: 
Successfully generated and loaded private key. Corresponding public key available: /Users/plakhera/lakhera2014.pub
  • Then we’ll add ourselves as a signer to an image repository.
$ docker trust key generate lakhera2014
Generating key for lakhera2014...
Enter passphrase for new lakhera2014 key with ID 8480add: 
Repeat passphrase for new lakhera2014 key with ID 8480add: 
Successfully generated and loaded private key. Corresponding public key available: /Users/plakhera/lakhera2014.pub
plakhera-ltm:~ plakhera$ docker trust signer add --key lakhera2014.pub lakhera2014  lakhera2014/mydct-test
Adding signer "lakhera2014" to lakhera2014/mydct-test...
Initializing signed repository for lakhera2014/mydct-test...
You are about to create a new root signing key passphrase. This passphrase
will be used to protect the most sensitive key in your signing system. Please
choose a long, complex passphrase and be careful to keep the password and the
key file itself secure and backed up. It is highly recommended that you use a
password manager to generate the passphrase and keep it safe. There will be no
way to recover this key. You can find the key in your config directory.
Enter passphrase for new root key with ID e638abc: 
Repeat passphrase for new root key with ID e638abc: 
Enter passphrase for new repository key with ID 5d6a8b3: 
Repeat passphrase for new repository key with ID 5d6a8b3: 
Successfully initialized "lakhera2014/mydct-test"
Successfully added signer: lakhera2014 to lakhera2014/mydct-test

NOTE: Once again, be sure to make note of the passphrases used.

  • Let’s create a Dockerfile
$ cat Dockerfile 
FROM busybox
CMD echo coming from dct
  • Build the image
$ docker build -t lakhera2014/mydct:unsigned .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM busybox@sha256:fe301db49df08c384001ed752dff6d52b4305a73a7f608f21528048e8a08b51e
 ---> 19485c79a9bb
Step 2/2 : CMD echo coming from dct
 ---> Using cache
 ---> df88a4715edc
Successfully built df88a4715edc
Successfully tagged lakhera2014/mydct:unsigned
Tagging busybox@sha256:fe301db49df08c384001ed752dff6d52b4305a73a7f608f21528048e8a08b51e as busybox:latest
  • Run it
$ docker container run lakhera2014/mydct:unsigned
coming from dct
  • Let’s enable Docker Content Trust now and see the result
export DOCKER_CONTENT_TRUST=1
$ docker container run lakhera2014/mydct:unsigned
docker: Error: remote trust data does not exist for docker.io/lakhera2014/mydct: notary.docker.io does not have trust data for docker.io/lakhera2014/mydct.
See 'docker run --help'.
  • Let’s build the image but this time giving signed tag
$ docker build -t lakhera2014/mydct:signed .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM busybox@sha256:fe301db49df08c384001ed752dff6d52b4305a73a7f608f21528048e8a08b51e
 ---> 19485c79a9bb
Step 2/2 : CMD echo coming from dct
 ---> Using cache
 ---> df88a4715edc
Successfully built df88a4715edc
Successfully tagged lakhera2014/mydct:signed
Tagging busybox@sha256:fe301db49df08c384001ed752dff6d52b4305a73a7f608f21528048e8a08b51e as busybox:latest
  • Push a signed tag to the repo. Enter the passphrase — this will be the one that was chosen earlier when running the docker trust key generate command
$ docker trust sign lakhera2014/mydct:signed
Enter passphrase for root key with ID e638abc: 
Enter passphrase for new repository key with ID f626d57: 
Repeat passphrase for new repository key with ID f626d57: 
Enter passphrase for lakhera2014 key with ID 8480add: 
Created signer: lakhera2014
Finished initializing signed repository for lakhera2014/mydct:signed
Signing and pushing trust data for local image lakhera2014/mydct:signed, may overwrite remote trust data
The push refers to repository [docker.io/lakhera2014/mydct]
6c0ea40aef9d: Mounted from library/busybox 
signed: digest: sha256:13bc8974eb312c18d28ea46a356ab0af01565f7259eb6042803a2eda4f56b52f size: 527
Signing and pushing trust metadata
Enter passphrase for lakhera2014 key with ID 8480add: 
Successfully signed docker.io/lakhera2014/mydct:signed
  • NOTE: docker trust sign also pushes the image to dockerhub.
  • Run the container again
$ docker container run lakhera2014/mydct:signed
coming from dct
  • Turn off Docker Content Trust and attempt to run the unsigned image again
$ export DOCKER_CONTENT_TRUST=0
$ docker container run lakhera2014/mydct:unsigned
coming from dct

Encrypting Overlay Network

  • We can encrypt communication between containers on overlay networks in order to provide greater security within our swarm cluster.
  • Use the –opt encrypted flag when creating overlay network to encrypt it
docker network create --opt encrypted --driver overlay <network name>
  • Create a service using the overlay network
docker service create --name my-encrypted-overlay --network <overlay network name> --replicas 3 nginx

Please follow me with my Journey

This time to make learning more interactive, I am adding

  • Slack
  • Meetup

Please feel free to join this group.

Slack: 

https://100daysofdevops.slack.com/join/shared_invite/enQtNzg1MjUzMzQzMzgxLWM4Yjk0ZWJiMjY4ZWE3ODBjZjgyYTllZmUxNzFkNTgxZjQ4NDlmZjkzODAwNDczOTYwOTM2MzlhZDNkM2FkMDA

Meetup Group

If you are in the bay area, please join this meetup group https://www.meetup.com/100daysofdevops/