@vendure/cloud-sealing
v0.7.0
Published
Seals a Vendure Cloud secret to its Cell's key: the sealed-variable v1 format, in Node and in the browser.
Readme
@vendure/cloud-sealing
Seals a Vendure Cloud secret on the machine that holds it, so that Vendure Cloud stores and forwards
only ciphertext. A secret is sealed once per purpose: a runtime copy, and for a build-scoped
secret also a build copy. The runtime copy is opened only inside the Cell that runs the environment.
The build copy is opened only by the build unseal function (vc-sealing-build-unseal) in shared
services.
This package holds the sealed-variable v1 format: the HPKE (RFC 9180) construction, the binding of
each value to its environment, variable and purpose, the wire shape, and the version tokens a set of
sealed values materialises under. The Vendure Cloud CLI, the Vendure Console, the control plane and
each Cell's unseal function all use it. It runs in Node and in the browser: its only dependency is
hpke, pinned exactly, and every primitive is the platform's
WebCrypto.
import {
SealPurpose,
SecretPlaintext,
recipientFromSpki,
sealValue,
} from "@vendure/cloud-sealing";
// `publicKeySpki` and `fingerprint` come from a sealing key statement the caller has verified.
const recipient = await recipientFromSpki(publicKeySpki, fingerprint);
const sealed = await sealValue({
recipient,
environmentId,
variableKey: "STRIPE_SECRET_KEY",
purpose: SealPurpose.RUNTIME,
value: SecretPlaintext.fromString(value),
});Seal only to a key whose signed statement you have verified for the environment's Cell, with this
package's verifySealingKeyStatement and the verifying keys your client ships. A refusal is a
SealingKeyStatementRejected whose code (StatementRejection) is stable; its reason is prose.
import {
parseSignedSealingKeyStatement,
verifySealingKeyStatement,
} from "@vendure/cloud-sealing";
const verified = await verifySealingKeyStatement(parseSignedSealingKeyStatement(statement), {
trustedKeys,
expectedScope: { kind: "cell", cellSlug, accountId, region },
now: new Date(),
});
const recipient = await recipientFromSpki(verified.publicKeySpki, verified.fingerprint);vectors/sealed-variable-v1.json is published with the package. Any implementation of the format
should open every vector with the recipient key it records, and none under another vector's binding.
@vendure/cloud-sealing/open opens a value whose recipient private key stays in a key service: the
caller supplies the ECDH step, such as KMS DeriveSharedSecret, and the opener rebuilds the binding
from its own arguments. Vendure Cloud's build unseal function uses it; a client that only seals never
imports it.
