Quick Start


Get Develocity Provenance Governor running locally in under 10 minutes using k3d and basic HTTP ingress.

Prerequisites:

  • kubectl installed (Install kubectl)

  • macOS or Linux (for brew/bash commands)

  • Your Develocity license file saved as develocity.license in your current directory

  • The manifest.yaml file downloaded

This quick start creates a local, non-production environment with HTTP-only access for testing. For production deployments, see the complete Deployment Guide.

Step 1: Create a Local Kubernetes Cluster

Install k3d and create a cluster with port 80 exposed for HTTP traffic.

brew install k3d
k3d cluster create --port "80:80@loadbalancer"

Expected output: Cluster 'k3s-default' created successfully!

Step 2: Create the Namespace

Create a dedicated namespace for the Develocity Provenance Governor components. The manifest references this namespace but doesn’t create it.

kubectl create namespace develocity-provenance-governor

Step 3: Configure Ingress

Set up basic HTTP ingress using nip.io for local DNS resolution. This allows you to access the service at api.127.0.0.1.nip.io.

kubectl --namespace develocity-provenance-governor apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api.127.0.0.1.nip.io
spec:
  rules:
    - host: api.127.0.0.1.nip.io
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-http
                port:
                  number: 80
EOF

nip.io is a wildcard DNS service that maps 127.0.0.1.nip.io to 127.0.0.1, allowing you to use a domain name for local testing without editing /etc/hosts.

Step 4: Configure Image Pull Secret

Create a secret that allows Kubernetes to pull the Develocity Provenance Governor image from the Gradle registry. Your license file is used for authentication.

kubectl create secret docker-registry registry-secret \
  --namespace develocity-provenance-governor \
  --docker-server=https://registry.gradle.com \
  --docker-username=user \
  --docker-password=$(cat ./develocity.license)

The user: prefix in the command is for clarity and is ignored by the registry.

🚀 Alternative: Use local image with k3d (skip registry secret)

If you prefer to avoid creating a registry secret, you can load the image directly into k3d:

# First, pull the image locally using your license for authentication
docker login registry.gradle.com -p "ge:$(cat ./develocity.license)"
docker pull registry.gradle.com/develocity/provenance-governor:<version>

# Load the image into k3d
k3d image import registry.gradle.com/develocity/provenance-governor:<version>

# Then modify manifest.yaml to remove imagePullSecrets before applying in Step 6

Note: You’ll need to edit manifest.yaml and remove the imagePullSecrets section from the Deployment before applying it.

This approach is faster and simpler for local development but requires manual steps that aren’t needed with the registry secret approach.

Step 5: Create License Secret

Store your license file as a Kubernetes secret so the application can access it.

kubectl create secret generic license \
  --namespace develocity-provenance-governor \
  --from-file=develocity.license=./develocity.license

Step 6: Deploy the Application

Apply the manifest to deploy Develocity Provenance Governor and its components.

kubectl --namespace develocity-provenance-governor apply -f manifest.yaml

Step 7: Wait for Deployment

Wait for the deployment to complete (this may take 1-2 minutes).

kubectl rollout status deployment/api --namespace develocity-provenance-governor --timeout=90s

Expected output: deployment "api" successfully rolled out

Step 8: Verify the Installation

Check the application logs to confirm it started successfully.

kubectl logs deployment/api --namespace develocity-provenance-governor | head -n 50

Look for log messages indicating successful startup (no error messages).

Step 9: Test the Endpoint

Verify the service is accessible. You should receive a 401 Unauthorized response since authentication isn’t configured yet.

curl -i api.127.0.0.1.nip.io

Expected output:

HTTP/1.1 401 Unauthorized
...

A 401 Unauthorized response means the service is running correctly! You just need to configure authentication in the next steps.

Step 10: Configure Attestation Storage

Develocity Provenance Governor requires an attestation store (S3 or Artifactory) to function. For this quick start, we will deploy LocalStack to simulate an S3 bucket within the cluster.

