Skip to main content

Valint Gatekeeper Provider

Valint Gatekeeper Provider seamlessly integrates with OPA Gatekeeper's ExternalData feature to facilitate policy verification within your supply chain. This integration enables you to enforce a variety of supply chain policies, including signed image verification and various SDLC (Software Development Life Cycle) policies.

The Valint Gatekeeper Provider offers a means to enforce or generate alerts for any violations or successful policy evaluations based on evidence collected from the supply chain, whether signed or unsigned (or any combination thereof).

Policy As Code

Our policies, expressed in code, offer extensive customization options and can be tailored to suit specific needs.

For more detailed information, please visit our page on enforcing SDLC policies or refer to our policy reference guide.

Additionally, you have the option to reference or fork our default policy bundle repository.

Use Cases Examples

Use CaseDescription
Enforcing Image SigningEnsure that all images deployed to the production environment are signed and have a matching CycloneDX SBOM.
Enforcing Build pipeline vulnerability scannerVerify that the image build pipeline executes a vulnerability scanner with no critical CVEs.
Enforcing image built by CIVerify that images are built using continuous integration (CI) processes.
Enforcing SLSA Level 2Verify that images are built using CI and produce signed SLSA provenance.
Restricted Builder Dependency ManagementRestrict the use of banned builder dependencies during the build process.
Continuous Compliance MonitoringMonitor compliance with branch protection rules and push rules in Git repositories.
Vulnerability Assessment for InfrastructureDetect misconfigurations or vulnerabilities in Kubernetes clusters or Docker images.
License Compliance EnforcementEnsure that software artifacts comply with licensing policies and do not include banned licenses.
Deployment Environment ValidationValidate that deployment environments meet specified security and configuration standards.
Rollout VerificationVerify that deployments adhere to rollout strategies and policies, such as canary or blue-green deployments.
Dependency Version ControlControl the versioning and usage of dependencies in deployed applications to prevent security risks.
Configuration ConsistencyEnsure consistency in configuration settings across deployed instances to prevent misconfigurations.
Resource Utilization ManagementMonitor and manage resource usage during deployment to optimize performance and cost-effectiveness.

Installation

Step 1: Installing Gatekeeper

  • Deploy Gatekeeper with external data enabled (--enable-external-data)
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo update
helm install gatekeeper/gatekeeper \
--name-template=gatekeeper \
--namespace gatekeeper-system --create-namespace \
--set enableExternalData=true \
--set controllerManager.dnsPolicy=ClusterFirst,audit.dnsPolicy=ClusterFirst \
--set validatingWebhookTimeoutSeconds=30

Notice enableExternalData is set as true.

Ensure that the version you have is newer than 3.15.0.

Step 2: Pull Valint Gatekeeper helm Repo

Pull valint gatekeeper Helm chart

helm repo add scribe https://scribe-security.github.io/gatekeeper-valint
helm repo update

Step 3: Generate TLS certificate and key for the provider

Gatekeeper enforces TLS when communicating with the provider, so certificates must be provided. For more details see Gatekeepers TLS support.

  1. To generate new certificates, use may use the quick-start generate-tls-cert script:
curl -sSfL https://raw.githubusercontent.com/scribe-security/gatekeeper-valint/main/scripts/generate-tls-cert.sh | bash
  1. This will create CA and certificate files in certs directory.

Step 4: Installing Provider with Scribe Evidence store

Scribe evidence store allows you store evidence using scribe Service.

Alternatively, you can explore the OCI-supported alternative evidence stores.

Before you begin

Integrating Scribe Hub with admission controller requires the following credentials that are found in the Integrations page. (In your Scribe Hub go to integrations)

  • Client Secret
Scribe Integration Secrets

Enable Scribe client and add related Client Secret.

helm install scribe/gatekeeper-valint --name-template=gatekeeper-valint \
--namespace gatekeeper-valint --create-namespace \
--set certs.caBundle=$(cat certs/ca.crt | base64 | tr -d '\n') \
--set certs.tlsCrt="$(cat certs/tls.crt)" \
--set certs.tlsKey="$(cat certs/tls.key)" \
--set scribe.client_secret=$SCRIBE_TOKEN

