I have written some version of "never hardcode secrets, store them in Key Vault instead" in at least five of my last nine posts on this blog. I never actually stopped to explain what that means in practice. This post fixes that, using the real secrets this very blog depends on: a database connection string, an admin panel password, and a set of GitHub deployment credentials.
What Azure Key Vault Actually Is
Azure Key Vault is a managed service for storing secrets, encryption keys, and certificates securely in the cloud. Instead of a password sitting in a configuration file or a public GitHub repository where anyone with read access can see it, the password lives in Key Vault - encrypted, access-controlled, and logged every single time it is read.
Picture your code as a house with see-through walls - anyone looking at the repository can see everything inside, including any password left lying on the kitchen table. Key Vault is a bank vault a few streets away. Your code does not hold the password directly; it holds a key card that lets it walk over and request the password at the exact moment it is needed. Lose the key card, and you still cannot get into the vault without proper identity verification on top of it.
Three Things Key Vault Stores
Secrets are plain string values - passwords, connection strings, API keys, tokens.
Keys are cryptographic keys used for encrypting and decrypting data, or for signing and verifying it.
Certificates are X.509 certificates used for TLS or client authentication between services.
Most applications, including this one, primarily use the Secrets feature.
An Honest Admission About TechStackBlog's Own Setup
This blog does not actually use Key Vault directly today. The database password lives in Azure App Service Configuration. The admin panel password and deployment credentials live in GitHub Secrets. For a single-application personal project, this is a perfectly reasonable and secure setup.
Key Vault earns its place once you have multiple applications that need to share the same secret, once you need automated secret rotation, or once a compliance requirement demands a complete audit trail of every single
read. Understanding when a simpler tool is genuinely sufficient is as much a part of good engineering judgment as knowing how to use the more powerful tool when it is actually warranted.
Setting It Up For Real
Creating a Key Vault starts the same way as any other Azure resource - through the portal, in the same resource group as everything else. Adding a secret is a matter of giving it a name and a value under the Secrets blade.
The access model is where most of the real decisions happen. The modern, recommended approach uses Azure RBAC rather than the older Access Policies model - assign the "Key Vault Secrets User" role to whatever identity needs to read secrets, rather than the much more powerful "Key
Vault Administrator" role, which can also modify access policies and delete the vault entirely. An application that only needs to read a connection string should never hold administrator-level access.
Enabling Managed Identity on the consuming App Service is the final piece - this gives the application its own identity within Azure Active Directory, with no password or client secret to manage at all on the application's side.
The Code That Actually Reads a Secret
After installing the Azure.Identity and Azure.Security.KeyVault.Secrets NuGet packages, reading a secret from C# looks like this conceptually: construct a SecretClient pointed at your vault's URL, authenticate using DefaultAzureCredential, and call GetSecretAsync with the secret's name.
DefaultAzureCredential is the detail that makes this genuinely pleasant to work with rather than painful. It tries several authentication methods in sequence automatically - environment variables for CI/CD contexts, Managed Identity when running inside Azure, then falls back to your local Azure CLI or Visual Studio sign-in when running on your own machine during development. The practical result is that the exact same line of code works identically whether you are debugging locally or running in production App Service. No environment-specific branching, no "if local environment use this connection string, if production use that one."
For even simpler integration, App Service Configuration supports Key Vault references directly - a special value syntax that tells App Service to resolve the actual secret value from Key Vault at startup, using its own Managed Identity, with zero Key Vault SDK code required anywhere in the application at all.
Why Versioning Matters More Than It Sounds
Key Vault never overwrites a secret's value outright - updating a secret creates a new version while preserving every previous version with its own timestamp. Retrieving a secret without specifying a version always returns the current one, but a specific old version remains retrievable by its version identifier if ever needed.
The practical benefit is a built-in safety net. Roll back to a previous secret value instantly if a rotation goes wrong. Maintain a complete history of every value a secret has ever held. Accidentally overwriting a secret with the wrong value becomes a recoverable mistake rather than a permanent one.
Knowing Who Read What, And When
Every read of every secret can be logged automatically by enabling diagnostic settings on the vault and routing those logs into a Log Analytics workspace - the same workspace already used for Application Insights telemetry in a typical setup. From there, a KQL query against the diagnostic logs answers genuinely useful questions: did anyone access this secret outside normal business hours, which specific application is reading this secret and how frequently, and is some old deprecated application still pulling a secret it should no longer have access to at all.
Mistakes Worth Avoiding
Granting Key Vault Administrator when Key Vault Secrets User would suffice is the most common over-permissioning mistake - the application almost never needs to manage access policies or delete the vault, it just needs to read values.
Caching a secret value in application memory indefinitely with no refresh mechanism means that if the underlying secret rotates, the application keeps using the stale value until its next restart. Either set a reasonable cache expiry explicitly or rely on Key Vault references in App Service Configuration, which handle refresh automatically without any extra code.
Storing ordinary, non-sensitive configuration values in Key Vault is a subtler mistake - Key Vault has per-operation rate limits and an associated cost, and a simple page size or feature flag does not need the protection a real secret does. Reserve Key Vault for things that genuinely need secrecy.
Finally, Key Vault has soft-delete enabled by default, meaning deleted secrets remain recoverable for a retention period rather than disappearing instantly. This is usually a helpful safety net, but it also means a vault name cannot always be reused immediately after deletion during that window - worth knowing before it causes unexpected confusion during a rebuild.
Summary
Azure Key Vault exists so that passwords, connection strings, and certificates never have to sit directly inside application code or a public repository. Managed Identity removes the need to manage a credential purely to access your other credentials. Versioning provides a built-in safety net. Diagnostic logging provides real visibility into who is reading what.
None of this is mandatory for every project from day one - but understanding it properly means being able to make a deliberate, informed choice about when a simpler option like App Service Configuration is genuinely enough, and when it is time to bring in the vault.
Originally published at TechStack Blog:
https://www.techstackblog.com/post.html?slug=azure-key-vault-secrets-management
More from TechStack Blog, by category:
Azure: https://www.techstackblog.com/category.html?cat=azure
C# / .NET: https://www.techstackblog.com/category.html?cat=csharp
Follow for weekly posts on Azure, C#, and cloud engineering.
Top comments (0)