Deploy LocalStack and expose it
kubectl create deployment localstack --image=localstack/localstack:3.0.0 --port=4566 -n develocity-provenance-governor
kubectl expose deployment localstack --port=4566 --name=localstack -n develocity-provenance-governor
kubectl rollout status deployment/localstack -n develocity-provenance-governor --timeout=120s
Create an S3 bucket named 'dpg-bucket'
kubectl run aws-cli --image=amazon/aws-cli --restart=Never -n develocity-provenance-governor \
  --env="AWS_ACCESS_KEY_ID=test" --env="AWS_SECRET_ACCESS_KEY=test" --env="AWS_REGION=us-east-1" \
  -- s3 mb s3://dpg-bucket --endpoint-url=http://localstack:4566

Step 11: Configure Policies and Properties

Now configure the application to use the S3 bucket and define the basic policies.

Create placeholder Secrets/ConfigMaps
kubectl create secret generic secrets --namespace develocity-provenance-governor --dry-run=client -o yaml | kubectl apply -f - || true
kubectl create configmap properties --namespace develocity-provenance-governor --dry-run=client -o yaml | kubectl apply -f - || true
kubectl create configmap policies --namespace develocity-provenance-governor --dry-run=client -o yaml | kubectl apply -f - || true
Add Access Control (including S3 access) and Build policies to the policies ConfigMap
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: policies
  namespace: develocity-provenance-governor
data:
  access-control.yaml: |
    apiVersion: policy.gradle.com/v1
    kind: AccessControl
    metadata:
      name: admin-full-access
    spec:
      identityMatchingStrategy:
        withBasicIdentity:
          - withName: "admin"
      canPerform:
        - publish-attestations
        - publish-policy-scans
        - read-attestations
      withResources:
        - "*:*/*"
        - "s3:local-s3/*"
        - "pkg:maven/*"

  scan-build.yaml: |
    apiVersion: policy.gradle.com/v1
    kind: PolicyScanDefinition
    metadata:
      name: build
    spec:
      description: Validate the software package against the build gate policies.
      policy-selector:
        match-labels:
          gate: build

  policy-require-build-tool.yaml: |
    apiVersion: policy.gradle.com/v1
    kind: AttestationsExist
    metadata:
      name: require-build-tool
      labels:
        gate: build
    spec:
      description: Ensure Build Tool attestation exists
      remediation: Fix build
      matchingStrategy: must-match
      expectedPredicates:
        - https://gradle.com/attestation/build-tool/v1
EOF
Configure Develocity and S3 Properties (Replace https://develocity.example.com with your instance URL)
kubectl patch configmap properties --namespace develocity-provenance-governor --type=merge -p '{"data":{
  "develocity.instances.main.uri": "https://develocity.example.com",
  "s3.instances.local-s3.region": "us-east-1",
  "s3.instances.local-s3.endpoint": "http://localstack:4566",
  "s3.instances.local-s3.bucket-name": "dpg-bucket",
  "s3.instances.local-s3.path-style-access": "true"
}}'
Configure Secrets (Replace YOUR_DEVELOCITY_ACCESS_KEY with your actual key)
kubectl patch secret secrets --namespace develocity-provenance-governor --type=merge -p '{"stringData":{
  "develocity.instances.main.access-key": "YOUR_DEVELOCITY_ACCESS_KEY",
  "s3.instances.local-s3.access-key-id": "test",
  "s3.instances.local-s3.secret-access-key": "test",
  "basic.identities.admin": "{noop}admin"
}}'
Restart the deployment to apply configuration
kubectl rollout restart deployment/api --namespace develocity-provenance-governor
kubectl rollout status deployment/api --namespace develocity-provenance-governor --timeout=90s

Step 12: Test Attestation Publishing and Build Gate Verification