Credentials will be stored as a secret named valint-scribe-cred-secret.

Tls cert and key are stored as a secret named gatekeeper-valint-certs

Verifying signed evidence

By default, the verification uses Sigstore Keyless signatures. However, you have the option to switch to X509 certificates if needed. In your policies you then can set what rules should be verified over signed evidence by setting the signed field.

- uses: <some_rule>
with:
signed: true

Signing evidence

You can sign image SBOMs or any other type of evidence using Valint. For more information see attestation page.

X509-based Signatures

To enable the provider to verify X509-based signatures, follow these steps:

  • Set the x509.ca field to specify the CA chain to verify against.
  • Set the valint.attest.default to default to x509-env.

For example, to perform an upgrade with X509-based verification:

helm upgrade gatekeeper-valint scribe/gatekeeper-valint \
--namespace gatekeeper-valint \
--reuse-values --force \
--set valint.attest.default=x509-env \
--set x509.ca="$(cat certs/evidence.crt)"

Certificate is mapped to valint-x509-secret secret.

Please replace the evidence.key and evidence.crt generated by our scripts/generate-tls-cert.sh with your own organization's trusted CA.

signing with valint
# Signing a image
valint <bom, slsa> <target> -o attest --attest.default <x509,x509-env> \
--key <key path/env/url> \
--cert <cert path/env/url> \
--ca <ca-chain path/env/url> [FLAGS]

# Signing third party evidence
valint evidence som_evidence.json -o attest --attest.default <x509,x509-env> \
--key <key path/env/url> \
--cert <cert path/env/url> \
--ca <ca-chain path/env/url> [FLAGS]

# Verifing a image
valint verify <target> -i <attest, attest-slsa, attest-generic> --attest.default <x509,x509-env> \
--ca <cert path/env/url> \
--crl <crl path/env/url> [FLAGS]

For more information see attestation page.

Sigstore Keyless Signatures

To enable the provider to verify Sigstore Keyless signatures, set the valint.attest.default field to default to sigstore.

For example, to perform an upgrade with sigstore-based verification:

helm upgrade gatekeeper-valint scribe/gatekeeper-valint \
--namespace gatekeeper-valint \
--reuse-values --force \
--set valint.attest.default=sigstore
signing with valint
# Signing a image
valint <bom, slsa> <target> -o attest [FLAGS]

# Signing third party evidence
valint evidence som_evidence.json -o attest [FLAGS]

# Verifing a image
valint verify <target> -i <attest, attest-slsa, attest-generic> [FLAGS]

For more information see attestation page.

Demo: Enforcing Image Sigstore Signing Policies Over Scribe store

To showcase the enforcement of image signing policies using Gatekeeper Valint, we'll apply a simplistic unsigned image error policy and upgrade our gate accordingly.

Upgrade your gate with the following command,

helm upgrade gatekeeper-valint scribe/gatekeeper-valint \
--values signed_image_policy.yaml \
--namespace gatekeeper-valint \
--reuse-values --force
signed_image_policy.yaml file
select:
gate: signed_images_gate
apply:
- namespace: "" # Any
glob:
- "my_company/**"
filter-by:
- target
policy:
name: require_signed_images
rules:
- name: error_on_unsigned_image
uses: sbom/artifact-signed@v1
level: error

In the provided signed_image_policy.yaml, we specify a policy to enforce signature verification for images admitted from the my_company Dockerhub account.

Now lets try and apply deployments before signing the image.

kubectl apply -f signed-deployment.yaml 2>&1 | echo -e "$(cat -)"
signed-deployment.yaml file
apiVersion: apps/v1
kind: Deployment
metadata:
name: signed-deployment
labels:
app: signed-deployment
spec:
replicas: 0 # testing purposes only
selector:
matchLabels:
app: signed-deployment
template:
metadata:
labels:
app: signed-deployment
spec:
containers:
- name: valid
image: my_company/signed:latest

In the output, you should see a rejected admission error due to the unsigned image SBOM.

