How to Configure Azure AADDS using Terraform in your Azure Subscription

Deploying Azure Active Directory Domain Services (AADDS) using Terraform

Azure AD Domain Services (AADDS) is a great service that allow you to deploy a managed domain in your Azure subscription. 
One of the great things is that you don’t need to deploy Virtual Machines in order to install the ADDS role. It means that you also don’t need to manage the AADDS servers, and you don’t need to patch the domain controllers.


Here we will deploy AADDS through Terraform and we will create
  1. Resource group
  2. VNET
  3. Subnet inside a VNET
  4. NSG and will associate NSG with Subnet
  5. And last AADDS.

Hence lets start
if new to Terraform refer this blog

https://terraformwithkushagra.blogspot.com/2020/04/how-to-create-resource-in-azure-using.html



Create a Folder Named AADDS in side C:\drive

   create another directory aadds-arm-master
     copy template.json file in this directory
~~Start of template.json file~~
=======================
  {
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "apiVersion": {
            "type": "string"
        },
        "domainConfigurationType": {
            "type": "string"
        },
        "domainName": {
            "type": "string"
        },
        "filteredSync": {
            "type": "string"
        },
        "location": {
            "type": "string"
        },
        "subnetName": {
            "type": "string"
        },
        "vnetName": {
            "type": "string"
        },
        "vnetResourceGroup": {
            "type": "string"
        }
    },
    "resources": [
        {
            "apiVersion": "2017-06-01",
            "type": "Microsoft.AAD/DomainServices",
            "name": "[parameters('domainName')]",
            "location": "[parameters('location')]",
            "dependsOn": [],
            "properties": {
                "domainName": "[parameters('domainName')]",
                "subnetId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('vnetResourceGroup'), '/providers/Microsoft.Network/virtualNetworks/', parameters('vnetName'), '/subnets/', parameters('subnetName'))]",
                "filteredSync": "[parameters('filteredSync')]",
                "domainConfigurationType": "[parameters('domainConfigurationType')]",
             
                "notificationSettings": {
                    "notifyGlobalAdmins": "Enabled",
                    "notifyDcAdmins": "Enabled",
                    "additionalRecipients": []
                    }
            }
        }
    ],
    "outputs": {}
}

~End of Template.json file~~
~in side AADDS  directory create a File named main.tf
~~~ main.tf~~~~~~~~~~~~~~~~~~~
==============================
resource "azurerm_resource_group" "rg1" {
  name     = "${var.resource-group-name}"
  location = "${var.location}"
}

resource "azurerm_virtual_network" "web_server_vnet" {
  name                = "${var.resource-group-name}-vnet"
  location            = var.location
  resource_group_name = azurerm_resource_group.rg1.name
  address_space       = [var.web_server_address_space]
   dns_servers         = [
           "10.0.1.4",
           "10.0.1.5"
        ]
}

resource "azurerm_network_security_group" "nsg" {
    name = "aadds-nsg"
    location            = var.location
   resource_group_name  = azurerm_resource_group.rg1.name
    security_rule       = [
        {
            access                                     = "Allow"
            description                                = ""
            destination_address_prefix                 = "*"
            destination_address_prefixes               = []
            destination_application_security_group_ids = []
            destination_port_range                     = "3389"
            destination_port_ranges                    = []
            direction                                  = "Inbound"
            name                                       = "AllowRD"
            priority                                   = 201
            protocol                                   = "Tcp"
            source_address_prefix                      = "CorpNetSaw"
            source_address_prefixes                    = []
            source_application_security_group_ids      = []
            source_port_range                          = "*"
            source_port_ranges                         = []
        },
        {
            access                                     = "Allow"
            description                                = ""
            destination_address_prefix                 = "*"
            destination_address_prefixes               = []
            destination_application_security_group_ids = []
            destination_port_range                     = "443"
            destination_port_ranges                    = []
            direction                                  = "Inbound"
            name                                       = "AllowSyncWithAzureAD"
            priority                                   = 101
            protocol                                   = "Tcp"
            source_address_prefix                      = "AzureActiveDirectoryDomainServices"
            source_address_prefixes                    = []
            source_application_security_group_ids      = []
            source_port_range                          = "*"
            source_port_ranges                         = []
        },
        {
            access                                     = "Allow"
            description                                = ""
            destination_address_prefix                 = "*"
            destination_address_prefixes               = []
            destination_application_security_group_ids = []
            destination_port_range                     = "5986"
            destination_port_ranges                    = []
            direction                                  = "Inbound"
            name                                       = "AllowPSRemoting"
            priority                                   = 301
            protocol                                   = "Tcp"
            source_address_prefix                      = "AzureActiveDirectoryDomainServices"
            source_address_prefixes                    = []
            source_application_security_group_ids      = []
            source_port_range                          = "*"
            source_port_ranges                         = []
        },
    ]

}

