Script to promote DC with constraints

· 10 min read
Script to promote DC with constraints
Hello folks,
Recently i have defined with colleagues a specifications document for deploy new domain controllers in existing forest.
For this deploy, first constraint is fixed replication ports between domain controllers, please see KB Microsoft .
Second constraint is to check the minimal hardware system configuration.
Third constraint is verify if flux networks are open between the new DC and the replicate source DC.
The fourth constraint is to validate the installation of new DC is good.
And the last constraint is set the replication port of DFSR.
Because the delay of deployement is short, i have write this script to deploy automaticly and check all prerequisites.
The script wrote steps informations in registry key. You need to launch several times the script to install domain controler. I do these steps for look the result of differents steps.
You can use this script to create yours, to simplify the deployement of a lot domain controlers in an international infrastructure.
Please enjoy 😉
#Function TCPPort Test
function Test-Port($hostname, $port){
 
    # This works no matter in which form we get $host - hostname or ip address
    try {
        $ip = [System.Net.Dns]::GetHostAddresses($hostname) | 
            select-object IPAddressToString -expandproperty  IPAddressToString
        if($ip.GetType().Name -eq "Object[]")
        {
            #If we have several ip's for that address, let's take first one
            $ip = $ip[0]
        }
    } catch {
        Write-Host "Possibly $hostname is wrong hostname or IP"
        return
    }
    $t = New-Object Net.Sockets.TcpClient
    # We use TryCatch to remove exception info from console if we can't connect
    try
    {
        $t.Connect($ip,$port)
    } catch {}
 
    if($t.Connected)
    {
        $t.Close()
        $msg = "Port $port is operational"
        return $true
    }
    else
    {
        $msg = "Port $port on $ip is closed, "
        $msg += "You may need to contact your IT team to open it. "                                 
    }
    #Write-Host $msg
    return $false
}
 
$ports =
#('137','NetBios Session'),
#('138','NetBios'),
('139','NetBios NetLogon and Browsing'),
('389','LDAP'),
('636','LDAPS'),
('3268','LDAP GC'),
('3269','LDAPS GC'),
('53','DNS'),
('88','KERBEROS'),
('445','SMB'),
#('123','W32Time'),
('135','RPC EndPoint'),
('464','KERBEROS Password Change')
 
 
#Main script
Import-Module ServerManager
clear
$OS = ""
$Type = ""
$memory = ""
$cpu = ""
$nbrdisk = ""
$DisqueC = ""
$DisqueD = ""
$DisqueE = ""
$ipAddress = @((Get-NetIPAddress | where {$_.AddressFamily -eq "IPv4" -and $_.InterfaceAlias -notlike "Loopback*"}).IPAddress)
 
 
if ((Get-Host).Version.Major -lt "2") {
Write-Host "Sorry, install Powershell V2 minimum, exit ..." -ForegroundColor Yellow
return
} 
 
