Building Production-Ready Microsoft Entra Domain Services with Terraform

Microsoft Entra Domain Services (formerly Azure AD Domain Services) is a crucial component for organizations looking to implement hybrid identity solutions in Azure. While Azure provides managed domain controllers, setting up a production-ready deployment with proper security, monitoring, and networking requires careful planning and configuration.

Microsoft Entra Domain Services (formerly Azure AD Domain Services) is a crucial component for organizations looking to implement hybrid identity solutions in Azure. While Azure provides managed domain controllers, setting up a production-ready deployment with proper security, monitoring, and networking requires careful planning and configuration.

In this post, I’ll walk you through a comprehensive Terraform template I’ve developed that automates the deployment of Microsoft Entra Domain Services with enterprise-grade security, monitoring, and CI/CD integration.

Why Terraform for Domain Services?

Traditional Azure portal deployments can be time-consuming and error-prone, especially when dealing with complex networking and security requirements. Infrastructure as Code (IaC) with Terraform provides:

  • Reproducible deployments across environments
  • Version control for infrastructure changes
  • Automated validation and security scanning
  • Consistent configuration and compliance
  • Documentation through code

Template Architecture

The template creates a complete authentication infrastructure with the following components:

Core Infrastructure

  • Resource Group with proper tagging and naming conventions
  • Virtual Network with dedicated subnet for Domain Services
  • Network Security Groups with least-privilege access rules
  • Microsoft Entra Domain Services using the latest AzAPI provider

Security Features

  • Key Vault integration for certificate management
  • Secure LDAP (LDAPS) support with automated certificate handling
  • Network isolation with dedicated subnets and NSG rules
  • Role-based access control (RBAC) for service principals

Monitoring & Observability

  • Log Analytics Workspace for centralized logging
  • Diagnostic settings for comprehensive telemetry
  • Security alerts for failed authentication attempts
  • Performance monitoring with custom dashboards

High Availability

  • Replica sets support for multi-region deployments
  • Backup configuration for Enterprise SKU
  • Health monitoring and automated recovery

Key Technical Challenges Solved

1. AzAPI Provider Requirement

One of the first challenges was discovering that Microsoft Entra Domain Services requires the AzAPI provider instead of the standard AzureRM provider:

# ❌ This doesn't work
resource "azurerm_active_directory_domain_service" "main" {
  # Not available in AzureRM provider
}

# ✅ Correct approach
resource "azapi_resource" "domain_services" {
  type      = "Microsoft.AAD/DomainServices@2021-05-01"
  name      = var.domain_name
  parent_id = azurerm_resource_group.main.id
  # ... configuration
}

2. Variable Validation Constraints

Terraform variable validation has strict rules about cross-variable references. I had to refactor validation logic to only reference the variable being validated:

# ❌ Invalid - references other variables
validation {
  condition = var.enable_secure_ldap == false || length(var.certificate_thumbprint) > 0
  error_message = "Certificate required when LDAP enabled."
}

# ✅ Valid - only references itself
validation {
  condition = var.certificate_thumbprint == "" || length(var.certificate_thumbprint) >= 40
  error_message = "Certificate thumbprint must be at least 40 characters."
}

3. CI/CD Without Azure Authentication

Creating a testing strategy that validates the template without requiring Azure credentials:

# CI/CD testing approach
ARM_SKIP_PROVIDER_REGISTRATION=true ARM_USE_CLI=false \
  terraform plan -var-file="terraform.tfvars.ci"

This allows complete validation of syntax, logic, and variable constraints in automated pipelines.

Security Best Practices Implemented

Network Security

# Restrictive NSG rules for Domain Services
security_rule {
  name                       = "AllowLDAPS"
  priority                   = 1001
  direction                  = "Inbound"
  access                     = "Allow"
  protocol                   = "Tcp"
  source_port_range         = "*"
  destination_port_range    = "636"
  source_address_prefixes   = var.allowed_source_addresses
  destination_address_prefix = var.subnet_address_prefix
}

Identity & Access Management

# Custom RBAC role for Domain Services operators
resource "azurerm_role_definition" "domain_services_operator" {
  name        = "Domain Services Operator"
  scope       = azurerm_resource_group.main.id
  description = "Manage domain services resources"

  permissions {
    actions = [
      "Microsoft.AAD/domainServices/read",
      "Microsoft.AAD/domainServices/write",
      "Microsoft.AAD/domainServices/restart/action"
    ]
    not_actions = [
      "Microsoft.AAD/domainServices/delete"
    ]
  }
}

Certificate Management

resource "azurerm_key_vault" "main" {
  # Security features
  enable_rbac_authorization   = true
  enabled_for_disk_encryption = true
  purge_protection_enabled    = true
  soft_delete_retention_days  = 90

  # Network access controls
  public_network_access_enabled = false
  
  network_acls {
    default_action = "Deny"
    bypass         = "AzureServices"
    virtual_network_subnet_ids = [azurerm_subnet.domain_services.id]
  }
}

