Fulcio is the certificate authority at the heart of Sigstore's keyless code signing ecosystem. When a developer runs cosign sign or a CI pipeline signs a container image, Fulcio validates the OIDC identity token, issues a short-lived X.509 certificate, and records the issuance in a Certificate Transparency log. If Fulcio goes down — API crash, OIDC provider connectivity loss, CT log submission failure — all new code signing stops. Pipelines that enforce signature verification start rejecting unsigned artifacts, blocking deployments. Vigilmon gives you external monitoring that watches Fulcio from the client's perspective and alerts the moment certificate issuance is at risk.
What You'll Build
- A Vigilmon HTTP monitor for Fulcio's health and certificate issuance endpoints
- A heartbeat monitor to verify OIDC-to-certificate issuance end-to-end
- A CT log connectivity probe
- Alert channels routed to your security and platform teams
Prerequisites
- A running Fulcio instance (self-hosted) or access to the Sigstore public instance
- Network access to expose Fulcio's gRPC/HTTP endpoints with TLS
- A valid OIDC provider (e.g. Google, GitHub Actions, Dex) configured in Fulcio
- A free account at vigilmon.online
Why Monitoring Fulcio Matters
Fulcio sits on the critical path for every keyless signing operation. Its failure modes are particularly impactful for software supply chain security:
API unavailability blocks all new code signing. In environments that enforce signature verification at deploy time (via policy controllers, Kyverno, or OPA Gatekeeper), an unavailable Fulcio means no new deployments succeed. The failure cascades from a signing service outage into a deployment outage.
OIDC provider connectivity loss prevents Fulcio from validating identity tokens. Even if the Fulcio API is reachable, certificate issuance fails if it cannot call the OIDC provider's JWKS endpoint to verify the token signature. This is a silent dependency — Fulcio's /healthz may return 200 while all certificate issuance fails.
Certificate Transparency log submission failures cause Fulcio to fail issuance in strict mode. Fulcio submits every issued certificate to a CT log (typically Rekor or an RFC 6962-compliant log). If the CT log is unreachable or rejects submissions, certificate issuance stops.
Certificate clock drift causes OIDC token validation to fail. Fulcio validates the iat and exp claims in OIDC tokens; if the Fulcio server's clock drifts more than the OIDC provider's allowed skew, all certificate issuance fails with token validation errors.
External monitoring with Vigilmon detects all of these from outside the system, from the same network path a signing client uses.
Step 1: Monitor the Fulcio Health Endpoint
Fulcio exposes an HTTP health endpoint at /healthz:
# For self-hosted Fulcio
curl https://fulcio.internal.yourdomain.com/healthz
# For the Sigstore public instance
curl https://fulcio.sigstore.dev/healthz
In the Vigilmon dashboard:
- Go to Add Monitor → HTTP
- Configure:
| Field | Value |
|---|---|
| Name | fulcio /healthz |
| URL | https://fulcio.internal.yourdomain.com/healthz |
| Method | GET |
| Expected status | 200 |
| Check interval | 1 minute |
| Timeout | 10 seconds |
| Alert after | 2 consecutive failures |
Step 2: Monitor the Certificate Issuance Endpoint
The health endpoint doesn't verify that Fulcio can actually issue certificates. Add a monitor for the certificate issuance API route that checks reachability and TLS validity:
# Verify the signing certificate chain endpoint is reachable
curl -I https://fulcio.internal.yourdomain.com/api/v2/signingCert
# Expect 400 (missing request body) — proves the route is alive and TLS is valid
Add a second Vigilmon HTTP monitor:
| Field | Value |
|---|---|
| Name | fulcio /api/v2/signingCert reachable |
| URL | https://fulcio.internal.yourdomain.com/api/v2/signingCert |
| Method | POST |
| Expected status | 400 |
| Check interval | 2 minutes |
| Timeout | 15 seconds |
| Alert after | 2 consecutive failures |
A 400 Bad Request (missing body) is the expected response when Fulcio is healthy — it proves the route is routed and the TLS certificate is valid. A 502 or connection timeout means the API process is down.
Step 3: Monitor the Root Certificate Endpoint
Verify Fulcio's signing certificate chain is accessible — clients need this to verify issued certificates:
In Vigilmon, add a third HTTP monitor:
| Field | Value |
|---|---|
| Name | fulcio root certificate |
| URL | https://fulcio.internal.yourdomain.com/api/v2/trustBundle |
| Method | GET |
| Expected status | 200 |
| Response body contains | chains |
| Check interval | 5 minutes |
| Timeout | 10 seconds |
| Alert after | 2 consecutive failures |
Step 4: Heartbeat Monitor for End-to-End OIDC Signing
The most critical probe validates the full signing path: OIDC token acquisition → Fulcio certificate issuance. This catches OIDC connectivity loss that pod-level health checks miss.
Create a CronJob that uses cosign to perform a full keyless signing operation against a test OCI artifact:
# fulcio-signing-probe.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: fulcio-signing-probe
namespace: security-monitoring
spec:
schedule: "*/15 * * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
serviceAccountName: fulcio-probe
containers:
- name: signing-probe
image: gcr.io/projectsigstore/cosign:v2.2.0
env:
- name: FULCIO_URL
value: "https://fulcio.internal.yourdomain.com"
- name: REKOR_URL
value: "https://rekor.internal.yourdomain.com"
- name: OIDC_TOKEN_URL
value: "https://your-oidc-provider/token"
- name: HEARTBEAT_URL
valueFrom:
secretKeyRef:
name: vigilmon-secrets
key: fulcio-signing-heartbeat-url
command:
- /bin/sh
- -c
- |
set -e
# Acquire OIDC token using Kubernetes service account token
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
# Attempt to get a certificate from Fulcio
# Uses cosign's built-in OIDC exchange
cosign sign \
--fulcio-url="$FULCIO_URL" \
--rekor-url="$REKOR_URL" \
--identity-token="$TOKEN" \
--yes \
ttl.sh/vigilmon-canary:5m 2>&1 | tee /tmp/cosign_output.txt
# Verify signing succeeded
if grep -q "error\|Error\|FAIL" /tmp/cosign_output.txt; then
echo "FAIL: Signing probe encountered errors"
cat /tmp/cosign_output.txt
exit 1
fi
wget -qO- "$HEARTBEAT_URL"
echo "Fulcio signing heartbeat sent"
volumes:
- name: service-account-token
projected:
sources:
- serviceAccountToken:
audience: sigstore
expirationSeconds: 3600
path: token
Create the heartbeat monitor in Vigilmon:
- Add Monitor → Heartbeat
- Name:
fulcio end-to-end signing - Expected interval: 15 minutes
- Grace period: 10 minutes
Store the secret:
kubectl create secret generic vigilmon-secrets \
--from-literal=fulcio-signing-heartbeat-url='https://vigilmon.online/heartbeat/YOUR_TOKEN' \
-n security-monitoring
Step 5: Monitor CT Log Connectivity
Fulcio requires a Certificate Transparency log for certificate submission. Monitor it separately so you can distinguish Fulcio API failures from CT log dependencies:
# fulcio-ctlog-probe.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: fulcio-ctlog-probe
namespace: security-monitoring
spec:
schedule: "*/10 * * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: ctlog-probe
image: curlimages/curl:latest
env:
- name: CTLOG_URL
value: "https://ctfe.internal.yourdomain.com"
- name: HEARTBEAT_URL
valueFrom:
secretKeyRef:
name: vigilmon-secrets
key: fulcio-ctlog-heartbeat-url
command:
- /bin/sh
- -c
- |
set -e
# Check CT log STH (Signed Tree Head) endpoint
STH=$(curl -sf "$CTLOG_URL/ct/v1/get-sth")
if [ -z "$STH" ]; then
echo "FAIL: CT log STH endpoint returned empty response"
exit 1
fi
# Verify tree_size is present (indicates active log)
echo "$STH" | grep -q "tree_size" || {
echo "FAIL: CT log STH missing tree_size"
exit 1
}
wget -qO- "$HEARTBEAT_URL"
echo "CT log heartbeat sent"
Step 6: Configure Alert Channels
Route Fulcio alerts to both security and platform teams:
- In Vigilmon: Alert Channels → Add Channel → Slack Webhook
- Add your
#security-alertsand#platform-alertswebhooks - Assign both channels to all Fulcio monitors
For the end-to-end signing probe (complete signing pipeline failure):
- Alert Channels → Add Channel → PagerDuty or email
- Assign it only to the
fulcio end-to-end signingheartbeat - This is an on-call escalation — signing failure blocks deployments
What You're Now Monitoring
| Component | Monitor Type | What It Detects |
|---|---|---|
| Fulcio API process | HTTP /healthz | Service crash or restart |
| Issuance route | HTTP POST /api/v2/signingCert | Route routing or API process issues |
| Trust bundle | HTTP GET /api/v2/trustBundle | Certificate chain unavailable |
| End-to-end signing | Heartbeat (15 min) | OIDC connectivity, full signing pipeline |
| CT log | Heartbeat (10 min) | CT log unreachable (blocks issuance) |
Conclusion
Fulcio is a foundational component of keyless supply chain security, but its failure is invisible until developers try to sign and fail, or verifying systems start rejecting unsigned artifacts and blocking deployments. External monitoring with Vigilmon gives your security team early warning from the same network path signing clients use — not just pod-level health signals.
Get started free at vigilmon.online. The trust bundle monitor and signing heartbeat together give you the two most important signals in under ten minutes: is Fulcio reachable, and can it actually issue certificates?