Chapter 3. Creating a policy An Enterprise Contract policy is a rule or set of rules and Enterprise Contract-specific annotations. Enterprise Contract can perform several types of policy checks, including checking all of policy rules required for Red Hat products . Enterprise Contract uses the general purpose policy engine called Open Policy Agent, or OPA. OPA defines its policy rules in their own language, called Rego. This means that the policy rules from OPA that are in an Enterprise Contract policy are also defined in Rego. Procedure Create a Rego file to define a new policy rule, as in the following example: 1 The METADATA comment block- the first 10 lines of code, which are all preceded by hashtags (#)--is how rego specifies rules annotations so that Enterprise Contract can include those annotation details its successes and violations report. For more information about rego metadata and annotations, see Metadata . For more information about the annotations that Enterprise Contract policy rules must contain, see Rule annotations . 2 This single policy rule verifies that the builder.id in your new policy rule matches the builder.id in your Supply-chain Levels for Software Artifacts, or SLSA , provenance. 3 input is a Rego object that contains all of the information about your container image, its signature, and its attestations. The input.attestations attribute of the input object contains a list of attestations associated with the image. For more information about where and how Enterprise Contract defines input.attestations contents, refer to the Policy Input . Tip You can save the input object to a JSON file to view the available values, which is helpful in writing new policy rules. To save the input object as a JSON file named input.json , run a command similar to the following example: Create a policy configuration to use your new policy rule, as in the following example: echo " --- sources: - policy: - USD(pwd)/rules.rego " > policy.yaml Use your new policy to validate your container image, and to display additional information in the successes and violations report, as in the following example: Verification Check the Successes and violations report to make sure that your new rule is in the successes list. Additional resources For a set of useful Enterprise Contract policy rules, see the ec-policies GitHub repository. For more information about OPA and Rego, see OPA's Policy Language content. For more information about SLSA provenance, see SLSA Provenance . 3.1. Configuring a policy You can configure an Enterprise Contract policy with an inline JSON or YAML string. This policy, sometimes called a config or a contract , specifies where Enterprise Contract should find the rules and data to use to apply the policies you want to enforce. You can also include or exclude a single rule or a particular package of rules. Procedure Configure your policy in the command line as a JSON or YAML string, as in the following example: (Optional) Exclude a particular package of rules from your Enterprise Contract policy, as in the following example: This command includes every rule from every package except for the rules in the specified packages. (Optional) Exclude a single rule, as in the following example: This commands includes every rule from the attestation_task_bundle package except for the unacceptable_task_bundle rule. (Optional) Include rules from only a particular package, as in the following example: This command includes only the rules from the specified packages. (Optional) Include only some rules from a particular package. This means that you can specify both include and exclude to select only the rules you want your Enterprise Contract policy to include, as in the following example: 1 The asterisk (*) acts as a wildcard to match any package. Note that it does not match partial names, which means that, for example, you can't specify "s*" to match every package that starts with "s". These commands specify that you want to include only the unacceptable_task_bundle rule from the attestation_task_bundle package, and exclude all the other rules in that package. (Optional) Exclude certain checks so that Enterprise Contract can validate your container image even if those checks fail or don't complete, as in the following example: This command specifies that, if either of the identified checks fails or doesn't complete, Enterprise Contract can still finish to validate your container image. (Optional) Modify the defaults for rules in a package by running either the config.policy.include command or the config.policy.exclude command, along with a list of strings. Your list of strings should include one of the following: "package name" - Choose from the packages in the Available rule collections list. "rule name" - Specify a rule name by entering the name of the package and the rule code, separated by a dot (.), as in this example: attestation_type.unknown_att_type . You can find rule codes under "Attestation type" here . "package name:term" - Some policy rules process a list of items. When you add "term" to the "package name" string, you can exclude or include a particular item from that list. This works similarly to "package name," except that it applies only to policy rules in the package that match that term. For example, if you run the test package, you can choose to ignore a given test case but include all the others. "rule name:term" - This is similar to "package name:term" except that, instead of including or excluding an item from a package, you can include ot exclude a particular package policy rule . "@collection name" - Add this to your string to specify a predefined collection of rules. TMake sure you prefix the collection name with the @ symbol. Choose from the available rule collections here . Additional resources For a comprehensive list of release policy details, see Release Policy .

Commands:
echo 'package zero_to_hero import future.keywords.contains import future.keywords.if import future.keywords.in METADATA 1 title: Builder ID description: Verify the SLSA Provenance has the builder.id set to the expected value. custom: short_name: builder_id 2 failure_msg: The builder ID %q is not the expected %q solution: >- Ensure the correct build system was used to build the container image. deny contains result if { some attestation in input.attestations 3 attestation.statement.predicateType == "https://slsa.dev/provenance/v0.2" expected := "https://localhost/dummy-id" got := attestation.statement.predicate.builder.id expected != got result := { "code": "zero_to_hero.builder_id", "msg": sprintf("The builder ID %q is not expected, %q", [got, expected]) } } ' > rules.rego
ec validate image --public-key cosign.pub --image "USDREPOSITORY:latest" --policy policy.yaml --output policy-input=input.json
echo " --- sources: - policy: - USD(pwd)/rules.rego " > policy.yaml
ec validate image --public-key cosign.pub --image "USDREPOSITORY:latest" --policy policy.yaml --show-successes --info --output yaml
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"]} } ] }'
{ "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", "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": { "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": { "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": [ ""*"", 1 "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": { "exclude": [ "test:get-clair-scan", "test:clamav-scan" ] } } ] }