New-AaddsForest.ps1

<#PSScriptInfo
 
.VERSION 1.2.0
 
.GUID b75293b3-db35-4550-8d86-1daf3c0ec231
 
.AUTHOR aaddsfb@microsoft.com
 
.COMPANYNAME Microsoft Corporation
 
.COPYRIGHT (c) Microsoft Corporation
 
.TAGS Azure-AD-Domain-Services ResourceInstance
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
    07/19/2020 - Initial release
    01/09/2024 - Migrate from AzureAD PowerShell to MS Graph PowerShell, rebrand to Microsoft Entra Domain Services, retire Resource Forest concept
#>


<#
 
.SYNOPSIS
    Creates an Microsoft Entra Domain Services resource instance.
 
.DESCRIPTION
    Creates an Microsoft Entra Domain Services resource instance.
 
.PARAMETER azureSubscriptionId
    The subscription ID used for Microsoft Entra Domain Services billing.
    You can get the list of subscriptions using the Get-AzureRMSubscription cmdlet.
    This parameter is MANDATORY
 
.PARAMETER aaddsAdminUser
    The user principal name of the first Microsoft Entra Domain Services administrator
    This user and the user running this script will be Microsoft Entra Domain Services Administrators
    This parameter is MANDATORY
 
.PARAMETER aaddsDomainName
    The FQDN of the Microsoft Entra Domain Services forest. This name MUST be different from your on-premises forest.
    The first part of the domain name cannot exceed 15 characters. It is recommended to use 'aadds' or 'aaddsrf'
    This parameter is MANDATORY
 
.PARAMETER aaddsResourceGroupName
    The resource group hosting the Microsoft Entra Domain Services instance (and its associated resources).
    This can be an existing resource group or a new one that will be created.
    This parameter is MANDATORY
 
.PARAMETER aaddsVnetName
    The name of the virtual network hosting the Microsoft Entra Domain Services instance.
    This can be an existing virtual network or a new one that will be created.
    This parameter is MANDATORY
 
.PARAMETER aaddsVnetCIDRAddressSpace
    The virtual network's address range in CIDR notation.
    This parameter is MANDATORY when creating a new virtual network.
    OMIT/SKIP this parameter if you are using an existing virutal network.
 
.PARAMETER aaddsSubnetName
    The name of the subnet hosting Microsoft Entra Domain Services.
    This CANNOT be an existing subnet on the virtual network.
    This parameter is MANDATORY
 
.PARAMETER aaddsSubnetCIRDAddressRange
    The subnet's address range in CIDR notation for the Microsoft Entra Domain Services instance (e.g. 192.168.1.0/24).
    It must be contained by the address range of the virtual network and different from other subnets.
    This parameter is MANDATORY
 
.PARAMETER aaddsLocation
    The name of the Azure Region hosting your Microsoft Entra Domain Services instance.
    Use "Get-AzLocation | fl -Property Location" for a list of locations.
    This parameter is MANDATORY
 
.PARAMETER createResourceForest
    DEPRECATED: Determines if the Microsoft Entra Domain Services instance created by the script is a resource forest.
    $true = creates a resource forest; $false = creates a user forest [default]
    This parameter is OPTIONAL
 
.PARAMETER createWorkloadSubnet
    Determines if the script creates a workload subnet for your application
    workloads. $true = workload subnet is created; $false = workload subnet is not created.
    This parameter is OPTIONAL
 
.PARAMETER disableOnPremPasswordSync
    Determines if on-prem password sync will be disabled or not. Note that on-prem password sync is always
    disabled in resource forest and is enabled by default in user forest.
    This parameter is OPTIONAL
 
.PARAMETER workloadSubnetName
    The name of the subnet of the $aaddsVnetName virtual network that hosts your
    application workload (if the workload is hosted on the same virtual network).
    NOTE! It is recommended you host your application in its own virtual network and peer the workload virtual network
    to the virtual network hosting Microsoft Entra Domain Services.
    This parameter is OPTIONAL
 
.PARAMETER workloadSubnetCIRDAddressRange
    The subnet's address range in CIDR notation for application workload (e.g. 192.168.1.0/24).
    It must be contained by the address range of the virtual network and different from other subnets.
    This parameter is OPTIONAL
 
.NOTES
    * This cmdlet requires you install the Microsoft Graph PowerShell SDK: https://review.learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0&branch=main
 
    * This cmdlet creates a new Microsoft Entra Domain Services instance in the tenant and subscription.
 
    * The cmdlet prompts for authentication twice. The first authentication is to Entra ID. The
      second authentication is to Azure Resource Manager.
 
    * Your tenant must have an active subscription. You must authenticate as a global adminstrator of the tenant
      to create an instance of Microsoft Entra Domain Services.
 
    * The cmdlet create a new resource group and virtual network if the named items do not exist.
 
    * The cmdlet MUST create the subnet that hosts Microsoft Entra Domain Services and fails if the named subnet exists.
 
    * The cmdlet can optionally create a workload subnet. If it exists, it will skip the operation.
 
    * The concept of resource forest has been deprecated.
 
 
#>

[CmdletBinding()]
Param (

    [Parameter(
        Mandatory=$true,
        Position=0)]
        [string]
        $azureSubscriptionId,

    [Parameter(
        Mandatory=$true,
        Position=1)]
        [string]
        $aaddsAdminUser,

    [Parameter(
        Mandatory=$true,
        Position=2)]
        [string]
        $aaddsDomainName,

    [Parameter(
        Mandatory=$true,
        Position=3)]
        [string]
        $aaddsResourceGroupName,

    [Parameter(
        Mandatory=$true,
        Position=4)]
        [string]
        $aaddsVnetName,

    [Parameter(
        Mandatory=$false,
        Position=5)]
        [string]
        $aaddsVnetCIDRAddressSpace,

    [Parameter(
        Mandatory=$true,
        Position=6)]
        [string]
        $aaddsSubnetName,

    [Parameter(
        Mandatory=$true,
        Position=7)]
        [string]
        $aaddsSubnetCIRDAddressRange,

    [Parameter(
        Mandatory=$true,
        Position=8)]
        [string]
        $aaddsLocation,

    [Parameter(
        Mandatory=$false,
        Position=9)]
        [switch]
        $createResourceForest = $false,

    [Parameter(
        Mandatory=$false,
        Position=10)]
        [switch]
        $createWorkloadSubnet = $false,

    [Parameter(
        Mandatory=$false,
        Position=11)]
        [switch]
        $disableOnPremPasswordSync = $false,

    [Parameter(
        Mandatory=$false,
        Position=12)]
        [string]
        $workloadSubnetName,

    [Parameter(
        Mandatory=$false,
        Position=13)]
        [string]
        $workloadSubnetCIRDAddressRange


)

