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.

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.

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

configuration:
  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
{
    "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/"
          ]
        }
      }
    }
  ]
}