Configuring PolicyServers to use a private Sigstore instance
You can configure a PolicyServer to use a private or self-hosted Sigstore instance for policy signature verification, instead of the default public Sigstore infrastructure. This is useful in air-gapped environments or when you operate your own Sigstore deployment.
Step 1 - Generate the ClientTrustConfig JSON
The PolicyServer expects a ClientTrustConfig JSON that describes your private
Sigstore instance’s trust anchors and signing configuration.
Obtain certificates and public keys
Retrieve the following from your private Sigstore instance:
-
fulcio.pem- Fulcio CA certificate chain (PEM) -
rekor.pub- Rekor transparency log public key -
tsa.pem- Timestamp Authority certificate chain (PEM) -
ctfe.pub- CT log public key
# Fulcio CA certificate chain
curl --fail -o fulcio.pem "${FULCIO_URL}/api/v1/rootCert"
# Rekor transparency log public key
curl --fail -o rekor.pub "${REKOR_URL}/api/v1/log/publicKey"
# Timestamp Authority certificate chain
curl --fail -o tsa.pem "${TSA_URL}/api/v1/timestamp/certchain"
# CT log public key (from the Kubernetes secret in tuf-system namespace)
kubectl get secret -o json -n tuf-system ctlog-public-key \
| jq -r ".data.public" | base64 -d > ctfe.pub
|
Security consideration
Make sure that you safely download the certificates and keys from your Sigstore instance. Otherwise, you may end up configuring SUSE Security Admission Controller with compromised data. The above commands are examples of how to do that in a testing environment. Consult the appropriate team in your organization to learn how to get this information properly. |
Generate the trusted root and signing config
Set environment variables pointing to your private Sigstore service URLs:
export FULCIO_URL=https://fulcio.example.com
export REKOR_URL=https://rekor.example.com
export TSA_URL=https://tsa.example.com
export CTLOG_URL=https://ctlog.example.com
export ISSUER_URL=https://oidc.example.com
Run cosign to generate the trusted root:
cosign trusted-root create \
--fulcio="url=$FULCIO_URL,certificate-chain=fulcio.pem" \
--rekor="url=$REKOR_URL,public-key=rekor.pub,start-time=2024-01-01T00:00:00Z" \
--tsa="url=$TSA_URL,certificate-chain=tsa.pem" \
--ctfe="url=$CTLOG_URL,public-key=ctfe.pub,start-time=2024-01-01T00:00:00Z" \
--out trusted_root.json
Run cosign to generate the signing config:
cosign signing-config create \
--fulcio="url=$FULCIO_URL,api-version=1,start-time=2024-01-01T00:00:00Z,operator=sigstore.dev" \
--rekor="url=$REKOR_URL,api-version=1,start-time=2024-01-01T00:00:00Z,operator=sigstore.dev" \
--rekor-config="ANY" \
--oidc-provider="url=$ISSUER_URL/auth,api-version=1,start-time=2024-01-01T00:00:00Z,operator=sigstore.dev" \
--tsa="url=$TSA_URL/api/v1/timestamp,api-version=1,start-time=2024-01-01T00:00:00Z,operator=sigstore.dev" \
--tsa-config="EXACT:1" \
--out signing_config.json
|
The |
For a full description of all available flags and JSON field definitions for both commands, refer to the cosign CLI reference and the Sigstore client trust config specification.
Step 2 - Create a ConfigMap in the kubewarden namespace
Store the ClientTrustConfig JSON in a ConfigMap with the key
sigstore-trust-config. The ConfigMap must be in the admission
controller namespace. In this example is kubewarden:
kubectl --namespace kubewarden create configmap my-sigstore-trust-config \
--from-file=sigstore-trust-config=trust_config.json
Step 3 - Create a verification config ConfigMap
Create a verification_config.yaml file specifying the certificate identity
constraints for your signed policies. For example, when using a Kubernetes
service account token:
allOf:
- kind: genericIssuer
issuer: https://kubernetes.default.svc.cluster.local
subject:
equal: https://kubernetes.io/namespaces/<namespace>/serviceaccounts/<serviceaccount>
anyOf: null
Replace <namespace> and <serviceaccount> with the namespace and service
account used when signing the policy.
Create the ConfigMap:
kubectl --namespace kubewarden create configmap my-verification-config \
--from-file=verification-config=verification_config.yaml
|
The ConfigMap key must be |
Step 4 - Configure the PolicyServer
Set spec.sigstoreTrustConfig and spec.verificationConfig on your PolicyServer
to the names of the ConfigMaps you created:
apiVersion: policies.kubewarden.io/v1
kind: PolicyServer
metadata:
name: default
spec:
image: ghcr.io/kubewarden/policy-server:latest
replicas: 1
sigstoreTrustConfig: my-sigstore-trust-config
verificationConfig: my-verification-config
The controller mounts the ConfigMaps into the policy-server pod and configures it to use your private Sigstore instance for signature verification, enforcing the identity constraints specified in the verification config.
|
Security consideration
Any user with write access to the ConfigMap referenced by Restrict access to this ConfigMap using Kubernetes RBAC, following the principle of least privilege. |