This template repository bootstraps a project for managing Azure infrastructure with Terraform.
Table of Contents
🔄 Continuous-integration with terraform plan
on every pull-request
🚀 Continuous-deployment with terraform apply
on every merge to the main branch
🔎 Static code analysis with terraform validate
🔐 Federated authentication to Azure from Github w/ OIDC (no credentials to manage)
📦️ Remote terraform state in Azure Blob Storage
📈 Rich change tracking with formatted information parsed from terraform's execution plan
🦺 Automatic resource locking in Azure (prevents configuration drift due to manual operations)
Setup your own project by following these steps
- An Azure subscription
- An account with the required permissions on the subscription
- Managed Identity Contributor or more privileged role
- Role Based Access Control Administrator or more privileged role
- Storage Account Contributor or more privileged role
- Key Vault Administrator role on the KeyVault
- An Azure Resource Group to deploy to
- An Azure Key Vault (with Soft-delete and Purge Protection enabled) to store an encryption key
-
Clone the new repository to your local machine
-
Edit the
utils/bootstrap/terraform.tfvars
file, replacing the indicated valuesVariable Required Description example/default location no Azure region to provision the managed identity northcentralus create_new_identity yes Whether to create a new managed identity (to use an existing identity see here) true resource_group_name yes Azure resource group to provision the managed identity in managed_identity_name yes Name to give the user assigned managed identity {App}-Terraform federated_credential_name yes Name to give the Github federated credential {App}-GH github_org yes The organization the new repository is in github_repository yes The name of the repository created from this template leave the
create_storage_account
andstorage_account_name
variables for now -
Continue to Configuring a Storage Account for remote state
-
Clone the new repository to your local machine
-
Edit the
utils/bootstrap/terraform.tfvars
file, replacing the indicated valuesVariable Required Description example/default create_new_identity yes Whether to create a new identity or use an existing one. This should be changed to false
true resource_group_name yes Azure resource group the managed identity is in managed_identity_name yes Name of the managed identity to use federated_credential_name yes Name to give the Github federated credential {App}-GH github_org yes The organization the new repository is in github_repository yes The name of the repository created from this template leave the
create_storage_account
andstorage_account_name
variables for now -
Continue to Configuring a Storage Account for remote state
-
Edit the
utils/bootstrap/terraform.tfvars
file, replacing the indicated valuesVariable Required Description example/default create_storage_account yes Whether to create a new storage account. This should be changed to true false storage_account_name yes The name of the storage account to create {App}-Infrastructure-Storage keyvault_name yes Keyvault to store a user managed encryption key for the storage account keyvault_resource_group no The resource group the keyvault is in. If not provided, uses the var.resource_group_name variable var.resource_group_name storage_account_whitelist_ips yes Set of IPs that are allowed to access the storage account. The IP of the execution environment for the setup script is included by default subscriptions_prefix yes Prefix of Azure subscription that the user has permissions to assign role assignment scopes to {Organization}- -
Continue to Run the setup script
This capability hasn't been added yet. Pull requests welcome!
The initial setup requires that you authenticate as your user principal to both Azure and Github.
Both providers can leverage access tokens issued to their CLI clients.
-
Authenticate with the Azure cli
If your user principal has all required permissions in Azure, you should be able to simply login.
az login
This will issue an access token (managed by the cli application) that the azurerm terraform provider will use to perform operations in Azure on your behalf.
-
Authenticate with the Github cli
To authenticate to Github and allow organization-level access, you need to configure two things.
-
Set
GITHUB_OWNER='<your-github-org>'
environment variableThis tells the Github cli to operate on your org, and not your personal account.
-
Create a classic Personal-Access-Token on your Github account
Required scopes:
- repo
- admin:org
- admin:public_key
Copy the token for the next step.
You may need to configure SSO if your enterprise uses Saml auth. Click the "Configure SSO" dropdown next to your new token and select the organization to authorize the token for.
-
Login to the Github cli
gh auth login
- select "GitHub.com"
- select "SSH" for the git protocol
- select an SSH key associated with your Github account
- press Enter for the SSH key title
- select "Paste an authentication token" and paste the previously created PAT
This will issue an access token (managed by the cli application) that the github terraform provider will use to perform operations in your Github org on your behalf.
-
-
From the
utils/bootstrap
directory, runterraform init terraform apply
This will configure your managed identity, create a federated token, create a storage account, and create some repository secret values in Github.
See bootstrap for more details.
By default, the managed identity has only one RBAC role assigned.
This role is required to allow the identity to manage remote terraform state in the storage account.
Other access and roles needed for managing your infrastructure must be setup yourself.
The project's main terraform script file must be at the project root.
Azure resources can be locked to prevent malicious or accidental misconfiguration by a user.
The included continuous-deployment pipeline provides automated resource locking after every deploy.
The only thing you need to do to opt-in to this feature is to add the desired resources to the locks.tf file.
Resource locks are recursively enforced. This means if you apply a resource lock on an Azure Resource Group, that lock also applies to all contained resources.
Creating and destroying resource locks with Terraform takes comparatively longer than most other resources (it takes between 90 and 150 seconds per lock for both destroy and create), so it's best to use as few as possible to keep your CI/CD runs short.