resource "azurerm_subnet" "web_server_subnet" {
  name                 = "${var.resource-group-name}-subnet"
  resource_group_name  = azurerm_resource_group.rg1.name
  virtual_network_name = azurerm_virtual_network.web_server_vnet.name
  address_prefix       = var.web_server_address_prefix[0]
  enforce_private_link_endpoint_network_policies = false
  enforce_private_link_service_network_policies  = false
  network_security_group_id = azurerm_network_security_group.nsg.id
}


resource "azurerm_template_deployment" "aadds" {
  name                = "acctesttemplate-01"
  resource_group_name = azurerm_resource_group.rg1.name
  template_body       = file("aadds-arm-master/template.json")
  parameters = {
    apiVersion              = "2017-06-01"
    domainConfigurationType = "FullySynced"
    domainName              = "adven.com"
    filteredSync            = "Disabled"
    location                = azurerm_resource_group.rg1.location
    subnetName              = azurerm_subnet.web_server_subnet.name
    vnetName                = azurerm_virtual_network.web_server_vnet.name
    vnetResourceGroup       = azurerm_resource_group.rg1.name
  }
  deployment_mode = "Incremental"
  #depends_on      = [module.vnet]
}
~~~~~~End of main.tf~~~~~~~~~~
~~~~~~Variables.tf File~~~~~~~~~
variable "resource-group-name" {
  default = "terraform-resource-group1"
  description = "The prefix used for all resources in this example"
}
variable "location" {
  default = "East US"
  description = "The Azure location where all resources in this example should be created"
}

variable "web_server_address_space" {
     default = "10.0.0.0/16"
}

variable "web_server_address_prefix" {
    type= list
     default = ["10.0.1.0/24","10.0.2.0/24"]
}

~~~~~~~~~~~End of variables.tf~~~~~~~~~~~~~~~~~~~~~~~~~

copy main.tf  and variable.tf inside the AADDS  Folder and ensure you have template.json file inside a folder aads.arm-master

run Terraform plan and Terraform Apply.
  (How to make your system for Terraform refer blog below)

https://terraformwithkushagra.blogspot.com/2020/04/how-to-create-resource-in-azure-using.html

it will take around 40 Minutes

outputs
===============
azurerm_template_deployment.aadds: Still creating... [37m0s elapsed]
azurerm_template_deployment.aadds: Still creating... [37m10s elapsed]
azurerm_template_deployment.aadds: Still creating... [37m20s elapsed]
azurerm_template_deployment.aadds: Creation complete after 37m30s [id=/subscriptions/9239f519-8504-4e92-ae6f-c84d53ba3714/resourceGroups/terraform-resource-group1/providers/Microsoft.Resources/deployments/acctesttemplate-01]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Releasing state lock. This may take a few moments...
PS C:\BEK>



After some time
---------------------

-- you will observe in VNET >> DNS Servers 2 IP addresses has been allocated.


Similar you will observe AADS_NSG will created with below inbound and outbound rule. 

Below Diagram shows health of AADDS and it shows when last synchronization with Azure AD done. 
On the Properties tab, you will see two IP addresses at which domain controllers are available for the virtual network.


Now you are good to add your VMs to the Domain..

In Next blog, i will write how to create a VM through Terraform and add the VM into adven.com domain.

Thanks for Reading..



Comments

  1. Does not work, Fails at 15 mins everytime

    ReplyDelete
    Replies
    1. Fails with Error testing domain controller connectivity through PowerShell. A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

      Delete

Post a Comment

Popular posts from this blog

How to use Custom Script Extensions for windows using Azure PowerShell - AZ CLI and from Terraform

How to create a Resource group in Azure using Terraform Part -1

Error inspecting states in the "azurerm" backend: storage: service returned error: StatusCode=403, ErrorCode=AuthenticationFailed