Files
kca/ocsp-responder/README.md
T
woggioni 69d78939a1
CI / Build and push docker image (push) Successful in 3m23s
CI / Build and push OCSP image (push) Successful in 7m53s
Build static musl OCSP image in Gitea Actions
2026-10-23 10:00:36 +00:00

90 lines
2.8 KiB
Markdown

# KCA OCSP responder
Standalone Rust/Axum responder. It reads one full JSON status snapshot per CA
from S3-compatible object storage, caches it for one second with a single-flight
refresh, and signs OCSP responses with a delegated responder certificate.
It has **no KCA database access**, no Redis access, and no KCA master key. It
only needs:
- `s3:GetObject` on the configured bucket/prefix;
- the CA certificate for each issuer;
- a delegated OCSP signer certificate and private key for each CA. The
responder currently accepts RSA-SHA256 and ECDSA P-256 signers in PKCS#8,
PKCS#1 RSA, or SEC1 EC PEM form.
## Snapshot layout
KCA publishes objects as:
```
<prefix>/<CA certificate SHA-256>.json
```
KCA publishes these objects when `KCA_OCSP_S3_BUCKET` is configured. The JSON
contains all certificates issued by that CA, both valid and revoked. The
responder never infers status from a partial revoked-only list.
## Run locally
1. Create a config based on `responder.example.yaml`.
2. Put your CA certificates and delegated signer files where the config points.
3. Export standard AWS credentials / endpoint variables as needed.
4. Make the signer key readable by the container user (`65532:65532` in the
published scratch image), or mount it via a Docker secret.
5. Run:
```sh
OCSP_CONFIG=./responder.yaml cargo run
```
The default listen address is `0.0.0.0:2560`.
The published image is built by Gitea Actions on `release/*` tags:
```sh
docker run --rm -p 2560:2560 \
-v "$PWD/responder.yaml:/etc/ocsp/responder.yaml:ro" \
-v "$PWD/ca:/etc/ocsp/ca:ro" \
-v "$PWD/signers:/etc/ocsp/signers:ro" \
-e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY \
gitea.woggioni.net/woggioni/kca-ocsp:latest
```
It runs `FROM scratch` and contains only a statically linked musl executable
and a CA bundle for outbound S3 HTTPS. There is no shell or package manager in
the image.
## Verify with OpenSSL
For a CA certificate `ca.crt` and leaf certificate `leaf.crt`:
```sh
openssl ocsp \
-issuer ca.crt \
-cert leaf.crt \
-url http://127.0.0.1:2560/ocsp \
-resp_text \
-noverify
```
`-noverify` skips local trust setup; the response still shows the signature
algorithm and included responder certificate. For production verification,
build a trust store containing the CA or validate with your normal PKI tooling.
## Endpoints
- `POST /ocsp` — `application/ocsp-request`
- `GET /ocsp/<base64url-request>` — optional GET form
- `GET /healthz`
- `GET /readyz`
## Cache and availability
- Per-CA cache TTL: `s3.cache_ttl_ms` (default 1000 ms).
- Concurrent requests for the same CA share one S3 `GetObject`.
- If S3 fails, a previously cached snapshot is served for
`s3.stale_grace_seconds`; otherwise the OCSP response is `tryLater`.
- With multiple CAs, the TTL is per CA. If you need a global one-request-per-
second limit across all CAs, that requires a shared rate limiter.