Creating high-quality container images is hard. How to choose an optimal base image? How to configure a multistage build to make the end image slim? How to keep the vulnerability scanners calm? One must be a true container expert to get it right. However, there might be an alternative way.
Automated container image hardening
- Build an image FROM your favorite base.
- Instrument the image with our sensors.
- Run an instrumented container "probing" its functionality.
- Build a hardened version of the image using collected intelligence.
-
A fresh version of the Slim CLI installed and configured
-
An ability to run the instrumented image (e.g., using Docker or Kubernetes)
Before we move to the steps, let's visualise how the flow looks like!
The first step involves instrumenting the image and simply speaking it means that the Slim engine's sensor is going to act like an intelligence agent to collect data for the further probe 🕵️
$ slim instrument \
--include-path /etc/passwd \
--stop-grace-period 999s \
ghcr.io/mritunjaysharma394/node-app:latest
NOTE: Make sure the instrumented image, in our case, ghcr.io/mritunjaysharma394/node-app:latest-slim-instrumented
is available through the connector.
Now that we have our agent aka sensor in the target's territory, its time to implement the mission! That is let the container run using the instrumented image and get all the important data to harden it and reduce the vulnerablities in next step. 😎
Make sure you use the root user and give it ALL capabilities (notice that this is a requirement only for the instrumented containers - hardened containers won’t need any extra permissions):
- Run the container:
$ docker run -d --rm \
--user root \
--cap-add ALL \
-p 8080:8080 \
--name app-instrumented ghcr.io/mritunjaysharma394/node-app:latest-slim-instrumented
- “Probe” the instrumented node app container:
$ curl localhost:8080
- Stop the container gracefully giving the sensor(s) enough time to finalize and submit the reports:
$ docker stop -t 999 app-instrumented
Good job so far by the agent! Now that we have the data via automatically submitted reports, let's harden the target image and bring down its vulnerabilites and size 🚀:
- Let's get the NX ID
$ NX_ID=$(docker inspect --format '{{ index .Config.Labels "slim.nx"}}' ghcr.io/mritunjaysharma394/node-app:latest-slim-instrumented)
- Harden using the NX ID
$ slim harden --id $NX_ID
- Run a new container using the hardened image (notice that it doesn’t require any extra privileges):
$ docker run -d --rm \
-p 8081:8080 \
--name app-hardened ghcr.io/mritunjaysharma394/node-app:latest-slim-hardened
- Verify that the hardened image works:
$ curl localhost:8081
$ docker stop app-hardened
Hurray, so you learnt the magic to harden your image quick right? It's time for celebration🍾
But wait, want too see all these steps in Actions? (Oh, we love puns!) So what are you waiting for? Check out how it is implemented in the workflow of the GitHub actions and how you can implement the same in your CI/CD!