Policy Configuration

When ec command line requires configuration, e.g. for ec validate image command, the configuration can be provided as an inline JSON or YAML string, such as in this example:

ec validate image --policy '{
    "sources": [
        {
            "policy": ["oci::quay.io/enterprise-contract/ec-release-policy:latest"],
            "data": ["git::https://github.com/enterprise-contract/ec-policies//example/data"],
            "config": {
                "include": ["@minimal"]
            }
        }
    ]
}' ...

The configuration can be provided as a reference to a EnterpriseContractPolicy Kubernetes custom resource by either name (e.g. "my-policy") in the current namespace, or by providing namespace and the name separaded by slash (/) character, such as in this example:

ec validate image --policy my-namespace/my-policy

If the explicit policy is not provided via the --policy parameter, the default policy named default is loaded from enterprise-contract-service namespace of the cluster accessed using the current Kubernetes client configuration.

Including and excluding rules

By default, all rules are included.

You can modify the defaults by setting config.policy.include and config.policy.exclude. Each of those values should be a list of strings.

The strings in the list should be one of the the following:

A "package name"

Package names can be found in the policy documentation, for example the Attestation Type package name is attestation_type. Specifing a package name by itself in the include or exclude list means every rule from that package should be included or excluded.

A "rule name"

A rule name consists of the rule’s package name and the rule’s "code" separated by a dot. Rule codes can be see in the documentation also. For example the Unknown attestation type found rule name is attestation_type.unknown_att_type.

A "package name:term"

Some policy rules process a list of items, "term" allows a particular item to be excluded or included. This matcher behaves like "package name" but only applies to policy rules in the package that match the "term". For example, the Test package emits results for each test case. A particular test case can be ignored without ignoring the remaining ones.

It is also possible that a policy rule emits a list of terms. In such cases, the matcher only needs to match one of those terms. For example, if a policy rule emits multiple terms (a, b, and c), then a matcher that includes b will successfully match it.

A "rule name:term"

This is similar to "package name:term", but allows finer granularity by only applying to a particular policy rule within the package.

A "@collection name"

Specify a predefined collection. The collection name must be prefixed with @.

"*"

The "*" acts as a wildcard to match any package. Note that it does not match partial names, so you can’t specify "s*" to match every package starting with "s" for example.

You can also specify "<packagename>.*" and it works the same as just "<packagename>" to represent every rule in a package.

A certain rule may match one or more items in the list of includes or excludes. In order to determine the precedence between these two lists, and, ultimately, whether a rule should be included, a specificity score is calculated for every match on each list. A score over the list of includes that is higher than the score over the list of excludes means the rule is included. Otherwise, the rule is excluded.

For each name in each of the lists, the guidelines for computing the score are as such:

  1. If the name starts with "@" the returned score is exactly 10, e.g. "@collection". No further processing is done.

  2. Add 1 if the name covers everything, i.e. "*"

  3. Add 10 if the name specifies a package name, e.g. "release.test", "release.test.", "release.test.*", or "release.test.test_result_failures"

  4. Add 100 if a term is used, e.g. "*:term", "release.test:clamav-scan" or "release.test.test_result_failures:clamav-scan"

  5. Add 100 if a rule is used, e.g. "release.test.test_result_failures"

Except for collections, the score is cumulative. If a name is covered by multiple items in the guidelines, they are added together. For example, "release.test.test_result_failures:clamav-scan" scores at 210.

Volatile inclusions and exclusions

It is also possible to specify a time for which an inclusion or an exclusions is applicable. For example, you may want to specify that particular policy rule is excluded only until a certain date. To do so, use the volatileConfig attribute. For example:

  • YAML

  • JSON

