Skip to content

Commit 36db526

Browse files
committed
policy template
1 parent d0b38a9 commit 36db526

7 files changed

Lines changed: 301 additions & 0 deletions

File tree

4_identity-security/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Last updated: 2026-02-09
1717
- [Microsoft Entra ID (Entra ID)](./entra_id)
1818
- [Azure Key Vault](./key-vault)
1919
- [User Assigned Managed Identity](./managed-identity)
20+
- [Azure Policy Assignment](./policy)
2021

2122
<!-- START BADGE -->
2223
<div align="center">
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Terraform Template - Azure Policy Assignment (with Managed Identity)
2+
3+
Costa Rica
4+
5+
[![GitHub](https://img.shields.io/badge/--181717?logo=github&logoColor=ffffff)](https://github.com/)
6+
[brown9804](https://github.com/brown9804)
7+
8+
Last updated: 2026-02-09
9+
10+
------------------------------------------
11+
12+
> This template contains Terraform configurations to create an Azure Policy Assignment scoped to a Resource Group, using a User Assigned Managed Identity.
13+
14+
> [!NOTE]
15+
> Some Azure Policies (for example, `DeployIfNotExists` / remediation scenarios) require an identity on the assignment. This template always creates a User Assigned Managed Identity and attaches it to the assignment.
16+
17+
## File Descriptions
18+
19+
- **main.tf**: Creates the Resource Group, User Assigned Managed Identity, and the Azure Policy Assignment.
20+
- **variables.tf**: Defines the input variables used in the Terraform configuration.
21+
- **provider.tf**: Configures the Azure provider to interact with Azure resources.
22+
- **terraform.tfvars**: Provides example values for the variables defined in `variables.tf`.
23+
- **outputs.tf**: Defines outputs such as the policy assignment ID and identity IDs.
24+
25+
## Variables
26+
27+
| Variable Name | Description | Type | Example Value |
28+
| --- | --- | --- | --- |
29+
| `resource_group_name` | The name of the Azure Resource Group to create and scope the assignment to. | string | `"rg-identity-security-dev"` |
30+
| `location` | The Azure region where the Resource Group and identity will be created. | string | `"East US"` |
31+
| `managed_identity_name` | The name of the User Assigned Managed Identity to create. | string | `"id-policy-identity-security-dev-001"` |
32+
| `policy_assignment_name` | The name of the Azure Policy Assignment. | string | `"pa-identity-security-dev-001"` |
33+
| `policy_definition_id` | The policy definition resource ID (built-in or custom). | string | `"/providers/Microsoft.Authorization/policyDefinitions/<id>"` |
34+
| `policy_assignment_display_name` | Optional display name for the assignment. | string | `"Identity/Security policy assignment (dev)"` |
35+
| `policy_assignment_description` | Optional description for the assignment. | string | `"Example policy assignment scoped to a resource group."` |
36+
| `policy_parameters_json` | Optional policy parameters JSON string. | string | `jsonencode({ effect = { value = "Audit" } })` |
37+
| `enforce` | Whether the policy should be enforced. | bool | `true` |
38+
| `tags` | A map of tags to assign to the resources. | map(string) | `{ "env": "dev" }` |
39+
40+
## Usage
41+
42+
1. Authenticate:
43+
44+
```sh
45+
az login
46+
```
47+
48+
2. Ensure Azure CLI has the correct active subscription:
49+
50+
```sh
51+
az account show
52+
# If needed:
53+
az account set --subscription "<subscription-id-or-name>"
54+
```
55+
56+
3. Initialize:
57+
58+
```sh
59+
terraform init -upgrade
60+
```
61+
62+
4. Validate and plan:
63+
64+
```sh
65+
terraform validate
66+
terraform plan
67+
```
68+
69+
5. Apply:
70+
71+
```sh
72+
terraform apply -auto-approve
73+
```
74+
75+
> [!NOTES]
76+
>
77+
> - This template creates the Resource Group for you.
78+
> - If you leave `policy_definition_id` as a placeholder, `terraform apply` will fail with `PolicyDefinitionNotFound`. Use Azure CLI to find a valid definition ID (built-in or custom), for example: `az policy definition list --query "[0].id" -o tsv`.
79+
> - If your policy requires remediation, you may need to grant the assignment identity additional Azure RBAC permissions at the assignment scope.
80+
81+
<!-- START BADGE -->
82+
<div align="center">
83+
<img src="https://img.shields.io/badge/Total%20views-1646-limegreen" alt="Total views">
84+
<p>Refresh Date: 2026-02-09</p>
85+
</div>
86+
<!-- END BADGE -->

4_identity-security/policy/main.tf

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# main.tf
2+
# This file contains the main configuration for creating an Azure Policy Assignment.
3+
# It creates a Resource Group, a User Assigned Managed Identity, and a Policy Assignment scoped to the Resource Group.
4+
5+
resource "azurerm_resource_group" "example" {
6+
name = var.resource_group_name
7+
location = var.location
8+
9+
tags = var.tags
10+
}
11+
12+
resource "azurerm_user_assigned_identity" "example" {
13+
name = var.managed_identity_name
14+
location = azurerm_resource_group.example.location
15+
resource_group_name = azurerm_resource_group.example.name
16+
17+
tags = var.tags
18+
19+
depends_on = [
20+
azurerm_resource_group.example
21+
]
22+
}
23+
24+
resource "azurerm_resource_group_policy_assignment" "example" {
25+
name = var.policy_assignment_name
26+
resource_group_id = azurerm_resource_group.example.id
27+
policy_definition_id = var.policy_definition_id
28+
29+
location = azurerm_resource_group.example.location
30+
display_name = var.policy_assignment_display_name
31+
description = var.policy_assignment_description
32+
parameters = var.policy_parameters_json
33+
34+
enforce = var.enforce
35+
36+
identity {
37+
type = "UserAssigned"
38+
identity_ids = [azurerm_user_assigned_identity.example.id]
39+
}
40+
41+
depends_on = [
42+
azurerm_user_assigned_identity.example
43+
]
44+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# outputs.tf
2+
# This file defines the outputs of the Terraform configuration.
3+
4+
output "policy_assignment_id" {
5+
description = "The resource ID of the Policy Assignment."
6+
value = azurerm_resource_group_policy_assignment.example.id
7+
}
8+
9+
output "policy_assignment_name" {
10+
description = "The name of the Policy Assignment."
11+
value = azurerm_resource_group_policy_assignment.example.name
12+
}
13+
14+
output "policy_assignment_scope" {
15+
description = "The scope of the Policy Assignment."
16+
value = azurerm_resource_group.example.id
17+
}
18+
19+
output "managed_identity_id" {
20+
description = "The resource ID of the User Assigned Managed Identity used by the Policy Assignment."
21+
value = azurerm_user_assigned_identity.example.id
22+
}
23+
24+
output "managed_identity_name" {
25+
description = "The name of the User Assigned Managed Identity used by the Policy Assignment."
26+
value = azurerm_user_assigned_identity.example.name
27+
}
28+
29+
output "managed_identity_client_id" {
30+
description = "The client ID (application ID) of the User Assigned Managed Identity."
31+
value = azurerm_user_assigned_identity.example.client_id
32+
}
33+
34+
output "managed_identity_principal_id" {
35+
description = "The principal ID (object ID) of the User Assigned Managed Identity."
36+
value = azurerm_user_assigned_identity.example.principal_id
37+
}
38+
39+
output "resource_group_name" {
40+
description = "The name of the Resource Group created for this template."
41+
value = azurerm_resource_group.example.name
42+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# provider.tf
2+
# This file configures the Azure provider to interact with Azure resources.
3+
# It specifies the required provider and its version, along with provider-specific configurations.
4+
5+
terraform {
6+
required_version = ">= 1.8, < 2.0"
7+
8+
required_providers {
9+
azurerm = {
10+
source = "hashicorp/azurerm"
11+
version = "~> 3.116"
12+
}
13+
}
14+
}
15+
16+
provider "azurerm" {
17+
features {
18+
resource_group {
19+
prevent_deletion_if_contains_resources = false
20+
}
21+
}
22+
23+
# Uses the current Azure CLI context (az login + az account set)
24+
skip_provider_registration = false
25+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Example values for the Azure Policy Assignment template
2+
3+
resource_group_name = "rg-identity-security-dev"
4+
location = "East US"
5+
managed_identity_name = "id-policy-identity-security-dev-001"
6+
policy_assignment_name = "pa-identity-security-dev-001"
7+
8+
# Provide a built-in or custom policy definition ID.
9+
# Example format: /providers/Microsoft.Authorization/policyDefinitions/<policyDefinitionId>
10+
# Tip: list definitions with:
11+
# az policy definition list --query "[0].id" -o tsv
12+
policy_definition_id = "/providers/Microsoft.Authorization/policyDefinitions/0004bbf0-5099-4179-869e-e9ffe5fb0945"
13+
14+
# Optional
15+
policy_assignment_display_name = "Identity/Security policy assignment (dev)"
16+
policy_assignment_description = "Example policy assignment scoped to a resource group."
17+
18+
# Optional parameters JSON (only if your policy expects parameters)
19+
# policy_parameters_json = jsonencode({
20+
# effect = {
21+
# value = "Audit"
22+
# }
23+
# })
24+
25+
enforce = true
26+
27+
tags = {
28+
env = "dev"
29+
app = "identity-security"
30+
owner = "terraform"
31+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# variables.tf
2+
# This file defines the input variables used in the Terraform configuration.
3+
4+
variable "resource_group_name" {
5+
description = "The name of the Azure Resource Group to create and scope the Policy Assignment to."
6+
type = string
7+
}
8+
9+
variable "location" {
10+
description = "The Azure region where the Resource Group (and Managed Identity) will be created."
11+
type = string
12+
}
13+
14+
variable "managed_identity_name" {
15+
description = "The name of the User Assigned Managed Identity to create for the Policy Assignment."
16+
type = string
17+
18+
validation {
19+
condition = length(trimspace(var.managed_identity_name)) > 0
20+
error_message = "managed_identity_name must not be empty."
21+
}
22+
}
23+
24+
variable "policy_assignment_name" {
25+
description = "The name of the Azure Policy Assignment."
26+
type = string
27+
28+
validation {
29+
condition = length(trimspace(var.policy_assignment_name)) > 0 && length(var.policy_assignment_name) <= 64
30+
error_message = "policy_assignment_name must be 1-64 characters."
31+
}
32+
}
33+
34+
variable "policy_definition_id" {
35+
description = "The resource ID of the Policy Definition (built-in or custom) to assign. Example: /providers/Microsoft.Authorization/policyDefinitions/<id>"
36+
type = string
37+
38+
validation {
39+
condition = length(trimspace(var.policy_definition_id)) > 0
40+
error_message = "policy_definition_id must not be empty."
41+
}
42+
}
43+
44+
variable "policy_assignment_display_name" {
45+
description = "Optional display name for the Policy Assignment."
46+
type = string
47+
default = null
48+
}
49+
50+
variable "policy_assignment_description" {
51+
description = "Optional description for the Policy Assignment."
52+
type = string
53+
default = null
54+
}
55+
56+
variable "policy_parameters_json" {
57+
description = "Optional policy parameters JSON string. Example: jsonencode({ effect = { value = \"Audit\" } })"
58+
type = string
59+
default = null
60+
}
61+
62+
variable "enforce" {
63+
description = "Whether the Policy Assignment should be enforced. Defaults to true."
64+
type = bool
65+
default = true
66+
}
67+
68+
variable "tags" {
69+
description = "A map of tags to assign to the resources."
70+
type = map(string)
71+
default = {}
72+
}

0 commit comments

Comments
 (0)