= 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:

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

The configuration can be provided as a reference to a
xref:ecc:ROOT:reference.adoc[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:

[,bash]
----
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 following:

A "package name"::

Package names can be found in the policy documentation, for example the
xref:policy:ROOT:packages/release_attestation_type.adoc[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
xref:policy:ROOT:packages/release_attestation_type.adoc#attestation_type__known_attestation_type[Known attestation type found] rule
name is `attestation_type.known_attestation_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
xref:policy:ROOT:packages/release_test.adoc[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:

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - oci::quay.io/conforma/release-policy:latest
    data:
      - git::https://github.com/conforma/policy//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"
----
JSON::
+
[source,json]
----
{
  "sources": [
    {
      "policy": [
        "oci::quay.io/conforma/release-policy:latest"
      ],
      "data": [
        "git::https://github.com/conforma/policy//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:

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - oci::quay.io/conforma/release-policy:latest
    data:
      - git::https://github.com/conforma/policy//example/data
    volatileConfig:
      exclude:
        # Ignore violations from the `test` package for any image matching the digest.
        - value: test
          imageRef: sha256:4e388ab32b10dc8dbc7e28144f552830adc74787c1e2c0824032078a79f227fb
----
JSON::
+
[source,json]
----
{
  "sources": [
    {
      "policy": [
        "oci::quay.io/conforma/release-policy:latest"
      ],
      "data": [
        "git::https://github.com/conforma/policy//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.

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - oci::quay.io/conforma/release-policy:latest
    data:
      - git::https://github.com/conforma/policy//example/data
    volatileConfig:
      include:
        - value: java
        - value: test
          imageRef: sha256:4e388ab32b10dc8dbc7e28144f552830adc74787c1e2c0824032078a79f227fb
----
JSON::
+
[source,json]
----
{
  "sources": [
    {
      "policy": [
        "oci::quay.io/conforma/release-policy:latest"
      ],
      "data": [
        "git::https://github.com/conforma/policy//example/data"
      ],
      "volatileConfig": {
        "include": [
          {
            "value": "java"
          },
          {
            "value": "test",
            "imageRef": "sha256:4e388ab32b10dc8dbc7e28144f552830adc74787c1e2c0824032078a79f227fb"
          }
        ]
      }
    }
  ]
}
----
====

NOTE: 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.

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - oci::quay.io/conforma/release-policy:latest
    data:
      - git::https://github.com/conforma/policy//example/data
    config:
      include:
        - "@minimal"
      exclude:
        - attestation_type
        - slsa_build_scripted_build
----
JSON::
+
[source,json]
----
{
    "sources": [
        {
            "policy": ["oci::quay.io/conforma/release-policy:latest"],
            "data": ["git::https://github.com/conforma/policy//example/data"],
            "config": {
                "include": ["@minimal"],
                "exclude": ["attestation_type", "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.

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - oci::quay.io/conforma/release-policy:latest
    data:
      - git::https://github.com/conforma/policy//example/data
    config:
      include:
        - test
        - java
----
JSON::
+
[source,json]
----
{
    "sources": [
        {
            "policy": ["oci::quay.io/conforma/release-policy:latest"],
            "data": ["git::https://github.com/conforma/policy//example/data"],
            "config": {
                "include": ["test", "java"]
            }
        }
    ]
}
----
====

=== Excluding just one rule

This would include all rules except for the `pipelinerun_attestation_found` rule in
the `attestation_type` package. The other rules in the `attestation_type` would
be included.

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - oci::quay.io/conforma/release-policy:latest
    data:
      - git::https://github.com/conforma/policy//example/data
    config:
      exclude:
        - attestation_type.pipelinerun_attestation_found
----
JSON::
+
[source,json]
----
{
    "sources": [
        {
            "policy": ["oci::quay.io/conforma/release-policy:latest"],
            "data": ["git::https://github.com/conforma/policy//example/data"],
            "config": {
                "exclude": ["attestation_type.pipelinerun_attestation_found"]
            }
        }
    ]
}
----
====

=== Specifying that certain tests should be non-blocking

This example shows how to specify that a passing result should be produced
even if certain tests failed or didn't complete.

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - oci::quay.io/conforma/release-policy:latest
    data:
      - git::https://github.com/conforma/policy//example/data
    config:
      exclude:
        - test:get-clair-scan
        - test:clamav-scan
----
JSON::
+
[source,json]
----
{
    "sources": [
        {
            "policy": ["oci::quay.io/conforma/release-policy:latest"],
            "data": ["git::https://github.com/conforma/policy//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 `pipelinerun_attestation_found` rule from the
`attestation_type` package should be included. The other rules in the
`attestation_type` would be excluded.

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

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - oci::quay.io/conforma/release-policy:latest
    data:
      - git::https://github.com/conforma/policy//example/data
    config:
      include:
        - *
        - attestation_type.pipelinerun_attestation_found
      exclude:
        - attestation_type.*
----
JSON::
+
[source,json]
----
{
    "sources": [
        {
            "policy": ["oci::quay.io/conforma/release-policy:latest"],
            "data": ["git::https://github.com/conforma/policy//example/data"],
            "config": {
                "include": ["*", "attestation_type.pipelinerun_attestation_found"],
                "exclude": ["attestation_type.*"]
            }
        }
    ]
}
----
====

== Data Sources

Some of the Conforma policy rules, defined in the policy 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 policy git repository also defines values
for Rule Data, see
xref:policy:ROOT:attachment$rule_data.yml[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 policy 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:

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - git::https://github.com/conforma/policy.git//policy
    data:
      - git::https://github.com/conforma/policy//example/data
----
JSON::
+
[source,json]
----
{
    "sources": [
        {
            "policy": ["git::https://github.com/conforma/policy.git//policy"],
            "data": ["git::https://github.com/conforma/policy//example/data"]
        }
    ]
}
----
====

It is also possible to provide an link:https://www.conftest.dev/sharing/[OPA bundle]
as a data source, for example:

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - git::https://github.com/conforma/policy.git//policy
    data:
      - oci::quay.io/lucarval/policy-data:latest
----
JSON::
+
[source,json]
----
{
  "sources": [
    {
      "policy": ["git::https://github.com/conforma/policy.git//policy"],
      "data": ["oci::quay.io/lucarval/policy-data:latest"]
    }
  ]
}
----
====

NOTE: If the data source contains policy rules, those will be ignored.

NOTE: 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
xref:policy:ROOT:attachment$rule_data.yml[data/rule_data.yml].

NOTE: 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:

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - git::https://github.com/conforma/policy.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/
----
JSON::
+
[source,json]
----
{
  "sources": [
    {
      "policy": ["git::https://github.com/conforma/policy.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/"
          ]
        }
      }
    }
  ]
}
----
====
NOTE: It is possible to add multiple data sources.

[tabs]
====
YAML::
+
[source,yaml]
----
sources:
  - policy:
      - git::https://github.com/conforma/policy.git//policy
    data:
      - oci::quay.io/lucarval/policy-data:latest
      - oci::quay.io/lucarval/additional-policy-data:latest
    ruleData:
      rule_data_custom:
        allowed_registry_prefixes:
          - trusted-registry.io/trusted-images/
          - docker.io/acme-company/
----
JSON::
+
[source,json]
----
{
  "sources": [
    {
      "policy": ["git::https://github.com/conforma/policy.git//policy"],
      "data": [
        "oci::quay.io/lucarval/policy-data:latest",
        "oci::quay.io/lucarval/additional-policy-data:latest"
      ]
      "ruleData": {
        "rule_data_custom": {
          "allowed_registry_prefixes": [
            "trusted-registry.io/trusted-images/",
            "docker.io/acme-company/"
          ]
        }
      }
    }
  ]
}
----
====

WARNING: There must not be any duplicate entries under a top level key in the data sources. If there are, it will result in a merge error and failure.

NOTE: This example shows two data files, each from a different source, which would be valid

File 1:
[tabs]
====
YAML::
+
[source,yaml]
----
trusted_tasks:   
  git+https://github.com/konflux-ci/build-definitions.git//task/acs-deploy-check/0.1/acs-deploy-check.yaml:
    - effective_on: "2025-04-10T00:00:00Z"
      ref: 9f4fd8ca58128998e9a4ccce4bc1323f7e60fa23

----
====

File 2:
[tabs]
====
YAML::
+
[source,yaml]
----
trusted_tasks:   
  git+https://github.com/konflux-ci/build-definitions.git//task/acs-deploy-check/0.2/acs-deploy-check.yaml:
    - effective_on: "2025-04-10T00:00:00Z"
      ref: 6ab75f26ff7b66a01ddb20545adaada69ab4d3ab
----
====
This example is valid as the trusted task entries are unique, as one specifies the 0.1 version, while the other specifies the 0.2 version.

NOTE: This example shows two data files, each from a different source, which would be invalid

File 1:
[tabs]
====
YAML::
+
[source,yaml]
----
trusted_tasks:   
  git+https://github.com/konflux-ci/build-definitions.git//task/acs-deploy-check/0.1/acs-deploy-check.yaml:
    - effective_on: "2025-04-10T00:00:00Z"
      ref: 9f4fd8ca58128998e9a4ccce4bc1323f7e60fa23

----
====

File 2:
[tabs]
====
YAML::
+
[source,yaml]
----
trusted_tasks:   
  git+https://github.com/konflux-ci/build-definitions.git//task/acs-deploy-check/0.1/acs-deploy-check.yaml:
    - effective_on: "2025-03-20T00:00:00Z"
      expires_on: "2025-04-10T00:00:00Z"
      ref: 6ab75f26ff7b66a01ddb20545adaada69ab4d3ab
----
====
This example is invalid as the trusted task entries are not unique, as both specify the same URL for the task entry.

== 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.

* `file://<path>`

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

* `file::<path>`

NOTE: 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:///home/user/example/policy`
  - `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>`

NOTE: `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>`

NOTE: In all git URL forms, the `.git` extension is optional.

NOTE: In all git URL forms, the `?ref=<reference>` is optional and defaults to the repository's default branch.

NOTE: In all git URL forms, the `//<path>` is optional and defaults to the  root of the repository.

_Examples_:

  - `github.com/conforma/policy`
  - `github.com/conforma/policy.git?ref=tag//path/to/data`
  - `git::git@example.com:conforma/policy?ref=tag//example/data`

=== HTTPS

An HTTPS URL may be utilized:

* https://example.com/file.ext

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

* `http::example.com/file.ext`

NOTE: All URLs must use secure transport.

NOTE: 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>`

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