sources:
  - policy:
      - oci::quay.io/enterprise-contract/ec-release-policy:latest
    data:
      - git::https://github.com/enterprise-contract/ec-policies//example/data
    volatileConfig:
      exclude:
        # Ignore violations from the `test` package until the end of 2024.
        - value: test
          effectiveUntil: "2024-12-31T00:00:00Z"
        # Ignore violations from the `java` package starting on 2025.
        - value: java
          effectiveOn: "2024-12-31T00:00:00Z"
{
  "sources": [
    {
      "policy": [
        "oci::quay.io/enterprise-contract/ec-release-policy:latest"
      ],
      "data": [
        "git::https://github.com/enterprise-contract/ec-policies//example/data"
      ],
      "volatileConfig": {
        "exclude": [
          {
            "value": "test",
            "effectiveUntil": "2024-12-31T00:00:00Z"
          },
          {
            "value": "java",
            "effectiveOn": "2024-12-31T00:00:00Z"
          }
        ]
      }
    }
  ]
}

If both volatileConfig and config are used, they are both processed by the EC CLI as if they were merged together.

With volatileConfig you can also specify an exclusion for a particular image reference. For example:

  • YAML

  • JSON

sources:
  - policy:
      - oci::quay.io/enterprise-contract/ec-release-policy:latest
    data:
      - git::https://github.com/enterprise-contract/ec-policies//example/data
    volatileConfig:
      exclude:
        # Ignore violations from the `test` package for any image matching the digest.
        - value: test
          imageRef: sha256:4e388ab32b10dc8dbc7e28144f552830adc74787c1e2c0824032078a79f227fb
{
  "sources": [
    {
      "policy": [
        "oci::quay.io/enterprise-contract/ec-release-policy:latest"
      ],
      "data": [
        "git::https://github.com/enterprise-contract/ec-policies//example/data"
      ],
      "volatileConfig": {
        "exclude": [
          {
            "value": "test",
            "imageRef": "sha256:4e388ab32b10dc8dbc7e28144f552830adc74787c1e2c0824032078a79f227fb"
          }
        ]
      }
    }
  ]
}

Although unusual, it is also possible to specify an inclusion for an image reference. In the example below, the java and test packages are executed for the image matching the reference, while for all other image references only the java package is executed.

  • YAML

  • JSON

sources:
  - policy:
      - oci::quay.io/enterprise-contract/ec-release-policy:latest
    data:
      - git::https://github.com/enterprise-contract/ec-policies//example/data
    volatileConfig:
      include:
        - value: java
        - value: test
          imageRef: sha256:4e388ab32b10dc8dbc7e28144f552830adc74787c1e2c0824032078a79f227fb
{
  "sources": [
    {
      "policy": [
        "oci::quay.io/enterprise-contract/ec-release-policy:latest"
      ],
      "data": [
        "git::https://github.com/enterprise-contract/ec-policies//example/data"
      ],
      "volatileConfig": {
        "include": [
          {
            "value": "java"
          },
          {
            "value": "test",
            "imageRef": "sha256:4e388ab32b10dc8dbc7e28144f552830adc74787c1e2c0824032078a79f227fb"
          }
        ]
      }
    }
  ]
}
In the example above, omitting the java entry would cause an error when verifying any image for which its reference is different than the one mentioned in the test package inclusion. This is because no rules will be executed for such images.

Examples

The examples here are shown as the contents of config.policy formatted as YAML for brevity and readability.

Note that you can omit fields where the default value is what you need.

Excluding rules from particular packages

This would include all rules except for rules from the two specified packages. All other rules would be included.

  • YAML

  • JSON

sources:
  - policy:
      - oci::quay.io/enterprise-contract/ec-release-policy:latest
    data:
      - git::https://github.com/enterprise-contract/ec-policies//example/data
    config:
      include:
        - "@minimal"
      exclude:
        - attestation_task_bundle
        - slsa_build_scripted_build
{
    "sources": [
        {
            "policy": ["oci::quay.io/enterprise-contract/ec-release-policy:latest"],
            "data": ["git::https://github.com/enterprise-contract/ec-policies//example/data"],
            "config": {
                "include": ["@minimal"],
                "exclude": ["attestation_task_bundle", "slsa_build_scripted_build"]
            }
        }
    ]
}

Including only rules from a particular package

This would include just the rules from the specified packages and exclude all other rules.

  • YAML

  • JSON

