This map was written after v0.2.0 shipped — the release predates the parity map
itself, and a git tag is immutable — so it is a retrospective reading rather
than a document published at the time. It is drawn from the v0.2.0 tree: the 66
routes it registers, the crypto it implements, and the CI jobs it ran.
main sat exactly on v0.2.0 when the map was first written, so this snapshot
and the map at that moment describe the same surface.
How the emulator’s surface maps to real Key Vault (as documented at
learn.microsoft.com/azure/key-vault ),
and — the point of this table — whether real work happens or just the API shape .
The design bet is that the durable, testable surface is protocol + real
cryptography + identity , and those are done for real: real RS256 token
validation, real RSA/EC keys doing real signing and encryption, real X.509
issuance. What is left out is the infrastructure around the vault — ARM, the
HSM, private networking — which no localhost process can honestly provide.
“Real via our own wire-protocol implementation.” A row is 🟢 Real not
only when real cryptography does the work, but also when the emulator itself
implements Key Vault’s wire protocol and the logic behind it — so a real,
unmodified SDK gets byte- and behaviour-identical responses. The Entra
challenge handshake, the object model and the error envelope are all in this
category.
Absent means 404, not 501
Unlike its sibling emulators, this one has no 501 stubs : a feature that
isn’t implemented simply has no route, so the SDK sees a 404 . A 🔴 below
therefore means “absent”, not “honestly refused”.
Meaning 🟢 Real Genuine work: real signed JWTs verified, real crypto, real X.509, real logic enforced — no pretending. 🟡 Emulated Faithful API contract + persisted state, but no engine — clock-derived or management-only. 🟠 Bring-your-own-engine Real when you attach a real external engine; contract-only otherwise. 🔴 Not implemented Absent (404).
Key Vault feature Emulator Type Entra bearer challenge (401 + WWW-Authenticate) Tokenless request returns the real challenge — Bearer authorization="…", resource="https://vault.azure.net" with AKV code AKV10000; unmodified azidentity walks it 🟢 Real Token validation (RS256 / JWKS / issuer / audience / expiry) Signature verified before any claim is read ; issuer + audience (string or array) + exp/nbf with 60s skew, on the emulator’s controllable clock; JWKS cached by kid, refetched once on miss 🟢 Real Principal derivation (oid → sub; idtyp=app → service principal) Full 🟢 Real Multi-tenant / multiple trusted issuers Exactly one issuer is configured 🔴 Not implemented
Key Vault feature Emulator Type Set / get / list / list-versions, get by version Full; real bytes persisted 🟢 Real Versioning (32-hex version per write) Full — every write mints a new version 🟢 Real Attributes enabled Enforced — a disabled object is refused 🟢 Real Attributes nbf / exp Stored and returned, informational only — deliberately not enforced, matching the documented emulator posture 🟡 Emulated Backup / restore Round-trips a base64url JSON blob (name + versions), not an opaque encrypted blob as real Key Vault emits 🟡 Emulated
Key Vault feature Emulator Type Create key — RSA 2048/3072/4096, EC P-256/P-384/P-521 Real crypto/rsa + crypto/ecdsa keygen 🟢 Real Sign / verify — RS256/384/512, PS256/384/512, ES256/384/512 Real PKCS#1v15 / PSS / ECDSA; ES* uses Azure’s raw r‖s encoding 🟢 Real Encrypt / decrypt — RSA1_5, RSA-OAEP, RSA-OAEP-256 Real RSA 🟢 Real Wrap / unwrap key Real — the same RSA path as encrypt/decrypt 🟢 Real Import key (JWK) Real: RSA n/e/d/p/q precomputed + validated; EC crv/x/y/d checked on-curve 🟢 Real Get random bytes Real crypto/rand, 1–128 enforced 🟢 Real Public JWK exposure (private material never leaves) Full — private PKCS#8 stays in the store 🟢 Real RSA-HSM / EC-HSM key typesAccepted, then silently normalised to software keys — no HSM exists 🟡 Emulated Secure Key Release (/release) Real signed JWS with a fresh signer and public JWK header, but no attestation — the claim is self-declared 🟡 Emulated Key rotation policy (get/set) Stored and round-tripped verbatim 🟡 Emulated Rotate key (POST /keys/{name}/rotate)— no route 🔴 Not implemented key_ops enforcementStored and echoed into the JWK, but not enforced — a sign-only key will still encrypt 🔴 Not implemented oct / oct-HSM symmetric keys— only RSA/EC are generated 🔴 Not implemented AES algorithms (A128/192/256 CBC/CBCPAD/GCM, AESKW)— the crypto paths require an RSA key 🔴 Not implemented BYOK (KEK-wrapped import)— import takes raw private members only 🔴 Not implemented Key backup / restore Round-trips a JSON blob carrying the private DER, not an opaque encrypted blob 🟡 Emulated
Key Vault feature Emulator Type Create self-signed certificate Real x509.CreateCertificate — random 128-bit serial, KeyUsage/ExtKeyUsage/BasicConstraints, SAN DNS names 🟢 Real Certificate policy (key_props, x509_props, issuer) Honoured — key type/size/curve, subject, SANs, validity months 🟢 Real Import — PKCS#12 (PFX) and PEM (PKCS#8 / PKCS#1 / SEC1) Real parsing; cert-only PEM supported 🟢 Real Linked key + secret materialised under the same name Full on create, as real Key Vault 🟢 Real Certificate signing request (PKCS#10) for a named issuer Real CSR; the operation reports inProgress with the CSR bytes 🟢 Real Merge a signed chain Real — and the leaf’s public key is verified to match the pending key before merge (400 otherwise) 🟢 Real Issuance by a real CA The emulator generates the key and a real CSR and merges the chain your CA signs — real X.509 only when you attach that CA 🟠 BYO-engine Delete cascade to the linked key/secret Diverges from real Key Vault : creation cascades, deletion does not, so delete → purge → restore can leave the linked objects behind🟡 Emulated Issuers / contacts Opaque document round-trip; they do not drive issuance 🟡 Emulated Certificate backup / restore Round-trips a JSON blob, not an opaque encrypted blob 🟡 Emulated Cancel / delete a pending certificate operation — no route 🔴 Not implemented
Key Vault feature Emulator Type Soft-delete → list-deleted → recover → purge (secrets, keys, certificates) Real state machine; retention validated 7–90 days 🟡 Emulated Retention window expiry Genuinely clock-driven — an object past purgeAt is purged lazily on read/list, against the controllable clock 🟡 Emulated Name reuse while soft-deleted → 409 Conflict Enforced 🟢 Real Purge protection / non-purgeable recoveryLevelrecoveryLevel is always Recoverable+Purgeable; purge is always allowed🔴 Not implemented
Key Vault feature Emulator Type Host-routed vaults ({name}.vault.azure.net) Full — host selects the vault; anything else falls back to the default vault 🟢 Real Canonical object IDs (https://{vault}.vault.azure.net/...) Always rendered canonically regardless of the listen address 🟢 Real TLS with a cert covering *.vault.azure.net Real self-signed material, persisted so fingerprints are stable 🟢 Real Paging (maxresults, nextLink) Full, capped at 25 🟢 Real Key Vault error envelope + x-ms-request-id On every response 🟢 Real api-version validation / version-differentiated behaviourNever read — any value (or none) is accepted and merely echoed into nextLink🔴 Not implemented
Key Vault feature Emulator Type Data-plane authorization A per-principal operation allowlist (POST /_emulator/permissions, ops named {type}/{op}, * wildcard); empty = full access 🟡 Emulated RBAC data-plane roles (Key Vault Secrets User, …)— 🔴 Not implemented Access policies (the classic vault access-policy document)— 🔴 Not implemented
Feature Purpose Clock control (/_emulator/clock) Freeze/advance/offset — makes token expiry and soft-delete retention deterministic Fault injection (/_emulator/faults) Force 429 + Retry-After or 500 for the next N requests, to exercise SDK retry paths Permissions (/_emulator/permissions) The authorization allowlist above Read-only portal (/_emulator/portal/) Inspect vault state in a browser
Real client (pinned) Surface exercised Status azsecrets (Azure Go SDK)Secrets, versions, soft-delete 🟢 CI test azkeys (Azure Go SDK)Keys, sign/verify, encrypt/decrypt, wrap/unwrap 🟢 CI test azcertificates (Azure Go SDK)Certificate create/import/merge 🟢 CI test azidentity (ClientSecretCredential)The Entra challenge handshake, against an in-process real entra-emulator 🟢 CI test Three-emulator chain (vault secret → managed identity → Entra → Fabric) The family integration, incl. a negative test 🟢 CI chain (stdlib HTTP, not an SDK) azure-keyvault-secrets / azure-identity (Python )Documented in the quickstart 🔴 Not wired in CI .NET / JavaScript SDKs Asserted to work 🔴 Not wired in CI
The Go SDK tests are the real oracle: they reconstruct an *rsa.PublicKey from
the returned JWK and verify an SDK-produced signature outside the SDK, with a
tampered-signature negative alongside.
Azure feature Why out of scope Type ARM control plane (create/delete vaults, Microsoft.KeyVault/vaults)A different plane: subscriptions, resource groups, deployments. The emulator serves the data plane a vault client talks to 🔴 Managed HSM (managedhsm.azure.net)A distinct service and a hardware trust boundary — a localhost process cannot honestly emulate an HSM’s guarantees 🔴 Private endpoints / firewall / network ACLs Network topology, not vault behaviour 🔴 Customer-managed-key encryption of the vault itself Infrastructure-level 🔴 Real CA issuance (DigiCert / GlobalSign integrations)Needs a real CA — hence the BYO-engine CSR/merge path above 🔴 Diagnostic logs / Event Grid notifications / metrics Azure Monitor surface 🔴