Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Builtin experiments #1463

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,7 @@ node_modules

# kustomize expanded Helm charts
hack/**/charts

# Some other stuff we don't want to check in
hack/builtin-experiments/data
hack/builtin-experiments/policy
24 changes: 14 additions & 10 deletions acceptance/examples/sigstore.rego
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package sigstore
import rego.v1

# METADATA
# title: Image validation
# description: Check image and attestation signatures
# custom:
# short_name: valid
deny contains result if {
Expand All @@ -16,66 +18,66 @@ _errors contains error if {
}

_errors contains error if {
not data.config.default_sigstore_opts
not _sigstore_opts
error := "default sigstore options not set"
}

_errors contains error if {
info := ec.sigstore.verify_image(_image_ref, data.config.default_sigstore_opts)
info := ec.sigstore.verify_image(_image_ref, _sigstore_opts)
some raw_error in info.errors
error := sprintf("image signature verification failed: %s", [raw_error])
}

_errors contains error if {
info := ec.sigstore.verify_image(_image_ref, data.config.default_sigstore_opts)
info := ec.sigstore.verify_image(_image_ref, _sigstore_opts)
count(info.signatures) == 0
error := "verification successful, but no image signatures found"
}

_errors contains error if {
info := ec.sigstore.verify_image(_image_ref, data.config.default_sigstore_opts)
info := ec.sigstore.verify_image(_image_ref, _sigstore_opts)
some sig in info.signatures
not valid_signature(sig)
error := sprintf("not a valid image signature: %s", [sig])
}

_errors contains error if {
info := ec.sigstore.verify_attestation(_image_ref, data.config.default_sigstore_opts)
info := ec.sigstore.verify_attestation(_image_ref, _sigstore_opts)
some raw_error in info.errors
error := sprintf("image attestation verification failed: %s", [raw_error])
}

_errors contains error if {
info := ec.sigstore.verify_attestation(_image_ref, data.config.default_sigstore_opts)
info := ec.sigstore.verify_attestation(_image_ref, _sigstore_opts)
count(info.attestations) == 0
error := "verification successful, but no attestations found"
}

_errors contains error if {
info := ec.sigstore.verify_attestation(_image_ref, data.config.default_sigstore_opts)
info := ec.sigstore.verify_attestation(_image_ref, _sigstore_opts)
some att in info.attestations
count(att.signatures) == 0
error := sprintf("attestation has no signatures: %s", [att])
}

_errors contains error if {
info := ec.sigstore.verify_attestation(_image_ref, data.config.default_sigstore_opts)
info := ec.sigstore.verify_attestation(_image_ref, _sigstore_opts)
some att in info.attestations
some sig in att.signatures
not valid_signature(sig)
error := sprintf("not a valid attestation signature: %s", [sig])
}

_errors contains error if {
info := ec.sigstore.verify_attestation(_image_ref, data.config.default_sigstore_opts)
info := ec.sigstore.verify_attestation(_image_ref, _sigstore_opts)
some att in info.attestations

att.statement.predicateType != "https://slsa.dev/provenance/v0.2"
error := sprintf("unexpected statement predicate: %s", [att.statement.predicateType])
}

_errors contains error if {
info := ec.sigstore.verify_attestation(_image_ref, data.config.default_sigstore_opts)
info := ec.sigstore.verify_attestation(_image_ref, _sigstore_opts)
some att in info.attestations
builder_id := _builder_id(att)
builder_id != "https://tekton.dev/chains/v2"
Expand All @@ -84,6 +86,8 @@ _errors contains error if {

_image_ref := input.image.ref

_sigstore_opts := data.config.default_sigstore_opts

valid_signature(sig) if {
type_name(sig.keyid) == "string"
type_name(sig.signature) == "string"
Expand Down
105 changes: 105 additions & 0 deletions hack/builtin-experiments/demo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/bin/env bash
# Copyright The Enterprise Contract Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth adding a comment to explain what this experiment is.

GIT_ROOT=$(git rev-parse --show-toplevel)
EC=${EC:-"${GIT_ROOT}/dist/ec"}
LOCAL_DIR=${GIT_ROOT}/hack/builtin-experiments
DATA_DIR=${LOCAL_DIR}/data/data
POLICY_DIR=${LOCAL_DIR}/policy/policy

mkdir -p ${DATA_DIR} ${POLICY_DIR}

# This has no attestation currently...
#IMAGE=${IMAGE:-"quay.io/redhat-appstudio/ec-golden-image:latest"}

# This is the ec build for TAS so it should be good 🐕🥣
IMAGE=${IMAGE:-"quay.io/redhat-user-workloads/rhtap-contract-tenant/ec-v02/cli-v02:c862b0f77bb10082d1440e0d4b6a4e9645b83382"}

# The image digest must be specified explictly so go look it up
IMAGE_DIGEST=$(skopeo inspect --no-tags docker://$IMAGE | jq -r .Digest)
FULL_IMAGE_REF="$IMAGE@$IMAGE_DIGEST"

# Input looks like this
INPUT_JSON='{
"image": {
"ref": "'$FULL_IMAGE_REF'"
}
}'

# A minimal ECP using local files
# ec looks for specific subdirs under the source's root location
# so that's why we have policy/policy and data/data
POLICY_YAML='
sources:
- policy:
- '$POLICY_DIR'
- github.com/simonbaird/ec-policies//policy/lib?ref=builtin-experiments
- github.com/simonbaird/ec-policies//policy/release?ref=builtin-experiments

data:
- '$DATA_DIR'
- oci::quay.io/redhat-appstudio-tekton-catalog/data-acceptable-bundles:latest
- github.com/release-engineering/rhtap-ec-policy//data

config:
include:
# Fixme: I dont think it is running the sigstore check sin sigstore.rego
# now, not sure why
- "sigstore"
- "@slsa3"
'

# Public key for the signature of the image we're verifying
PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA
naYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==
-----END PUBLIC KEY-----"

# Hack hack...
echo '{
"sigstore_opts": {
"ignore_rekor": true,
"public_key": "'${PUBLIC_KEY//$'\n'/\\n}'"
}
}' > ${DATA_DIR}/sigstore_opts.json

# The acceptance test rego is pretty much prod-ready.. :)
# Tweak one line to make it work with the sigstore_opts data we just created above
sed \
-e 's/^_sigstore_opts :=.*/_sigstore_opts := object.union(data.config.default_sigstore_opts, data.sigstore_opts)/' \
-e 's/^package sigstore/package policy.release.sigstore/' \
${GIT_ROOT}/acceptance/examples/sigstore.rego \
> ${POLICY_DIR}/sigstore.rego

echo -e "\n* Input:\n"
echo "$INPUT_JSON" | yq -P

echo -e "\n* EC results:\n"
$EC validate input \
--file <(echo $INPUT_JSON) \
--policy "$(echo "$POLICY_YAML" | yq -ojson)" \
--show-successes \
| yq -P

# For debugging...
#echo "$INPUT_JSON" > i.json
#ec opa eval \
# --input i.json \
# 'data.lib._input_attestations' \
# --data ${DATA_DIR} \
# --data /home/sbaird/code/ec-policies/policy/lib \
# --data /home/sbaird/code/ec-policies/policy/release | yq -P
Loading