Skip to main content
Version: v0.25.0 (Latest)

KMS Container

nexus.sphereon.com/edk-docker/enterprise-tenant-kms is the cryptographic authority for tenant runtime services. Every key the issuer signs credentials with, every signing key on an OID4VP request object, every key alias a tenant AS uses to sign access tokens, and every audit-checkpoint signing key lives on this container. The other runtime containers do not generate or hold key material; they reference keys by alias and call the KMS REST to operate on them.

That centralisation is deliberate. It lets a deployment use a single provider backend (an HSM, AWS KMS, Azure Key Vault) across all of its issuer, verifier, AS, and DID activity, with one place to manage key lifecycles and one audit trail for crypto operations. It also keeps the issuer, verifier, and AS images free of provider SDKs they would otherwise need to ship.

KMS container internal architecture

Why the KMS Is Internal-Only

The KMS sees raw key material on its way in to the provider backend and sees plaintext payloads on their way in to be signed. There is no scenario in which a public client should call it directly: wallets do not call KMS; relying parties do not call KMS; only the EDK's own issuer, verifier, AS, and DID containers do.

The Helm chart binds the KMS service to an internal LB, internal ingress, port-forward path, or service-mesh-only endpoint. The admin REST sits behind the same internal binding, with a bearer-JWT auth requirement: operators reach it through a port-forward, a bastion, or whatever internal access pattern the customer's cluster provides.

If a deployment ever needs the KMS reachable from outside, the right answer is almost always to put a peer-authenticated EDK service in front of it, not to expose the KMS itself.

Providers

A provider is the actual backend that holds the key material and performs the operations. The EDK ships first-party providers for:

  • Software keystore. Keys generated and held in process. Useful for development and for non-critical signing duties.
  • AWS KMS. Keys live in AWS KMS; the EDK provider issues Sign, Verify, and GetPublicKey calls. Provider configuration carries the AWS region, credential strategy, and the key id mapping.
  • Azure Key Vault. Keys live in Azure Key Vault under the configured vault URL. Authentication via the Azure credential chain (managed identity, service principal, environment).
  • Digidentity CSC. Keys held in a Digidentity Cloud Signature Consortium account, suitable for eIDAS qualified signing.
  • REST. A KMS provider that itself fronts another KMS over the EDK KMS REST surface. Useful when a tenant needs to route to a remote KMS instance behind the EDK KMS facade.

Providers register through the admin REST as typed configuration, never as raw JSONB. The provider id is a stable identifier (software-default, aws-eu-west-1, azure-vault-prod) that tenants reference when they bind a key alias.

A KMS instance can have any number of providers registered simultaneously. A tenant chooses which provider to use per signing duty by binding a kms_provider integration row on the tenant that uses the key (the issuer, verifier, or AS), pointing at the provider id on this KMS.

Key Aliases

A key alias is a logical name a runtime service uses to refer to a key. The alias structure is (tenant, service, purpose):

  • tenant: the tenant slug the key belongs to.
  • service: which service uses it: issuer, verifier, as, did, audit.
  • purpose: what the key signs: credential-signing, request-object-signing, access-token-signing, audit-checkpoint, did-update.

The first time a runtime service needs a key for a given alias, it either resolves to a system-provisioned default (the deployment template generates one per tenant on first activity) or to an operator-supplied alias the tenant admin has configured through the signing-key admin REST. Either way, the service never sees the raw key, it only sees the alias and the provider routing.

Key rotation is per-alias and per-tenant. The KMS holds the key history; the runtime service queries the current public key when it needs to publish JWKS or to verify a counterparty signature.

What the REST Surface Provides

The KMS exposes several HTTP adapter families, split by operational concern:

  • KeysHttpAdapter: global key generation, key import, key registration, key listing, key deletion, and key metadata read. Tenant context is JWT-bound.
  • ProvidersHttpAdapter: provider registration, provider configuration, provider listing. Platform-admin scoped.
  • CapabilitiesHttpAdapter: provider capability listing and provider matching via /capabilities, /providers/{providerId}/capabilities, /providers/query, and /providers/query/best.
  • ResolversHttpAdapter: public-key resolution by alias or key id. This is what the issuer, verifier, and AS call when they need to publish JWKS or verify a counterparty signature.
  • SignaturesHttpAdapter: raw signature creation and verification. Issuer credential signing, AS access-token signing, OID4VP request-object signing, and audit-checkpoint signing all land here.
  • EncryptionHttpAdapter: content encryption/decryption, key wrap/unwrap, and key agreement.
  • CertificatesHttpAdapter: CSR generation, certificate issuing, trusted certificate storage, and certificate-chain storage.

For keys, generation is the normal POST /keys and POST /providers/{providerId}/keys flow. Externally supplied key material is imported through /keys/import or /providers/{providerId}/keys/import. POST /keys/register is reserved for registering an existing provider-side key reference.

Multi-tenant isolation is enforced on every call: a tenant can only operate on its own keys, and no call can reach another tenant's key material.

Persistence

The KMS stores only key-reference bookkeeping in the tenant workload database: the key_reference table maps (tenant, alias) to (provider_id, kid, metadata) inside the resolved tenant schema. The actual key material lives in the provider backend. That separation is important: even if the database is exfiltrated, no key material is in it.

The persistence module is lib-crypto-key-persistence-postgresql. It also has a MySQL counterpart (lib-crypto-key-persistence-mysql) for deployments that standardise on MySQL.

Image and Runtime

The image is nexus.sphereon.com/edk-docker/enterprise-tenant-kms:<enterprise-version>, pulled from Sphereon's authenticated registry with the credentials issued during onboarding. The runtime is eclipse-temurin:21-jre with a non-root appuser (uid 10001) and port 8080 exposed.

The Helm chart binds the KMS service to an internal-only Service by default. services.kms.publicIngress.enabled is false; services.kms.internalIngress.enabled can be enabled for an internal ingress class when the cluster uses one. Operators can also reach it through port-forwarding, a service mesh, or an internal load balancer.

The minimal application.yaml shipped in the image is intentionally permissive for local testing:

server:
rest:
port: 8080
auth:
enabled: false
anonymous:
allowed: true

A production deployment overrides this through the standard EDK config layering (environment variables, mounted YAML overlays, cloud config providers) to require bearer-JWT auth on every call and to disable anonymous access. Per-tenant configuration, including provider routing and key alias overrides, lives in the tenant workload database under tenant_config_property in the resolved tenant schema.

Operational Notes

  • Capacity. The KMS is rarely the bottleneck for low-to-medium throughput. When it is, the bottleneck is usually the provider backend (AWS KMS rate limits, HSM throughput) rather than the container.
  • Failure modes. If the KMS is unreachable, signing-dependent paths fail immediately on the calling service. There is no fallback to a local key, by design. The deployment template's readiness probes consider the KMS dependency healthy before marking issuer/verifier/AS ready.
  • Provider failover. A tenant can configure multiple kms_provider integration rows and switch between them at the application level. The KMS itself does not currently sequence cross-provider failover automatically.
  • Auditing. Every signing operation emits an audit event with the tenant, alias, provider id, kid, and timestamp. The audit signing key alias is a KMS key in its own right ((tenant, audit, audit-checkpoint)).