Hardening Docker with OPA and Harbor

denisrendler

Denis Rendler

Posted on February 3, 2024

Hardening Docker with OPA and Harbor

In my article Docker Chronicles - Securing Docker instances with OPA and Harbor I am discussing the benefits that Open-Policy-Agent (OPA) and Harbor bring to securing Docker instances.

This post aims to guide you through the technical steps that I implemented for leveraging OPA and Harbor to not only secure your Docker containers but also to streamline the management of the policies. With OPA's powerful policy-as-code capabilities and Harbor's efficient image management system, you'll discover how to build a Docker ecosystem that's robust, secure, and compliant with industry best practices.

Let's begin.

The Setup

The code repository we will be using can be found here: https://github.com/httpsec-eu/opa-article

First we need to create the Gitlab repository for our policies. I named my repository OPA policies. If you want to use the bash commands you should change the environment vars to your own values.

export GL=gitlab.example.com      
export AUTH_TOKEN=gl-123456789ABCDEFG

curl --request POST --header "PRIVATE-TOKEN: ${AUTH_TOKEN}" \
     --header "Content-Type: application/json" --data '{
        "name": "opa-policies", "description": "OPA Policies", "path": "opa-policies",
        "namespace_id": "1", "initialize_with_readme": "true"}' \
     --url "https://${GL}/api/v4/projects/"
Enter fullscreen mode Exit fullscreen mode

Now that we created the Gitlab project to host our policies, you can go ahead an copy the /docker folder from my repository. Along with the folder you can copy the .gitlab-ci.yml which provides you with the pipeline to create the OPA bundle and push it to Harbor.

The pipeline uses several variables described below:

Variable name Purpose Default value
BUNDLE the name of the bundle which will be used as a Harbor artefact name bundle
REPO the folder name to build ./docker
TAG the tag to set for the bundle when pushed to the repository 0.1
IMG_REPO the repository URL domain harbor.httpsec.eu
REPO_USER the robot account to be used to login to Harbor no value
REPO_PASS the robot account password no value

Next we need to create the Harbor repository. I named mine docker-opa. If you want, I provided a quick curl call to create and setup the project - please change the env vars to your own.

export REPO=harbor.example.com
export AUTH=[BASIC_AUTH_TOKEN_FOR_REOBOT_ACCOUNT_HERE]

curl -X 'POST' \
  "https://${REPO}/api/v2.0/projects" \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -H "authorization: Basic ${AUTH}" \
  -d '{
  "project_name": "docker-opa",
  "public": false,
  "metadata": {
    "enable_content_trust": "true",
    "enable_content_trust_cosign": "true"
  }
}'

Enter fullscreen mode Exit fullscreen mode

Once the repository is created we need to create a Harbor robot account which we will use to login to Harbor from our Gitlab instance. You can set the variables REPO_USER and REPO_PASS as environment variables in the Gitlab project so that you don't have to enter them manually each time you run the pipeline.

Build the first bundle

Now that we created the two repositories we need to build our first OPA bundle. Go to your Gitlab project and select Build > Pipelines and click on Run pipeline. Fill in the variables or use the default values and select Run. Once the pipeline finishes you should see a new entry in the Harbor project similar to figure below.

First bundle

NOTE: in the screenshot the name of the bundle is docker_auth because I set the Gitlab pipeline variable BUNDLE to the same name.

Configure Docker

The next steps are to install the Docker plugin and configure it to pull the policies from our Harbor instance.

Before we install the plugin we need to set the configuration file. The /etc/docker directory will be mounted as /opa in the container running the plugin, so let’s create a sub-directory for our configuration file there.

sudo mkdir -p /etc/docker/opa-config
Enter fullscreen mode Exit fullscreen mode

Now copy or move the config.yaml file from my repository to the /etc/docker/opa-confg/ folder.

To install the plugin run the following command:

docker plugin install openpolicyagent/opa-docker-authz-v2:0.9 opa-args="-config-file /opa/opa-config/config.yaml"
Enter fullscreen mode Exit fullscreen mode

To validate that our plugin has been installed correctly, run the following command:

docker plugin ls
Enter fullscreen mode Exit fullscreen mode

If the everything works you should see an output similar to this:

ID             NAME                                      DESCRIPTION                                     ENABLED
d6cee85ae9aa   openpolicyagent/opa-docker-authz-v2:0.9   A policy-enabled authorization plugin for Do…   true
Enter fullscreen mode Exit fullscreen mode

The last step is to configure Docker to use plugin. For this we need to edit the file, or create it if it doesn't exist, /etc/docker/daemon.json and add the following line:

"authorization-plugins": ["openpolicyagent/opa-docker-authz-v2:0.9"]
Enter fullscreen mode Exit fullscreen mode

Run the following command to restart the Docker daemon:

sudo systemctl restart docker
Enter fullscreen mode Exit fullscreen mode

To validate that everything is working run the following command:

docker image pull nginx:latest
Enter fullscreen mode Exit fullscreen mode

And you should now receive an error similar to this:

$ docker image pull nginx:latest
Error response from daemon: authorization denied by plugin openpolicyagent/opa-docker-authz-v2:0.9: request rejected by administrative policy
Enter fullscreen mode Exit fullscreen mode

Now your Docker instance is hardened.

Final thoughts

As we wrap up, hardening Docker environments by integrating Open Policy Agent (OPA) and Harbor represents a good starting step in securing containerised applications. Through this tutorial, we've seen how OPA's policy-as-code approach, combined with Harbor's robust image management capabilities, can create a more secure and manageable Docker ecosystem.

By implementing these tools, OPS and security teams can enforce consistent security policies and practices, reducing the risk of vulnerabilities and enhancing the overall security posture of their applications.

💖 💪 🙅 🚩
denisrendler
Denis Rendler

Posted on February 3, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Hardening Docker with OPA and Harbor
docker Hardening Docker with OPA and Harbor

February 3, 2024