Now, publish an attestation and run the build policy scan. This simulates a "Build Gate" check. If the scan passes (meaning the require-build-tool policy is satisfied), a Verification Summary Attestation (VSA) will be automatically generated and published.

Replace YOUR_BUILD_SCAN_ID with a valid Build Scan ID from your Develocity instance (e.g., 3skbdg5fgcgha). The SHA256_DIGEST can be any 64-character hex string for this test.

Publish an attestation
SHA256_DIGEST="73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497" # Placeholder
BUILD_SCAN_ID="YOUR_BUILD_SCAN_ID" # Replace with a real ID like 3skbdg5fgcgha
DPG_URL="http://api.127.0.0.1.nip.io" # Update port if you used a different one

curl -v -u admin:admin \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "sha256=$SHA256_DIGEST" \
  -d "repositoryUrl=repo.example.com/maven2" \
  -d "buildScan.ids=$BUILD_SCAN_ID" \
  "$DPG_URL/packages/maven/com.example/my-app/1.0.0/attestations"

Expected output: Look for HTTP/1.1 200 OK and a JSON response detailing successes for attestation storage.

Run the 'build' policy scan
SHA256_DIGEST="73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497" # Must match above
DPG_URL="http://api.127.0.0.1.nip.io" # Update port if you used a different one

# Run the 'build' policy scan.
# If successful, this will generate a VSA confirming the package passed the build gate.
POLICY_SCAN_RESULT=$(curl -v -u admin:admin \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "sha256=$SHA256_DIGEST" \
  -d "repositoryUrl=repo.example.com/maven2" \
  "$DPG_URL/packages/maven/com.example/my-app/1.0.0/policy-scans/build")

echo "$POLICY_SCAN_RESULT" | jq .

Expected output: The JSON response will include a PolicyScanDefinition result. If the scan passed, it will contain an attestationUri pointing to the newly generated Verification Summary Attestation (VSA).

Retrieve the generated VSA (optional)
# Replace VSA_ATTESTATION_URI with the actual URI from the previous step's output (e.g., /packages/maven/.../attestations/s3:local-s3/uuid)
# Make sure to include the full path, e.g., /packages/maven/com.example/my-app/1.0.0/sha256:73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497/attestations/s3:local-s3/fe618e2e-eb39-5ae7-9ad7-da5343397858
VSA_ATTESTATION_URI="/packages/maven/com.example/my-app/1.0.0/sha256:73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497/attestations/s3:local-s3/fe618e2e-eb39-5ae7-9ad7-da5343397858"
DPG_URL="http://api.127.0.0.1.nip.io"

curl -v -u admin:admin \
  -H "Accept: application/json" \
  "$DPG_URL$VSA_ATTESTATION_URI" | jq .

Expected output: A JSON object representing the DSSE envelope of the VSA.

🎉 Success!

Your Develocity Provenance Governor instance is now running locally and configured with basic policies.

What’s Next?

Essential Configuration

To make your instance production-ready, configure these key features:

Feature Description Guide

🔐 Authentication

Add Basic Auth or OIDC to secure your instance

Configure Auth

🔑 Signing Keys

Enable cryptographic signing of attestations

Setup Keys

📋 Policies

Define access control and verification rules

Create Policies

🔗 Integrations

Connect to Develocity and Artifactory instances

Develocity / Artifactory

🔒 HTTPS/TLS

Secure communication with TLS certificates

Setup TLS

New to Develocity Provenance Governor? Follow this order:

  1. Read the concepts - Understand how components work together

  2. Add authentication - Secure your instance before connecting other services

  3. Configure integrations - Connect to your Develocity and artifact repositories

  4. Set up signing - Enable attestation signatures for verification

  5. Define policies - Create rules for access control and compliance

Need Help?

  • Full Documentation: Complete Deployment Guide

  • Troubleshooting: Check logs with kubectl logs deployment/api -n develocity-provenance-governor

  • Clean Up: Delete the cluster with k3d cluster delete k3s-default