Deployment
Develocity Provenance Governor is provided as a container image that runs on a Kubernetes cluster (recommended) or a local Docker/Kubernetes environment. Make sure you have the prerequisites detailed in Prerequisites before proceeding.
Audience
This guide is written for a Platform / Infrastructure Engineer. It assumes:
-
Basic familiarity with Kubernetes (namespaces, secrets, configmaps, deployments, ingress)
-
Ability to obtain a Develocity license file (
develocity.license) -
(Optional) Ability to obtain access tokens/keys for Develocity and Artifactory instances
-
Access to a DNS domain (optional, for public HTTPS ingress)
Quickstart
Want to get started quickly with a local k3d cluster and basic HTTP ingress?
See the Quickstart Guide for condensed setup instructions.
The quickstart will guide you through:
-
Creating a local k3d cluster
-
Deploying Develocity Provenance Governor with basic HTTP ingress
-
Verifying the deployment
After completing the quickstart, return to the sections below to configure additional features like authentication, integrations, and policies.
Deployment Flow Overview
The recommended order is:
-
Choose / create a Kubernetes cluster (local k3d or existing)
-
Create namespace + required secrets (registry + license)
-
Configure Ingress (HTTP, then HTTPS + cert-manager) - Optional
-
Deploy the core workload (ServiceAccount, Services, Deployment, NetworkPolicy)
-
Create placeholder Secrets/ConfigMaps for dynamic configuration (
secrets,properties,policies) -
Add integrations (Develocity instances, Artifactory instances)
-
Enable authentication (Basic and/or OIDC)
-
Define policies (AccessControl manifests)
-
Roll out config changes as needed
Estimated setup time:
-
Local k3d (Quickstart): 15-30 minutes
-
Production setup with all integrations: 2-4 hours (depending on external service coordination and certificate setup)
Select Kubernetes Distribution
Before proceeding ensure access to a Kubernetes cluster has been provided, otherwise a local k3d cluster is also supported.
k3d
brew install k3d
k3d cluster create --port "80:80@loadbalancer"
Prepare the Kubernetes Namespace and Required Secrets
You must create a Kubernetes namespace and the secrets needed for the application to start.
Create Kubernetes Namespace
kubectl create namespace develocity-provenance-governor
Docker Registry Secret (Required)
Authenticate to registry.gradle.com to pull the product image.
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)
Ingress (Optional)
No default ingress is provided. Choose what aligns with organizational standards. Below examples cover:
-
Local development (nip.io hostname)
-
HTTPS with cert-manager & Let’s Encrypt
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
kubectl get ingress api.127.0.0.1.nip.io --namespace develocity-provenance-governor
NAME CLASS HOSTS ADDRESS PORTS AGE
http traefik api.127.0.0.1.nip.io 172.18.0.3 80 15s
curl api.127.0.0.1.nip.io -i
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Expires: 0
Pragma: no-cache
Referrer-Policy: no-referrer
Www-Authenticate: Basic realm="Realm"
...
Ingress with cert-manager
Alternative, ingress manifest using cert-manager, nginx, and signed certificate from Let’s Encrypt.
The ingress resource, can be used to expose the api service outside the cluster.
Modify the provided manifest to reflect the domain that you control paying close attention to tls[0].hosts[0] and rules[0].host.
kubectl --namespace develocity-provenance-governor apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: https
spec:
tls:
- hosts:
- provenance-governor.example.com
secretName: https-api-tls
rules:
- host: provenance-governor.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-http
port:
number: 80
EOF
At this point, the ingress controller might use a self-signed certificate provided as a default.
kubectl get ingress https --namespace develocity-provenance-governor
NAME CLASS HOSTS ADDRESS PORTS AGE
https traefik provenance-governor.example.com xxx.xxx.xx.x 80, 443 15s
If not already deployed, install cert-manager
kubectl --namespace develocity-provenance-governor create --edit -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: lets-encrypt
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: user@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: lets-encrypt
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
ingressClassName: nginx
EOF
| This will create a certificate issuer using the Production Instance of Let’s Encrypt. Edit accordingly based on desired certificate issuer implementation. If using Let’s Encrypt, ensure the ingress is publicly accessible and can handle a http01 challenge provider request to complete certificate issuance. Also, be sure to update the email address. |
kubectl describe issuer lets-encrypt \
--namespace develocity-provenance-governor
Detailed issuer information should be returned along with Status.Status: True and Status.Type: Ready.
Edit the https ingress resource to use the lets-encrypt issuer instead of the self signed certificate issuer.
kubectl edit ingress https \
--namespace develocity-provenance-governor
cert-manager.io/issuer: lets-encrypt to annotations:metadata:
annotations:
cert-manager.io/issuer: lets-encrypt
$ kubectl get certificate \
--namespace develocity-provenance-governor
NAME READY SECRET AGE
https-api-tls True https-api-tls 2m31s
$ curl https://provenance-governor.example.com -i HTTP/2 401 …
In this example, the request to https://provenance-governor.example.com returns a 401 Unauthorized status code because no credentials were provided.
This confirms that the Ingress is correctly routing traffic to the service and that the service is up and running.
To verify the service health:
curl https://provenance-governor.example.com/readyz -i
No SSL negotiation exceptions should be thrown and a 401 should be returned.
Deploy Core Components
Apply the workload manifests. (See Quickstart)
Download the manifest.yaml file.
kubectl --namespace develocity-provenance-governor apply -f manifest.yaml
kubectl rollout status deployment/api \
--timeout=90s \
--namespace develocity-provenance-governor
Expected output: deployment "api" successfully rolled out.
If rollout fails:
-
Verify
registry-secretcredentials and image digest/tag -
Verify
licensesecret presence and correct file content
kubectl logs deployment/api \
--namespace develocity-provenance-governor | grep -i license
Develocity license enabled, with license [...]
Started ProvenanceGovernor in ...
Create Placeholders for Dynamic Configuration (Optional but Recommended)
The Deployment mounts (optionally) these resources:
Resource |
Kind |
Purpose |
Required |
Mounted Path |
license |
Secret |
Develocity product license |
Yes |
/workspace/config/license |
secrets |
Secret |
Sensitive values (access tokens, private keys) |
No |
/workspace/config/secrets |
properties |
ConfigMap |
Non-sensitive configuration (URIs, public keys) |
No |
/workspace/config/properties |
policies |
ConfigMap |
Policy manifests |
No |
/workspace/config/policies |
Create empty resources to prepare for configuration:
kubectl create secret generic secrets --namespace develocity-provenance-governor || true
kubectl create configmap properties --namespace develocity-provenance-governor || true
kubectl create configmap policies --namespace develocity-provenance-governor || true
Configure Develocity Instances (Optional)
Use one or more Develocity instances as attestation data sources.
Key patterns:
-
Secret:
develocity.instances.<NAME>.access-key -
ConfigMap:
develocity.instances.<NAME>.uri
<NAME> must be alphanumeric plus dashes or underscores.
kubectl edit secret secrets --namespace develocity-provenance-governor
Add access key (use stringData: when adding new values):
stringData:
develocity.instances.MY_INSTANCE.access-key: my-access-key-for-develocity
kubectl edit configmap properties --namespace develocity-provenance-governor
Add URI:
data:
develocity.instances.MY_INSTANCE.uri: https://develocity.example.com
Rollout & Verify:
kubectl rollout restart deployment/api --namespace develocity-provenance-governor
kubectl rollout status deployment/api --namespace develocity-provenance-governor --timeout=90s
kubectl logs deployment/api --namespace develocity-provenance-governor | grep -i "Develocity support enabled"
Expected log snippet:
Develocity support enabled, for instance [MY_INSTANCE:https://develocity.example.com]
Troubleshooting: Repeated Retrying [n/10] request … indicates connectivity or credential issues.
Configure Artifactory Instances (Optional)
Used to publish attestation data.
Key patterns:
-
Secret:
artifactory.instances.<NAME>.access-token(token preferred over legacy key) -
ConfigMap:
artifactory.instances.<NAME>.uri
kubectl edit secret secrets --namespace develocity-provenance-governor
Add token:
stringData:
artifactory.instances.MY_ARTIFACTORY.access-token: my-access-token-for-artifactory
kubectl edit configmap properties --namespace develocity-provenance-governor
Add URI:
data:
artifactory.instances.MY_ARTIFACTORY.uri: https://artifactory.example.com
Rollout & Verify:
kubectl rollout restart deployment/api --namespace develocity-provenance-governor
kubectl rollout status deployment/api --namespace develocity-provenance-governor --timeout=90s
kubectl logs deployment/api --namespace develocity-provenance-governor | grep -i "Artifactory support enabled"
Expected log snippet:
Artifactory support enabled, for instance [MY_ARTIFACTORY:https://artifactory.example.com]
Configure Signing Keys (Optional but Recommended for Attestations)
Attestations are wrapped in a Dead Simple Signing Envelope (DSSE) signed by a key pair.
Required key property patterns:
-
Secret (private key, base64 PEM):
signing.key.<FRIENDLY_KEY_NAME>.private-pem -
ConfigMap (public key PEM block):
signing.key.<FRIENDLY_KEY_NAME>.public-pem
Choose a naming convention like <ORG_OR_PRODUCT>_YYYY-MM-DD for rotation clarity.
Create Ed25519 Key Pair
Recommended (128-bit security, small key sizes/signatures).
openssl genpkey \
-algorithm Ed25519 \
-out private-key.pem
openssl pkey \
-in private-key.pem \
-pubout \
-out public-key.pem
kubectl edit secret secrets \
--namespace develocity-provenance-governor
Base64 and add private key (Secret):
base64 -i private-key.pem | pbcopy
kubectl edit secret secrets --namespace develocity-provenance-governor
Paste under data: (Kubernetes will not modify pasted base64):
data:
signing.key.FRIENDLY_KEY_NAME.private-pem: <PASTE_BASE64_PRIVATE_KEY>
cat public-key.pem | sed 's/^/ /' | pbcopy
kubectl edit configmap properties --namespace develocity-provenance-governor
Paste under data::
data:
# PASTE THE PUBLIC KEY BLOCK HERE FROM CLIPBOARD
signing.key.FRIENDLY_KEY_NAME.public-pem: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
Rollout & Verify:
kubectl rollout restart deployment/api --namespace develocity-provenance-governor
kubectl logs deployment/api --namespace develocity-provenance-governor | grep -i "Signature support enabled"
Expected log:
Signature support enabled, for key pair [name:FRIENDLY_KEY_NAME:keyid:XXXXXX:signing-algorithm:ed25519]
Key ID is a 6-character abbreviation of the SHA-256 digest of the public key.
Other Supported Algorithms
Elliptic Curve (ECDSA) and RSA are also supported. Substitute commands below; follow the same secret/configmap procedure.
Authentication (Optional)
Supported schemes:
Enable Basic Authentication
Add identities under:
-
Secret key pattern:
basic.identities.<NAME>
<NAME> is a human-friendly identifier.
No default credentials exist.
kubectl edit secret secrets --namespace develocity-provenance-governor
stringData:
basic.identities.some-user: "\{noop\}some-pass"
Recommendation: Replace {noop} with {bcrypt} and supply a bcrypt-hashed password.
kubectl rollout restart deployment/api \
--namespace develocity-provenance-governor
kubectl logs deployment/api \
--namespace develocity-provenance-governor |
grep -i "Basic Identity support"
Basic Identity support enabled, for identity [some-user]
Policies (Optional)
Policies are YAML documents stored inside the policies ConfigMap.
Each key corresponds to a file-style name ending with .yaml.
Access Control Policies
Define who can do what on which resources.
identityMatchingStrategy supported:
-
withBasicIdentity– must match a key underbasic.identities.<NAME>insecrets -
withOidc– relies on issuer discovery; ensure network accessibility
canPerform supported actions:
* publish-attestations - publish DSSE-wrapped attestations to an Attestation Store (e.g., Artifactory)
* publish-policy-scans - publish Policy Scan™ results to an Attestation Store
withResources supported patterns:
-
pkg:pkg-type/pkg-namespace/pkg-name@pkg-vesion- specific Package URL pattern to match or use wildcards:-
pkg:maven/*- all Maven packages -
pkg:oci/*- all OCI packages (container images) -
pkg:maven/org.example/@- all Maven packages inorg.examplenamespace and any version -
pkg:maven/org.example/my-app@1.0.0- specific Maven package -
pkg:oci/image-name@v1*- specific OCI image with wildcard version
-
-
*:REPLACE_WITH_DV_INSTANCE_NAME/*- allow to read build scans from the Develocity Instance to source data for attestations. -
*:REPLACE_WITH_ARTIFACTORY_INSTANCE_NAME/*- allow to publish attestations to the Artifactory Instance. Replace*with the repository name in artifactory to restrict access further. -
*:*/*- allows authenticated identity access to all resources (not recommended for production use)
Basic Identity Policy Example
kubectl edit configmap policies --namespace develocity-provenance-governor
data:
basic-identity-some-user-full-access.yaml: |
apiVersion: policy.gradle.com/v1
kind: AccessControl
metadata:
name: basic-identity-some-user-full-access
spec:
identityMatchingStrategy:
withBasicIdentity:
- withName: "some-user"
canPerform:
- publish-attestations
- publish-policy-scans
withResources:
- "*:*/*"
OIDC Policy Example (GitHub Actions)
kubectl edit configmap policies --namespace develocity-provenance-governor
data:
oidc-github-action-full-access.yaml: |
apiVersion: policy.gradle.com/v1
kind: AccessControl
metadata:
name: oidc-github-action-full-access
spec:
identityMatchingStrategy:
withOidc:
- fromIssuerUri: https://token.actions.githubusercontent.com
withClaims:
job_workflow_ref: org/automation-repo/.github/workflows/build-image.yml@*
canPerform:
- publish-attestations
- publish-policy-scans
withResources:
- "*:*/*"
Public Key Verification Policy Example
kubectl edit configmap policies --namespace develocity-provenance-governor
data:
public-key-verification-policy.yaml: |
apiVersion: policy.gradle.com/v1
kind: TrustedPublicKeys
metadata:
name: public-keys
spec:
resultsLabels: []
description: Public keys trusted for attestations.
remediation: Update the list of trusted public keys to ensure only verified attestations are accepted.
keys:
DEPLOYMENT_KEY_2025_10_01:
pem: |
-----BEGIN PUBLIC KEY-----
....
-----END PUBLIC KEY-----
Replace DEPLOYMENT_KEY_2025_10_01 and the PEM block with your actual trusted public keys, for example the ones used to sign attestations.
kubectl rollout restart deployment/api \
--namespace develocity-provenance-governor
kubectl rollout status deployment/api \
--namespace develocity-provenance-governor \
--timeout=90s
kubectl logs deployment/api \
--namespace develocity-provenance-governor |
grep -i "Loading Policy Resource from file"
Loading Policy Resource from file [/workspace/config/policies/public-key-verification-policy.yaml]
Troubleshooting Deployment Rollouts
Common rollout hang:
Waiting for deployment "api" rollout to finish: 1 old replicas are pending termination...
error: timed out waiting for the condition
Inspect pods:
kubectl get pods --namespace develocity-provenance-governor
Identify failing pod (e.g., CrashLoopBackOff) and fetch logs:
kubectl logs api-<POD_ID> --namespace develocity-provenance-governor
Example configuration error:
***************************
APPLICATION FAILED TO START
***************************
Failed to bind properties under 'artifactory.instances.INSTANCE_NAME_GOES_HERE' ... Reason: java.lang.IllegalArgumentException: uri must not be null
Remediation:
-
Missing URI – edit
propertiesConfigMap keyartifactory.instances.<NAME>.uri -
Missing token – edit
secretskeyartifactory.instances.<NAME>.access-token
After fixing, restart:
kubectl rollout restart deployment/api --namespace develocity-provenance-governor
kubectl rollout status deployment/api --namespace develocity-provenance-governor --timeout=90s
Verification and Next Steps
After completing the deployment, verify that Develocity Provenance Governor is running correctly:
-
Check Pod Status
kubectl get pods -n develocity-provenance-governorYou should see the
apipod inRunningstate with1/1ready. -
Check Application Logs
kubectl logs deployment/api -n develocity-provenance-governor --tail=50Look for messages indicating: License loaded successfully Integrations enabled (e.g., "Develocity support enabled", "Artifactory support enabled") Policies loaded (if configured) No error messages
-
Test API Accessibility
curl -i http://your-provenance-governor-hostnameYou should receive a
401 Unauthorizedresponse, which confirms the application is running and authentication is required.The actuator endpoints (health, readiness, liveness, prometheus) are exposed on port 9090 and not accessible through the public ingress. Develocity Provenance Governor also exposes
/livezand/readyzendpoints on the main application port for health checking when Kubernetes probes are enabled. -
Verify Integration Configuration
Check that your configured integrations were loaded:
kubectl logs deployment/api -n develocity-provenance-governor | grep "support enabled"
|
Successfully deployed? If all verification steps passed and you’re ready to start using Develocity Provenance Governor, proceed to Publishing Attestations to learn how to publish attestations and evaluate policies. |
What to Do Next:
-
Configure Your First Integration - If you haven’t already, set up connections to Develocity and Artifactory. See Application Configuration.
-
Set Up Authentication - Configure access control policies to secure your API. See Access Control.
-
Write Your First Policy - Define policies for your software supply chain governance. See Writing Policies.
-
Publish Test Attestations - Try publishing attestations for a test package. See Publishing Attestations.
-
Integrate with CI/CD - Add Develocity Provenance Governor to your build and deployment pipelines. See GitHub Actions or CI/CD Integration.
If you encounter issues, consult the Troubleshooting section.
Summary Cheat Sheet
Integration |
Secret Key Pattern |
ConfigMap Key Pattern |
Mandatory |
Notes |
License |
(file) |
n/a |
Yes |
Provided via |
Registry Auth |
|
n/a |
Yes |
JSON auth file for image pulls |
Develocity Instance |
|
|
No |
Multiple supported |
Artifactory Instance |
|
|
No |
Token preferred |
Signing Key (Private) |
|
n/a |
No |
Base64 PEM |
Signing Key (Public) |
n/a |
|
No |
PEM block |
Basic Identity |
|
n/a |
No |
|
Policies |
n/a |
|
No |
AccessControl docs |