Development Experience Features

Cross-Platform Tooling

The template includes both Makefile for Linux/macOS and PowerShell scripts for Windows:

# Linux/macOS
make test-ci      # Run CI validation
make security     # Security scan
make docs         # Generate documentation

# Windows
.\scripts.ps1 test-ci    # Run CI validation
.\scripts.ps1 security   # Security scan
.\scripts.ps1 docs       # Generate documentation

Pre-commit Hooks

Automated quality gates using pre-commit hooks:

repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
  rev: v1.83.5
  hooks:
    - id: terraform_fmt
    - id: terraform_validate
    - id: terraform_tfsec
    - id: terraform_docs

Comprehensive Documentation

The template includes extensive documentation:

  • Architecture diagrams and technical details
  • Configuration guide with environment-specific examples
  • Security best practices and compliance guidelines
  • Troubleshooting guide with common issues and solutions

CI/CD Pipeline Integration

GitHub Actions

name: 'Terraform Validation'

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  terraform-validate:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: hashicorp/setup-terraform@v3
    
    - name: Terraform Validate
      run: terraform validate
      
    - name: Security Scan
      uses: aquasecurity/tfsec-action@v1.0.3
      
    - name: Plan with CI Config
      run: terraform plan -var-file="terraform.tfvars.ci"
      env:
        ARM_SKIP_PROVIDER_REGISTRATION: true
        ARM_USE_CLI: false

Azure DevOps

The template includes Azure DevOps pipeline with:

  • Multi-stage validation
  • Security compliance checks
  • Automated documentation generation
  • Cost estimation integration

Real-World Usage Examples

Development Environment

# terraform.tfvars for development
resource_group_name = "rg-entradomain-dev"
domain_name        = "dev.contoso.local"
sku               = "Standard"
enable_secure_ldap = false
replica_sets      = []

Production Environment

# terraform.tfvars for production
resource_group_name = "rg-entradomain-prod"
domain_name        = "contoso.local"
sku               = "Premium"
enable_secure_ldap = true

replica_sets = [
  {
    location = "North Europe"
    subnet_id = "/subscriptions/.../subnets/replica-subnet"
  }
]

notification_settings = {
  notify_dc_admins      = true
  notify_global_admins  = true
  additional_recipients = ["ops-team@contoso.com"]
}

Lessons Learned

1. Provider Limitations

Not all Azure services are available in the standard AzureRM provider. Always check the AzAPI provider for newer services.

2. Validation Complexity

Terraform’s variable validation system has constraints that require careful design of validation logic.

3. CI/CD Strategy

Creating effective CI/CD pipelines for infrastructure requires balancing security with automation capabilities.

4. Documentation is Critical

Infrastructure templates need comprehensive documentation for successful adoption and maintenance.

Performance and Cost Considerations

SKU Selection

  • Standard: Development and testing workloads
  • Enterprise: Production workloads with forest trusts
  • Premium: Mission-critical applications requiring highest performance

Cost Optimization

# Use Infracost for cost estimation
infracost breakdown --path=. --format=json

The template includes cost estimation integration for budget planning.

Future Enhancements

Planned Features

  • Terraform Cloud integration for remote state management
  • Azure Policy integration for compliance automation
  • Azure Sentinel integration for advanced security monitoring
  • Multi-tenant support for managed service providers

Community Contributions

The template is open-source and welcomes contributions for:

  • Additional monitoring dashboards
  • Extended security configurations
  • Integration with other Azure services
  • Documentation improvements

Getting Started

Prerequisites

  • Azure subscription with Global Administrator rights
  • Terraform v1.5.0+
  • Azure CLI installed and configured

Quick Start

# Clone the repository
git clone https://github.com/ITlusions/ITL.AuthServices.git
cd ITL.AuthServices

# Configure your deployment
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your values

# Deploy
terraform init
terraform plan
terraform apply

Testing Without Azure

# Validate configuration without Azure authentication
.\scripts.ps1 test-ci

Conclusion

Building production-ready infrastructure for Microsoft Entra Domain Services requires attention to security, monitoring, networking, and operational concerns. This Terraform template addresses these challenges while providing a foundation for scalable, maintainable authentication infrastructure.

The template demonstrates several important patterns:

  • Security-first design with defense in depth
  • Operational excellence through comprehensive monitoring
  • Developer experience with cross-platform tooling
  • CI/CD integration for automated validation and deployment

Whether you’re implementing hybrid identity for the first time or looking to improve your existing infrastructure automation, this template provides a solid foundation for Microsoft Entra Domain Services in Azure.

Resources


Have questions about implementing Microsoft Entra Domain Services with Terraform? Feel free to reach out or contribute to the project on GitHub!

Share this post: