The need to store sensitive information securely in Cloud environments is both hugely important and challenging. Azure Key Vault can help.
Imagine a simple scenario where you are part of a team developing a Cloud-native application. The application needs to access an Azure SQL Database and an Azure Storage account. You should avoid hard-coding your authentication credentials and instead consider using the Key Vault.
First, let’s define what Azure Key Vault actually is. It is a SaaS platform specifically designed for storing Secrets, Keys, and Certificates which your applications can then use via client libraries, calling on the vault to retrieve and store the contents rather than hard-coding them in to your code. When you create one, it is exposed directly to the Internet and is assigned a Fully Qualified Domain Name, although at time of creation there is nothing inside the vault. You control access to the Key Vault itself using standard IAM Roles. You control access to the contents of Key Vault by using Access Policies. In either case, IAM allows you to assign permissions to users and applications (applications being represented as Service Principals or Managed Identities). Azure Key Vault is now a supported Service Endpoint as well, which means you can attach it to a VNET in Azure and restrict access to it via a firewall policy. Bear in mind while this is definitely a recommended practice, no matter how you slice it, this is a public endpoint. Secure your vaults accordingly.
Second, a bit of clarification. Just because you are storing things in Key Vault doesn’t mean that those contents are fully secured. The purpose of Key Vault is to allow your applications to read values from the vault so that they don’t exist as unsecured strings in your code, not necessarily to hide the secrets from developers. If you are writing an application and leveraging Key Vault, not only can that application read data from the vault, but any developer with access to modify and run the application can easily see the contents of the vault.
Let’s dive in…
The following commands will create your Key Vault in a new Resource Group.
# Login in to Azure az login # Set your Subscription az account set --subscription <subscription name or ID> # Create a Resource Group in the specified Region az group create -n "KeyVaultGroup" -l "East US" # Create the Key Vault az keyvault create --name "ApplicationVault" --resource-group \ "KeyVaultGroup" --location "East US"
Now that you have a Key Vault, you need to store your desired sensitive authentication information. One way to do so is by leveraging Key Vault Secrets. A secret in Key Vault is very straightforward; you store a value as a secret, Key Vault encrypts it, and you allow people or applications to perform Operations on the Secret, such as Get. A secret value could be many things, but in this scenario we’re going to store both an Azure SQL password and an Azure Storage Account SAS token.
# Login in to Azure az login # Set your Subscription az account set --subscription <subscription name or ID> # Create a Resource Group in the specified Region az group create -n "KeyVaultGroup" -l "East US" # Create the Key Vault az keyvault create --name "ApplicationVault" --resource-group \ "KeyVaultGroup" --location "East US"
# Add a secret containing the Azure SQL password az keyvault secret set --vault-name "ApplicationVault" --name "DevSQLPassword" --value "complexpasswordhere" # Add a secret containing an Azure Storage Account SAS token az keyvault secret set --vault-name "ApplicationVault" --name "DevStorageSASToken" --value "https://myaccount.blob.core.windows.net/?<sastokenhere>"
Now you’ve got two secret values in a Key Vault and you need to access them from an application. It helps to understand how Key Vault access actually works.
There are two independent security controls on a Key Vault–the IAM Roles and the Access Policies. The IAM Roles are assigned at the resource level (the actual Key Vault itself) and the Access Policies are attached to what you are storing in the Key Vault. Let’s assume that an Azure AD user has been granted the Contributor role, which essentially gives the user full rights to the Key Vault (less the ability to further control access to the Key Vault resource). You might think that as a Contributor, you have access to all Secrets, Certificates, and Keys in the vault. You would be wrong there.
In order to access Secrets, Certificates, and Keys within the vault, you must also be attached to the appropriate Access Policy permitting you to do so. If you are not attached to any access policies, you have absolutely no access to secrets, certificates, or keys, regardless of your IAM Role set at the Key Vault resource level. To remedy this, you need to be assigned to an Access Policy and that policy must have the appropriate Operations attached. See the Azure Key Vault API documentation for full details regarding Operations. Access Policies are granular. For example, you could assign a user to an access policy that can List secrets only. As you may expect, that user wouldn’t be able to actually Read the Secret value, but they could List secrets in that vault. In practice, this allows you to effectively manage the contents of your Key Vault where concepts such as least privilege and separation of duties come in to play. If you are interested in reading more about Key Management Best Practices, the NIST Key Management Guidelines are a great reference.
Back to the issue at hand! We still need to allow our application access to secrets in our Key Vault. I just described how Access Policies work, using a User as an example. For an application, the recommended approach is to use a Service Principal in Azure AD, which is essentially an identity for your application. Rather than a username and a password, a service principal has an Application ID and key, or an Application ID and certificate. Using a certificate is the more secure of the two options as you need the certificate itself to authenticate, but it is slightly more difficult to configure and manage. We will use a principal with a key (aka a secret) instead.
# Create the Service Principal, skip tenant-level permissions assignments az ad sp create-for-rbac -n "MyDevApp" --skip-assignment # Assign an access policy that allows your app to retrieve (Get) secrets from the vault az keyvault set-policy --name "ApplicationVault" --spn <appidgoeshere> --secret-permissions get
Be sure to make note of the password that was generated, as it will not be available to you later and it is possible that you will need it at some point. You could actually store it in a Key Vault as a secret. Also note, this key tied to the Service Principal will expire in 1 year, although that is configurable. See the az cli documentation for further information.
It is pretty clear what we’ve just done. Using az ad sp we created a Service Principal for our application. Using az keyvault, we attached this identity to a policy on the Key Vault which has permissions to Read secrets. If possible, always practice least privilege access, which we’ve just done by allowing the Service Principal access to only Read secrets. Check Secret Operations for a detailed listing of all Secret Operations.
That’s it. You now have a Key Vault, two secrets, and a Service Principal which serves as an identity for your application. That Service Principal is attached to an Access Policy that will allow your application to retrieve/read the secrets in the Key Vault. The only thing left is to configure your application. Check back later for a post that describes doing just that. In the meantime, you may want to check out the Azure Key Vault Client.