sources:
  - policy:
      - oci::quay.io/enterprise-contract/ec-release-policy:latest
    data:
      - git::https://github.com/enterprise-contract/ec-policies//example/data
    config:
      include:
        - test
        - java
{
    "sources": [
        {
            "policy": ["oci::quay.io/enterprise-contract/ec-release-policy:latest"],
            "data": ["git::https://github.com/enterprise-contract/ec-policies//example/data"],
            "config": {
                "include": ["test", "java"]
            }
        }
    ]
}

Excluding just one rule

This would include all rules except for the unacceptable_task_bundle rule in the attestation_task_bundle package. The other rules in the attestation_task_bundle would be included.

  • YAML

  • JSON

sources:
  - policy:
      - oci::quay.io/enterprise-contract/ec-release-policy:latest
    data:
      - git::https://github.com/enterprise-contract/ec-policies//example/data
    config:
      exclude:
        - attestation_task_bundle.unacceptable_task_bundle
{
    "sources": [
        {
            "policy": ["oci::quay.io/enterprise-contract/ec-release-policy:latest"],
            "data": ["git::https://github.com/enterprise-contract/ec-policies//example/data"],
            "config": {
                "exclude": ["attestation_task_bundle.unacceptable_task_bundle"]
            }
        }
    ]
}

Specifying that certain tests should be non-blocking

This example shows how to specify that the Enterprise Contract is allowed to pass even if certain tests failed or didn’t complete.

  • YAML

  • JSON

sources:
  - policy:
      - oci::quay.io/enterprise-contract/ec-release-policy:latest
    data:
      - git::https://github.com/enterprise-contract/ec-policies//example/data
    config:
      exclude:
        - test:get-clair-scan
        - test:clamav-scan
{
    "sources": [
        {
            "policy": ["oci::quay.io/enterprise-contract/ec-release-policy:latest"],
            "data": ["git::https://github.com/enterprise-contract/ec-policies//example/data"],
            "config": {
                "exclude": ["test:get-clair-scan", "test:clamav-scan"]
            }
        }
    ]
}

Including only some rules from a package

You can specify both include and exclude to pick out just the rules you want.

This example specifies that only the unacceptable_task_bundle rule from the attestation_task_bundle package should be included. The other rules in the attestation_task_bundle would be excluded.

Notice the higher specificity include rule takes precedence over the exclude rule in this example.

  • YAML

  • JSON

sources:
  - policy:
      - oci::quay.io/enterprise-contract/ec-release-policy:latest
    data:
      - git::https://github.com/enterprise-contract/ec-policies//example/data
    config:
      include:
        - *
        - attestation_task_bundle.unacceptable_task_bundle
      exclude:
        - attestation_task_bundle.*
{
    "sources": [
        {
            "policy": ["oci::quay.io/enterprise-contract/ec-release-policy:latest"],
            "data": ["git::https://github.com/enterprise-contract/ec-policies//example/data"],
            "config": {
                "include": ["*", "attestation_task_bundle.unacceptable_task_bundle"],
                "exclude": ["attestation_task_bundle.*"]
            }
        }
    ]
}

Data Sources

Some of the Enterprise Contract policy rules, defined in the ec-policies git repository, rely on certain data values when evaluated. For example, a policy rule exists to ensure all the parent container images used during the build process have been retrieved from an acceptable registry. The list of acceptable registries is a data value. This type of data is called Rule Data.

In addition to policy rules, the ec-policies git repository also defines values for Rule Data, see rule_data.yml . As a user, you can provide a custom data source with modified Rule Data allowing the same policy rules to be used to best fit your use cases.

There are different ways to create a custom data source. The simplest form is to copy the example/data directory of the ec-policies git repository to your own repository, and change the values of rule_data.yml. Then, simply provide your repo as a data source. For example:

  • YAML

  • JSON

sources:
  - policy:
      - git::https://github.com/enterprise-contract/ec-policies.git//policy
    data:
      - git::https://github.com/enterprise-contract/ec-policies//example/data
{
    "sources": [
        {
            "policy": ["git::https://github.com/enterprise-contract/ec-policies.git//policy"],
            "data": ["git::https://github.com/enterprise-contract/ec-policies//example/data"]
        }
    ]
}

