Caution
This project is in an early preview state and contains experimental code. It is under active development and not ready for production use. Breaking changes are likely, and stability or security is not guaranteed. Use at your own risk.
This integrates OPA Gatekeeper's ExternalData feature with Artifact attestations to allow for policy evaluation based on image's signed SLSA build provenance.
Important
For this to work, OPA Gatekeeper must run with
enableExternalData=true
, which can be configured during
installation.
- mTLS between OPA Gatekeeper and the external data provider is not yet implemented, only server side TLS
- No offline mode exposed via the helm chart
The Artifact Attestations OPA Provider needs to have network access to:
- The OCI registry where the containers are stored, to be able to download the SLSA build provenance documents.
https://tuf-repo.github.com
to update and verify the trust root for GitHub's Sigstore instance.https://tuf-repo-cdn.sigstore.dev
to update and verify the trust root for Sigstore's public good instance (this can be disabled with the-no-public-good
flag)
Before the installation starts, these steps are required to prepare:
- How OPA Gatekeeper authenticates the OPA External Data Provider. This is done via regular TLS certificates, but they must be created and made available to the services.
- If private OCI registries are used, the authentication must be configured.
- Determine if you are executing within GitHub Enterprise with a
ghe.com
subdomain.
Currently there are two tested authentication methods known to work with private OCI registries:
- Using
imagePullSecrets
- Using Managed Identities with Azure Managed Kubernetes Service (AKS)
Although these are the only tested authentication methods, others may work (Azure using Sevice Principals, GKE and EKS configurations) as long as the POD/Service Accounts are configured properly.
To use imagePullSecrets
, prepare the secret in the namespace used by
the Artifact Attestations OPA Provider. The default name is
aa-login-secret
but can be changed if needed, just make sure to
update the value in values.yaml
before installing.
To use Azure Managed Identities, first configure the Managed Identity with the required permission (ACR Pull against the relevant registries), then configure a federated credential against the K8s cluster.
To enable the use of Azure Managed Identities, you must provide the
Managed Identity's Client ID: --set azureClientId=${AZURE_CLIENT_ID}
during helm install.
Note
Tested version of OPA Gatekeeper up to version 3.18.2 only supports RSA keys for the TLS certificates.
OPA Gatekeeper relies on TLS authentication when communicating with external data providers. There is a provided script to generate a self signed CA and TLS certificate. The certificate can be created via other means, as long as the private key can be mounted as a secret to the Artifact Attestations OPA Provider POD.
When installing the Artifacts Attestations OPA Provider, the CA certificate bundle must be provided to configure the root of trust.
The secret containing the TLS certificate and private key can be
automatically created, or created separately from the helm
installation. The secret must have the name provider-tls-cert
.
If you are running with an enterprise account with a custom ghe.com
subdomain, you need to configure this as a trust domain.
Run this command to find the trust domain needed:
$ TRUST_DOMAIN=`gh api meta --jq .domains.artifact_attestations.trust_domain`
then provide that value during helm install
: --set trustDomain=${TRUST_DOMAIN}
Important
When a custom domain is used, the issuer in the rego policy must
be updated too. The format of the issuer is
https://token.actions.${SUBDOMAIN}.ghe.com
.
$ helm install artifact-attestations-opa-provider charts/artifact-attestations-opa-provider \
--set provider.tls.caBundle="$(cat certs/ca.crt | base64 | tr -d '\n\r')" \
--set serverCert="$(cat certs/tls.crt | base64 | tr -d '\n\r')" \
--set serverKey="$(cat certs/tls.key | base64 | tr -d '\n\r')" \
--set imagePullSecrets=<name-of-your-secret> \
--namespace provider-system \
--create-namespace
$ helm install artifact-attestations-opa-provider charts/artifact-attestations-opa-provider \
--set provider.tls.caBundle="$(cat certs/ca.crt | base64 | tr -d '\n\r')" \
--set serverCert="$(cat certs/tls.crt | base64 | tr -d '\n\r')" \
--set serverKey="$(cat certs/tls.key | base64 | tr -d '\n\r')" \
--set azureClientId=${AZURE_CLIENT_ID} \
--namespace provider-system \
--create-namespace
$ helm install artifact-attestations-opa-provider charts/artifact-attestations-opa-provider \
--set provider.tls.caBundle="$(cat certs/ca.crt | base64 | tr -d '\n\r')" \
--set serverCert="" \
--set azureClientId=${AZURE_CLIENT_ID} \
--namespace provider-system \
--create-namespace
GitHub Artifact Attestations OPA provider is a regular OPA Gatekeeper external data provider.
It works by interacting with OCI registries to fetch Sigstore bundles containing attestations for the container to be deployed. The Artifact Attestations OPA provider will fetch the bundles, verify the cryptographic integrity, and if valid, return them to OPA Gatekeeper, where the data can be used during policy evaluation. This means only the cryptographic properties are verified within the Artifact Attestations OPA provider, the rego policy is evaluated by OPA Gatekeeper with normal constraint objects. In the constraint configuration is where affected resources and namespaces are configured.
Note
OPA Gatekeeper has a hard timeout on 3 seconds, which include the time for the external data provider. Be sure that you don't have unnecessary attestations stored in the OCI registry as it may impact the duration so that a timeout can occur.
sequenceDiagram
participant k8s as K8s
participant opag as OPA Gatekeeper
participant opadp as Artifact Attestations OPA Provider
participant ocir as OCI Registry
k8s->>opag: Admit OCI image ref?
opag->>opadp: Validate OCI image ref
opadp->>ocir: Fetch attestations for image ref
ocir->>opadp: Zero or more attestations
opadp->>opadp: Verify integrity and authenticity of attestations
opadp->>opag: Verified attestations
opag->>opag: Perform rego policy evaluation on attestations
opag->>k8s: Policy decision
Three examples are provided that can be used as references when building out the policy.
The policies are regular OPA Gatekeeper Constraints, where the enforcement action can be set, and the targeted/ignored resources.
When writing the policy using the provided examples, the organization
should be the name of the GitHub org, like octo-org
, and the
repository must include the org name like octo-org/octo-repo
.
The following three examples are provided:
- Verify image is built from a list of provided organizations.
- Verify image is built from a list of provided repositories.
- Verify image is originating from a list of organizations, and built with a reusable workflow from a list of provided repositories.
The examples are also defined in policies.rego with tests, and example data. An example policy for working with a custom attestation type is also provided.
Assuming the policy for verifying images originating from a specific repository is updated to contain the expected repositories, apply them to OPA Gatekeeper with the following command:
$ kubectl apply -f validation/from-repo-constraint-template.yaml
$ kubectl apply -f validation/from-repo-constraint.yaml
The GitHub Artifact Attestations OPA data provider provided Prometheus
metrics, exposed via http
at :9090/metrics
. The port can be
configured with the -metrics-port
flag (9090
is the default).
The metrics exposed beyond the default Prometheus metrics are:
aaop_attestations_retrieved_total
: the total number of attestations downloaded from the OCI registry.aaop_attestations_retrieved_failed
: the total number of failed attestations downloaded from the OCI registry.aaop_attestations_verified_ok
: the total number of verified attestations.aaop_attestations_verified_failed
: the total number of attestations that failed to verify.aaop_attestations_request_timer
: the duration in seconds for the validation webhook.aaop_attestations_retrieved_timer
: the duration in seconds for the time it takes to download the attestations from the OCI registry.aaop_attestations_verification_timer
: the duration in seconds for the time it takes to verify the retrieved attestations.
$ kubectl delete -f validation
$ helm uninstall artifact-attestations-opa-provider -n provider-system
This project is licensed under the terms of the MIT open source license. Please refer to the LICENSE for the full terms.