This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Working with Policies

Introduction

Policies are central to the concept of Anchore Enterprise, this article provides information on how to create, delete, update, and describe policies using AnchoreCTL to interact with a running Anchore Enterprise deployment.

At a high-level Anchore Enterprise consumes policies store in a Policy that contain:

  • Policies
  • Allowlists
  • Mappings
  • Allowlisted Images
  • Denylisted Images

Anchore Enterprise can store multiple policies for each account, but only one policy can be active at any point in time. All users within an account share the same set of policies. It is common to store historic policies to allow previous policies and evaluations to be inspected. The active policy is the one used for evaluation for notifications, incoming kubernetes webhooks (unless configured otherwise), and other automatic system functions, but a user may request evaluation of any policy stored in the system using its id.

For more information on the content and semantics of policies see: Policies and Evaluation

Creating Policies

Policies are just JSON documents. Anchore Enterprise includes a default policy configured at installation that performs basic CVE checks as well as some Dockerfile checks.

To create custom polices, you may:

  • Edit JSON manually and upload a file
  • Use the Anchore Enterprise UI to edit policies

Managing Policies

Policies can be managed directly using the REST API or the anchorectl policy command.

Adding Policies using AnchoreCTL

The anchorectl tool allows you to upload policies to Anchore Enterprise.

# anchorectl policy add --input /path/to/policy/policy.json

Note: Adding a policy will not automatically set the policy to be active, you will need to activate the policy using the activate command.

Listing Policies

Anchore Enterprise may store multiple policies however at a given time only one policy may be active. Policies can be listed using the policy list command.


# anchorectl policy list
 ✔ Fetched policies
┌────────────────┬──────────────────────────────────────┬────────┬──────────────────────┐
│ NAME           │ POLICY ID                            │ ACTIVE │ UPDATED              │
├────────────────┼──────────────────────────────────────┼────────┼──────────────────────┤
│ Default policy │ 2c53a13c-1765-11e8-82ef-23527761d060 │ true   │ 2023-10-25T20:39:28Z │
│ devteam1policy │ da8208a2-c8ae-4cf2-a25b-a52b0cdcd789 │ false  │ 2023-10-25T20:47:16Z │
└────────────────┴──────────────────────────────────────┴────────┴──────────────────────┘

Each policy has a unique ID that will be reference in policy evaluation reports.

Note: Times are reported in UTC.

Viewing Policies

Using the policy get command, summary or detailed information about a policy can be retrieved. The policy is referenced using its unique id.


# anchorectl policy get 2c53a13c-1765-11e8-82ef-23527761d060
 ✔ Fetched policy
Name: Default policy
ID: 2c53a13c-1765-11e8-82ef-23527761d060
Comment: Default policy
Policies:
  - artifactType: image
    comment: System default policy
    id: 48e6f7d6-1765-11e8-b5f9-8b6f228548b6
    name: DefaultPolicy
    rules:
      - action: STOP
        gate: dockerfile
        id: ce7b8000-829b-4c27-8122-69cd59018400
        params:
          - name: ports
            value: "22"
          - name: type
            value: denylist
        trigger: exposed_ports
...
...

The policy can be downloaded in JSON format by passing the --detail parameter.

# anchorectl policy get 2c53a13c-1765-11e8-82ef-23527761d060 --detail -o json-raw > policy.json
 ✔ Fetched policy

Activating Policies

The policy activate command can be used to activate a policy. The policy is referenced using its unique id which can be retrieved using the policy list command.


# anchorectl policy activate 2c53a13c-1765-11e8-82ef-23527761d061
 ✔ Activate policy
┌─────────────────┬──────────────────────────────────────┬────────┬──────────────────────┐
│ NAME            │ POLICY ID                            │ ACTIVE │ UPDATED              │
├─────────────────┼──────────────────────────────────────┼────────┼──────────────────────┤
│ Default policy  │ 2c53a13c-1765-11e8-82ef-23527761d061 │ true   │ 2023-10-25T20:50:17Z │
└─────────────────┴──────────────────────────────────────┴────────┴──────────────────────┘

Note: If Anchore Enterprise has been configured to automatically synchronize policies from the Anchore Cloud then the active policy may be overridden automatically during the next sync.

Deleting Policies

Policies can be deleted from Anchore Enterprise using the policy del command The policy is referenced using its unique id. A policy marked as active cannot be deleted, another policy has to be marked active before deleting the currently active policy.


# anchorectl policy delete 2c53a13c-1765-11e8-82ef-23527761d061
 ✔ Deleted policy
No results

See Anchore Policy Checks for information about available policy gates and triggers in Anchore Enterprise.

1 - Anchore Policy Checks

Introduction

For an list of all available gates/triggers, refer to Anchore Policy Checks

2 - Evaluating Images Against Policies

Introduction

The evaluate command can be used to evaluate a given image for policy compliance.

The image to be evaluated can be in the following format:

  • Image Digest
  • Image ID
  • registry/repo:tag

Using the Evaluate command


