End To End DemoEN
End-to-End Zero-Trust Gateway Demo
This guide demonstrates the full pipeline of the pki core + pki-gateway: issue certificates → enforce policy at the gateway → audit traceability.
System Architecture
┌──────────────────────────────────────────────────────────┐
│ Administrator AI Agent │
│ varwof issue pki-agent (to be built) │
└─────────┬──────────────────────┬──────────────────────────┘
│ Issue certs with OU roles │ API calls
┌─────────▼──────────────────────▼──────────────────────────┐
│ pki core (CA) │
│ • Issues short-lived agent-proxy certificates (≤1h) │
│ • OU required: gateway:<role> → cert-bound permissions │
│ • CRL publishing: revocations take effect immediately │
└─────────────────────────┬──────────────────────────────────┘
│ Certificates + CRL
┌─────────────────────────▼──────────────────────────────────┐
│ pki-gateway (zero-trust gateway) │
│ 1. mTLS handshake → verify certificate chain │
│ 2. CRL check → reject revoked certificates │
│ 3. Extract OU roles → compare against allow_roles │
│ 4. Audit log → TSA-signed tamper proof │
│ 5. Port forwarding → connect to the target service │
└─────────────────────────┬──────────────────────────────────┘
│ mTLS tunnel
┌─────────────────────────▼──────────────────────────────────┐
│ Target services (MySQL / Redis / SSH / HTTP API) │
└────────────────────────────────────────────────────────────┘
Prerequisites
- Go 1.21+
- openssl CLI (for certificate verification)
- Build artifacts:
pki,pki-gateway
# Build
go build -o pki ./cmd/pki/
go build -o pki-gateway /path/to/pki-gateway/
Steps
1. Create the CA Hierarchy
# Root CA
varwof init-ca --name "Demo Root CA" --key-type ecdsa-p256 \
--ca-type root --org "Demo" --country "CN" --out ./ca
# Issuing CA
varwof init-ca --name "Demo Issuing CA" --key-type ecdsa-p256 \
--ca-type sub --parent-ca ./ca/demo-root-ca \
--org "Demo" --country "CN" --out ./ca
2. Issue Gateway Client Certificates
Uses the agent-proxy profile—which enforces a mandatory OU and a validity of ≤1 hour:
varwof issue --ca ./ca/demo-issuing-ca --profile agent-proxy \
--cn "mysql-agent" \
--subject "/CN=mysql-agent/OU=gateway:mysql-prod" \
--out ./certs --name mysql-agent
Verify the certificate:
openssl x509 -in ./certs/mysql-agent.pem -noout -subject
# → subject=CN=mysql-agent, OU=gateway:mysql-prod, ...
openssl x509 -in ./certs/mysql-agent.pem -noout -ext keyUsage,extendedKeyUsage
# → X509v3 Key Usage: Digital Signature
# → X509v3 Extended Key Usage: TLS Web Client Authentication
3. Configure and Start the Gateway
{
"mappings": [
{
"name": "mysql-prod",
"listen": "127.0.0.1:9443",
"target": "127.0.0.1:3306",
"tls_mode": "mtls",
"mtls": {
"ca_cert_file": "./ca/demo-issuing-ca/ca.pem",
"cert_file": "./ca/demo-issuing-ca/ca.pem",
"key_file": "./ca/demo-issuing-ca/ca-key.pem",
"crl_url": "http://crl.internal:8080/demo-issuing-ca.crl",
"allow_roles": ["gateway:mysql-prod"],
"audit_file": "/var/log/pki-gateway/audit.log"
}
}
]
}
pki-gateway server -config ./gw.json
4. Client Connection
# Access MySQL through the gateway (no need to know MySQL's real address)
mysql -h 127.0.0.1 -P 9443 -u app_user -p \
--ssl-cert ./certs/mysql-agent.pem \
--ssl-key ./certs/mysql-agent-key.pem \
--ssl-ca ./ca/demo-issuing-ca/ca.pem
5. Unauthorized Attempts Are Blocked
Attempt to connect to a mapping with allow_roles: ["gateway:mysql-prod"] using a certificate carrying the gateway:readonly role:
# Issue a read-only certificate
varwof issue --ca ./ca/demo-issuing-ca --profile agent-proxy \
--cn "readonly-agent" \
--subject "/CN=readonly-agent/OU=gateway:readonly" \
--out ./certs --name readonly-agent
# Connection rejected by the gateway
mysql -h 127.0.0.1 -P 9443 ... --ssl-cert ./certs/readonly-agent.pem ...
# → ERROR 2013 (HY000): Lost connection to MySQL server
Gateway log:
denied: src=10.0.0.5 mapping=mysql-prod reason="unauthorized role" roles=["gateway:readonly"]
6. Revoke a Certificate
# Revoke
varwof revoke --ca ./ca/demo-issuing-ca --cert ./certs/mysql-agent.pem
varwof crl --ca ./ca/demo-issuing-ca --out ./crl/demo-issuing-ca.crl
# Hot-reload the CRL on the gateway
kill -HUP $(pgrep pki-gateway)
# or
curl -X POST https://admin:9443/api/v1/gateway/crl-reload \
--cert admin.pem --key admin-key.pem
Connections using the revoked certificate are rejected immediately.
7. View Audit Logs
# Query audits via the management API
curl --cert admin.pem --key admin-key.pem \
https://admin:9443/api/v1/gateway/audit?since=2026-07-05T00:00:00Z
Each audit log line contains:
{"entry":{"time":"2026-07-05T12:34:56.123456789Z","action":"connected","client_cn":"mysql-agent","client_serial":"ABC123","roles":["gateway:mysql-prod"],"mapping":"mysql-prod","target":"127.0.0.1:3306"},"tst":"MIIF...TQ=="}
The tst field is an RFC 3161 TSA signature proving the log entry has not been tampered with.
Automated Testing
bash deploy/test-gateway-e2e.sh
The script automatically:
- Creates the CA hierarchy
- Issues agent-proxy certificates
- Starts an echo test server
- Starts the gateway
- Tests role authentication
- Tests unauthorized-access rejection
- Tests revocation enforcement
- Verifies audit logs
FAQ
Q: Issuance reports "requires at least one OU"?
A: The agent-proxy profile requires an OU, in the format:
--subject "/CN=<name>/OU=gateway:<role>"
Q: Certificate validity too long and got truncated?
A: agent-proxy enforces a maximum of 1 hour. For a temporarily longer validity, use the tls-client profile and specify --ttl manually.
Q: Windows config path?
A: The default path is %ProgramData%\varwof\pki-gateway\pki-gateway.json.