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:
-
If the name starts with "@" the returned score is exactly 10, e.g. "@collection". No further processing is done.
-
Add 1 if the name covers everything, i.e. "*"
-
Add 10 if the name specifies a package name, e.g. "release.test", "release.test.", "release.test.*", or "release.test.test_result_failures"
-
Add 100 if a term is used, e.g. "*:term", "release.test:clamav-scan" or "release.test.test_result_failures:clamav-scan"
-
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:
-
file::../example/policy
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.
|