Error from server (Forbidden): error when creating "policy/examples/signed-deployment.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [gatekeeper-valint] image not accepted: {"errors": [], "responses": [], "status_code": 200, "system_error": "
Scribe Admission refused 'scribesecurity/signed:latest' deployment to 'default'.

- policy check failed, Policies [require_signed_images] failed with the following errors.
* rule [error_on_unsigned_image] failed resource not found, no evidence found
"}

To resolve this, sign your image SBOM using the Valint tool:

valint bom my_company/signed:latest -o attest  --product-key scribesecurity/signed:latest [FLAGS]

Then, re-apply the deployment:

kubectl apply -f signed-deployment.yaml

Upon successful deployment, you'll see a detailed evaluation summary in the admission logs, providing insights into the policy checks performed and their outcomes.

[2024-03-11 10:05:27]  INFO Target 'my_company/signed:latest' results
[2024-03-11 10:05:27] INFO Policy "require_signed_images" Evaluation Summary:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Policy "require_signed_images" Evaluation Summary │
├─────────────────────────┬────────┬────────────────────────┬───────────────────┬────────────────────────────────────────────┤
│ RULE NAME │ SIGNED │ SIGNATURE VERIFICATION │ POLICY EVALUATION │ COMMENT │
├─────────────────────────┼────────┼────────────────────────┼───────────────────┼────────────────────────────────────────────┤
│ error_on_unsigned_image │ true │ passed │ │ 1/1 evidence origin and signature verified │
├─────────────────────────┼────────┼────────────────────────┼───────────────────┼────────────────────────────────────────────┤
│ AGGREGATE POLICY RESULT │ │ │ PASSED │ │
└─────────────────────────┴────────┴────────────────────────┴───────────────────┴────────────────────────────────────────────┘

Finally, if you consult the management console, you'll be able to view both the unsuccessful and successful outcomes of the policy.

Policy Results view
Policy Result Context
Context Details view

Policy Gate

The Gate Policies in Valint Gatekeeper Provider allow for fine-grained control over policy evaluation for images admitted into the system.

Gate Configuration options

select:
gate: default_gate # Requried
apply:
- namespace: <string> # Optional
glob: <string> # Optional
filter-by: <string> # Optional
product-key: <string> # Optional
policy: <object> # Reuquired
  • gate: Specifies the gate name.
  • apply: list of policies to apply
  • namespace: Specifies the namespace to which the policy should apply to.
  • glob: Defines the image reference pattern to which the policy is applied to.
  • filter-by: Determines the scope of the policy evaluation. Supported options include:
    • target: Evaluate policies scoped by the admission imageID.
    • pipeline: Evaluate policies scoped by the image build pipeline.
    • product-key: Evaluate policies scoped by a specific product.
  • policy: Set policy to evaluate, for more details see enforcing SDLC policies or refer to our policy reference guide.

policy gate configuration are mapped to a configmap named gatekeeper-valint-policies.

Defining Namespace for Gatekeeper Constraints

Setting Gatekeeper Constraints Namespace To set the namespace for gatekeeper constraints, please configure the set constraint.namespace fields. The distinction from setting the policy gate namespace is that API calls will only be triggered for constraint.namespace.

For example, to perform an upgrade to your policy gate:

helm upgrade gatekeeper-valint scribe/gatekeeper-valint \
--set constraint.namespace=my_namespace \
--namespace gatekeeper-valint \
--reuse-values --force

Updating Your Policy Gate

For example, to perform an upgrade to your policy gate:

helm upgrade gatekeeper-valint scribe/gatekeeper-valint \
--values my_gate.yaml \
--namespace gatekeeper-valint \
--reuse-values --force

In the my_gate.yaml file, you can specify policy rules like this:

select:
gate: my_gate
apply:
- namespace: "some_namespace"
glob:
- "**"
filter-by:
- target
policy:
name: cluster-policy
rules:
- name: fresh-image
uses: images/fresh-image@v1
level: warning
with:
max_days: 356

Filter-By Options

The filter-by field allows you to specify the scope of the policy evaluation. Below are the available options:

Target Evaluation

