Vault Transit on Cloudflare Workers
Keys for Pulumi, SOPS and OpenBao, with no secret stored in CI.
edgekms answers the part of Vault's API that encryption clients use. A CI job logs in with GitHub's OIDC token, a person with an SSH key or a GitHub account, and each gets a short-lived token for exactly the keys its role allows. Your clients only need VAULT_ADDR.
Request an invite Read the quickstart
edgekms.dev is invite-only for now. Already in? Sign in to the console.
Works with what you already run
- Pulumi
hashivault://wraps each stack's data key. One decrypt perup. - SOPSSecrets files in git, decrypted with an edgekms token in a terminal or in CI.
- OpenBao
seal "transit"auto-unseal, with a revocable token that can use one key. - GitHub ActionsLog in with the job's OIDC token, bound to a repository and branch by id.
From sign-in to an encrypted stack
Your first sign-in gives you a tenant, https://<you>.edgekms.dev, with a key called default
and a role for your GitHub account. Log in to it with GitHub's device flow, and a Pulumi stack's
secrets can be wrapped under that key:
export VAULT_ADDR=https://you.edgekms.dev
export VAULT_TOKEN="$(edgekms login github --addr "$VAULT_ADDR" --role owner \
--client-id "$(curl -fsS https://api.edgekms.dev/v1/info | jq -r .github_client_id)")"
pulumi stack init prod --secrets-provider hashivault://default
In CI the same token comes from the job's OIDC token instead, so nothing long-lived is stored in the repository. The GitHub Actions guide shows the step.
You can always leave
An owner can export a tenant's root key whenever they like, even from a suspended tenant. With it
and the tenant's config, the open edgekms CLI decrypts everything offline, hands any key version
to OpenBao's or Vault's BYOK import, or a self-hosted edgekms Worker in
your own Cloudflare account serves the same keys. Every ciphertext and token stays valid.
How it keeps keys
Each tenant has its own root key, stored only wrapped under a master key in Cloudflare Secrets Store and used as a non-extractable WebCrypto key. Keys are derived from it, never stored. Every operation is audited before it returns, and plaintext, ciphertext and tokens are never logged. How it works is the overview, and the security model the detail, threat model included.