58. pepsi-keys

Manage the end-to-end key store.

58.1. Role

pepsi-keys is the operator’s tool for Pepsi’s end-to-end cryptography key store: pepsi.crypto_identity (the key pairs of the addresses we serve, private half included and wrapped at rest), pepsi.peer_key (remote correspondents’ cached public keys and certificates) and pepsi.ca_trust (the CA certificates inbound S/MIME chains are validated against). It connects through the shared [pepsi-postgres] section and reads the [pepsi] CRYPTO_* options and the [pepsi-crypto] section. It is not a stage. Reference: pepsi-keys(1); the design is explained in Key management.

It is one of the standalone binaries, outside the unified pepsi executable, for two reasons: it is the only program that generates key material (folding it in would link key generation and certificate issuance into every stage worker), and a site may install it setuid so users can manage their own identities — a bit a shared multi-call binary cannot carry.

58.2. Features

  • identity list / show — what material exists for an address: protocol, purpose, status, whether it is the primary for its capability, whether it is published, whether the private half is present, purged or was never held.

  • identity generate — create key material and store it. OpenPGP produces one transferable key (Ed25519 by default, RSA optional); S/MIME produces a signing and an encryption certificate, each self-signed for immediate use, or one certificate with both key usages under CRYPTO_SMIME_SHARED_KEY. --csr additionally emits a PKCS#10 request over each key, so a real CA can issue a replacement without re-keying.

  • identity import / export / csr — store material generated elsewhere, write material back out in its own binary form (--pem for X.509), or build a certificate request over an identity’s existing key.

  • identity revoke / retire / forget-private — the lifecycle. Revocation and the periodic retire sweep destroy private signing material and retain decryption material; forget-private is the explicit, confirmed way to destroy a decryption key.

  • identity set-primary / publish / delete — choose the material used for new messages, opt an address in or out of publication, or remove a row outright.

  • peer list / show / import / pin / unpin / refresh / remove — the cached peer keys. show applies the matching rule (an exact address always beats a hand-entered *@domain fallback); import stores a key with source manual, the only source permitted to name a whole domain.

  • ca list / add / enable / disable / remove — the S/MIME trust anchors. A certificate without basicConstraints CA:TRUE is refused, since no chain could ever end at it.

  • wrap rotate — re-wrap every stored private key under a new key-encryption key, incrementally and with --dry-run to look first.

  • dns — print the OPENPGPKEY (RFC 7929) and SMIMEA (RFC 8162) records that publish an address, under the hashed owner names those standards define. Only worth publishing in a DNSSEC-signed zone, which the output says.

58.3. Privilege model

Reaching a private key takes two independently guarded things: the pepsi-crypto database role — the only one granted the crypto_identity.private_wrapped column, every other service role holding a column-level grant that omits it — and the key-encryption key, which lives only in secrets.d/pepsi-crypto.secret. A stolen database yields ciphertext; the secret alone yields nothing.

pepsi-keys assumes that role only for the duration of each database call: started as root it becomes the account (root has no database role of its own) and returns afterwards. PostgreSQL peer authentication keys off the effective uid, not the gid, so a setgid bit would grant the group that guards the secret fragment but not the database identity.

The binary ships without a setuid bit, unlike pepsi-whitelist: one program able to open every private key in a deployment is a much larger prize than a single whitelist table. A site that wants users to manage their own identities installs it setuid pepsi-crypto; identities are owned by the passwd login their address resolves to, and an unprivileged caller may see and change only their own — enforced either way, so making it setuid is a site decision rather than a code change. Peer keys and trust anchors are deployment-wide and operator-only, listing included.

58.4. See also

Key management, pepsi-setup, pepsi-whitelist, pepsi-settings, Architecture, pepsi-keys(1), pepsi.conf(5).