Option available for both scribe and OCI stores.

The target option evaluates policies based on the imageID for admission. This allows you to run policies directly on the images themselves.

select:
gate: image_gate
apply:
- namespace: ""
glob:
- "**"
filter-by:
- target
policy:
name: cluster-policy
rules:
- name: fresh-image
uses: images/fresh-image@v1
level: warning
with:
max_days: 356

This policy aims to ensure that images admitted into the system are fresh, defined as being built within the last year. The fresh-image rule is applied with a warning level severity.

Pipeline Evaluation

Option only available when using scribe store.

The pipeline option evaluates policies based on the image build runID and workflow. This allows you to run policies related to the image build pipeline.

select:
gate: pipeline_gate
apply:
- namespace: ""
glob:
- "my_company/**"
filter-by:
- pipeline
policy:
name: pipeline-scanners
rules:
- name: check-vulnerabilities
uses: sarif/verify-sarif@v1
evidence:
tool: "Trivy Vulnerability Scanner"
with:
rule_level:
- critical

The policy named pipeline-scanners is applied, which requires that images admitted from the my_company Dockerhub repository undergo vulnerability scanning using Trivy. The check-vulnerabilities rule is defined within this policy, configured to check for any critical vulnerabilities in the image. If critical vulnerabilities are detected, the policy will trigger a violation, indicating a failure.

For CI integrations see CI integration

Collecting evidence in pipeline

For all our CI integration, the relevant fields are automatically set by our CI integration.

However, if you need to mock this locally, you can manually set the RUN_ID and WORKFLOW fields while collecting evidence. Once set, you can proceed to collect your scanner report and attach it as evidence in the pipeline.

# Create evidence in the pipeline
RUN_ID=44 WORKFLOW=my_workflow.yaml valint bom busybox:latest [FLAGS]

# Generate a third-party report
trivy image --format sarif -o report.sarif busybox:latest

# Attach the third-party SARIF report as evidence in the pipeline
RUN_ID=44 WORKFLOW=my_workflow.yaml valint evidence report.sarif [FLAGS]

Product Evaluation

Option only available when using scribe store.

The product option evaluates policies based on the product, allowing you to verify critical aspects of the product evidence associated with the image.

select:
gate: product_gate
apply:
- namespace: ""
glob:
- "**"
product-key: my-product
filter-by:
- product
policy:
name: pipeline-scanners
rules:
- name: check-vulnerabilities
uses: sarif/verify-sarif@v1
evidence:
tool: "Trivy Vulnerability Scanner"
with:
rule_level:
- critical

In this example, the pipeline-scanners policy is applied to evaluate images associated with the my-product. Specifically checking for vulnerabilities using the Trivy Vulnerability Scanner. This ensures that product undergo thorough vulnerability assessment.

Collecting evidence in product

To attach evidence to a product, use the product-key and product-version flags. Then, collect your scanner report and attach it as evidence in the product.

# Create evidence in the pipeline
# Create evidence in the product
valint bom busybox:latest --product-key my_product --product-version v1 [FLAGS]

# Generate a third-party report
trivy image --format sarif -o report.sarif busybox:latest

# Attach the third-party SARIF report as evidence in the product
valint evidence report.sarif --product-key my_product --product-version v1 [FLAGS]

Policy results

Policy results are generated individually for each image evaluation, delivered in Sarif format as evidence. For further details, please refer to the policy results page.

Admission Policy Results Context is attached with resource identification, including labels and namespaces, of the Kubernetes resources that were admitted, along with information about the admission provider.

Signing policy result

Currently, signing policy results are only supported when using X509 keys. To set this up:

  • Set the x509.key field to specify the policy result signer key. It must be under the same CA the evidence is verified in.

For example, to perform an upgrade with X509-based signing:

helm upgrade gatekeeper-valint scribe/gatekeeper-valint \
--namespace gatekeeper-valint \
--reuse-values --force \
--set valint.attest.default=x509-env \
--set valint.verify.formats=attest \
--set x509.ca="$(cat certs/ca.crt)"
--set x509.key="$(cat certs/evidence.key)"

