Docker recently announced an exciting new release of Docker Datacenter that included Integrated Secrets Management from Docker 1.13. Many containers need access to sensitive information as part of their configuration, for example, they may need the password to access a database or the API key to access web services. These secrets need to be securely passed to the running container. In the past various other mechanisms have been used to pass secrets including using environment variables and volume mounting files from the host into the container. Each of these, and other, alternatives have their own individual drawbacks but all share the same issue: they store unencrypted secrets on the host that an administrator may be able to see. There are other solutions that can be used to securely manage secrets, for example, the popular Vault project from HashiCorp, however, having integrated secrets management is a great step forward.
As many organizations are now moving away from legacy approaches such as environment variables and volumes to pass secrets to using Docker’s new integrated secrets management or 3rd party solutions such as Vault it is important to ensure that you are not already inadvertently including sensitive information such as passwords, certificates and API keys within your image.
During testing and development, it is very easy to leave artifacts such as private certificates or keys within your image to simplifying testing and in many cases these can inadvertently be carried forward into your production deployment. The most famous example of this occurred last summer when Twitter’s now-defunct Vine service was analyzed by a security researcher who found that they had mistakenly disabled authentication on their Internet-facing Docker registry. The researcher was able to pull Vine’s images down to his laptop and inspect them. Within these images, he found API keys, source code and other secrets.
While many users are scanning their images for CVEs, an image may pass this basic check but may still be insecure, misconfigured or in some other way out of compliance. Container images typically contain hundreds, often thousands of files – some coming from operating system packages, some from configuration files, some from 3rd party software libraries such as Node.JS NPMs, Ruby GEMs, Python modules, Java Archives, and some may be supplied by the user. Each one of these artifacts should undergo the same level scrutiny as the operating system packages. One of the critical checks that should be performed before an image is deployed is to ensure that it does not contain source code, sensitive configuration information and secrets such as API keys and passwords.
Anchore takes a very different approach to image security than traditional image scanners that look for CVEs. Using Anchore users can define policies that specify rules to govern security vulnerabilities, package whitelists and blacklists, configuration file contents, presence of credentials in an image, manifest changes, exposed ports or any user-defined checks. These policies can be deployed site-wide or customized for specific images or categories of applications.
You can read more about Anchore’s policy-based approach, however, if you want to take a more practical approach you can use open source Anchore Engine to inspect your own images and look for secrets. The following guide will walk you through setting up Anchore and analyzing your images, it should take no more than 10 minutes.
There are a number of ways to install Anchore including using operating system packages, PIP or even via a container. In this example, I’m using a CentOS 7 host that is already running Docker. If the system is not already configured to use the Extra Packages for Enterprise Linux (EPEL) repository then I need to run:
# yum install epel-release
Installing Anchore is as simple as installing a YUM repo file and then installing a single package.
# yum install http://repo.ancho.re/anchore/1.1/centos/7/noarch/anchore-release-1.1.0-1.el7.centos.noarch.rpm
# yum install anchore
At this point Anchore is installed, all we need to do now is run a sync to download the latest security data from the Anchore service.
# anchore feeds sync
Now we are ready to analyze containers.
Presuming the container image has been pulled to the localhost you can simply run the analyze command. In my example, I’m analyzing the myapp:latest image.
# anchore analyze --image=myapp:latest
If the Dockerfile is available then you can pass the Dockerfile to the anchore command, this provides a little more information to the analysis routine but is not required.
# anchore analyze --image=myapp:latest --dockerfile=/path/to/my/Dockerfile
We can now run a policy check on the image.
The default policy does not perform any checks for secrets but we can easily add that check.
Create a file named mypolicy and enter the following lines:
DOCKERFILECHECK:NOTAG:STOP
DOCKERFILECHECK:SUDO:GO
DOCKERFILECHECK:EXPOSE:STOP:DENIEDPORTS=22
DOCKERFILECHECK:FROMSCRATCH:WARN
DOCKERFILECHECK:NOFROM:STOP
SUIDDIFF:SUIDFILEDEL:GO
SUIDDIFF:SUIDMODEDIFF:STOP
SUIDDIFF:SUIDFILEADD:STOP
PKGDIFF:PKGVERSIONDIFF:STOP
PKGDIFF:PKGADD:WARN
PKGDIFF:PKGDEL:WARN
ANCHORESEC:VULNUNKNOWN:GO
ANCHORESEC:VULNHIGH:STOP
ANCHORESEC:VULNMEDIUM:WARN
ANCHORESEC:VULNLOW:GO
ANCHORESEC:VULNCRITICAL:STOP
ANCHORESEC:UNSUPPORTEDDISTRO:WARN
FILECHECK:FILENAMEMATCH:STOP:FILECHECK_NAMEREGEXP=.*/.ssh/id_rsa$
The last line uses the FILECHECK policy check. Here we are looking at a list of all the files in the image and using a regular expression to look for any private ssh keys in the image.
The FILECHECK policy module (or gate) can do matching on filenames or on filecontents, for example looking for specific strings within any file in the image. In this example, we are simply looking for ssh keys.
# anchore gate --image=myapp:latest --policy=/path/to/mypolicy
In my test image policy check returns two lines. The last line gives the final result of the policy check issuing a “STOP” meaning that the image has failed. The first line shows the policy that triggered this failure. Depending on your image you may see more or fewer policy violations.
+--------------+-------------------+-----------+---------------+-------------------+-------------+
| Image Id | Repo Tag | Gate | Trigger | Check Output | Gate Action |
+--------------+-------------------+-----------+---------------+-------------------+-------------+
| 9f767c5486f4 | aic-secret:latest | FILECHECK | FILENAMEMATCH | application of | STOP |
| | | | | regexp matched | |
| | | | | file found in | |
| | | | | container: file=/ | |
| | | | | root/.ssh/id_rsa | |
| | | | | regexp=.*/.ssh/id | |
| | | | | _rsa$ | |
| 9f767c5486f4 | aic-secret:latest | FINAL | FINAL | | STOP |
+--------------+-------------------+-----------+---------------+-------------------+-------------+
This simple policy performs just a few checks on your image and in the case of secrets only looks for private SSH keys however this policy can easily be extended to look for any secrets or blacklisted artifacts in your image.