Azure 48: Per-Service Key Vault naming — `{service}-{abbrev}-kv-{env}`
easy⏱ 5 mincourseazure
Why per-service vaults
Blast radius. If odyssey-api's vault gets a misfiring RBAC change, cart-service is unaffected. It also keeps RBAC tight: only the workload identity that needs a secret has Read on that vault. A 'one vault to rule them all' approach inevitably grows wildcard Reader access until everything sees everything.
The naming components
service-prefix (e.g. odyssey, cart, lease, vehicle-search), purpose-abbrev (one letter or short code: cr = cron, s = subscriber, p = publisher, kv = generic), then kv, then env (dev|test|uat|prod). Total length must be ≤ 24 chars (Azure Key Vault limit). The convention forces you to keep prefixes short.
# Real Lythia vaults (from values-prod.yaml vaultNames)
odyssey-cr-p-kv-prod # Odyssey cron, publisher
lease-cons-s-kv-prod # Lease consumer, subscriber
vehicle-search-s-kv-prod # Vehicle search, subscriber
vehicle-avail-s-kv-prod # Vehicle availability, subscriber
dwmerchandis-kv-prod # DW merchandising (generic kv)
How pipelines consume them
Service pipelines list vaultNames: [odyssey-cr-p-kv-prod, lease-cons-s-kv-prod, …]. helm-deploy-v2.yaml loops over the list, runs AzureKeyVault@2 for each, and exposes the secrets as pipeline variables prefixed by the vault name (e.g. $(odyssey-cr-p-kv-prod-connectionstring)). The helm --set lines then reference those variables.
Build name generator + validator
Write buildVaultName(service, purpose, env) returning the dashed name; reject service longer than 14 chars, env not in dev/test/uat/prod, total length > 24. Write parseVaultName(name) returning { service, purpose, env } or null if invalid. Log generation for 3 valid combinations, then parse them back to verify round-tripping, then try an invalid one.
Use Azure region constraint
Pin every vault to the same region as its consumer (westus2 for Lythia). A cross-region Key Vault read costs you ~30ms of round-trip per startup. With 14 services × prod's 6 pods each = 84 startups; that's two seconds of latency you don't need.
Quiz: what if two services need the same secret?
DON'T put the same value in two vaults. Pick the owning team's vault and grant the second team Read. The Terraform module exposes the secret URI; the consumer references https://owner-vault.vault.azure.net/secrets/SECRET-NAME/. One value, one rotation, two readers.