# anchorectl image check docker.io/debian:latest
 ✔ Evaluated against policy                  [failed]                                                                                                                                                                                              docker.io/debian:latest
Tag: docker.io/debian:latest
Digest: sha256:0fcb5a38077422c4e70c5c43be21831193ff4559d143e27d8d5721e7a814bdcc
Policy ID: 2c53a13c-1765-11e8-82ef-23527761d060
Last Evaluation: 2023-10-25T20:34:43Z
Evaluation: fail

By default only the summary of the evaluation is shown. Passing the --detail parameter will show the policy checks that raised warnings or errors.


# anchorectl image check docker.io/debian:latest --detail
 ✔ Evaluated against policy                  [failed]                                                                                                                                                                                              docker.io/debian:latest
Tag: docker.io/debian:latest
Digest: sha256:0fcb5a38077422c4e70c5c43be21831193ff4559d143e27d8d5721e7a814bdcc
Policy ID: 2c53a13c-1765-11e8-82ef-23527761d060
Last Evaluation: 2023-10-25T20:35:05Z
Evaluation: fail
Final Action: stop
Reason: policy_evaluation

Policy Evaluation Details:
┌─────────────────┬─────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┐
│ GATE            │ TRIGGER     │ DESCRIPTION                                                                                                                                    │ STATUS │
├─────────────────┼─────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┤
│ dockerfile      │ instruction │ Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check                                                            │ warn   │
│ vulnerabilities │ package     │ MEDIUM Vulnerability found in os package type (dpkg) - libgnutls30 (CVE-2011-3389 - https://security-tracker.debian.org/tracker/CVE-2011-3389) │ warn   │
│ vulnerabilities │ package     │ CRITICAL Vulnerability found in os package type (dpkg) - zlib1g (CVE-2022-37434 - https://security-tracker.debian.org/tracker/CVE-2022-37434)  │ stop   │
└─────────────────┴─────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┘

In this example we specified library/repo:tag which could be ambiguous. At the time of writing the image Digest for library/debian:latest was sha256:0fc..... however previously different images may have been tagged as library/debian:latest. The --history parameter can be passed to show historic evaluations based on previous images or previous policies.

Anchore supports allowlisting and denylisting images by their name, ID or digest. A denylist or allowlist takes precedence over any policy checks. For example if an image is explicitly listed as denylisted then even if all the individual policy checks pass the image will still fail evaluation.


# anchorectl image check docker.io/debian:latest --detail
 ✔ Evaluated against policy                  [failed]                                                                                                                                                                                              docker.io/debian:latest
Tag: docker.io/debian:latest
Digest: sha256:0fcb5a38077422c4e70c5c43be21831193ff4559d143e27d8d5721e7a814bdcc
Policy ID: 2c53a13c-1765-11e8-82ef-23527761d060
Last Evaluation: 2023-10-25T20:39:36Z
Evaluation: fail
Final Action: stop
Reason: denylisted

Policy Evaluation Details:
┌─────────────────┬─────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┐
│ GATE            │ TRIGGER     │ DESCRIPTION                                                                                                                                    │ STATUS │
├─────────────────┼─────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┤
│ dockerfile      │ instruction │ Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check                                                            │ warn   │
│ vulnerabilities │ package     │ MEDIUM Vulnerability found in os package type (dpkg) - libgnutls30 (CVE-2011-3389 - https://security-tracker.debian.org/tracker/CVE-2011-3389) │ warn   │
└─────────────────┴─────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┘

In this example even though the image only had one policy check that raised a warning the image fails policy evaluation since it is present on a denylist.

Evaluating status based on Digest or ID

Performing an evaluation on an image specified by name is not recommended since an image name is ambiguous. For example the tag docker.io/library/centos:latest refers to whatever image has the tag library/centos:latest at the time of evaluation. At any point in time another image may be tagged as library/centos:latest.

It is recommended that images are referenced by their Digest. For example at the time of writing the digest of the ‘current’ library/centos:latest image is sha256:191c883e479a7da2362b2d54c0840b2e8981e5ab62e11ab925abf8808d3d5d44

If the image to be evaluated is specified by Image ID or Image Digest then the --tag parameter must be added. Policies are mapped to images based on registry/repo:tag so since an Image ID may may to multiple different names we must specify the name user in the evaluation.

For example - referencing by Image Digest:

# anchorectl image check docker.io/debian@sha256:0fcb5a38077422c4e70c5c43be21831193ff4559d143e27d8d5721e7a814bdcc --detail --tag docker.io/debian:latest
 ✔ Evaluated against policy                  [failed]                                                                                                                             docker.io/debian@sha256:0fcb5a38077422c4e70c5c43be21831193ff4559d143e27d8d5721e7a814bdcc
Tag: docker.io/debian:latest
Digest: sha256:0fcb5a38077422c4e70c5c43be21831193ff4559d143e27d8d5721e7a814bdcc
Policy ID: 2c53a13c-1765-11e8-82ef-23527761d060
Last Evaluation: 2023-10-25T20:44:24Z
Evaluation: fail
Final Action: stop
Reason: denylisted

Policy Evaluation Details:
┌─────────────────┬─────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┐
│ GATE            │ TRIGGER     │ DESCRIPTION                                                                                                                                    │ STATUS │
├─────────────────┼─────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┤
│ dockerfile      │ instruction │ Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check                                                            │ warn   │
│ vulnerabilities │ package     │ MEDIUM Vulnerability found in os package type (dpkg) - libgnutls30 (CVE-2011-3389 - https://security-tracker.debian.org/tracker/CVE-2011-3389) │ warn   │
│ vulnerabilities │ package     │ CRITICAL Vulnerability found in os package type (dpkg) - zlib1g (CVE-2022-37434 - https://security-tracker.debian.org/tracker/CVE-2022-37434)  │ stop   │
└─────────────────┴─────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┘

For example - referencing by image ID:


# anchorectl image check dd8bae8d259fed93eb54b3bca0adeb647fc07f6ef16745c8ed4144ada4d51a95  --detail --tag docker.io/debian:latest
 ✔ Evaluated against policy                  [failed]                                                                                                                                                     dd8bae8d259fed93eb54b3bca0adeb647fc07f6ef16745c8ed4144ada4d51a95
Tag: docker.io/debian:latest
Digest: sha256:0fcb5a38077422c4e70c5c43be21831193ff4559d143e27d8d5721e7a814bdcc
Policy ID: 2c53a13c-1765-11e8-82ef-23527761d060
Last Evaluation: 2023-10-25T20:45:20Z
Evaluation: fail
Final Action: stop
Reason: denylisted

Policy Evaluation Details:
┌─────────────────┬─────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┐
│ GATE            │ TRIGGER     │ DESCRIPTION                                                                                                                                    │ STATUS │
├─────────────────┼─────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┤
│ dockerfile      │ instruction │ Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check                                                            │ warn   │
│ vulnerabilities │ package     │ MEDIUM Vulnerability found in os package type (dpkg) - libgnutls30 (CVE-2011-3389 - https://security-tracker.debian.org/tracker/CVE-2011-3389) │ warn   │
│ vulnerabilities │ package     │ CRITICAL Vulnerability found in os package type (dpkg) - zlib1g (CVE-2022-37434 - https://security-tracker.debian.org/tracker/CVE-2022-37434)  │ stop   │
└─────────────────┴─────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┘

3 - Policy Gate: dockerfile

Introduction

This article reviews the “dockerfile” gate and its triggers. The dockerfile gate allows users to perform checks on the content of the dockerfile or docker history for an image and make policy actions based on the construction of an image, not just its content. This is particularly useful for enforcing best practices or metadata inclusion (e.g. labels) on images.

Anchore is either given a dockerfile or infers one from the docker image layer history. There are implications to what data is available and what it means depending on these differing sources, so first, we’ll cover the input data for the gate and how it impacts the triggers and parameters used.

The “dockerfile”

The data that this gate operates on can come from two different sources:

  1. The actual dockerfile used to build an image, as provided by the user at the time of running anchorectl image add <img ref> --dockerfile <filename> or the corresponding API call to: POST /images?dockerfile=
  2. The history from layers as encoded in the image itself (see docker history <img> for this output)

All images have data from history available, but data from the actual dockerfile is only available when a user provides it. This also means that any images analyzed by the tag watcher functionality will not have an actual dockerfile.

The FROM line

In the actual dockerfile, the FROM instruction is preserved and available as used to build the image, however in the history data, the FROM line will always be the very first FROM instruction used to build the image and all of its dependent based image. Thus, for most images, the value in the history will be omitted and Anchore will automatically infer a FROM scratch line, which is logically inserted for this gate if the dockerfile/history does not contain an explicit FROM entry.

For example, using the docker.io/jenkins/jenkins image:

IMAGE                                                                     CREATED             CREATED BY                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       SIZE                COMMENT
sha256:3b9c9666a66e53473c05a3c69eb2cb888a8268f76935eecc7530653cddc28981   11 hours ago        /bin/sh -c #(nop) COPY file:3a15c25533fd87983edc33758f62af7b543ccc3ce9dd570e473eb0702f5f298e in /usr/local/bin/install-plugins.sh                                                                                                                                                                                                                                                                                                                                                                                                                                8.79kB              
<missing>                                                                 11 hours ago        /bin/sh -c #(nop) COPY file:f97999fac8a63cf8b635a54ea84a2bc95ae3da4d81ab55267c92b28b502d8812 in /usr/local/bin/plugins.sh                                                                                                                                                                                                                                                                                                                                                                                                                                        3.96kB              
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ENTRYPOINT ["/sbin/tini" "--" "/usr/local/bin/jenkins.sh"]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop) COPY file:dc942ca949bb159f81bbc954773b3491e433d2d3e3ef90bac80ecf48a313c9c9 in /bin/tini                                                                                                                                                                                                                                                                                                                                                                                                                                                        529B                
<missing>                                                                 11 hours ago        /bin/sh -c #(nop) COPY file:a8f986413b77bf4d88562b9d3a0dce98ab6e75403192aa4d4153fb41f450843d in /usr/local/bin/jenkins.sh                                                                                                                                                                                                                                                                                                                                                                                                                                        1.45kB              
<missing>                                                                 11 hours ago        /bin/sh -c #(nop) COPY file:55594d9d2aed007553a6743a43039b1a48b30527f8fb991ad93e1fd5b1298f60 in /usr/local/bin/jenkins-support                                                                                                                                                                                                                                                                                                                                                                                                                                   6.12kB              
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  USER jenkins                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ENV COPY_REFERENCE_FILE_LOG=/var/jenkins_home/copy_reference_file.log                                                                                                                                                                                                                                                                                                                                                                                                                                                                         0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  EXPOSE 50000                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  EXPOSE 8080                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   0B                  
<missing>                                                                 11 hours ago        |9 JENKINS_SHA=e026221efcec9528498019b6c1581cca70fe9c3f6b10303777d85c6699bca0e4 JENKINS_URL=https://repo.jenkins-ci.org/public/org/jenkins-ci/main/jenkins-war/2.161/jenkins-war-2.161.war TINI_VERSION=v0.16.1 agent_port=50000 gid=1000 group=jenkins http_port=8080 uid=1000 user=jenkins /bin/sh -c chown -R ${user} "$JENKINS_HOME" /usr/share/jenkins/ref                                                                                                                                                                                                  328B                
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ENV JENKINS_INCREMENTALS_REPO_MIRROR=https://repo.jenkins-ci.org/incrementals                                                                                                                                                                                                                                                                                                                                                                                                                                                                 0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ENV JENKINS_UC_EXPERIMENTAL=https://updates.jenkins.io/experimental                                                                                                                                                                                                                                                                                                                                                                                                                                                                           0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ENV JENKINS_UC=https://updates.jenkins.io                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     0B                  
<missing>                                                                 11 hours ago        |9 JENKINS_SHA=e026221efcec9528498019b6c1581cca70fe9c3f6b10303777d85c6699bca0e4 JENKINS_URL=https://repo.jenkins-ci.org/public/org/jenkins-ci/main/jenkins-war/2.161/jenkins-war-2.161.war TINI_VERSION=v0.16.1 agent_port=50000 gid=1000 group=jenkins http_port=8080 uid=1000 user=jenkins /bin/sh -c curl -fsSL ${JENKINS_URL} -o /usr/share/jenkins/jenkins.war   && echo "${JENKINS_SHA}  /usr/share/jenkins/jenkins.war" | sha256sum -c -                                                                                                                  76MB                
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG JENKINS_URL=https://repo.jenkins-ci.org/public/org/jenkins-ci/main/jenkins-war/2.161/jenkins-war-2.161.war                                                                                                                                                                                                                                                                                                                                                                                                                                0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG JENKINS_SHA=5bb075b81a3929ceada4e960049e37df5f15a1e3cfc9dc24d749858e70b48919                                                                                                                                                                                                                                                                                                                                                                                                                                                              0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ENV JENKINS_VERSION=2.161                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG JENKINS_VERSION                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop) COPY file:c84b91c835048a52bb864c1f4662607c56befe3c4b1520b0ea94633103a4554f in /usr/share/jenkins/ref/init.groovy.d/tcp-slave-agent-port.groovy                                                                                                                                                                                                                                                                                                                                                                                                 328B                
<missing>                                                                 11 hours ago        |7 TINI_VERSION=v0.16.1 agent_port=50000 gid=1000 group=jenkins http_port=8080 uid=1000 user=jenkins /bin/sh -c curl -fsSL https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-$(dpkg --print-architecture) -o /sbin/tini   && curl -fsSL https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-$(dpkg --print-architecture).asc -o /sbin/tini.asc   && gpg --no-tty --import ${JENKINS_HOME}/tini_pub.gpg   && gpg --verify /sbin/tini.asc   && rm -rf /sbin/tini.asc /root/.gnupg   && chmod +x /sbin/tini   866kB               
<missing>                                                                 11 hours ago        /bin/sh -c #(nop) COPY file:653491cb486e752a4c2b4b407a46ec75646a54eabb597634b25c7c2b82a31424 in /var/jenkins_home/tini_pub.gpg                                                                                                                                                                                                                                                                                                                                                                                                                                   7.15kB              
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG TINI_VERSION=v0.16.1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      0B                  
<missing>                                                                 11 hours ago        |6 agent_port=50000 gid=1000 group=jenkins http_port=8080 uid=1000 user=jenkins /bin/sh -c mkdir -p /usr/share/jenkins/ref/init.groovy.d                                                                                                                                                                                                                                                                                                                                                                                                                         0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  VOLUME [/var/jenkins_home]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    0B                  
<missing>                                                                 11 hours ago        |6 agent_port=50000 gid=1000 group=jenkins http_port=8080 uid=1000 user=jenkins /bin/sh -c mkdir -p $JENKINS_HOME   && chown ${uid}:${gid} $JENKINS_HOME   && groupadd -g ${gid} ${group}   && useradd -d "$JENKINS_HOME" -u ${uid} -g ${gid} -m -s /bin/bash ${user}                                                                                                                                                                                                                                                                                            328kB               
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ENV JENKINS_SLAVE_AGENT_PORT=50000                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ENV JENKINS_HOME=/var/jenkins_home                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG JENKINS_HOME=/var/jenkins_home                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG agent_port=50000                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG http_port=8080                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG gid=1000                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG uid=1000                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG group=jenkins                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             0B                  
<missing>                                                                 11 hours ago        /bin/sh -c #(nop)  ARG user=jenkins                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              0B                  
<missing>                                                                 11 hours ago        /bin/sh -c apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/*                                                                                                                                                                                                                                                                                                                                                                                                                                                                          0B                  
<missing>                                                                 3 weeks ago         /bin/sh -c set -ex;   if [ ! -d /usr/share/man/man1 ]; then   mkdir -p /usr/share/man/man1;  fi;   apt-get update;  apt-get install -y --no-install-recommends   openjdk-8-jdk="$JAVA_DEBIAN_VERSION"  ;  rm -rf /var/lib/apt/lists/*;   [ "$(readlink -f "$JAVA_HOME")" = "$(docker-java-home)" ];   update-alternatives --get-selections | awk -v home="$(readlink -f "$JAVA_HOME")" 'index($3, home) == 1 { $2 = "manual"; print | "update-alternatives --set-selections" }';  update-alternatives --query java | grep -q 'Status: manual'                    348MB               
<missing>                                                                 3 weeks ago         /bin/sh -c #(nop)  ENV JAVA_DEBIAN_VERSION=8u181-b13-2~deb9u1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    0B                  
<missing>                                                                 3 weeks ago         /bin/sh -c #(nop)  ENV JAVA_VERSION=8u181                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        0B                  
<missing>                                                                 3 weeks ago         /bin/sh -c #(nop)  ENV JAVA_HOME=/docker-java-home                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               0B                  
<missing>                                                                 3 weeks ago         /bin/sh -c ln -svT "/usr/lib/jvm/java-8-openjdk-$(dpkg --print-architecture)" /docker-java-home                                                                                                                                                                                                                                                                                                                                                                                                                                                                  33B                 
<missing>                                                                 3 weeks ago         /bin/sh -c {   echo '#!/bin/sh';   echo 'set -e';   echo;   echo 'dirname "$(dirname "$(readlink -f "$(which javac || which java)")")"';  } > /usr/local/bin/docker-java-home  && chmod +x /usr/local/bin/docker-java-home                                                                                                                                                                                                                                                                                                                                       87B                 
<missing>                                                                 3 weeks ago         /bin/sh -c #(nop)  ENV LANG=C.UTF-8                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              0B                  
<missing>                                                                 3 weeks ago         /bin/sh -c apt-get update && apt-get install -y --no-install-recommends   bzip2   unzip   xz-utils  && rm -rf /var/lib/apt/lists/*                                                                                                                                                                                                                                                                                                                                                                                                                               2.21MB              
<missing>                                                                 3 weeks ago         /bin/sh -c apt-get update && apt-get install -y --no-install-recommends   bzr   git   mercurial   openssh-client   subversion     procps  && rm -rf /var/lib/apt/lists/*                                                                                                                                                                                                                                                                                                                                                                                         142MB               
<missing>                                                                 3 weeks ago         /bin/sh -c set -ex;  if ! command -v gpg > /dev/null; then   apt-get update;   apt-get install -y --no-install-recommends    gnupg    dirmngr   ;   rm -rf /var/lib/apt/lists/*;  fi                                                                                                                                                                                                                                                                                                                                                                             7.81MB              
<missing>                                                                 3 weeks ago         /bin/sh -c apt-get update && apt-get install -y --no-install-recommends   ca-certificates   curl   netbase   wget  && rm -rf /var/lib/apt/lists/*                                                                                                                                                                                                                                                                                                                                                                                                                23.2MB              
<missing>                                                                 3 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  0B                  
<missing>                                                                 3 weeks ago         /bin/sh -c #(nop) ADD file:da71baf0d22cb2ede91c5e3ff959607e47459a9d7bda220a62a3da362b0e59ea in /                                                                                                                                                                                                                                                                                                                                                                                                                                                                 101MB

Where the actual dockerfile for that image is:

FROM openjdk:8-jdk-stretch

RUN apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/*

ARG user=jenkins
ARG group=jenkins
ARG uid=1000
ARG gid=1000
ARG http_port=8080
ARG agent_port=50000
ARG JENKINS_HOME=/var/jenkins_home

ENV JENKINS_HOME $JENKINS_HOME
ENV JENKINS_SLAVE_AGENT_PORT ${agent_port}

# Jenkins is run with user `jenkins`, uid = 1000
# If you bind mount a volume from the host or a data container,
# ensure you use the same uid
RUN mkdir -p $JENKINS_HOME \
  && chown ${uid}:${gid} $JENKINS_HOME \
  && groupadd -g ${gid} ${group} \
  && useradd -d "$JENKINS_HOME" -u ${uid} -g ${gid} -m -s /bin/bash ${user}

# Jenkins home directory is a volume, so configuration and build history
# can be persisted and survive image upgrades
VOLUME $JENKINS_HOME

# `/usr/share/jenkins/ref/` contains all reference configuration we want
# to set on a fresh new installation. Use it to bundle additional plugins
# or config file with your custom jenkins Docker image.
RUN mkdir -p /usr/share/jenkins/ref/init.groovy.d

# Use tini as subreaper in Docker container to adopt zombie processes
ARG TINI_VERSION=v0.16.1
COPY tini_pub.gpg ${JENKINS_HOME}/tini_pub.gpg
RUN curl -fsSL https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-$(dpkg --print-architecture) -o /sbin/tini \
  && curl -fsSL https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-$(dpkg --print-architecture).asc -o /sbin/tini.asc \
  && gpg --no-tty --import ${JENKINS_HOME}/tini_pub.gpg \
  && gpg --verify /sbin/tini.asc \
  && rm -rf /sbin/tini.asc /root/.gnupg \
  && chmod +x /sbin/tini

COPY init.groovy /usr/share/jenkins/ref/init.groovy.d/tcp-slave-agent-port.groovy

# jenkins version being bundled in this docker image
ARG JENKINS_VERSION
ENV JENKINS_VERSION ${JENKINS_VERSION:-2.121.1}

# jenkins.war checksum, download will be validated using it
ARG JENKINS_SHA=5bb075b81a3929ceada4e960049e37df5f15a1e3cfc9dc24d749858e70b48919

# Can be used to customize where jenkins.war get downloaded from
ARG JENKINS_URL=https://repo.jenkins-ci.org/public/org/jenkins-ci/main/jenkins-war/${JENKINS_VERSION}/jenkins-war-${JENKINS_VERSION}.war

# could use ADD but this one does not check Last-Modified header neither does it allow to control checksum
# see https://github.com/docker/docker/issues/8331
RUN curl -fsSL ${JENKINS_URL} -o /usr/share/jenkins/jenkins.war \
  && echo "${JENKINS_SHA}  /usr/share/jenkins/jenkins.war" | sha256sum -c -

ENV JENKINS_UC https://updates.jenkins.io
ENV JENKINS_UC_EXPERIMENTAL=https://updates.jenkins.io/experimental
ENV JENKINS_INCREMENTALS_REPO_MIRROR=https://repo.jenkins-ci.org/incrementals
RUN chown -R ${user} "$JENKINS_HOME" /usr/share/jenkins/ref

# for main web interface:
EXPOSE ${http_port}

# will be used by attached slave agents:
EXPOSE ${agent_port}

ENV COPY_REFERENCE_FILE_LOG $JENKINS_HOME/copy_reference_file.log

USER ${user}

COPY jenkins-support /usr/local/bin/jenkins-support
COPY jenkins.sh /usr/local/bin/jenkins.sh
COPY tini-shim.sh /bin/tini
ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/jenkins.sh"]

# from a derived Dockerfile, can use `RUN plugins.sh active.txt` to setup /usr/share/jenkins/ref/plugins from a support bundle
COPY plugins.sh /usr/local/bin/plugins.sh
COPY install-plugins.sh /usr/local/bin/install-plugins.sh

Anchore will detect the history/dockerfile as this, if not explicitly provided (note order is reversed from docker history output, so it reads in same order as actual dockerfile):

[
   {
      "Size" : 45323792,
      "Tags" : [],
      "Comment" : "",
      "Id" : "sha256:cd8eada9c7bb496eb685fc6d2198c33db7cb05daf0fde42e4cf5bf0127cbdf38",
      "Created" : "2018-12-28T23:29:37.981962131Z",
      "CreatedBy" : "/bin/sh -c #(nop) ADD file:da71baf0d22cb2ede91c5e3ff959607e47459a9d7bda220a62a3da362b0e59ea in / "
   },
   {
      "Size" : 0,
      "Tags" : [],
      "Comment" : "",
      "Id" : "<missing>",
      "Created" : "2018-12-28T23:29:38.226681736Z",
      "CreatedBy" : "/bin/sh -c #(nop)  CMD [\"bash\"]"
   },
   {
      "Size" : 10780911,
      "Comment" : "",
      "Tags" : [],
      "CreatedBy" : "/bin/sh -c apt-get update && apt-get install -y --no-install-recommends \t\tca-certificates \t\tcurl \t\tnetbase \t\twget \t&& rm -rf /var/lib/apt/lists/*",
      "Created" : "2018-12-29T00:04:28.920875483Z",
      "Id" : "sha256:c2677faec825930a8844845f55454ee0495ceb5bea9fc904d5b3125de863dc1d"
   },
   {
      "Comment" : "",
      "Tags" : [],
      "Size" : 4340024,
      "CreatedBy" : "/bin/sh -c set -ex; \tif ! command -v gpg > /dev/null; then \t\tapt-get update; \t\tapt-get install -y --no-install-recommends \t\t\tgnupg \t\t\tdirmngr \t\t; \t\trm -rf /var/lib/apt/lists/*; \tfi",
      "Created" : "2018-12-29T00:04:34.642152001Z",
      "Id" : "sha256:fcce419a96b1219a265bf7a933d66b585a6f8d73448533f3833c73ad49fb5e88"
   },
   {
      "Size" : 50062697,
      "Tags" : [],
      "Comment" : "",
      "Id" : "sha256:045b51e26e750443c84216071a1367a7aae0b76245800629dc04934628b4b1ea",
      "CreatedBy" : "/bin/sh -c apt-get update && apt-get install -y --no-install-recommends \t\tbzr \t\tgit \t\tmercurial \t\topenssh-client \t\tsubversion \t\t\t\tprocps \t&& rm -rf /var/lib/apt/lists/*",
      "Created" : "2018-12-29T00:04:59.676112605Z"
   },
 ... <truncated for brevity> ...
   {
      "Tags" : [],
      "Comment" : "",
      "Size" : 0,
      "Id" : "<missing>",
      "CreatedBy" : "/bin/sh -c #(nop)  ENTRYPOINT [\"/sbin/tini\" \"--\" \"/usr/local/bin/jenkins.sh\"]",
      "Created" : "2019-01-21T08:56:30.737221895Z"
   },
   {
      "Size" : 1549,
      "Tags" : [],
      "Comment" : "",
      "Id" : "sha256:283cd3aba8691a3b9d22d923de66243b105758e74de7d9469fe55a6a58aeee30",
      "Created" : "2019-01-21T08:56:32.015667468Z",
      "CreatedBy" : "/bin/sh -c #(nop) COPY file:f97999fac8a63cf8b635a54ea84a2bc95ae3da4d81ab55267c92b28b502d8812 in /usr/local/bin/plugins.sh "
   },
   {
      "Comment" : "",
      "Tags" : [],
      "Size" : 3079,
      "Created" : "2019-01-21T08:56:33.158854485Z",
      "CreatedBy" : "/bin/sh -c #(nop) COPY file:3a15c25533fd87983edc33758f62af7b543ccc3ce9dd570e473eb0702f5f298e in /usr/local/bin/install-plugins.sh ",
      "Id" : "sha256:b0ce8ab5a5a7da5d762f25af970f4423b98437a8318cb9852c3f21354cbf914f"
   }
]

NOTE: Anchore processes the leading /bin/sh commands, so you do not have to include those in any trigger param config if using the docker history output.

The actual_dockerfile_only Parameter

The actual vs history impacts the semantics of the dockerfile gate’s triggers. To allow explicit control of the differences, most triggers in this gate includes a parameter: actual_dockerfile_only that if set to true or false will ensure the trigger check is only done on the source of data specified. If actual_dockerfile_only = true, then the trigger will evaluate only if an actual dockerfile is available for the image and will skip evaluation if not. If actual_dockerfile_only is false or omitted, then the trigger will run on the actual dockerfile if available, or the history data if the dockerfile was not provided.

Differences in data between Docker History and actual Dockerfile

With Actual Dockerfile:

  1. FROM line is preserved, so the parent tag of the image is easily available
  2. Instruction checks are all against instructions created during the build for that exact image, not any parent images
    1. When the actual_dockerfile_only parameter is set to true, all instructions from the parent image are ignored in policy processing. This may have some unexpected consequences depending on how your images are structured and layered (e.g. golden base images that establish common patterns of volumes, labels, healthchecks)
  3. COPY/ADD instructions will maintain the actual values used
  4. Multistage-builds in that specific dockerfile will be visible with multiple FROM lines in the output

With Docker History data, when no dockerfile is provided:

  1. FROM line is not accurate, and will nearly always default to ‘FROM scratch’
  2. Instructions are processed from all layers in the image
  3. COPY and ADD instructions are transformed into SHAs rather than the actual file path/name used at build-time
  4. Multi-stage builds are not tracked with multiple FROM lines, only the copy operations between the phases

Trigger: instruction

This trigger evaluates instructions found in the “dockerfile”

Supported Directives/Instructions:

Parameters

actual_dockerfile_only (optional): See above

instruction: The dockerfile instruction to check against. One of:

  • ADD
  • ARG
  • COPY
  • CMD
  • ENTRYPOINT
  • ENV
  • EXPOSE
  • FROM
  • HEALTHCHECK
  • LABEL
  • MAINTAINER
  • ONBUILD
  • USER
  • RUN
  • SHELL
  • STOPSIGNAL
  • VOLUME
  • WORKDIR

check: The comparison/evaluation to perform. One of: =, != , exists, not_exists, like, not_like, in, not_in.

value (optional): A string value to compare against, if applicable

Examples

  1. Ensure an image has a HEALTHCHECK defined in the image (warn if not found):
{
  "gate": "dockerfile",
  "trigger": "instruction", 
  "action": "warn", 
  "parameters": [ 
    {
      "name": "instruction",
      "value": "HEALTHCHECK"
    }, 
    {
      "name": "check",
      "value": "not_exists"
    }
  ]
}
  1. Check for AWS environment variables set:
{
  "gate": "dockerfile",
  "trigger": "instruction", 
  "action": "stop", 
  "parameters": [ 
    {
      "name": "instruction",
      "value": "ENV"
    }, 
    {
      "name": "check",
      "value": "like"
    },
    {
      "name": "value",
      "value": "AWS_.*KEY"
    }
  ]
}

Trigger: packages_added

This trigger warns if a package was added to the SBOM.

Parameters

Optional parameter: “package_type”

Example

Raise a warning if packages were added.

  {
   "action": "WARN",
   "gate": "tag_drift",
   "trigger": "packages_added",
   "params": [],
   "id": "1ba3461f-b9db-4a6c-ac88-329d38e08df5"
  }

Trigger: packages_removed

This trigger warns if a package was deleted from the SBOM.

Parameters

Optional parameter: “package_type”

Example

Raise a warning if packages were deleted.

  {
   "action": "WARN",
   "gate": "tag_drift",
   "trigger": "packages_removed",
   "params": [],
   "id": "de05d77b-1f93-4df4-a65d-57d9042b1f3a"
  }

Trigger: packages_modified

This trigger warns if a package was changed in the SBOM.

Parameters

Optional parameter: “package_type”

Example

Raise a warning if packages were changed.

  {
   "action": "WARN",
   "gate": "tag_drift",
   "trigger": "packages_modified",
   "params": [],
   "id": "1168b0ac-df6c-4715-8077-2cb3e016cf63"
  }

Trigger: effective_user

This trigger processes all USER directives in the dockerfile or history to determine which user will be used to run the container by default (assuming no user is set explicitly at runtime). The detected value is then subject to a allowlist or denylist filter depending on the configured parameters. Typically, this is used for denylisting the root user.

Parameters

actual_dockerfile_only (optional): See above

users: A string with a comma delimited list of username to check for

type: The type of check to perform. One of: ‘denylist’ or ‘allowlist’. This determines how the value of the ‘users’ parameter is interpreted.

Examples

  1. Denylist root user
{
  "gate": "dockerfile",
  "trigger": "effective_user", 
  "action": "stop", 
  "parameters": [ 
    {
      "name": "users",
      "value": "root"
    }, 
    {
      "name": "type",
      "value": "denylist"
    }
  ]
}
  1. Denylist root user but only if set in actual dockerfile, not inherited from parent image
{
  "gate": "dockerfile",
  "trigger": "effective_user", 
  "action": "stop", 
  "parameters": [ 
    {
      "name": "users",
      "value": "root"
    }, 
    {
      "name": "type",
      "value": "denylist"
    },
    {
      "name": "actual_dockerfile_only",
      "value": "true"
    }
  ]
}
  1. Warn if the user is not either “nginx” or “jenkins”
{
  "gate": "dockerfile",
  "trigger": "effective_user", 
  "action": "warn", 
  "parameters": [ 
    {
      "name": "users",
      "value": "nginx,jenkins"
    }, 
    {
      "name": "type",
      "value": "allowlist"
    }
  ]
}

Trigger: exposed_ports

This trigger processes the set of EXPOSE directives in the dockerfile/history to determine the set of ports that are defined to be exposed (since it can span multiple directives). It performs checks on that set to denylist/allowlist them based on parameter settings.

Parameters

actual_dockerfile_only (optional): See above

ports: String of comma delimited port numbers to be checked

type: The type of check to perform. One of: ‘denylist’ or ‘allowlist’. This determines how the value of the ‘users’ parameter is interpreted

Examples

  1. Allow only ports 80 and 443. Trigger will fire on any port defined to be exposed that is not 80 or 443
{
  "gate": "dockerfile",
  "trigger": "exposed_ports", 
  "action": "warn", 
  "parameters": [ 
    {
      "name": "ports",
      "value": "80,443"
    }, 
    {
      "name": "type",
      "value": "allowlist"
    }
  ]
}
  1. Denylist ports 21 (ftp), 22 (ssh), and 53 (dns) . Trigger will fire a match on ports 21, 22, 53 if found in EXPOSE directives
{
  "gate": "dockerfile",
  "trigger": "exposed_ports", 
  "action": "warn", 
  "parameters": [ 
    {
      "name": "ports",
      "value": "21,22,53"
    }, 
    {
      "name": "type",
      "value": "denylist"
    }
  ]
}

Trigger: no_dockerfile_provided

This trigger allows checks on the way the image was added, firing if the dockerfile was not explicitly provided at analysis time. This is useful in identifying and qualifying other trigger matches.

Parameters

None

Examples

  1. Raise a warning if no dockerfile was provided at analysis time
{
  "gate": "dockerfile",
  "trigger": "no_dockerfile_provided", 
  "action": "warn", 
  "parameters": [] 
}