Quickstart
Install Diffhold on a local kind cluster, load an example policy and watch it allow, deny and hold agent calls. About 10 minutes.
1. Create a cluster and build the image
kind create cluster --name diffhold --image kindest/node:v1.35.0 cd diffhold # your checkout of the source make build # bin/diffhold, used below docker build -t diffhold:dev . kind load docker-image diffhold:dev --name diffhold
2. Create an agent identity
Agents act through a ServiceAccount in an agent namespace (agents by default). Its RBAC is the hard ceiling: Diffhold can only narrow it. The test fixtures create the agents/agent-sre-bot ServiceAccount, a role for it in team-a, a sample Deployment and an approver ServiceAccount oncall/alice.
kubectl apply -f test/e2e/fixtures.yaml
3. Install the chart
helm install diffhold charts/diffhold -n diffhold-system --create-namespace \ --set image.repository=diffhold --set image.tag=dev --set image.pullPolicy=Never --wait
The chart generates the webhook CA, the gRPC server and gateway client certificates, the admin token, the grant signing key and the audit signing key, and keeps all of them across upgrades.
4. Load a policy
kubectl apply -f examples/agentpolicy.yaml kubectl -n diffhold-system get agentpolicies
NAME AGENTS MODE READY AGE
sre-bot sre-bot enforce True 4s
Check the policy offline at any time, and run its test suite:
bin/diffhold policy check examples/agentpolicy.yaml
bin/diffhold test examples/agentpolicy_test.yaml # 10/10 passed
5. Connect a gateway
Point agentgateway's guardrail processor at diffhold.diffhold-system.svc:9000 with the client certificate from Secret diffhold-gateway-client. See Connect agentgateway.
To try the full path without a gateway, run the end-to-end suite. It calls Diffhold over mTLS the way agentgateway does, uses the returned tokens against the API server and checks every result:
DIFFHOLD_E2E_CONTEXT=kind-diffhold hack/e2e-helm.sh
6. Approve a held call
kubectl -n diffhold-system port-forward svc/diffhold 9001 &
kubectl -n diffhold-system get secret diffhold-gateway-client -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt
kubectl -n diffhold-system get secret diffhold-admin -o jsonpath='{.data.token}' | base64 -d > admin.token
export DIFFHOLD_ADMIN=https://localhost:9001 DIFFHOLD_CA_FILE=ca.crt
TLS="--tls-server-name diffhold.diffhold-system.svc"
bin/diffhold approvals list $TLS --token-file admin.token
kubectl create token alice -n oncall --audience diffhold > alice.token
bin/diffhold approvals approve CALL_ID $TLS --token-file alice.token
Check that no agent ServiceAccount can switch Diffhold off:
bin/diffhold permissions check agents/agent-sre-bot --context kind-diffhold # OK agents/agent-sre-bot
The agent retries the same call and it goes through once. See Approvals.
Uninstall
helm uninstall diffhold -n diffhold-system
A pre-delete hook revokes every outstanding per-call token before the webhook goes away. Helm leaves the CRD in place.