Process
{
    Set-Item Env:\SuppressAzurePowerShellBreakingChangeWarnings "true"

    Write-Host ([String]::Empty)
    Write-Host ([String]::Empty)
    Write-Host -ForegroundColor Cyan "New-AaddsForest"
    Write-Host ([String]::Empty)
    Write-Host -ForegroundColor White "This cmdlet creates an Microsoft Entra Domain Services resource. You will need to authenticate two times."
    Write-Host ([String]::Empty)
    Write-Host -ForegroundColor White "1. Use Entra ID Global Adminstrator credentials from your Entra ID for the first authentication."
    Write-Host -ForegroundColor White "This creates the service principal, group and group memberships needed for the managed domain."
    Write-Host -ForegroundColor White "2. For the second authentication, use credentials that allow you to create resources in the"
    Write-host -ForegroundColor white "provided subscription id. This is the subscription that will host your Microsoft Entra Domain Services instance."
    Write-Host ([String]::Empty)
    Write-Host -ForegroundColor Green "Type 'Yes' to continue or 'No' to quit"

    $answer = Read-Host
    if("Yes" -cne $answer)
    {
        Write-Host "User canceled."
        Return
    }


    $scriptStart = Get-Date



    # The constructed Microsoft Entra Domain Services resource id.
    $aaddsResourceId = `
    "/subscriptions/$AzureSubscriptionId/resourceGroups/$aaddsResourceGroupName/providers/Microsoft.AAD/DomainServices/$aaddsDomainName"

    # Microsoft Entra Domain Services AppID
    $aaddsAppId = "2565bd9d-da50-47d4-8b85-4c97f669dc36"

    #
    # Authenticate to Azure to create AAD DC Administrators group and group memberships
    Write-Host ([string]::Empty)
    Write-Host ([string]::Empty)
    Write-Host -ForegroundColor White "First authentication..."
    Write-Host "Authenticating to Azure... " -NoNewline
    Connect-MgGraph -Scopes "Application.ReadWrite.All","Group.ReadWrite.All" -ErrorAction SilentlyContinue
    $azSession = Get-MgContext
    if($null -eq $azSession)
    {
        # Authentication failed
        Write-Host -ForegroundColor Red "[Failed!]"
        Write-Host -ForegroundColor Red "ERROR: Could not authenticate to Azure. Check your credentials and try again."
        Return
    }

    Write-Host -ForegroundColor Green "[Success!]"
    Write-Host "INFO: Authenticated to Azure as $($azSession.Account)..."

    #
    # Check of AAD service principal
    Write-Host "Searching for Microsoft Entra Domain Services service principal..." -NoNewline
    $aaddsServicePrincipal = Get-MgServicePrincipal -all:$true | Where-Object {$_.AppID -eq $aaddsAppId} -ErrorAction SilentlyContinue
    if($null -eq $aaddsServicePrincipal)
    {
        Write-Host -ForegroundColor Yellow "[Not Found!]"
        Write-Host "Creating Microsoft Entra Domain Services service principal..." -NoNewline
        $aaddsServicePrincipal = New-MgServicePrincipal -AppId "2565bd9d-da50-47d4-8b85-4c97f669dc36" -ErrorAction SilentlyContinue
        if($null -eq $aaddsServicePrincipal)
        {
            Write-Host -ForegroundColor Red "[Failed!]"
            Write-Host -ForegroundColor Red "ERROR: Could not create the Microsoft Entra Domain Services service principal."
            Return
        }
        else
        {
            Write-Host -ForegroundColor Green "[Success!]"
        }
    }
    else
    {
        Write-Host -ForegroundColor Green "[Found!]"
    }

    #
    # Check if the Service Principal is enabled
    Write-Host "Checking the Microsoft Entra Domain Services service principal is enabled..." -NoNewline
    if($true -ne $aaddsServicePrincipal.AccountEnabled)
    {
        Write-Host -ForegroundColor Yellow "[Disabled!]"
        Write-Host "Enabling the Microsoft Entra Domain Services service principal..." -NoNewline
        Update-MgServicePrincipal -ServicePrincipalId $aaddsServicePrincipal.Id -AccountEnabled $true -ErrorAction SilentlyContinue
        $aaddsServicePrincipal = Get-MgServicePrincipal -Id $aaddsServicePrincipal.Id -ErrorAction SilentlyContinue
        if($true -ne $aaddsServicePrincipal.AccountEnabled)
        {
            Write-Host -ForegroundColor Red "[Failed!]"
            Write-Host -ForegroundColor Red "ERROR: Failed to enable the Microsoft Entra Domain Services service principal"
            Return
        }
        else
        {
            Write-Host -ForegroundColor Green "[Enabled!]"
        }
    }
    else
    {
        Write-Host -ForegroundColor Green "[Enabled!]"
    }

    #
    # Create the delegated administration group for Microsoft Entra Domain Services (AAD DC Administrators group)
    Write-Host "Searching Entra ID for an existsing AAD DC Administrators group in Entra ID... " -NoNewline
    $aaddsAdminGroup = $null
    $aaddsAdminGroup = Get-MgGroup |Where-Object -Property DisplayName -eq "AAD DC Administrators" -ErrorAction SilentlyContinue
    if($null -eq $aaddsAdminGroup)
    {
        Write-Host -ForegroundColor Yellow "[Not Found!]"

        Write-Host "Creating the AAD DC Administrators group in Entra ID... " -NoNewline
        $aaddsAdminGroup = New-MgGroup `
         -DisplayName "AAD DC Administrators" `
         -SecurityEnabled:$true `
         -MailEnabled:$false `
         -MailNickName "AADDCAdministrators" -ErrorAction SilentlyContinue
         if($null -eq $aaddsAdminGroup)
         {
            Write-Host -ForegroundColor Red "[Failed!]"
            Write-Host -ForegroundColor Red "FAILURE: Could not create AAD DC Administrators group."
            Return
         }
         else
         {
            Write-Host -ForegroundColor Green "[Successs!]"
         }
     }
     else
     {
        Write-Host -ForegroundColor Green "[Found!]"
        if(1 -eq $aaddsAdminGroup.Count)
        {
            Write-Host "INFO: Using the existing group."
        }
        else
        {
            Write-Host -ForegroundColor Red "ERROR: There is more than one AAD DC Administrators group."
            Write-Host -ForegroundColor Red "ERROR: Delete one or more groups and try the operation again."
            Return
        }
     }


    #
    # Get an instance of the Microsoft Entra Domain Services admin user
    $skipUser = $false
    Write-Host "Searching Entra ID for the Microsoft Entra Domain Services delegated admin user... " -NoNewline

    $aaddsAdmin = Get-MgUser -Filter "UserPrincipalName eq '$aaddsAdminUser'"

    if($null -eq $aaddsAdmin)
    {
        # Skip if the named user account is not found in Entra ID
        Write-Host -ForegroundColor Yellow "[Not Found!]"
        Write-Host -ForegroundColor Yellow "WARNING: $aaddsAdminUser not found. Skipping. Add user manually."
        $skipUser = $true
    }
    else
    {
        # Account Found. Check if it's already a member of the group
        Write-Host -ForegroundColor Green "[Found!]"

        Write-Host "Checking Group Membership for the delegated user $($aaddsAdmin.UserPrincipalName) in $($aaddsAdminGroup.DisplayName)..." -NoNewline
        $memberOf = Get-MgGroupMember -GroupId $aaddsAdminGroup.Id |`
         Where-Object -Property Id -eq $aaddsAdmin.Id
         if($null -eq $memberOf)
         {
            # Not a member of the group. Add.
            Write-Host -ForegroundColor Yellow "[Not Found!]"
            Write-Host "INFO: Adding user to group..." -NoNewline

            New-MgGroupMember -GroupId $aaddsAdminGroup.Id -DirectoryObjectId $aaddsAdmin.Id
            $memberOf = $null
            $memberOf = Get-MgGroupMember -GroupId $aaddsAdminGroup.Id |`
                Where-Object -Property Id -eq $aaddsAdmin.Id
            if($null -eq $memberOf)
            {
                Write-Host -ForegroundColor Yellow "[Failed!]"
                Write-Host -ForegroundColor Yellow "WARNING: Manually add $($aaddsAdmin.UserPrincipalName) to $($aaddsAdminGroup.DisplayName)"
            }
            else
            {
                Write-Host -ForegroundColor Green "[Success!]"
            }
         }
         else
         {
            # Already a member of the group
            Write-Host -ForegroundColor Green "[Found!]"
            Write-Host "INFO: $($aaddsAdmin.UserPrincipalName) is already a member of $($aaddsAdminGroup.DisplayName). Skipping!"
         }
    }

    # Add the currently signed in User to the Group
    $tempUser = $($azSession.Account)
    Write-Host "Searching Entra ID for the current user: $tempUser..." -NoNewline
    $currentUser = Get-MgUser -Filter "UserPrincipalName eq '$tempUser'"

    if($null -eq $currentUser)
    {
        Write-Host -ForegroundColor Yellow "[Not Found!]"
        if($true -eq $skipUser)
        {
            Write-Host -ForegroundColor Yellow "WARNING: The AAD DC Administrators group is empty. Add users manually using Entra ID."
        }
        else
        {
            Write-Host -ForegroundColor White "INFO: The current user $tempUser was not added to the AAD DC Administratrors group."
        }
    }
    else
    {
        # Account Found. Check if it's already a member of the group
        Write-Host -ForegroundColor Green "[Found!]"

        Write-Host "Checking Group Membership for the current user $($currentUser.UserPrincipalName) in $($aaddsAdminGroup.DisplayName)..." -NoNewline
        $memberOf = $null
        $memberOf = Get-MgGroupMember -GroupId $aaddsAdminGroup.Id |`
         Where-Object -Property Id -eq $currentUser.Id
         if($null -eq $memberOf)
         {
            # Not a member of the group. Add.
            Write-Host -ForegroundColor Yellow "[Not Found!]"
            Write-Host "INFO: Adding user to group..." -NoNewline

            New-MgGroupMember -GroupId $aaddsAdminGroup.Id -RefObjectId $currentUser.Id
            $memberOf = $null
            $memberOf = Get-MgGroupMember -GroupId $aaddsAdminGroup.Id |`
            Where-Object -Property ObjectId -eq $currentUser.Id
            if($null -eq $memberOf)
            {
                Write-Host -ForegroundColor Yellow "[Failed!]"
                Write-Host -ForegroundColor Yellow "WARNING: Manually add $($currentUser.UserPrincipalName) to $($aaddsAdminGroup.DisplayName)"
            }
            else
            {
                Write-Host -ForegroundColor Green "[Success!]"
            }
         }
         else
         {
            # Already a member of the group
            Write-Host -ForegroundColor Green "[Found!]"
            Write-Host "INFO: $($currentUser.UserPrincipalName) is already a member of $($aaddsAdminGroup.DisplayName). Skipping!"
         }
    }

    #
    # Authenticate to Azure Resource Manager
    Write-Host ([string]::Empty)
    Write-Host ([string]::Empty)
    Write-Host -ForegroundColor White "Second authentication (Azure Resource Manager)..." -NoNewline
    $armSession = Connect-AzAccount -ErrorAction SilentlyContinue
    if($null -eq $armSession)
    {
        # Authentication failed
        Write-Host -ForegroundColor Red "[Failed!]"
        Write-Host -ForegroundColor Red "ERROR: Could not authenticate to Azure Resource Manager. Check your credentials and try again."
        Return
    }


    Write-Host -ForegroundColor Green "[Successs!]"
    Write-Host "INFO: Authenticated to Azure as $($armSession.Context.Account.Id)..."

    Set-AzContext $azureSubscriptionId | Out-Null

    #
    # Microsoft Entra Domain Services Resource Group
    Write-Host "Checking for the resource group $aaddsResourceGroupName in $aaddsLocation..." -NoNewline
    $aaddsResourceGroup = Get-AzResourceGroup -Name $aaddsResourceGroupName -Location $aaddsLocation -ErrorAction SilentlyContinue
    if($null -eq $aaddsResourceGroup)
    {
        # not found; create
        Write-Host -ForegroundColor Yellow "[Not Found!]"
        Write-Host "Creating resource group $aaddsResourceGroupName in $aaddsLocation..." -NoNewline

        $aaddsResourceGroup = New-AzResourceGroup `
         -Name $aaddsResourceGroupName `
         -Location $aaddsLocation -ErrorAction SilentlyContinue
        if($null -eq $aaddsResourceGroup)
        {
            Write-Host -ForegroundColor Red "[Failed!]"
            Write-Host -ForegroundColor Red "ERROR: Failed creating the resource group $aaddsResourceGroupName."
            Return
        }
        else
        {
            Write-Host -ForegroundColor Green "[Success!]"
        }

    }
    else
    {
        Write-Host -ForegroundColor Green "[Found!]"
        Write-Host "INFO: Reusing existing resouce group ->$($aaddsResourceGroup.ResourceGroupName)"
    }


    #
    #
    # Microsoft Entra Domain Services Virtual Network
    Write-Host "Checking for the $aaddsVnetName virtual network..." -NoNewline
    $aaddsVirtualNetwork = Get-AzVirtualNetwork -Name $aaddsVnetName -ResourceGroupName $aaddsResourceGroupName -ErrorAction SilentlyContinue
    if($null -eq $aaddsVirtualNetwork)
    {

        Write-Host -ForegroundColor Yellow "[Not Found!]"

        # Check if the virtual Network CIDR address space was provided
        if( ($null -eq $aaddsVnetCIDRAddressSpace) -or ("" -eq $aaddsVnetCIDRAddressSpace))
        {
            Write-Host -ForegroundColor Red "ERROR: Missing the virtual address space information."
            Write-Host -ForegroundColor Red "ERROR: Run the cmdlet again with the -aaddsVnetCIDRAddressSpace parameter and the appropriate value."
            Return
        }

        Write-Host "Creating $aaddsVnetName virtual network..." -NoNewline

        #
        # Create a virtual network to host Microsoft Entra Domain Services
        $aaddsVirtualNetwork = New-AzVirtualNetwork `
         -ResourceGroupName $aaddsResourceGroupName `
         -Location $aaddsLocation `
         -Name $aaddsVnetName `
         -AddressPrefix $aaddsVnetCIDRAddressSpace -ErrorAction SilentlyContinue
        if($null -eq $aaddsVirtualNetwork)
        {
            Write-Host -ForegroundColor Red "[Failed!]"
            Write-host -ForegroundColor Red "ERROR: Failed creating the $aaddsVnetName virtual network."
        }
        else
        {
            Write-Host -ForegroundColor Green "[Success!]"
        }

    }
    else
    {
        write-Host -ForegroundColor Green "[Found!]"
        Write-Host "INFO: Reusing existing virtual network ->$($aaddsVirtualNetwork.Name)"
    }


    #
    #
    # Search the subnet, the script MUST create the Microsoft Entra Domain Services subnet
    # Create a dedicated subnet to host Microsoft Entra Domain Services
    # Get the Microsoft Entra Domain Services subnet from the virtual network
    Write-Host "Checking for the $aaddsSubnetName subnet in $($aaddsVirtualNetwork.Name)..." -NoNewline
    $aaddsSubnet = Get-AzVirtualNetworkSubnetConfig `
     -Name $aaddsSubnetName `
     -VirtualNetwork $aaddsVirtualNetwork -ErrorAction SilentlyContinue
    if($null -ne $aaddsSubnet)
    {
        # Subnet Exists
        # Do not allow the reuse of a subnet
        Write-Host -ForegroundColor Red "[Found!]"
        Write-Host -ForegroundColor Red "ERROR: A subnet with the name $($aaddsSubnet.Name) exists in the $($aaddsVirtualNetwork.Name) virtual network."
        Write-Host -ForegroundColor Red "ERROR: Choose a different name or delete the subnet."
        Return
    }
    else
    {
        Write-Host -ForegroundColor Green "[Not Found!]"
        Write-Host "Creating the $aaddsSubnetName subnet and adding it to the $($aaddsVirtualNetwork.Name) virtual network..." -NoNewline

        $rv = $null
        $rv = Add-AzVirtualNetworkSubnetConfig `
            -Name $aaddsSubnetName `
            -VirtualNetwork $aaddsVirtualNetwork `
            -AddressPrefix $aaddsSubnetCIRDAddressRange -ErrorAction SilentlyContinue

        $aaddsVirtualNetwork = Set-AzVirtualNetwork -VirtualNetwork $aaddsVirtualNetwork -ErrorAction SilentlyContinue

        $aaddsSubnet = Get-AzVirtualNetworkSubnetConfig `
            -Name $aaddsSubnetName `
            -VirtualNetwork $aaddsVirtualNetwork -ErrorAction SilentlyContinue


        if( ($null -eq $rv) -or ($null -eq $aaddsVirtualNetwork) -or ($null -eq $aaddsSubnet) )
        {
            Write-Host -ForegroundColor Red "[Failed!]"
            Write-Host -ForegroundColor Red "ERROR: Could not create the $aaddsSubnetName subnet."
            Return
        }
        else
        {
            Write-Host -ForegroundColor Green "[Success!]"
        }
    }

    #
    #
    # Create the default Microsoft Entra Domain Services NSG with rules and link it to Microsoft Entra Domain Services Subnet
    Write-Host "Creating network security group network security group in the $aaddsResourceGroupName resource group..." -NoNewline

    #
    # Build the rules
    $nsg101 = New-AzNetworkSecurityRuleConfig -Name AllowSyncWithAzureAD `
        -Access Allow -Protocol Tcp -Direction Inbound -Priority 101 `
        -SourceAddressPrefix AzureActiveDirectoryDomainServices `
        -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 443

    $nsg201 = New-AzNetworkSecurityRuleConfig -Name AllowRD `
        -Access Allow -Protocol Tcp -Direction Inbound -Priority 201 `
        -SourceAddressPrefix CorpNetSaw `
        -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 3389

    $nsg301 = New-AzNetworkSecurityRuleConfig -Name AllowPSRemoting `
        -Access Allow -Protocol Tcp -Direction Inbound -Priority 301 `
        -SourceAddressPrefix AzureActiveDirectoryDomainServices `
        -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 5986

    #
    # Find an available name for the NSG
    $nsgNamePrefix = "aadds-nsg-"
    $nsgName = [String]::Empty
    $rv = $true
    for($inc = 1; $rv -eq $true; $inc++)
    {
        $nsgName = [String]::Concat($nsgNamePrefix,$inc)
        $tempNsg = Get-AzNetworkSecurityGroup -Name  $nsgNAme -ResourceGroupName $aaddsResourceGroupName -ErrorAction SilentlyContinue
        if($null -eq $tempNsg)
        {
            break
        }

        if($inc -gt 50)
        {
            Write-Host -ForegroundColor Red "[Failed!]"
            Write-Host -ForegroundColor Red "There are more than 50 network security groups that begin with aadds-nsg-."
            Write-Host -ForegroundColor Red "Remove the unused network security groups and run the script again."
            Return
        }
    }

    #
    # Create the NSG with the rules
    $nsg = New-AzNetworkSecurityGroup -Name $nsgName -ResourceGroupName $aaddsResourceGroupName `
        -Location $aaddsLocation -SecurityRules $nsg101,$nsg201,$nsg301 -ErrorAction SilentlyContinue

    if($null -eq $nsg)
    {
        Write-Host -ForegroundColor Red "[Failed!]"
        Write-Host -ForegroundColor Red "ERROR: Could not create a network security group in the $aaddsResourceGroupName resource group."
        Return
    }
    else
    {
        Write-Host -ForegroundColor Green "[Success!]"
    }

    #
    # Link the NSG to the subnet
    Write-Host "Linking the $nsgName network security group to the $aaddsSubnetName subnet in $($aaddsVirtualNetwork.Name)..." -NoNewline
    $aaddsSubnet = Set-AzVirtualNetworkSubnetConfig -VirtualNetwork $aaddsVirtualNetwork `
        -Name $aaddsSubnetName -AddressPrefix $aaddsSubnetCIRDAddressRange `
        -NetworkSecurityGroup $nsg -ErrorAction SilentlyContinue

    #
    # Commit the changes to the virtual network
    $aaddsVirtualNetwork = Set-AzVirtualNetwork -VirtualNetwork $aaddsVirtualNetwork -ErrorAction SilentlyContinue

    #
    # Get the aadds subnet with the latest settings
    $aaddsSubnet = Get-AzVirtualNetworkSubnetConfig `
        -Name $aaddsSubnetName `
        -VirtualNetwork $aaddsVirtualNetwork -ErrorAction SilentlyContinue

    if($null -eq $aaddsSubnet)
    {
        Write-Host -ForegroundColor Red "[Failed!]"
        Write-Host -ForegroundColor Red "ERROR: Could not link the $nsgName network security group to the $aaddsSubnetName subnet."
        Return
    }
    else
    {
        Write-Host -ForegroundColor Green "[Success!]"
    }


    #
    # Workload subnet detection and creation

    if($createWorkloadSubnet)
    {
        Write-Host "INFO: Create Workload subnet detected"
        Write-Host "Checking for the $workloadSubnetName subnet in $($aaddsVirtualNetwork.Name)..." -NoNewline
        $workloadSubnet = Get-AzVirtualNetworkSubnetConfig `
            -Name $workloadSubnetName `
            -VirtualNetwork $aaddsVirtualNetwork -ErrorAction SilentlyContinue

        if($null -ne $workloadSubnet)
        {
            # Subnet Exists
            Write-Host -ForegroundColor Yellow "[Found!]"
            Write-Host "INFO: A subnet with the name $($workloadSubnet.Name) exists in the $($aaddsVirtualNetwork.Name) virtual network. Skipping!"
        }
        else
        {
            Write-Host -ForegroundColor Green "[Not Found!]"
            Write-Host "Creating the $workloadSubnetName subnet and adding it to the $($aaddsVirtualNetwork.Name) virtual network..." -NoNewline

            $rv = $null
            $rv = Add-AzVirtualNetworkSubnetConfig `
                -Name $workloadSubnetName `
                -VirtualNetwork $aaddsVirtualNetwork `
                -AddressPrefix $workloadSubnetCIRDAddressRange -ErrorAction SilentlyContinue

            $aaddsVirtualNetwork = Set-AzVirtualNetwork -VirtualNetwork $aaddsVirtualNetwork -ErrorAction SilentlyContinue


            if( ($null -eq $rv) -or ($null -eq $aaddsVirtualNetwork) )
            {
                Write-Host -ForegroundColor Red "[Failed!]"
                Write-Host -ForegroundColor Yellow "WARNING: Could not create the $workloadSubnetName subnet."
                Write-Host "INFO: Skipping workload subnet creation. Please create manually."
            }
            else
            {
                Write-Host -ForegroundColor Green "[Successs!]"
            }
        }
    }


    #
    # Check Resource Provider Registration within the subscription
    # Fixes SubscriptionNotRegistered (timing issue) and MissingSubscriptionRegisteration
    Write-Host "Checking Azure resource provider registration with the subscription..."  -NoNewline
    $rv = (Get-AzResourceProvider -ProviderNamespace Microsoft.AAD)[0].RegistrationState
    if("Registered" -ne $rv)
    {
        Write-Host -ForegroundColor Yellow "[Unregistered!]"
        Write-Host "Registering Microsoft.AAD resource provider. Please wait..." -NoNewline
        Register-AzResourceProvider -ProviderNamespace Microsoft.AAD | Out-Null
        while("Registered" -ne (Get-AzResourceProvider -ProviderNamespace Microsoft.AAD)[0].RegistrationState)
        {
            Write-Host "." -NoNewline
            Start-Sleep -Seconds 2 | Out-Null
        }
        Write-Host -ForegroundColor Green "[Registered!]"
    }
    else
    {
        Write-Host -ForegroundColor Green "[Registered!]"
    }


    #
    # Get the start time
    $domainCreateStart = Get-Date

    Write-Host ([string]::Empty)

    Write-Host "Creating Microsoft Entra Domain Services forest."
    Write-Host "Sending request to Azure. This action may take 45 and 60 minutes to complete. Please wait..."
    #
    # Enable Microsoft Entra Domain Services forest for the directory.
    if($disableOnPremPasswordSync.IsPresent)
    {
        New-AzResource `
            -ResourceId $aaddsResourceId `
            -Location $aaddsLocation `
            -ApiVersion "2017-06-01" `
            -Properties @{"DomainName"=$aaddsDomainName; `
            "SubnetId"=$aaddsSubnet.Id; `
            "DomainSecuritySettings"=@{"SyncOnPremPasswords"="Disabled"} } `
            -Force
    }
    else
    {
        New-AzResource `
            -ResourceId $aaddsResourceId `
            -Location $aaddsLocation `
            -ApiVersion "2017-06-01" `
            -Properties @{"DomainName"=$aaddsDomainName; `
            "SubnetId"=$aaddsSubnet.Id;} `
            -Force
    }


    #
    # Get the stop time
    $scriptStop = Get-Date

    Write-Host ([String]::Empty)
    Write-Host "Script Elapsed Time: " ($scriptStop - $scriptStart)

    Write-Host "Microsoft Entra Domain Services Creation Elapsed Time: " ($scriptStop - $domainCreateStart)

}
# SIG # Begin signature block
# MIIrgwYJKoZIhvcNAQcCoIIrdDCCK3ACAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBzFAWFS6LGn5J8
# vwaweNdzonEMbtqBk1RAdkjD9s34k6CCEXgwggiIMIIHcKADAgECAhM2AAABzxvV
# hIv3HFTwAAIAAAHPMA0GCSqGSIb3DQEBCwUAMEExEzARBgoJkiaJk/IsZAEZFgNH
# QkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFNRSBDUyBDQSAwMTAe
# Fw0yMzAzMjAyMDAwMzJaFw0yNDAzMTkyMDAwMzJaMC8xLTArBgNVBAMTJE1pY3Jv
# c29mdCBBenVyZSBEZXBlbmRlbmN5IENvZGUgU2lnbjCCASIwDQYJKoZIhvcNAQEB
# BQADggEPADCCAQoCggEBAOREEBJi/WoqvCPTpdI+NM1fM/zljtamVZMTJaEFhALS
# 3v0oF6vWx7zJy9McdDOyA9wY8x75/uBmwl1n8d5l/cLSD+PExSnU1o/zDyr80He+
# K1yZlVCdYSYsoWDsOeYCI0+sf6O6U2Y2kp+pIVLSf1j7amZd+vkbjHCbxRA28njz
# MCxv66EZS2Sh5yTH+uFi+RzUWMaJltkPurDraCRNKKubmOpAmqbtaPu+FEIs+nyn
# +xzFwefTOGNanTyOs2wmxBJ8VkQGU9tlRlbNrURi/5TtdktoTnM0Vn4M/2MbPlYC
# QBcJtVadNVheejpKNhinXiZw8i9TsGHDOJvuz05Hl7UCAwEAAaOCBYkwggWFMCkG
# CSsGAQQBgjcVCgQcMBowDAYKKwYBBAGCN1sDATAKBggrBgEFBQcDAzA8BgkrBgEE
# AYI3FQcELzAtBiUrBgEEAYI3FQiGkOMNhNW0eITxiz6Fm90Wzp0SgWDigi2HkK4D
# AgFkAgEOMIICdgYIKwYBBQUHAQEEggJoMIICZDBiBggrBgEFBQcwAoZWaHR0cDov
# L2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NlcnRzL0JZMlBLSUNTQ0EwMS5B
# TUUuR0JMX0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcnQwUgYIKwYBBQUHMAKGRmh0
# dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUNTQ0EwMS5BTUUuR0JMX0FNRSUy
# MENTJTIwQ0ElMjAwMSgyKS5jcnQwUgYIKwYBBQUHMAKGRmh0dHA6Ly9jcmwyLmFt
# ZS5nYmwvYWlhL0JZMlBLSUNTQ0EwMS5BTUUuR0JMX0FNRSUyMENTJTIwQ0ElMjAw
# MSgyKS5jcnQwUgYIKwYBBQUHMAKGRmh0dHA6Ly9jcmwzLmFtZS5nYmwvYWlhL0JZ
# MlBLSUNTQ0EwMS5BTUUuR0JMX0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcnQwUgYI
# KwYBBQUHMAKGRmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUNTQ0EwMS5B
# TUUuR0JMX0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcnQwga0GCCsGAQUFBzAChoGg
# bGRhcDovLy9DTj1BTUUlMjBDUyUyMENBJTIwMDEsQ049QUlBLENOPVB1YmxpYyUy
# MEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9
# QU1FLERDPUdCTD9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlm
# aWNhdGlvbkF1dGhvcml0eTAdBgNVHQ4EFgQUF8EGJdg3VCco3OMElEnYjfOsKQAw
# DgYDVR0PAQH/BAQDAgeAMEUGA1UdEQQ+MDykOjA4MR4wHAYDVQQLExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xFjAUBgNVBAUTDTIzNjE2OSs1MDAzNjQwggHmBgNVHR8E
# ggHdMIIB2TCCAdWgggHRoIIBzYY/aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br
# aWluZnJhL0NSTC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3JshjFodHRwOi8vY3Js
# MS5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3JshjFodHRwOi8v
# Y3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3JshjFodHRw
# Oi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3JshjFo
# dHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3Js
# hoG9bGRhcDovLy9DTj1BTUUlMjBDUyUyMENBJTIwMDEoMiksQ049QlkyUEtJQ1ND
# QTAxLENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNl
# cyxDTj1Db25maWd1cmF0aW9uLERDPUFNRSxEQz1HQkw/Y2VydGlmaWNhdGVSZXZv
# Y2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50
# MB8GA1UdIwQYMBaAFJZRhOBrb3v+2Aarw/KF5imuavnUMB8GA1UdJQQYMBYGCisG
# AQQBgjdbAwEGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQAy72n19XEpbA0F
# OW2VYlwvvLf8AVlRHgV5AnFegvbNSGIlfvbTizxYyHrzzldeW/xZxpLMOfnU8Ymo
# Oe3cpJYN6qX99cL50D2F0QibG6eJ4XpVNKDbt1YbaR+ekLgHoATohGFqAeI0LHO8
# jIQBJaICrYeLNXRcP8kXV0BrLtKXPsUojlvSxHzaECg7F2fhKt7WQkVZexhZB6QO
# VGj/VQY9TjWsHi6D5evjT3o819ZINUG1mCKbBFL1pFHMDjFICKlPDFIt9oL2QbZZ
# 27gH2HHcOqCIWeFlrz3qcH+dwcVGEOHz6j5SDMSIWBpS3pebi5kb0jnOu7m6uAz0
# Q8ksXFl/MIII6DCCBtCgAwIBAgITHwAAAFHqj/accwyoOwAAAAAAUTANBgkqhkiG
# 9w0BAQsFADA8MRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYD
# QU1FMRAwDgYDVQQDEwdhbWVyb290MB4XDTIxMDUyMTE4NDQxNFoXDTI2MDUyMTE4
# NTQxNFowQTETMBEGCgmSJomT8ixkARkWA0dCTDETMBEGCgmSJomT8ixkARkWA0FN
# RTEVMBMGA1UEAxMMQU1FIENTIENBIDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
# MIIBCgKCAQEAyZpSCX0Bno1W1yqXMhT6BUlJZWpa4p3xFeiTHO4vm2Q6C/azR5xw
# xnyYHrkSGDtS2P9X+KDE64V20mmEQkubxnPNeOVnE2RvdPGxgwlq+BhS3ONdVsQP
# j79q7XgHM9HhzB9+qk0PC9KN1zm9p/seyiRS6JF1dbOqRf1pUl7FAVxmgiCFgV8h
# HIb/rDPXig7FDi3S0yEx2CUDVpIq8jEhG8anUFE1WYxM+ni0S5KHwwKPKV4qyGDo
# DO+9AmDoma3Chyu5WDlW5cdtqXTWsGPE3umtnX6AmlldUFLms4OVR4guKf+n5LIB
# CC6bTiocfXPomqYjYTKx7AGMfaVLaaXmhQIDAQABo4IE3DCCBNgwEgYJKwYBBAGC
# NxUBBAUCAwIAAjAjBgkrBgEEAYI3FQIEFgQUEmgkQiFHy9RrvjHPIKTACyN/P0cw
# HQYDVR0OBBYEFJZRhOBrb3v+2Aarw/KF5imuavnUMIIBBAYDVR0lBIH8MIH5Bgcr
# BgEFAgMFBggrBgEFBQcDAQYIKwYBBQUHAwIGCisGAQQBgjcUAgEGCSsGAQQBgjcV
# BgYKKwYBBAGCNwoDDAYJKwYBBAGCNxUGBggrBgEFBQcDCQYIKwYBBQUIAgIGCisG
# AQQBgjdAAQEGCysGAQQBgjcKAwQBBgorBgEEAYI3CgMEBgkrBgEEAYI3FQUGCisG
# AQQBgjcUAgIGCisGAQQBgjcUAgMGCCsGAQUFBwMDBgorBgEEAYI3WwEBBgorBgEE
# AYI3WwIBBgorBgEEAYI3WwMBBgorBgEEAYI3WwUBBgorBgEEAYI3WwQBBgorBgEE
# AYI3WwQCMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAS
# BgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFCleUV5krjS566ycDaeMdQHR
# CQsoMIIBaAYDVR0fBIIBXzCCAVswggFXoIIBU6CCAU+GMWh0dHA6Ly9jcmwubWlj
# cm9zb2Z0LmNvbS9wa2lpbmZyYS9jcmwvYW1lcm9vdC5jcmyGI2h0dHA6Ly9jcmwy
# LmFtZS5nYmwvY3JsL2FtZXJvb3QuY3JshiNodHRwOi8vY3JsMy5hbWUuZ2JsL2Ny
# bC9hbWVyb290LmNybIYjaHR0cDovL2NybDEuYW1lLmdibC9jcmwvYW1lcm9vdC5j
# cmyGgapsZGFwOi8vL0NOPWFtZXJvb3QsQ049QU1FUm9vdCxDTj1DRFAsQ049UHVi
# bGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlv
# bixEQz1BTUUsREM9R0JMP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9v
# YmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2ludDCCAasGCCsGAQUFBwEBBIIB
# nTCCAZkwRwYIKwYBBQUHMAKGO2h0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2lp
# bmZyYS9jZXJ0cy9BTUVSb290X2FtZXJvb3QuY3J0MDcGCCsGAQUFBzAChitodHRw
# Oi8vY3JsMi5hbWUuZ2JsL2FpYS9BTUVSb290X2FtZXJvb3QuY3J0MDcGCCsGAQUF
# BzAChitodHRwOi8vY3JsMy5hbWUuZ2JsL2FpYS9BTUVSb290X2FtZXJvb3QuY3J0
# MDcGCCsGAQUFBzAChitodHRwOi8vY3JsMS5hbWUuZ2JsL2FpYS9BTUVSb290X2Ft
# ZXJvb3QuY3J0MIGiBggrBgEFBQcwAoaBlWxkYXA6Ly8vQ049YW1lcm9vdCxDTj1B
# SUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29u
# ZmlndXJhdGlvbixEQz1BTUUsREM9R0JMP2NBQ2VydGlmaWNhdGU/YmFzZT9vYmpl
# Y3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0aG9yaXR5MA0GCSqGSIb3DQEBCwUAA4IC
# AQBQECO3Tw/o317Rrd7yadqcswPx1LvIYymkaTN6KcmuRt6HKa0Xe73Ux2/AQ30T
# fgA9GBJngweRykKBusRzyOU17iIubJvy3gA21dwtqtB0DsoEv1U/ptVu2v++doTC
# J/i+GbssVXkgaX8H+6EOGEmT4evp4GbwR4HwWlc+Dvf8HH8PdUA2Z04CvcwIfckS
# ipbNm84jxJ8XjmTFTWscldL9edj2NsY6iGnyJFIyur2PS7VRYyV3p1VAJp91gj1j
# RQtWEyCB8P5g9nE3z8u0ANaU/hjwEQCrdGyravWgnf2JtG+bT26YAokbc8m+32zU
# tXRO+NK3tAjhOu2FdsG3qNrF4sc7y37R/C+7Pcb/cFfhttqsirepZii4xStcjMOD
# YuXzGm3IJs0b0owHG6oKd7ZOGvHpmmh9K8/DLriD/sq8bURD10qi/wuW8zM7IpLg
# 1vcR9dIK2mc0pj44pc6UX0XbttP/VEJgu3lT2eI9VjWtaKjx38xE9woSMyekPRtz
# TwgfuysF9DkJisr+yA4po/FPxpbBw9c/hBf32DH/GFxteS2pmjgKIbMP8sDukmEq
# 3lVvuWNJsybrZwQvQpvaM49fv+JKpLK5YWYEfwksYRR9wU8Hh/ID9hRCEkbUoQ2W
# 7mMpsp2Nbp/kcn4ivfolUy3Q9Yf0scsQ6WTLYpm+AoCUJTGCGWEwghldAgEBMFgw
# QTETMBEGCgmSJomT8ixkARkWA0dCTDETMBEGCgmSJomT8ixkARkWA0FNRTEVMBMG
# A1UEAxMMQU1FIENTIENBIDAxAhM2AAABzxvVhIv3HFTwAAIAAAHPMA0GCWCGSAFl
# AwQCAQUAoIGuMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC
# AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCARnSTac56NX1BC8idJ
# /V6NqDuEVO6ZCKCnxw2iWCsgdzBCBgorBgEEAYI3AgEMMTQwMqAUgBIATQBpAGMA
# cgBvAHMAbwBmAHShGoAYaHR0cDovL3d3dy5taWNyb3NvZnQuY29tMA0GCSqGSIb3
# DQEBAQUABIIBAEe16GWUzH1V5qsd4JYhVAFbgW029Wzfx4rV3sXsV9Ppx/DSTLuC
# 2XpTGtWZIJwlDm1MB6fIfrKdnjv419Hdd7EJ7/mCMNn6a5UtbxMGPMYT/7AwLgbP
# MGP2I/opvTDDrta/a8e3PIrXzS4Mc/BJoYMqD4WSRQRR634gHCnYaObOU+uRSFy7
# YyeO98GW1daDpoHCm8EehEetwffupBjzlOCbPn6tck0UwSKr69oY9RCHqWXL0NcC
# XcWMwSL6EaUef0Q1JJh1Cf2dVCwy9+v2FE+3XrrSk+2f4D4g6bW6+F6+dAWqh+pJ
# UPSbr6F9sdJ6YBROJXcoDjPYdj2o9O6M+9ihghcpMIIXJQYKKwYBBAGCNwMDATGC
# FxUwghcRBgkqhkiG9w0BBwKgghcCMIIW/gIBAzEPMA0GCWCGSAFlAwQCAQUAMIIB
# WQYLKoZIhvcNAQkQAQSgggFIBIIBRDCCAUACAQEGCisGAQQBhFkKAwEwMTANBglg
# hkgBZQMEAgEFAAQgfQ1pfq/3vh1PhKzjCQW/fbWcTVkkvRfcDd/xalxCYFYCBmWC
# 1iRyIBgTMjAyNDAxMTUwNzI1MTYuMTQ0WjAEgAIB9KCB2KSB1TCB0jELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0
# IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNT
# IEVTTjoyQUQ0LTRCOTItRkEwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3Rh
# bXAgU2VydmljZaCCEXgwggcnMIIFD6ADAgECAhMzAAAB3p5InpafKEQ9AAEAAAHe
# MA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n
# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4X
# DTIzMTAxMjE5MDcxMloXDTI1MDExMDE5MDcxMlowgdIxCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5k
# IE9wZXJhdGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046MkFE
# NC00QjkyLUZBMDExJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZp
# Y2UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0gfQchfVCA4QOsRaz
# p4sP8bA5fLEovazgjl0kjuFTEI5zRgKOVR8dIoozBDB/S2NklCAZFUEtDJepEfk2
# oJFD22hKcI4UNZqa4UYCU/45Up4nONlQwKNHp+CSOsZ16AKFqCskmPP0TiCnaaYY
# COziW+Fx5NT97F9qTWd9iw2NZLXIStf4Vsj5W5WlwB0btBN8p78K0vP23KKwDTug
# 47srMkvc1Jq/sNx9wBL0oLNkXri49qZAXH1tVDwhbnS3eyD2dkQuKHUHBD52Ndo8
# qWD50usmQLNKS6atCkRVMgdcesejlO97LnYhzjdephNJeiy0/TphqNEveAcYNzf9
# 2hOn1G51aHplXOxZBS7pvCpGXG0O3Dh0gFhicXQr6OTrVLUXUqn/ORZJQlyCJIOL
# Ju5zPU5LVFXztJKepMe5srIA9EK8cev+aGqp8Dk1izcyvgQotRu51A9abXrl70Kf
# HxNSqU45xv9TiXnocCjTT4xrffFdAZqIGU3t0sQZDnjkMiwPvuR8oPy+vKXvg62a
# GT1yWhlP4gYhZi/rpfzot3fN8ywB5R0Jh/1RjQX0cD/osb6ocpPxHm8Ll1SWPq08
# n20X7ofZ9AGjIYTccYOrRismUuBABIg8axfZgGRMvHvK3+nZSiF+Xd2kC6PXw3Wt
# WUzsPlwHAL49vzdwy1RmZR5x5QIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFGswJm8b
# HmmqYHccyvDrPp2j0BLIMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1Gely
# MF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv
# cHMvY3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNy
# bDBsBggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9z
# b2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBD
# QSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYB
# BQUHAwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQDilMB7Fw2n
# Bjr1CILORw4D7NC2dash0ugusHypS2g9+rWX21rdcfhjIms0rsvhrMYlR85ITFvh
# aivIK7i0Fjf7Dgl/nxlIE/S09tXESKXGY+P2RSL8LZAXLAs9VxFLF2DkiVD4rWOx
# PG25XZpoWGdvafl0KSHLBv6vmI5KgVvZsNK7tTH8TE0LPTEw4g9vIAFRqzwNzcpI
# kgob3aku1V/vy3BM/VG87aP8NvFgPBzgh6gU2w0R5oj+zCI/kkJiPVSGsmLCBkY7
# 3pZjWtDr21PQiUs/zXzBIH9jRzGVGFvCqlhIyIz3xyCsVpTTGIbln1kUh2QisiAD
# QNGiS+LKB0Lc82djJzX42GPOdcB2IxoMFI/4ZS0YEDuUt9Gce/BqgSn8paduWjli
# f6j4Qvg1zNoF2oyF25fo6RnFQDcLRRbowiUXWW3h9UfkONRY4AYOJtzkxQxqLeQ0
# rlZEII5Lu6TlT7ZXROOkJQ4P9loT6U0MVx+uLD9Rn5AMFLbeq62TPzwsERuoIq2J
# p00Sy7InAYaGC4fhBBY1b4lwBk5OqZ7vI8f+Fj1rtI7M+8hc4PNvxTKgpPcCty78
# iwMgxzfhcWxwMbYMGne6C0DzNFhhEXQdbpjwiImLEn/4+/RKh3aDcEGETlZvmV9d
# EV95+m0ZgJ7JHjYYtMJ1WnlaICzHRg/p6jCCB3EwggVZoAMCAQICEzMAAAAVxedr
# ngKbSZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp
# ZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4
# MzIyNVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG
# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3
# DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qls
# TnXIyjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLA
# EBjoYH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrE
# qv1yaa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyF
# Vk3v3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1o
# O5pGve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg
# 3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2
# TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07B
# MzlMjgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJ
# NmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6
# r1AFemzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+
# auIurQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3
# FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl
# 0mWnG1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUH
# AgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0
# b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMA
# dQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAW
# gBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8v
# Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRf
# MjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEw
# LTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL
# /Klv6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu
# 6WZnOlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5t
# ggz1bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfg
# QJY4rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8s
# CXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCr
# dTDFNLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZ
# c9d/HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2
# tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8C
# wYKiexcdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9
# JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDB
# cQZqELQdVTNYs6FwZvKhggLUMIICPQIBATCCAQChgdikgdUwgdIxCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJ
# cmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRTUyBF
# U046MkFENC00QjkyLUZBMDExJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVAGigUorMuMvOqZfF8ttgiWRMRNrzoIGD
# MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG
# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwDQYJKoZIhvcNAQEF
# BQACBQDpTvDdMCIYDzIwMjQwMTE1MDc0NjM3WhgPMjAyNDAxMTYwNzQ2MzdaMHQw
# OgYKKwYBBAGEWQoEATEsMCowCgIFAOlO8N0CAQAwBwIBAAICEOswBwIBAAICEYIw
# CgIFAOlQQl0CAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgC
# AQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQBLLSjUF27VQHMh
# nWA0WwPzPt7pANVVMzuEBahAjDYiktFIGahiKWVP1wH+1jcsJ2X6z2QW5m2pSnEM
# L+T+O2CNUav89UleXbeq0CP7N2VALvqSlU0oCLPAP0zP0vn6qiyS1E9agoPaHGnG
# DVzNdkNtHdZPAefhomNXk1MxoUJO6DGCBA0wggQJAgEBMIGTMHwxCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBU
# aW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB3p5InpafKEQ9AAEAAAHeMA0GCWCGSAFl
# AwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcN
# AQkEMSIEIEedI0C35+39sU7n2Wq6Xg1y4ilc3PQcdhncps/E4N5wMIH6BgsqhkiG
# 9w0BCRACLzGB6jCB5zCB5DCBvQQgjj4jnw3BXhAQSQJ/5gtzIK0+cP1Ns/NS2A+O
# B3N+HXswgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAA
# Ad6eSJ6WnyhEPQABAAAB3jAiBCBcU36IUsZs5GW0tE807ueJRPn5NXJMHN0EQa1s
# MrwoUTANBgkqhkiG9w0BAQsFAASCAgCKJ98+5sdBwUZDDjUldEWcmtAgHw1XF4D2
# Huqz3yl6o3kdeFHaUPNtW3/IXecEBnj5p8B5MvAsn0g50ert0zJWKCK4bV1VvSCk
# lnG4vT+xWdAGbgAWZHeXwqvCmhhgHYC0EAZqveIrK8OpLFzrv5qDKMeNByWaDPAB
# +MgjRS0k9vxYN4Dc2f77EBW5zUqU2RSzDWUmOGSqnJ5VnwOjxAh/u/d/WHg/+pSJ
# qwISIxtIVl9gOFtF+GlVeBJLu76mpsiGISC1LEazjWXQ/ylAjmDAfMsOA5GzOvB8
# tsMbBMB7Q+xnK7FFcgygQ+rDe4gZA1u+nRhmOjFJwWwjqjk0xOWkfRofEDuuqHT0
# XcwOiIhnvy1ReySbE/VTDmYk9q4jLuGwGwy+gb1c8BMEjxPbrOm1nmmryP0L9h10
# any+hDpUXeL822uiRh4dIEzEGhT30tkshRdwTDiuzpqIHJmpb+BkYBUacLt0ks0l
# 9XN2mMwbOCQ4DEWY7zxrdVK9lEmKaIFebIfrDbVaadZ8UggO+Pa2+EUAnWF/fY44
# HYjndblR49Oo2FEWaBtR0QkUh0wUJUSytR1Ru1xM7mG1pBpwQvKuNODBfXrl0fbY
# 8obWVwY6Ux+EBhTJDGJTnfPsH/5VmTdvN3+Zy/BZU03XvMtxZmZ3SZ3WHqFItnGe
# hC+1P/RLSg==
# SIG # End signature block