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

  1. 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
}
  1. 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

  1. 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"
      }
    }
  }
}
  1. 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

  1. 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

  1. Security

    • Enable MFA
    • Use conditional access
    • Implement least privilege
    • Regular access reviews
  2. Identity Management

    • Use groups for access
    • Implement naming standards
    • Regular cleanup
    • Monitor sign-ins
  3. Application Management

    • Secure client secrets
    • Review permissions
    • Monitor usage
    • Regular updates
  4. Governance

    • Implement policies
    • Regular audits
    • Document processes
    • Monitor changes

Advanced Features

  1. 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"
  ]
}
  1. 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