A small, long-lived cluster-side resolver that lets the External Secrets Operator (ESO) sync seekrit secrets into Kubernetes — on stock, unmodified ESO — without the seekrit API ever seeing plaintext.
This repo is a read-only mirror, published from seekrit's monorepo so this service is auditable before you trust it with a service token inside your cluster. Don't commit directly here — it'll be overwritten on the next sync. Issues and PRs are welcome; accepted changes get ported upstream by a maintainer.
seekrit is zero-knowledge: GET /v1/resolve returns only ciphertext plus a DEK
wrapped to the caller's public key, and decryption happens client-side. ESO,
which expects to pull plaintext from a provider, therefore can't talk to the
seekrit API directly. This service is the missing client: it holds a service
token, resolves + decrypts locally via vendor/seekrit-core
(the same zero-knowledge path seekrit-run and seekrit-proxy use elsewhere in
seekrit), caches the result, and serves it over a tiny bearer-authed HTTP API
that ESO's built-in webhook provider reads.
ExternalSecret ─▶ ESO (stock) ──GET /v1/secret/NAME──▶ seekrit-sdk-server ──GET /v1/resolve──▶ seekrit API
(you write) (unmodified) Authorization: <key> holds skt_ token, (ciphertext +
decrypts locally, caches, wrapped DEK)
refreshes on a timer
Most users never run this directly — the
seekrit-eso Helm chart
deploys it and wires ESO for you. See the
Kubernetes guide.
- Startup (fail-closed). Reads
SEEKRIT_TOKEN, callsGET /v1/resolve, and decrypts every granted secret into memory. If the token is bad, the API is unreachable, or a layer won't decrypt, it refuses to start. - Serving. Answers three routes (below). Plaintext lives only in this
process, in
Zeroizingbuffers scrubbed on drop. - Refresh. Re-resolves every
--refresh-interval(default 60s) and swaps the snapshot atomically. A failed refresh is non-fatal — it keeps serving the last-good snapshot and logs a warning, so a transient API blip never breaks ESO syncs. - Auth.
/v1/secret*requireAuthorization: Bearer <api-key>(constant-time compared). The service decrypts everything the token can reach, so it must not be an open in-cluster endpoint; the key is the second line of defense behind the Service's network reachability.
| Method / path | Auth | Response |
|---|---|---|
GET /v1/secret/<name> |
Bearer <api-key> |
200 {"value":"…"} — or 404 if the name isn't in the resolved environment (lets ESO honor its deletionPolicy). |
GET /v1/secrets |
Bearer <api-key> |
200 {"data":{NAME:value,…}} — the whole environment, for target.template pulls. |
GET /healthz |
none | 200 (liveness/readiness). |
ESO's webhook provider reads a single value with result.jsonPath: "$.value".
export SEEKRIT_TOKEN=skt_…
export SEEKRIT_SDK_API_KEY=… # gates /v1/secret*
seekrit-sdk-server --listen 0.0.0.0:8080| Flag | Default | Meaning |
|---|---|---|
--listen <addr> |
0.0.0.0:8080 (SEEKRIT_SDK_LISTEN) |
Bind address. |
-t, --token <skt_…> |
SEEKRIT_TOKEN |
Service token (required). |
--api-key <key> |
SEEKRIT_SDK_API_KEY |
Bearer key for /v1/secret* (required). |
--api-url <url> |
SEEKRIT_API_URL or https://api.seekrit.dev |
API base URL. |
--refresh-interval <d> |
60s (SEEKRIT_SDK_REFRESH_INTERVAL) |
Re-resolve cadence: 30s, 5m, 1h, or bare seconds. |
One token = one environment. A service token binds to a single app environment (plus its composed group slices); that scope is this service's blast radius. To serve multiple environments, run one instance per token.
Published to Docker Hub as seekritdev/sdk-server (multi-arch, a single static
musl binary on scratch — no OS, no shell). latest + <version> are cut on
release; edge tracks main. Built and published from seekrit's monorepo CI,
not from this repo.
docker run --rm \
-e SEEKRIT_TOKEN=skt_… -e SEEKRIT_SDK_API_KEY=… \
-p 8080:8080 seekritdev/sdk-servercargo build --release # target/release/seekrit-sdk-server
cargo test # unit + HTTP integration tests
# Container (the shared crate is a named build context):
docker build -f Dockerfile --build-context seekrit_core=vendor/seekrit-core \
-t seekritdev/sdk-server .Vendored, not developed here: it's seekrit's shared,
transport-free zero-knowledge crate (service-token key recovery, DEK unwrap,
secret decryption), also used by seekrit-run and seekrit-proxy in the
private monorepo. Its canonical source lives there — changes to it arrive here
via the same mirror sync as everything else in this repo.