Repository navigation
v0.9.0
Kryptkeeper v0.9.0
Kryptkeeper is a self-hosted machine-identity and certificate-lifecycle
platform: a Go hub that runs your own CAs, issues certificates over ACME, EST,
SCEP, CMP and Microsoft autoenrollment (WSTEP/XCEP), publishes CRL and OCSP,
issues SSH certificates, discovers and inventories certificates across a
fleet, and renews and installs them without manual steps. A React dashboard
sits on top of the API. It runs from Docker Compose, Helm, Terraform or a
plain binary on SQLite or Postgres.
This is the first public release. Earlier versions (v1.0 to v2.2) were
internal milestones and were never published. Treat v0.9.0 as a release
candidate for 1.0: the core is validated against real clients (below), several
areas are labelled beta or experimental, and the version number says so.
Highlights
- Issuance and CAs: root and intermediate CAs, templates with name,
key-strength and SSH policy, CSR-in issuance, renew, revoke, import, fullchain
download, PQC (ML-DSA, hybrid) certificates with software keys. - Protocols: ACME (http-01, dns-01 for wildcards), EST, SCEP with one-time
challenges, CMP, WSTEP/XCEP for Windows GPO autoenrollment, CRL and OCSP. - Unattended renewal: the scheduler renews and installs on nginx, Apache or
HAProxy over SSH, on hosts running the agent, and on F5, Citrix, Kubernetes
and IIS targets. It verifies the served certificate, rolls back on failure,
retries with backoff, and tells the owner when it gives up. - Delivery plugins: sandboxed WebAssembly plugins with signed manifests and
trust tiers; F5 and Citrix ship as first-party plugins. - Discovery and inventory: network TLS scan (including ML-KEM detection),
Kubernetes and service-mesh discovery, WinRM agentless discovery (SSH agentless certificate discovery is not wired in v0.9),
read-only Cloud Keys inventory page. - Governance: append-only audit log with optional SIEM forwarding, approval
queue with proposer and approver separated, key dual control on by default,
custom roles, SSO (OIDC, SAML), SCIM, MCP server whose writes are
proposal-only. - Postgres, fully tested: every database-backed store has a round-trip test
on PostgreSQL (users and API keys, notifications, CA lifecycle and more), and
any purely additive migration is tolerated automatically on upgrade. - Key ceremonies: root-CA ceremonies work on SQLite and PostgreSQL; a root
stays pending until approved. A hub whose active CA has no key now refuses to
start (KRYPTKEEPER_ALLOW_MISSING_CA_KEYS=truefor recovery). - Notification rules: rules persist and fire under the default
delivery
provider, and are validated. - Complete audit trail: approval holds, dual-control proposals, skipped
alerts and workload attestations are all stored (migration000076), and
the Audit page andGET /api/v1/audit?outcome=filter by every outcome.
Notification providers that only record (file,db) skip alerts and audit
them asskippedinstead of reporting them sent. - Template validity:
validity_period(P30D,P1Y,72h,90d) is
honoured on issue and renew. - Security: a deep audit run on 2026-10-09 and the fixes for it (below).
What's validated
Results from 2026-10-11 on v0.9.0-rc.7 (main at 2f9e766) against real clients (full table
in docs/release/LIVE_RESULTS_v0.9.md).
Per-feature status for all 77 inventoried features is in
docs/release/FEATURE_VALIDATION_v0.9.md.
| Suite | Result | Real peer |
|---|---|---|
Smoke (tests/smoke) |
331/331 | hub binary, curl, local OIDC JWKS stub |
ACME (tests/live/acme) |
28/28 | certbot, lego |
Protocols (tests/live/protocols) |
all steps passed | openssl EST, SCEP, CMP, OCSP, CRL |
TLS (tests/live/tls) |
all steps passed | globalsign/est over the hub's own TLS |
SSH CA (tests/live/sshca) |
all steps passed | OpenSSH sshd and client |
Plugins (tests/live/plugins) |
all steps passed (27 checks) | example plugin, mock appliance, cosign |
Autopilot (tests/live/autopilot) |
all pass (29 checks) | nginx hosts and the agent, unattended |
Agent (tests/live/agent) |
18 passed, 0 failed | Linux container agent |
SSH install (tests/live/ssh-install) |
all pass (nginx, apache, rollback) | OpenSSH, nginx, apache |
go test ./..., the same with a PostgreSQL 16 test database (-p 1), and make test-race each pass
on 50 packages. The upgrade test was re-run on rc.5 (nine scenarios on SQLite and PostgreSQL) and
spot-checked on rc.7 (SQLite rc.1 and rc.2 and PostgreSQL rc.4 to rc.7, schema 76, including audit rows with
the new outcomes being stored); see
UPGRADE_TEST_v0.9.md.
Older dated runs not repeated on 2026-10-11 (Kubernetes, service mesh, notifications,
PKCS#11 on SoftHSM2, Docker Compose, WinRM/IIS, WSTEP/XCEP on a Windows lab
with Kerberos) are recorded in docs/UAT_PLAN.md.
Beta, experimental, and not in v0.9
- Beta (works; unit and integration tested only): reports, compliance
evidence, CBOM and PQC readiness; rollout groups and PQC migration waves;
SAML, OIDC and SCIM (tested against in-process IdPs, not Keycloak, Okta or
Entra); CT monitoring; cloud inventory; ADCS sync; Terraform provider;
air-gap bundle; MCP server; Helm chart (never install-tested on a cluster);
the UI has no browser end-to-end tests. - Experimental: multi-tenancy (see Security); HashiCorp Vault and GCP Cloud
KMS key stores (no tests). - Not verified on real hardware or accounts: the F5 and Citrix plugins
(mock devices only), cloud KMS (emulators only), SCEP from network devices,
the ACME upstream connector against Let's Encrypt staging (dns-01 via
Cloudflare; the live run is still pending). - Not in v0.9: finding exceptions and risk acceptance (v0.10); issuer
connectors other thaninternaland ACME (DigiCert, EST, SCEP and WSTEP
upstream connectors).
Upgrading from internal builds
v0.9.0 turns on several secure defaults. Before starting a v0.9.0 hub, read
"Upgrade notes (breaking or behaviour changes)" in the
CHANGELOG. The ones that stop a hub or
lock out an operator most often:
- Key export, backup and escrow need a second human to approve
(KRYPTKEEPER_KEY_DUAL_CONTROL=falseopts out). AUTH_MODE=jwtandoidcbearer tokens are read-only until
APP_AUTH_ROLE_CLAIMandAPP_AUTH_ROLE_MAP_JSONmap a role.- Secrets under 32 bytes, and OIDC mode without issuer and audience, are
startup errors. - Docker Compose needs
KRYPTKEEPER_KEYSTORE_PASSPHRASE, different from the
bootstrap token. - SSH certificates need a template with an
ssh_policy. - Behind a reverse proxy, set
APP_TRUSTED_PROXY_CIDRS. - API keys minted through
POST /api/v1/api-keyson earlier builds were lost at
every restart; re-mint them once (CHANGELOG upgrade notes 56 and 57). - An active CA with no key in the keystore stops the hub (note 58); existing
notification rules start alerting (note 59); templates withP1Ynow issue
1-year certificates (note 60).
Security
A deep audit of the whole repository (SAST, secrets in code and history,
dependencies, OWASP Web Top 10, OWASP LLM Top 10 for the MCP server, cloud,
IaC and CI, STRIDE threat model, 19 attack chains) ran on 2026-10-09 and
found 3 CRITICAL and 9 HIGH issues. A challenger review re-checked all 13
(none was wrong; three had their severity lowered). No live
secrets were found in code or git history, and no dependency is on the CISA KEV
list.
Everything CRITICAL and HIGH is fixed except tenant isolation. Fix groups FG-1
to FG-5 and FG-7 to FG-14 are merged (ACME issuance, key egress and separation
of duties, RBAC escalation, SSH CA policy, token hardening, login and session,
egress policy, issuance policy, plugins and MCP, cloud KMS, IaC and CI,
dependencies, documentation). Fixes ship with regression tests, and the live
smoke, ACME and SSH CA suites were re-run (results above).
Known limits you should plan around:
- Multi-tenancy is experimental (FG-6, due in v0.10). Tenant isolation is
not a security boundary: a tenant admin can act across tenants. The hub
refusesMULTI_TENANCYunlessKRYPTKEEPER_MULTI_TENANCY_EXPERIMENTAL=accept-risk
is set. Do not use it to separate mutually untrusting parties. See
docs/design/TENANCY_POSTURE.md. - Residual risks per OWASP category, such as in-memory refresh tokens and
replay caches (a restart forgets them), a denylist rather than a sandbox for
pluginremote_exec, and CMP using one shared secret per server, are listed
indocs/security/OWASP_TRACKER.mdand
docs/security/final-report.md.
Reporting a vulnerability: do not open a public issue. Use GitHub's
private "Report a vulnerability" advisory on this repository, or email
security@kryptkeeper.io. Targets: acknowledgement in 48 hours, initial
assessment in 5 business days, coordinated disclosure within 90 days. Full
policy: SECURITY.md.
Install
git clone https://github.com/bpmforge/kryptkeeper.git
cd kryptkeeper
cp env.example .env # set APP_BOOTSTRAP_TOKEN and KRYPTKEEPER_KEYSTORE_PASSPHRASE
docker compose up -dBoth values must differ; generate each with openssl rand -hex 32. The README
Quick Start continues through creating a template, issuing from a CSR,
fetching the CA certificate and verifying the chain. Helm, Terraform, binary
and air-gap installs are in docs/deployment.md and
docs/ops/AIRGAP_INSTALL.md.
Verify the release
The release workflow (.github/workflows/release.yml, driven by
.goreleaser.yaml) runs on a v* tag and publishes:
- archives for
kryptkeeper,kryptkeeper-agent,kryptkeeper-certmanager
andkryptkeeper-mcp(linux amd64 and arm64, darwin arm64),.deband
.rpmpackages for the hub,checksums.txt, and a CycloneDX SBOM per
archive; - multi-arch images at
ghcr.io/bpmforge/<name>, tagged0.9.0,0.9and
latest(novprefix).
What is signed: checksums.txt and the image manifests are signed
keyless with cosign (Sigstore, using the workflow's GitHub OIDC identity).
There is no long-lived signing key to fetch or trust. Archives, packages and
SBOMs are covered by the checksums, not signed individually.
V=0.9.0
curl -fsSLO https://github.com/bpmforge/kryptkeeper/releases/download/v$V/checksums.txt
curl -fsSLO https://github.com/bpmforge/kryptkeeper/releases/download/v$V/checksums.txt.sig
curl -fsSLO https://github.com/bpmforge/kryptkeeper/releases/download/v$V/checksums.txt.pem
cosign verify-blob \
--certificate-identity "https://github.com/bpmforge/kryptkeeper/.github/workflows/release.yml@refs/tags/v$V" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
--signature checksums.txt.sig --certificate checksums.txt.pem checksums.txt
sha256sum --ignore-missing -c checksums.txt # after downloading an archive
cosign verify \
--certificate-identity "https://github.com/bpmforge/kryptkeeper/.github/workflows/release.yml@refs/tags/v$V" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
ghcr.io/bpmforge/kryptkeeper:$VThe image build and push has not been exercised end to end before this release
tag, so treat the first image verification as a check of the pipeline itself.
Delivery plugins are signed separately by their publishers with
cosign sign-blob (see docs/ops/DELIVERY_PLUGINS.md).
Full list of changes: CHANGELOG.