HarperFast / HarperFast/harper
Consider envelope-encrypting TLS certificate private keys at rest (design/decision)
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
## Current state
TLS private keys live as plaintext PEM files under `/keys/` (e.g. `privateKey.pem`); `hdb_certificate` rows reference keys by `private_key_name` — key material is never in a table, but is unprotected against disk theft, backup exposure, and filesystem-read primitives.
## Why this is not a straightforward retrofit
**Boot ordering is the crux.** TLS contexts are built at server start (`security/keys.ts` loads keys from disk into the worker-local map); secrets **custody** registers only when the Pro secrets component loads. Encrypting TLS keys with the cluster secrets key creates a chicken-and-egg: the node cannot terminate TLS until custody is up, and under the two-key custody model a rebooted node may not be able to decrypt *at all* until a remote/operator share arrives — turning a security win into an availability coupling on every restart (incl. rolling restarts).
## Proposed shape (if we proceed)
- **Opt-in, per key file**: the keys loader detects an `enc:v1:` PEM (same `isEncryptedEnvValue` marker as env secrets) and decrypts via the registered decryptor (`resources/secretDecryptor.ts` hook already exists; the deferral precedent is `deferEncryptedEnvValue`). Plaintext keys keep working unchanged.
- Fail loudly (or defer that listener's TLS start) when an encrypted key is present without custody — never serve without the intended cert silently.
- Certificate ops and the ACME renewal path must seal on write, or renewal reintroduces plaintext.
- File-watch reload (`handlePrivateKeyReload`) must decrypt on reload too.
## Decision needed
Whether the at-rest gain justifies the boot/availability coupling, and whether custody init can be ordered ahead of TLS listener start (or scoped: encrypt only non-default/uploaded certs, not the bootstrap self-signed pair).
Refs: #1550/#1554/#1582 (secrets store + envelope format), two-key custody design (Confluence SD).
— filed by KrAIs (Claude, Fable 5) for Kris
Contributor guide
Research direction
Start by reading security/keys.ts and resources/secretDecryptor.ts, then review the precedents in #1550, #1554, and #1582. Trace boot ordering, certificate operations, ACME renewal, and handlePrivateKeyReload. Done means documenting a decision on the availability tradeoff and an agreed encryption scope and startup behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nodejs, typescript
- Domain
- security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100