It is also possible to provide an OPA bundle as a data source, for example:

  • YAML

  • JSON

sources:
  - policy:
      - git::https://github.com/enterprise-contract/ec-policies.git//policy
    data:
      - oci::quay.io/lucarval/policy-data:latest
{
  "sources": [
    {
      "policy": ["git::https://github.com/enterprise-contract/ec-policies.git//policy"],
      "data": ["oci::quay.io/lucarval/policy-data:latest"]
    }
  ]
}
If the data source contains policy rules, those will be ignored.
When providing a data source, you must provide the full set of required data values. The full set depends on which policy rules are included in your policy configuration. See examples at data/rule_data.yml.
It’s also possible to add an additional data source containing rule data defined under the rule_data_custom top level key. Data under this key will take precedence over data defined under the rule_data top level key. So, for example you could use the default data source and still define your own values for allowed_registry_prefixes by adding a second data source that includes a file such as:
  • YAML

  • JSON

sources:
  - policy:
      - git::https://github.com/enterprise-contract/ec-policies.git//policy
    data:
      - oci::quay.io/lucarval/policy-data:latest
    ruleData:
      rule_data_custom:
        allowed_registry_prefixes:
          - trusted-registry.io/trusted-images/
          - docker.io/acme-company/
{
  "sources": [
    {
      "policy": ["git::https://github.com/enterprise-contract/ec-policies.git//policy"],
      "data": ["oci::quay.io/lucarval/policy-data:latest"]
      "ruleData": {
        "rule_data_custom": {
          "allowed_registry_prefixes": [
            "trusted-registry.io/trusted-images/",
            "docker.io/acme-company/"
          ]
        }
      }
    }
  ]
}

Policy & Data Source URL formats

The policy and data fields in the configuration represent the URI of the policy and data sources, respectively. The following formats are supported:

Local File

A local file path scheme, such as the following, may be utilized.

You may also use the file:: prefix to specify a local file path.

  • file::<path>

In both formats the path can be absolute, if a leading / is included, or relative without a leading /, to the current working directory.

Examples:

Git Repository

A Git Hub or GitLab repository URL may be utilized:

  • github.com/<org>/<repo>.git?ref=<reference>//<path>

  • git@github.com:<org>/<repo>.git?ref=<reference>//<path>

gitlab can be used in place of github for GitLab repositories.

You may also use the git:: prefix to specify a Git repository URL. The following formats are supported:

  • git::git@example.com:<user>/<repo>.git?ref=<reference>//<path>

  • git::example.com/<org>/<repo>.git?ref=<reference>//<path>

In all git URL forms, the .git extension is optional.
In all git URL forms, the ?ref=<reference> is optional and defaults to the repository’s default branch.
In all git URL forms, the //<path> is optional and defaults to the root of the repository.

Examples:

  • github.com/enterprise-contract/ec-policies

  • github.com/enterprise-contract/ec-policies.git?ref=tag//path/to/data

  • git::git@example.com:enterprise-contract/ec-policies?ref=tag//example/data

HTTPS

An HTTPS URL may be utilized:

You may also use the http:: prefix to specify an HTTPS URL.

  • http::example.com/file.ext

All URLs must use secure transport.
The URL must be a direct link to the file.

OCI

An OCI registry URL may be utilized. The following registry hosts have automatic support:

  • azurecr.io

  • gcr.io

  • registry.gitlab.com

  • pkg.dev

  • [0-9]{12}.dkr.ecr.[a-z0-9-]*.amazonaws.com

  • quay.io

You may also use the oci:: prefix to specify an OCI registry URL:

  • oci://<registry>/<repository>:<tag>

  • oci://<registry>/<repository>@<digest>

  • oci::<registry>/<repository>:<tag>

  • oci::<registry>/<repository>:<tag>@<digest>

the <tag> is optional and defaults to latest. NOTE: the <digest> is optional and defaults to the latest digest.