Secret is stored under a secret named valint-x509-secret.

Please replace the keys and certificates generated by our scripts/generate-tls-cert.sh for evidence signing and verification with your organization's trusted CA.

Default Policy - Unsigned Image Warning

By default, the provider is installed with a policy to warn on ANY image that is not signed. This serves as a basic security measure to alert users about potentially risky, unsigned images.

Default policy:

select:
gate: default_gate
apply:
- namespace: "" # Any
glob:
- "**" # Any
filter-by:
- target
Policy-bundle: default-provider-policy@v1 <=
policy:
name: default-provider-policy
rules:
- name: warn_on_unsigned_image
uses: sbom/artifact-signed@v1
level: "warning"

To pass the evaluation, you can sign your images using the valint tool, like so:

valint [bom,slsa] some_image -o attest [FLAGS]

By default, the provider utilizes Sigstore verification. However, you have the option to configure the provider to use X509-based signatures instead. For configuration instructions, please refer to the respective sections on X509-based signatures or Sigstore.

Private registries

To verify images from registries that require authentication, follow these steps:

  • Set the image.imagePullSecrets field with base64 docker config.

For example, to perform an upgrade with your local docker config:

helm upgrade scribe/gatekeeper-valint \
--namespace gatekeeper-valint \
--reuse-values --force \
--set image.imagePullSecrets="$(cat ~/.docker/config.json | base64 | tr -d '\n')"

Secret created should follow the following pattern

apiVersion: v1
kind: Secret
metadata:
name: valint-image-pull-secret
namespace: gatekeeper-valint
data:
.dockerconfigjson: ewoJImF1...g==
type: kubernetes.io/dockerconfigjson

Private Policy Bundles

By default policeis are pulled from our default policy bundle. To use private bundles from your preferred Git platform, follow these steps:

  • Set the image.bundlePullSecrets with read access token to bundle git repository.
  • Set valint.attest.bundle with your required bundle details.
  • Optionaly set valint.git.branch or valint.git.tag to set the bundle git refrence to pull.

For example, to perform an upgrade with your local docker config:

helm upgrade scribe/gatekeeper-valint \
--namespace gatekeeper-valint \
--reuse-values --force \
--set valint.attest.bundle=https://github.com/my_company/policies.git
--set image.bundlePullSecrets="ghp_****"

Secret is stored under a secret named valint-bundle-pull-secret.

Uploading signed evidence

Using valint -o attest flag you can upload signed evidence on the image.

valint [bom, slsa] my_image -o attest [--oci]

Alterative Evidence Stores

Valint supports both storage and verification flows for attestations and statement objects using an *OCI registry as an evidence store.
Using OCI registry as an evidence store allows you to upload and verify evidence across your supply chain in a seamless manner.

Related configmap flags:

  • valint.attest.cocosign.storer.OCI.enable - Enable OCI store.
  • valint.attest.cocosign.storer.OCI.repo - Evidence store location.

Before you begin

To guarantee access requirements for the Provider, you need to provide an Image Pull secret with the following permissions:

  • Read access to download evidence for the provider.
  • Write access to upload policy report evidence for the provider.

Can be skipped when valint.attest.report.disable is set to true

Access requirement for Evidence creation (CI or local)

  • Write access to upload evidence using the valint tool.

Install the provider with the following command:

helm install scribe/gatekeeper-valint --name-template=gatekeeper-valint \
--namespace gatekeeper-valint --create-namespace \
--set certs.caBundle=$(cat certs/ca.crt | base64 | tr -d '\n') \
--set certs.tlsCrt="$(cat certs/tls.crt)" \
--set certs.tlsKey="$(cat certs/tls.key)" \
--set valint.attest.report.disable=true \
--set image.imagePullSecrets="$(cat ~/.docker/config.json | base64 | tr -d '\n')" \
--set valint.attest.cocosign.storer.OCI.enable=true \
--set valint.attest.cocosign.storer.OCI.repo=[oci-repo]"

[oci-repo] is the URL of the OCI repository where all evidence will be uploaded.

  • Example: If your oci repo is somewhere/evidence_store create a evidence for example/my_image:latest, the evidence will be stored as under somewhere/evidence_store/image/SHA-256-DIGEST.sig

