Managing Azure Active Directory with Terraform
Learn how to manage Azure AD resources including users, groups, applications, and service principals using Terraform
Managing Azure Active Directory with Terraform
Azure Active Directory (Azure AD) is Microsoft’s cloud-based identity and access management service. This guide demonstrates how to manage Azure AD resources using Terraform.
Video Tutorial
Learn more about managing Azure Active Directory with Terraform in this comprehensive video tutorial:
Prerequisites
- Azure CLI configured with appropriate permissions
- Terraform installed (version 1.0.0 or later)
- Global Administrator or Privileged Role Administrator permissions
- Azure AD Premium P2 license (for some features)
Project Structure
terraform-azure-ad/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ └── ad/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── policies/
└── conditional_access.json
Azure AD Configuration
Create modules/ad/main.tf
:
# Azure AD Users
resource "azuread_user" "example" {
user_principal_name = "user@${var.domain_name}"
display_name = "Example User"
mail_nickname = "user"
password = var.user_password
force_password_change = true
usage_location = "US"
job_title = "Software Engineer"
department = "Engineering"
company_name = var.company_name
show_in_address_list = true
account_enabled = true
}
# Azure AD Groups
resource "azuread_group" "example" {
display_name = "Example Group"
description = "Example security group"
security_enabled = true
owners = [
data.azuread_client_config.current.object_id
]
members = [
azuread_user.example.object_id
]
}
# Azure AD Application
resource "azuread_application" "example" {
display_name = "Example Application"
web {
homepage_url = "https://example.com"
redirect_uris = ["https://example.com/auth/callback"]
implicit_grant {
access_token_issuance_enabled = true
id_token_issuance_enabled = true
}
}
required_resource_access {
resource_app_id = "00000003-0000-0000-c000-000000000000" # Microsoft Graph
resource_access {
id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d" # User.Read
type = "Scope"
}
}
api {
oauth2_permission_scope {
admin_consent_description = "Allow the application to access example on behalf of the signed-in user."
admin_consent_display_name = "Access example"
enabled = true
id = random_uuid.scope.result
type = "User"
user_consent_description = "Allow the application to access example on your behalf."
user_consent_display_name = "Access example"
value = "access_as_user"
}
}
}
# Service Principal
resource "azuread_service_principal" "example" {
application_id = azuread_application.example.application_id
app_role_assignment_required = false
features {
custom_single_sign_on_app = true
enterprise_application = true
}
tags = ["example", "terraform-managed"]
}
# App Role
resource "azuread_app_role" "example" {
application_object_id = azuread_application.example.object_id
allowed_member_types = ["User", "Application"]
description = "Example role for users"
display_name = "ExampleRole"
value = "example.role"
is_enabled = true
}
# Administrative Unit
resource "azuread_administrative_unit" "example" {
display_name = "Example Admin Unit"
description = "Example administrative unit for managing resources"
members = [
azuread_user.example.object_id
]
}
# Conditional Access Policy
resource "azuread_conditional_access_policy" "example" {
display_name = "Example Policy"
state = "enabled"
conditions {
client_app_types = ["all"]
applications {
included_applications = ["all"]
excluded_applications = []
}
users {
included_users = ["all"]
excluded_users = [
"GuestsOrExternalUsers"
]
}
platforms {
included_platforms = ["all"]
excluded_platforms = []
}
locations {
included_locations = ["all"]
excluded_locations = ["AllTrusted"]
}
}
grant_controls {
operator = "OR"
built_in_controls = ["mfa"]
}
session_controls {
application_enforced_restrictions_enabled = true
cloud_app_security_policy = "monitorOnly"
sign_in_frequency = 4
sign_in_frequency_period = "hours"
persistent_browser_mode = "always"
}
}
# Named Location
resource "azuread_named_location" "example" {
display_name = "Example Location"
ip_ranges = [
"203.0.113.0/24",
"198.51.100.0/24"
]
country {
countries_and_regions = [
"US",
"CA"
]
include_unknown_countries_and_regions = false
}
}
Authentication and Authorization
- OAuth2 Permissions
resource "azuread_application_oauth2_permission" "example" {
application_object_id = azuread_application.example.object_id
admin_consent_description = "Allow the application to access resources"
admin_consent_display_name = "Access Resources"
is_enabled = true
type = "User"
user_consent_description = "Allow the application to access resources on your behalf"
user_consent_display_name = "Access Resources"
value = "resource.access"
}
resource "azuread_application_password" "example" {
application_object_id = azuread_application.example.object_id
display_name = "Example Password"
end_date_relative = "8760h" # 1 year
}
- Role Assignments
resource "azuread_directory_role" "example" {
display_name = "Application Administrator"
}
resource "azuread_directory_role_assignment" "example" {
role_id = azuread_directory_role.example.template_id
principal_object_id = azuread_user.example.object_id
}
Security Configuration
- Authentication Methods
resource "azuread_authentication_strength_policy" "example" {
display_name = "Example Auth Policy"
description = "Example authentication strength policy"
allowed_combinations = ["password", "microsoftAuthenticator"]
}
resource "azuread_authentication_method_policy" "example" {
authentication_method_target {
target = "all_users"
authentication_method_target_state {
state = "enabled"
authentication_method_target_settings {
setting_name = "numberMatchingRequired"
setting_value = "true"
}
}
}
}
- Identity Protection
resource "azuread_identity_protection_policy" "sign_in_risk" {
display_name = "Sign-in risk policy"
state = "enabled"
conditions {
sign_in_risk_levels = ["high"]
users {
included_users = ["all"]
excluded_users = []
}
}
controls {
operation_type = "block"
}
}
Access Reviews
- Access Review Configuration
resource "azuread_access_review_schedule_definition" "example" {
display_name = "Example Access Review"
description = "Review access to resources"
scope {
query = "/groups/id-guid"
query_type = "MicrosoftGraph"
query_root = "group"
}
reviewers {
query = "/users/id-guid"
query_type = "MicrosoftGraph"
query_root = "user"
}
duration_in_days = 7
recurrence {
pattern {
type = "weekly"
interval = 1
}
range {
start_date = "2025-01-01"
number_of_occurrences = 52
}
}
}
Best Practices
-
Security
- Enable MFA
- Use conditional access
- Implement least privilege
- Regular access reviews
-
Identity Management
- Use groups for access
- Implement naming standards
- Regular cleanup
- Monitor sign-ins
-
Application Management
- Secure client secrets
- Review permissions
- Monitor usage
- Regular updates
-
Governance
- Implement policies
- Regular audits
- Document processes
- Monitor changes
Advanced Features
- Custom Security Attributes
resource "azuread_custom_security_attribute_definition" "example" {
attribute_name = "riskLevel"
attribute_type = "String"
is_collection = false
use_presets = false
permitted_values = [
"low",
"medium",
"high"
]
}
- Authentication Context
resource "azuread_authentication_context" "example" {
display_name = "High Security Access"
is_usable = true
}
resource "azuread_conditional_access_policy" "auth_context" {
display_name = "Require Strong Auth"
state = "enabled"
conditions {
client_app_types = ["all"]
applications {
included_applications = ["all"]
}
users {
included_users = ["all"]
}
authentication_context {
included_context_ids = [azuread_authentication_context.example.id]
}
}
grant_controls {
operator = "AND"
built_in_controls = ["mfa", "compliantDevice"]
}
}
Conclusion
You’ve learned how to manage Azure Active Directory using Terraform. This setup provides:
- User and group management
- Application registration
- Security policies
- Access controls
Remember to:
- Monitor security
- Review access regularly
- Update policies
- Maintain documentation