Here is a higher level view of the architecture and all the things that Terraform is provisioning. Based on my previous post, we know that certain things still require manual intervention but Terraform can provision a lot of stuff:
- Resource Group
- Event Grid Topics (but no Topics Subscriptions due to Function Access Key limitation)
- CosmosDB Account (but not databases or collections due to Throughput limitation)
- Key Vault (including Access Policies and Secrets)
- Azure Active Directory Application and Service Principal for the Application to use to authenticate itself
With this approach, each Azure Function is able to talk to Azure Key Vault to build connection strings to talk to the other Azure services we’re using (Event Grid and CosmosDB) and all secrets are protected through the Principle of Least Privledge using KeyVault Access Policies.
Application granted Access to Key Vault
- Service Principal created for application to authenticate itself with Azure Key Vault
- Azure Key Vault Access Policy created to allow application to access Key Vault
Secrets stored into Key Vault
In order to achieve this within Terraform we need to grant the Service Principal that Terraform is using with sufficient privledges to create / update / delete secrets within Azure Key Vault. You can adjust your access policy based on whether you want to break up create / delete operations. In a production environment you’ll probably use a different Service Principal to perform Terraform update / destroy operations.
Then we need to add the connection settings for Event Grid and CosmosDB into the Key Vault and finally jam those into our Function App’s Applications Settings.
- Azure Key Vault Access Policy created to allow Terraform to create / delete Azure Key Vault Secrets
- Event Grid topics’ endpoints and access keys are exported to Azure Key Vault
- CosmosDB endpoint, access key and connection strings are exported to Azure Key Vault
- Include application’s Terraform Service Principal into Function App’s App Settings
This is a pretty powerful configuration even with the given limitations of the AzureRM Terraform provider. Most of these activities would fall under the ‘do once and forget’ category but even these tasks are beneficial to codify given their proclivity to fade into obscurity. They say it takes 30 times of doing something before you can ‘master’ it. For these ‘do once and forget’ tasks the challenge is not getting them setup the first time. It’s about what happens after you dust them off after 3-6 months and need to do it again. Rather than asking yourself, Who actually set it up? Where did they put the documentation? What documentation? You can simply pull their git repo, alter the variables to the Terraform project and re-create everything they did. Immutable infrastructure is a wonderful thing, even when it happens to be serverless.