Cosign Style Evidence Attachment

If a dedicated oci-repo is not provided evidence assumed to b Attach the evidence to the same repo as the uploaded image.

  • Example: If you create a evidence for example/my_image:latest, the evidence will be stored as example/my_image:SHA-256-DIGEST.sig (oci-repo).

Demo: Enforcing Image X509 Signing Policies Over OCI store

To showcase the enforcement of image signing policies using Gatekeeper Valint, we'll apply a simplistic unsigned image error policy and upgrade our gate accordingly.

Upgrade your gate with the following command,

helm upgrade gatekeeper-valint scribe/gatekeeper-valint \
--values signed_image_policy.yaml \
--namespace gatekeeper-valint \
--set valint.attest.default=x509-env \
--set x509.ca="$(cat certs/ca.crt)" \
--reuse-values --force

x509.ca, valint-attest-default will configure the provider to verify using the CA. We strongly recommend replacing CA certificates with those from your trusted organization.

signed_image_policy.yaml file
select:
gate: signed_images_gate
apply:
- namespace: "" # Any
glob:
- "mycompany/**"
filter-by:
- target
policy:
name: require_signed_images
rules:
- name: error_on_unsigned_image
uses: sbom/artifact-signed@v1
level: error

In the provided signed_image_policy.yaml, we specify a policy to enforce signature verification for images admitted from the my_company Dockerhub account.

Now lets try and apply deployments before signing the image.

kubectl apply -f signed-deployment.yaml 2>&1 | echo -e "$(cat -)"
signed-deployment.yaml file
apiVersion: apps/v1
kind: Deployment
metadata:
name: signed-deployment
labels:
app: signed-deployment
spec:
replicas: 0 # testing purposes only
selector:
matchLabels:
app: signed-deployment
template:
metadata:
labels:
app: signed-deployment
spec:
containers:
- name: valid
image: mycompany/signed:latest

In the output, you should see a rejected admission error due to the unsigned image.

Error from server (Forbidden): error when creating "policy/examples/signed-deployment.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [gatekeeper-valint] image not accepted: {"errors": [], "responses": [], "status_code": 200, "system_error": "
Scribe Admission refused 'scribesecurity/signed:latest' deployment to 'default'.

- policy check failed, Policies [require_signed_images] failed with the following errors.
* rule [error_on_unsigned_image] failed resource not found, no evidence found
"}

To resolve this, sign your image using the Valint tool:

valint bom mycompany/signed:latest -o attest \
--components metadata \
--oci --oci-repo [oci-repo] [FLAGS]

--components metadata minimizes the size of the SBOM.

Then, re-apply the deployment:

kubectl apply -f signed-deployment.yaml

Upon successful deployment, you'll see a detailed evaluation summary in the admission logs, providing insights into the policy checks performed and their outcomes.

[2024-03-17 09:47:28]  INFO verify: [TRUSTED] verify success, CA: x509-verifier, CN: Gatekeeper Root CA, Emails: [], URIs: []
...
[2024-03-11 10:05:27] INFO Target 'mycompany/signed:latest' results
[2024-03-11 10:05:27] INFO Policy "require_signed_images" Evaluation Summary:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Policy "require_signed_images" Evaluation Summary │
├─────────────────────────┬────────┬────────────────────────┬───────────────────┬────────────────────────────────────────────┤
│ RULE NAME │ SIGNED │ SIGNATURE VERIFICATION │ POLICY EVALUATION │ COMMENT │
├─────────────────────────┼────────┼────────────────────────┼───────────────────┼────────────────────────────────────────────┤
│ error_on_unsigned_image │ true │ passed │ │ 1/1 evidence origin and signature verified │
├─────────────────────────┼────────┼────────────────────────┼───────────────────┼────────────────────────────────────────────┤
│ AGGREGATE POLICY RESULT │ │ │ PASSED │ │
└─────────────────────────┴────────┴────────────────────────┴───────────────────┴────────────────────────────────────────────┘