Managing Azure Policy with Terraform
/ 4 min read
Updated:Assuring the security of ones Cloud Environment is one of the Core Tasks of each Cloud (Security) Engineer. On the Azure Platform, Microsoft provides a diverse, sometimes overwhelming, set of tools to aid you with assessing and ensuring the security of your Infrastructure.
One of these tools is Azure Policy. Azure Policy is a service in Azure that you use to create, assign, and manage policies. These policies enforce different rules and effects over your resources, so those resources stay compliant with your corporate standards and regulatory requirements.
Azure Policy is especially helpful, because many of Azures Defaults that it might set for you are not always the most secure. Neither are they usually the most cost-effective and compliant with regulations.
In this article, we will explore how to manage Azure Policy with Terraform.
Prerequisites
To follow along with this guide you will need to already have the following:
- An active Azure Subscription with the permissions necessary to create Azure Policy Assignments and Definitions.
- Terraform installed on your local machine and configured to work with your Azure Subscription using the Azure Provider. (I recommend using the Azure CLI to authenticate with Azure)
- Basic knowledge of Azure Policy and Terraform.
Getting Started
To get started, we will first create a simple Terraform configuration that will deploy a Resource Group and a Storage Account. This will be the environment we will be using to demonstrate our further Azure Policy endeavors.
Create a new directory and add a new file named main.tf, this will contain everything we will use to test our Azure Configuration
terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "~>3.100.0" # Add the current Azure Provider Version } }}
# Configure the Azure Provider and Login via 'az login'provider "azurerm" { features {} subscription_id = "00000000-0000-0000-0000-000000000000"}
# Test Resource Groupresource "azurerm_resource_group" "rg" { name = "rg-policy-test" location = "germanywestcentral" tags = { testing = "true" }}
# Test Storage Accountresource "azurerm_storage_account" "test-account" { name = "sa-policy-test" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location account_tier = "Standard" account_replication_type = "GRS"
}With this now in place we can continue with assigning Policies to these Resources.
Step 1: Assigning a Policy Definition to a Resource Group
First we will try to assign a Policy Definition to our Resource Group. This will be a simple Policy that will deny the creation of any new Storage Accounts in our Resource Group.
To do this, we will use the built-in Policy Definition Deny storage accounts provided by Azure.
Add the following code to your main.tf file:
# Assigning the built-in Policy Definition to the Resource Groupresource "azurerm_policy_assignment" "deny_storage_accounts" { name = "deny-storage-accounts" scope = azurerm_resource_group.rg.id policy_definition_id = "/providers/Microsoft.Authorization/policyDefinitions/StorageAccounts_Deny"}Step 2: Creating a custom Policy Definition and Assigning it to a Resource Group
Next, we will create a custom Policy Definition that requires all Storage Accounts to have secure transfer enabled. We will then assign this Policy to our Resource Group.
Add the following code to your main.tf file:
# Custom Policy Definition to require secure transfer on Storage Accountsresource "azurerm_policy_definition" "require_secure_transfer" { name = "require-secure-transfer" policy_type = "Custom" mode = "All" display_name = "Require Secure Transfer on Storage Accounts" description = "This policy ensures that all Storage Accounts have secure transfer enabled." policy_rule = <<POLICY_RULE{ "if": { "field": "type", "equals": "Microsoft.Storage/storageAccounts" }, "then": { "effect": "deny", "details": { "field": "Microsoft.Storage/storageAccounts/supportsHttpsTrafficOnly", "equals": false } }}POLICY_RULE}# Assigning the custom Policy Definition to the Resource Groupresource "azurerm_policy_assignment" "assign_secure_transfer" { name = "assign-secure-transfer" scope = azurerm_resource_group.rg.id policy_definition_id = azurerm_policy_definition.require_secure_transfer.id}Step 3: Assigning and Creating a Policy Initiative
To assign multiple policies at once, we can create a Policy Initiative (also known as a Policy Set). In this step, we will create a Policy Initiative that includes both the built-in Deny storage accounts policy and our custom Require Secure Transfer on Storage Accounts policy.
Add the following code to your main.tf file:
# Creating a Policy Initiativeresource "azurerm_policy_set_definition" "storage_policy_initiative" { name = "storage-policy-initiative" policy_type = "Custom" display_name = "Storage Policy Initiative" description = "An initiative to enforce storage account policies." policy_definitions = [ { policy_definition_id = "/providers/Microsoft.Authorization/policyDefinitions/StorageAccounts_Deny" }, { policy_definition_id = azurerm_policy_definition.require_secure_transfer.id } ]}# Assigning the Policy Initiative to the Resource Groupresource "azurerm_policy_assignment" "assign_storage_initiative" { name = "assign-storage-initiative" scope = azurerm_resource_group.rg.id policy_definition_id = azurerm_policy_set_definition.storage_policy_initiative.id}Conclusion and Next Steps
This should allow you to get an overview on security weaknesses you might encounter.