Else { 
 
$computername=$env:COMPUTERNAME
 
    #Ckeck installation status
 
    #Define the variable to hold the location of Currently Installed Programs
 
    $Path="HKLM:SOFTWAREMicrosoft"
    $key = "DCInstall"
    $fullpathkey = $Path+''+$key
 
    Set-Location $Path
 
 
    if (-not (Test-Path .$Key)) {
 
    New-Item -Name $Key -Force
 
    Set-ItemProperty -Path .$key -Name Status -Value 1 -Type DWord -Force 
 
    Set-Location c:
 
    }
    Set-Location c:
 
    $keyValue = (Get-ItemProperty -Path $fullpathkey -Name Status).Status}
 
    If ($keyValue -eq 5) {Write-Warning "Server is a Domain Controler, please don't run this script"
    Start-Sleep 7 
    return
    }
 
    Else {
 
    if ($keyValue -eq 1) {
 
    #Add FireWall Rules
    Clear
    Write-Host "ADD Rules FireWall" -ForegroundColor Yellow
    Invoke-Expression "netsh advfirewall firewall add rule name='AD 2012 [TCP]' dir=in action=allow protocol=TCP localport=6504-6506" -Verbose
    Invoke-Expression "netsh advfirewall firewall add rule name='AD 2012 [UDP]' dir=in action=allow protocol=UDP localport=6504-6506"
    Invoke-Expression "netsh advfirewall firewall add rule name='DNS Socket [UDP]' dir=in action=allow protocol=UDP localport=6599-6699"
    Invoke-Expression "netsh advfirewall firewall add rule name='DFSR [UDP]' dir=in action=allow protocol=UDP localport=49155"
    Invoke-Expression "netsh advfirewall firewall add rule name='DFSR [TCP]' dir=in action=allow protocol=TCP localport=49155"
    Clear
    $intdom = (Get-WmiObject Win32_Computersystem).Domain
    $OS = if ((gwmi -Class Win32_OperatingSystem -ComputerName $env:COMPUTERNAME -Property Version).version -eq "6.3.9600") {"Microsoft Windows Server 2012R2"} else {"Wrong OS"}
    $Type = (gwmi -class win32_Bios).Manufactured
    $memory = [math]::round((gwmi -class Win32_ComputerSystem).TotalPhysicalMemory/1024/1024/1024, 0)
    $cpu = (gwmi -class Win32_PerfFormattedData_PerfOS_Processor).count -1
    $nbrdisk = (gwmi Win32_DiskDrive).count
    $DisqueC = (Get-Wmiobject win32_logicaldisk -ComputerName $env:COMPUTERNAME | where {$_.drivetype -eq 3 -and $_.DeviceID -eq "C:"}).size
    $DisqueC = [math]::round($DisqueC/1gB, 0)
    $DisqueD = (Get-Wmiobject win32_logicaldisk -ComputerName $env:COMPUTERNAME | where {$_.drivetype -eq 3 -and $_.DeviceID -eq "D:"}).size
    $DisqueD = [math]::round($DisqueD/1gB, 0)
    $DisqueE = (Get-Wmiobject win32_logicaldisk -ComputerName $env:COMPUTERNAME | where {$_.drivetype -eq 3 -and $_.DeviceID -eq "E:"}).size
    $DisqueE = [math]::round($DisqueE/1gB, 0)
    $model = (Get-WmiObject -Class Win32_computersystem -ComputerName $env:COMPUTERNAME -Property Model -ErrorAction SilentlyContinue).model 
    $Serial= (gwmi -Class Win32_SystemEnclosure -Property SerialNumber -ComputerName $env:COMPUTERNAME -ErrorAction SilentlyContinue).SerialNumber
    clear
    Write-Host "System Check" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Domain AD-DS :" $intdom -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Name Server :" $computername -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Operating System :" $OS -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Memory :" $memory "GB" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "CPU numbers cores :" $cpu -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Number of disks :" $nbrdisk -ForegroundColor Yellow
    Write-Host "Disk size C: :" $DisqueC "GB" -ForegroundColor Yellow
    if ($DisqueD -eq 0) {Write-Warning "Pas de disque D:"}
    Else {Write-Host "Disk size D: :" $DisqueD "GB" -ForegroundColor Yellow}
    if ($DisqueE -ne 0) {Write-Host "Disk size E: :" $DisqueE "GB" -ForegroundColor Yellow}
    Write-Host ""
    Write-Host "IP Address :" $ipAddress -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Model :" $model -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Serial Number :" $Serial -ForegroundColor Yellow
    Write-Host ""
    Write-host "The information above are correct? Y(Yes) N(No)" -ForegroundColor Yellow
    $choice = Read-Host
 
    If ($choice -eq "N") {
    Clear
    Write-Warning "Please update the machine with the requirements defined in the document of detailed specifications"
    Start-Sleep 5
    return
 
 
    }
    else {Set-ItemProperty -Path $fullpathkey -Name Status -Value 2 -Type DWord -Force 
    Write-Warning "To Install components AD-DS and DNS Server, please run the script again"
    Start-Sleep 5
    return}
 
    }#Fin 1
 
        Elseif ( $keyValue -eq 2) {
 
        Write-Host "Add Windows roles and features on" $env:COMPUTERNAME", please wait" -ForegroundColor Yellow
        $ADDSInstall = (Get-WindowsFeature AD-Domain-Services).Installed
        $DNSInstall = (Get-WindowsFeature DNS).Installed
 
        if (!$ADDSInstall -and !$DNSInstall) {
 
        $InstallRole = Add-WindowsFeature -Name AD-Domain-Services,RSAT-ADDS,RSAT-ADDS-Tools,DNS,RSAT-DNS-Server -Source D:Sourcessources -Restart:$true
 
        if (!$InstallRole.Success) {
        Write-Warning "Unable to install AD-DS installation package due of the following error:"
        Write-Warning $InstallRole.ExitCode
        return
        }
            Else {
            Set-ItemProperty -Path $fullpathkey -Name Status -Value 3 -Type DWord -Force 
            Write-Warning "Components AD-DS and DNS Server are installed, please run the script again"
            Start-Sleep 5 
            }
        }
 
        Else {
            Set-ItemProperty -Path $fullpathkey -Name Status -Value 3 -Type DWord -Force 
            Write-Warning "Components AD-DS and DNS Server are installed, please run the script again"
            Start-Sleep 5 
        }
 
        }#Fin 2
 
 
            Elseif ($keyValue -eq 3) {
            $DCinSiteArray = ""
            $DCinSite=""
            Import-Module ActiveDirectory
            $F = Get-WmiObject Win32_Computersystem
            $siteAD = Get-ADReplicationSite -Server $F.Domain
            $DCinSiteArray = Get-ADDomainController -Server $F.Domain -filter {Site -eq $siteAD.Name}
            $DCinsiteCount = $DCinSiteArray | Measure-Object
 
            if ($DCinsiteCount.Count -eq 1) {$DCinSite = $DCinSiteArray.HostName} 
 
            Else {
 
                foreach ($DC in $DCinSiteArray) {
 
                [array]$DCinSite += $DC.HostName
 
                } # Fin Foreach 
            }
 
 
            $DCinSite = $DCinSite | Sort | Select-Object -First 5
            #Clear
            Write-Host "Site Name :" $siteAD.Name -ForegroundColor Yellow
            Write-Host ""
            Write-Host "Dc in same Site :" $DCinSite -ForegroundColor Yellow
            Set-Location c:
            Write-Host ""
            Write-Host "Settings before promote DC" -ForegroundColor Yellow
            Write-Host ""
            $Dcreplica = read-Host "please indicate the FQDN name of replicate domain controller "
            Write-Host $Dcreplica -ForegroundColor Yellow
 
            If ($Dcreplica -eq " ") {
 
            Write-Host "Error Name empty" -ForegroundColor Red 
            Start-Sleep 5
            return}#Fin IF
 
            Else {
 
                if (! (Test-Connection $Dcreplica -Count 2 -Quiet)) { Write-Host "ICMP Error on $Dcreplica"}
 
                Else { 
                Clear
 
                Write-Host "Test ICMP OK" -ForegroundColor Green 
                Write-Host ""                                
                Write-Host "Start check open ports Active Directory" 
 
                    foreach ($port in $ports) {
 
                        if (! (Test-Port $Dcreplica $port[0])) {
                        Write-Warning "Unable to check connection on port : $port on $Dcreplica"
                        }
 
                            Else {Write-host "Port " $port[0] $port[1] "OK" -ForegroundColor Green}
 
                    }#Fin Foreach
                }#Fin Else
 
 
 
 
            } #Fin Else
            Write-Host ""
            Write-host "The information above are correct? Y(Yes) N(No)"
            $choice = Read-Host
 
            If ($choice -eq "N") {
 
            Write-Warning "Please check the openings of flow (Firewall Server and firewall network) with the requirements defined in the document of detailed specifications"
            Start-Sleep 5
            return
            }
 
            Else {
            $intdom = (Get-WmiObject Win32_Computersystem).Domain
            $intdomntb = $intdom.ToUpper().Split(".")[0]
 
            Write-Host "Promote DC" -ForegroundColor Yellow
 
            New-Item -Path D:AD -ItemType Directory -Value AD -Force -Confirm:$false
 
            Import-Module ADDSDeployment
 
            $RootAD = $((Get-ADForest).RootDomain)
 
            If ($intdom -eq $RootAD) {
 
            $promote = Install-ADDSDomainController `
                        -NoGlobalCatalog:$false `
                        -Credential (Get-Credential -Message "$RootAD Domain Admin Account") `
                        -CriticalReplicationOnly:$false `
                        -DatabasePath "D:ADNTDS" `
                        -DomainName $intdom `
                        -InstallDns:$true `
                        -LogPath "D:ADNTDS" `
                        -NoRebootOnCompletion:$false `
                        -ReplicationSourceDC $Dcreplica `
                        -SiteName $siteAD.Name `
                        -SysvolPath "D:ADSYSVOL" `
                        -Force:$true
 
                        #-CreateDnsDelegation:$true `
                        #-DnsDelegationCredential (Get-Credential -Message "Account with privileges or Domain Admin") `
            }
 
                Else { 
 
                    $promote = Install-ADDSDomainController `
                    -NoGlobalCatalog:$false `
                    -CreateDnsDelegation:$true `
                    -Credential (Get-Credential -Message "$intdomntb Domain Admin Account" -UserName $intdomntb"") `
                    -CriticalReplicationOnly:$false `
                    -DatabasePath "D:ADNTDS" `
                    -DnsDelegationCredential (Get-Credential -Message "GRS Enterprise Admin for DNS Delegation" -UserName "GRS") `
                    -DomainName $intdom `
                    -InstallDns:$true `
                    -LogPath "D:ADNTDS" `
                    -NoRebootOnCompletion:$false `
                    -ReplicationSourceDC $Dcreplica `
                    -SiteName $siteAD.Name `
                    -SysvolPath "D:ADSYSVOL" `
                    -Force:$true
                }
 
                    if ($promote.Status -eq "Error") {
                        Write-Warning "Unable to promote DC due of the following error:"
                        Write-Warning $promote.Message
                        Start-Sleep 7 
                    return
                    }
                        Else {
                            Set-ItemProperty -Path $fullpathkey -Name Status -Value 4 -Type DWord -Force 
                            Write-Warning "Promote OK, Check after reboot the DC health"
                            Write-Warning "launch script another time to set different configuration"
                            Start-Sleep 7 
                            return 
                        }
 
            }#Fin Else Promote DC
 
 
 
 
 }#Fin 3    
 
 
    #DEbut 4 Validation share and IS global ++ installation et configuration DFSR 
    Elseif ($keyValue -eq 4) {
    Clear
        Write-Host "Validation IS Global Catalog and Share SYSVOL & NETLOGON" -ForegroundColor Yellow
 
                    while ($true) {
                    if (Get-EventLog -LogName 'Directory Service' -Newest 10 | Where-Object {$_.EventID -eq 1119} -ErrorAction SilentlyContinue) {
                    Write-Host "The Server Is Global Catalog" -ForegroundColor Green
                    break
                    } else {
                    Write-Warning "Wait IS GLOBAL CATALOG"
                    Start-Sleep 60
                    }
 
                }
 
                while ($true) {
                    if (Get-SmbShare -Name "SYSVOL" -ErrorAction SilentlyContinue) {
                    Write-Host "The Server share SYSVOL" -ForegroundColor Green
                    break
                    } else {
                    Write-Warning "Wait SYSVOL Share"
                    Start-Sleep 60
                    }
 
                }
 
                while ($true) {
                    if (Get-SmbShare -Name "NETLOGON" -ErrorAction SilentlyContinue) {
                    Write-Host "The Server share NETLOGON" -ForegroundColor Green
                    break
                    } else {
                    Write-Warning "Wait NETLOGON Share"
                    Start-Sleep 60
                    }
 
                }
 
 
    Clear
    Write-Host "Add Tools DFS" -ForegroundColor Yellow
    #Add-WindowsFeature -Name RSAT-DFS-Mgmt-Con
 
        $DFSToolsInstall = [Bool](Get-WindowsFeature RSAT-DFS-Mgmt-Con).Available
 
        if ($DFSToolsInstall -eq $false) {
 
        $InstallTools = Add-WindowsFeature -Name RSAT-DFS-Mgmt-Con
 
        }
 
            if ($InstallTools.Success -eq $false) {
            #Write-Host "non" -ForegroundColor Red
            Write-Warning "Unable to install DFSR Tools installation package due of the following error:"
            Write-Warning $InstallRole.ExitCode
            return
            }# Fin IF
 
            Else {
 
                Write-Host "Execute DFSRDIAG" -ForegroundColor Yellow
 
                #Write-Host "yes" -ForegroundColor Green
 
                $F = Get-WmiObject Win32_Computersystem
 
                $fqdn = $F.Name+"."+$F.Domain
 
                $setDFSR = dfsrdiag.exe staticRPC "/port:49155" "/member:$fqdn"
 
                    if ($setDFSR -Like "*ERROR*") { 
                        Start-Sleep 5
                        Write-Warning "Unable to set value 49155 to DFSR RPC port"
                        #Write-Warning $setDFSR.ExitCode
                    } 
 
                        Else {
 
                        Set-ItemProperty -Path $fullpathkey -Name Status -Value 5 -Type DWord -Force 
                        Write-Warning "Components DFSR Tools is installed, Setting value RPC OK, Server Restart"
                        Start-Sleep 5
                        Restart-Computer -Force
                        }
 
            }# Fin Else
 
 
 
 
 
    } # Fin 4
 
    }#Fin IF