Using the Enterprise Contract command line

Installation

Downloading a binary

Visit the releases page, scroll and expand "Assets". Find the appropriate binary for your system, download it and copy it to somewhere in your path.

For example:

$ curl -sLO https://github.com/enterprise-contract/ec-cli/releases/download/snapshot/ec_linux_amd64
$ chmod 755 ec_linux_amd64
$ sudo mv ec_linux_amd64 /usr/local/bin/ec
$ ec version
$ ec --help

Running with docker or podman

If you have docker or podman installed you can also run ec like this:

$ docker pull quay.io/enterprise-contract/ec-cli:snapshot
$ docker run quay.io/enterprise-contract/ec-cli:snapshot

Substitute podman for docker in the above command if you’re using podman. For convenience you could create an alias. For example:

$ alias ec="docker run quay.io/enterprise-contract/ec-cli:snapshot"
$ ec version
$ ec --help
There might be some extra work needed to mount files inside the container, for example, if your public key is in a file, you would need to mount it when running docker.
$ docker run -v ./key.pub:/tmp/key.pub:Z quay.io/enterprise-contract/ec-cli:snapshot validate image ...

Compiling from source

To compile ec from source:

$ git clone git@github.com:enterprise-contract/ec-cli.git
$ cd ec-cli
$ make build
$ sudo cp dist/ec_linux_amd64 /usr/local/bin/ec
$ ec version
$ ec --help

Validating an image

To run ec against a particular container image built by Konflux, we use the ec validate image command. To see the command options you can use the --help flag, e.g.:

$ ec validate image --help

When validating an image we need to provide three things:

  • The image reference

  • The public key for verifying signatures

  • A policy configuration file which determines what policies are to be applied

For these examples I’m going to use a particular image with a known signing key.

Actually the public key can be provided via the policy configuration, but for these examples we’ll provide it separately using the --public-key flag.

For the sake of more readable examples, let’s create some environment variables and some files for the three pieces of information. For the policy.yaml we’ll download one of the predefined examples.

$ export IMAGE="quay.io/redhat-appstudio/ec-golden-image:latest"

$ echo '-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA
naYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==
-----END PUBLIC KEY-----' > key.pub

$ wget -q https://github.com/enterprise-contract/config/raw/main/slsa3/policy.yaml

Now we can run the ec like this:

$ ec validate image --image "$IMAGE" --public-key key.pub --policy policy.yaml --ignore-rekor --output yaml

NOTE:The image used in this example was signed and attested without using Rekor. This is why the --ignore-rekor flag is needed. You may not need this if you’re using a different image

Finding the public key

If you’ve run EC at least once using an integration test, as described in Getting started…​, the public key is visible in the logs for the pipeline run.

In the future there should be a better way to find the public key file for the signing secret used by Tekton Chains in the Konflux build system.

You can now modify the policy.yaml file and re-run the ec validate image command to try different policy configurations. See the configuration docs for more information on the policy.yaml file, or take a look at the examples here.

Validating arbitrary inputs

The ec validate input command line can be be used to validate arbitrary structured data, specifically in JSON or YAML formats. The subcommand ec validate input allows for checking the compliance of arbitrary number of files, provided via --file parameter, to a set policy, provided via --policy parameter.

For example let’s consider a YAML file containing a set of sign-offs for a release, and a policy mandating that a release must be signed-off by at least two persons from each relevant department.

data.yaml - the data for validation
---
image: registry.io/repository/image:tag  # the image that is signed-off on
quality_assurance:  # QA sign-offs
  - Elena Harper
  - Calvin Bean
product_development:  # product sign-offs
  - Lennon Bradford
  - Kate Levy
engineering:  # engineering sign-offs
  - Zayn Simmons
policy.yaml - the policy configuration
description: ACME & co sign-off policy
sources:
  - name: default-sign-off
    policy:
      - "git::https://github.com/acme/policy.git//policy?ref=prod"
signoff.rego - the policy rules in the github.com/acme/policy.git repository at policy/signoff.rego
#
# METADATA
# title: ACME & co Sign-off policy
# description: >-
#   Mandates the compliance of sign-offs within ACME & co
#
package signoff

import rego.v1

# METADATA
# title: Each department needs to provide two sign-offs
# description: >-
#   Makes sure that each relevant department provided two sign-offs
# custom:
#   short_name: two_signoffs
#
deny contains result if {
	some department in {"quality_assurance", "product_development", "engineering"}
	count(input[department]) < 2
	result := sprintf("Missing required sign-offs from the %s department", [department])
}

With this, running the CLI shows that there is a policy violation, one sign-off from the engineering department is missing:

$ ec validate input --file data.yaml --policy policy.yaml --output yaml
ec-version: v0.4.2
effective-time: "2024-04-25T11:07:35.025505232Z"
filepaths:
- filepath: data.yaml
  success: false
  success-count: 1
  successes: null
  violations:
  - msg: Missing required sign-offs from the engineering department
  warnings: []
policy:
  description: ACME & co sign-off policy
  sources:
  - name: default-sign-off
    policy:
    - git::https://github.com/acme/policy.git//policy?ref=prod
success: false
Error: success criteria not met

Validating policy configuration

As a convention, the policy_data collection includes rules that check the conformance of rule data. When customizing the rule data this can be used to validate that the data is well formed.

For this a policy as in the following example can be used:

policy.yaml - policy validating the rule data
description: Custom rule data validation
sources:
  - policy:
      - github.com/enterprise-contract/ec-policies//policy/lib
      - github.com/enterprise-contract/ec-policies//policy/release
    data:
      - /path/to/rule_data.yml
      - /path/to/required_tasks.yml
    config:
      include:
        - '@policy_data'

Given that the policy already includes all the data needed for the validation no input needs to be provided on the ec validate input command, an empty input can be provided for the --file parameter with: --file='{}'.