Automating Active Directory Deployment on Windows Server 2022 using PowerShell Script
Tags: windowsserver2022, activedirectory, powershellscript, servermanagement
Published: 2023-08-15 13:35:23

**Introduction:**
In the world of modern networking and system administration, the effective management of users, computers, and resources is essential for maintaining a secure and organized infrastructure. This guide will lead you through the process of automating the deployment of Active Directory (AD) on a Windows Server 2022 using a powerful PowerShell script. Windows Server 2022 stands as the pinnacle of Microsoft's server operating systems, boasting enhanced security features, improved performance, and advanced administrative capabilities. Within this framework, Active Directory serves as a fundamental pillar, providing centralized identity and access management for enterprises and organizations.

**Understanding Active Directory (AD):**
Active Directory is a comprehensive directory service developed by Microsoft, designed to facilitate the management of network resources and streamline user administration. It functions as a repository of critical information about users, computers, groups, and other network entities. Beyond its core function of authentication and authorization, AD enables the creation of a hierarchical structure that mirrors an organization's real-world structure. This structure, referred to as the domain hierarchy, allows administrators to manage and enforce security policies, deploy software, and facilitate resource sharing efficiently.

**Key Benefits of Active Directory:**
Active Directory brings a multitude of benefits to organizations, including:

1. Centralized Management: AD offers a centralized platform for managing users, groups, computers, and network resources. This streamlines administration and reduces the complexity of managing multiple user accounts and access rights.
2. Single Sign-On (SSO): With AD, users can access multiple services and applications using a single set of credentials, simplifying the authentication process and enhancing user experience.
3. Group Policy: AD's Group Policy feature enables administrators to enforce security settings, policies, and configurations across the network, ensuring consistent and standardized management.
4. Resource Sharing: AD facilitates seamless sharing of files, printers, and other resources within the organization, promoting collaboration and productivity.
5. Security and Access Control: AD provides robust security mechanisms, including access controls, encryption, and authentication, reducing the risk of unauthorized access and data breaches.

**Prerequisites and Script Customization:**
Before initiating the automated deployment of Active Directory using the PowerShell script, ensure the following prerequisites are met:

1. **Administrative Privileges**: You must have administrative privileges on the Windows Server 2022 system to execute the necessary configurations and settings.
2. **Windows Server 2022**: The script is designed specifically for Windows Server 2022. Make certain that you are utilizing the correct operating system version.
3. **Backup**: It is strongly recommended to create a backup of your system or a snapshot of your virtual machine. This precautionary measure ensures that you can revert to a previous state in case of unexpected issues.

**Preparing the Script:**
Before executing the PowerShell script, there are several pieces of information that you need to prepare and input into the script to customize it for your environment:

**Network Variables:**
$ethipaddress: Static IP address of the server.
$ethprefixlength: Subnet mask prefix length (in CIDR format, e.g., 24 for 255.255.255.0).
$ethdefaultgw: Default gateway.
$ethdns: DNS servers (you can add multiple DNS addresses separated by commas).
$globalsubnet: Global subnet used for DNS reverse lookup and Active Directory Sites and Services.
$subnetlocation: Location of the subnet for Active Directory Sites and Services.
$sitename: New name for Default-First-Site in Active Directory Sites and Services.

**Active Directory Variables:**
$domainname: Name of your Active Directory domain.

**Remote Desktop Variable:**
$enablerdp: Option to enable or disable Remote Desktop (yes or no).

**Disable IE Enhanced Security Configuration Variable:**
$disableiesecconfig: Option to enable or disable Internet Explorer Enhanced Security Configuration (yes or no).

**Hostname Variables:**
$computername: New server name.

**NTP Variables:**
$ntpserver1: First NTP server for time synchronization.
$ntpserver2: Second NTP server for time synchronization.

**DNS Variables:**
$reversezone: DNS reverse lookup zone.

**Execution and Customization:**
Review each variable carefully and input accurate values that align with your network configuration and preferences. Customize the script as needed, adjusting parameters to meet your specific requirements.

```
#--------------------------------------------------------------------------
#- Created by:             Emir Kurtovic                                  -
#- Version:                1.0                                            -
#--------------------------------------------------------------------------
# Change Log                                                              -
# 27th July 2023           Create AD - Windows Server 2022                -
#--------------------------------------------------------------------------

#-------------
#- Variables -                                         -
#-------------

# Network Variables
$ethipaddress = '192.168.80.250' # static IP Address of the server
$ethprefixlength = '24' # subnet mask - 24 = 255.255.255.0
$ethdefaultgw = '192.168.80.2' # default gateway
$ethdns = '8.8.8.8' # for multiple DNS, you can append DNS entries with commas
$globalsubnet = '192.168.80.0/24' # Global Subnet will be used in DNS Reverse Record and AD Sites and Services Subnet
$subnetlocation = 'Sarajevo'
$sitename = 'Main-Site' # Renames Default-First-Site within AD Sites and Services

# Active Directory Variables
$domainname = 'elab.local' # enter your active directory domain

# Remote Desktop Variable
$enablerdp = 'yes' # to enable RDP, set this variable to yes; to disable RDP, set this variable to no

# Disable IE Enhanced Security Configuration Variable
$disableiesecconfig = 'yes' # to disable IE Enhanced Security Configuration, set this variable to yes; to leave enabled, set this variable to no

# Hostname Variables
$computername = 'srv-dc01' # enter your server name

# NTP Variables
$ntpserver1 = '0.ba.pool.ntp.org'
$ntpserver2 = '1.ba.pool.ntp.org'

# DNS Variables
$reversezone = '80.168.192.in-addr.arpa'

# Timestamp
Function Timestamp {
    $Global:timestamp = Get-Date -Format "dd-MM-yyy_hh:mm:ss"
}

# Log File Location
$logfile = "C:\psscript\Win_2022_AD_Deployment_logs.txt"

# Create Log File
Write-Host "-= Get timestamp =-" -ForegroundColor Green

Timestamp

IF (Test-Path $logfile) {
    Write-Host "-= Logfile Exists =-" -ForegroundColor Yellow
} else {
    Write-Host "-= Creating Logfile =-" -ForegroundColor Green

    Try {
        New-Item -Path 'C:\psscript' -ItemType Directory
        New-Item -ItemType File -Path $logfile -ErrorAction Stop | Out-Null
        Write-Host "-= The file $($logfile) has been created =-" -ForegroundColor Green
    } Catch {
        Write-Warning -Message $("Could not create logfile. Error: " + $_.Exception.Message)
        Break
    }
}

# Check Script Progress via Logfile

$firstcheck = Select-String -Path $logfile -Pattern "1-Basic-Server-Config-Complete"

IF (!$firstcheck) {

    # Add starting date and time
    Write-Host "-= 1-Basic-Server-Config-Complete, does not exist =-" -ForegroundColor Yellow

    Timestamp
    Add-Content $logfile "$($Timestamp) - Starting Active Directory Script"

    ## 1-Basic-Server-Config ##

    #------------
    #- Settings -
    #------------

    # Set Network
    Timestamp
    Try {
        New-NetIPAddress -IPAddress $ethipaddress -PrefixLength $ethprefixlength -DefaultGateway $ethdefaultgw -InterfaceIndex (Get-NetAdapter).InterfaceIndex -ErrorAction Stop | Out-Null
        Set-DNSClientServerAddress -ServerAddresses $ethdns -InterfaceIndex (Get-NetAdapter).InterfaceIndex -ErrorAction Stop
        Write-Host "-= IP Address successfully set to $($ethipaddress), subnet $($ethprefixlength), default gateway $($ethdefaultgw), and DNS Server $($ethdns) =-" -ForegroundColor Green
        Add-Content $logfile "$($Timestamp) - IP Address successfully set to $($ethipaddress), subnet $($ethprefixlength), default gateway $($ethdefaultgw), and DNS Server $($ethdns)"
    } Catch {
        Write-Warning -Message $("Failed to apply network settings. Error: " + $_.Exception.Message)
        Break
    }

    # Set RDP
    Timestamp
    Try {
        IF ($enablerdp -eq "yes") {
            Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections" -Value 0 -ErrorAction Stop
            Enable-NetFirewallRule -DisplayGroup "Remote Desktop" -ErrorAction Stop
            Write-Host "-= RDP Successfully enabled =-" -ForegroundColor Green
            Add-Content $logfile "$($Timestamp) - RDP Successfully enabled"
        }
    } Catch {
        Write-Warning -Message $("Failed to enable RDP. Error: " + $_.Exception.Message)
        Break
    }

    IF ($enablerdp -ne "yes") {
        Write-Host "-= RDP remains disabled =-" -ForegroundColor Green
        Add-Content $logfile "$($Timestamp) - RDP remains disabled"
    }

    # Disable IE Enhanced Security Configuration
    Timestamp
    Try {
        IF ($disableiesecconfig -eq "yes") {
            Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}' -name IsInstalled -Value 0 -ErrorAction Stop
            Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}' -name IsInstalled -Value 0 -ErrorAction Stop
            Write-Host "-= IE Enhanced Security Configuration successfully disabled for Admin and User =-" -ForegroundColor Green
            Add-Content $logfile "$($Timestamp) - IE Enhanced Security Configuration successfully disabled for Admin and User"
        }
    } Catch {
        Write-Warning -Message $("Failed to disable IE Security Configuration. Error: " + $_.Exception.Message)
        Break
    }

    If ($disableiesecconfig -ne "yes") {
        Write-Host "-= IE Enhanced Security Configuration remains enabled =-" -ForegroundColor Green
        Add-Content $logfile "$($Timestamp) - IE Enhanced Security Configuration remains enabled"
    }

    # Set Hostname
    Timestamp
    Try {
        Rename-Computer -ComputerName $env:computername -NewName $computername -ErrorAction Stop | Out-Null
        Write-Host "-= Computer name set to $($computername) =-" -ForegroundColor Green
        Add-Content $logfile "$($Timestamp) - Computer name set to $($computername)"
    } Catch {
        Write-Warning -Message $("Failed to set a new computer name. Error: " + $_.Exception.Message)
        Break
    }

    # Add the first script complete to the logfile
    Timestamp
    Add-Content $logfile "$($Timestamp) - 1-Basic-Server-Config-Complete, starting script 2 =-"

    # Enable FIPS-compliant algorithms (Add the code block here)
    Timestamp
    Try {
        Write-Host "-= Enabling FIPS-compliant algorithms =-" -ForegroundColor Yellow
        $fipsPolicyValue = "Enabled"
        $fipsPolicyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\FipsAlgorithmPolicy"
        Set-ItemProperty -Path $fipsPolicyPath -Name "Enabled" -Value $fipsPolicyValue -ErrorAction Stop
        Write-Host "-= FIPS-compliant algorithms enabled successfully =-" -ForegroundColor Green
        Add-Content $logfile "$($Timestamp) - FIPS-compliant algorithms enabled successfully"
    } Catch {
        Write-Warning -Message $("Failed to enable FIPS-compliant algorithms. Error: " + $_.Exception.Message)
        Break
    }

    # Reboot Computer to apply settings
    Timestamp
    Write-Host "-= Save all your work, computer rebooting in 30 seconds =-" -ForegroundColor White -BackgroundColor Red
    Sleep 30

    Try {
        Restart-Computer -ComputerName $env:computername -ErrorAction Stop
        Write-Host "-= Rebooting Now!! =-" -ForegroundColor Green
        Add-Content $logfile "$($Timestamp) - Rebooting Now!!"
        Break
    } Catch {
        Write-Warning -Message $("Failed to restart the computer $($env:computername). Error: " + $_.Exception.Message)
        Break
    }

} # Close 'IF (!$firstcheck)'

# Check Script Progress via Logfile
$secondcheck1 = Get-Content $logfile | Where-Object { $_.Contains("1-Basic-Server-Config-Complete") }

IF ($secondcheck1) {
    $secondcheck2 = Get-Content $logfile | Where-Object { $_.Contains("2-Build-Active-Directory-Complete") }

    IF (!$secondcheck2) {

        ## 2-Build-Active-Directory ##

        Timestamp

        #-------------
        #- Variables -                                         -
        #-------------

        # Active Directory Variables
        $dsrmpassword = Read-Host "Enter Directory Services Restore Password" -AsSecureString

        #------------
        #- Settings -
        #------------

        # Install Active Directory Services
        Timestamp
        Try {
            Write-Host "-= Active Directory Domain Services installing =-" -ForegroundColor Yellow
            Install-WindowsFeature -name AD-Domain-Services -IncludeManagementTools
            Write-Host "-= Active Directory Domain Services installed successfully =-" -ForegroundColor Green
            Add-Content $logfile "$($Timestamp) - Active Directory Domain Services installed successfully"
        } Catch {
            Write-Warning -Message $("Failed to install Active Directory Domain Services. Error: " + $_.Exception.Message)
            Break
        }

        # Configure Active Directory
        Timestamp
        Try {
            Write-Host "-= Configuring Active Directory Domain Services =-" -ForegroundColor Yellow
            Install-ADDSForest -DomainName $domainname -InstallDNS -ErrorAction Stop -NoRebootOnCompletion -SafeModeAdministratorPassword $dsrmpassword -Confirm:$false | Out-Null
            Write-Host "-= Active Directory Domain Services configured successfully =-" -ForegroundColor Green
            Add-Content $logfile "$($Timestamp) - Active Directory Domain Services configured successfully"
        } Catch {
            Write-Warning -Message $("Failed to configure Active Directory Domain Services. Error: " + $_.Exception.Message)
            Break
        }

        # Add the second script complete to the logfile
        Timestamp
        Add-Content $logfile "$($Timestamp) - 2-Build-Active-Directory-Complete, starting script 3 =-"

        # Reboot Computer to apply settings
        Write-Host "-= Save all your work, computer rebooting in 30 seconds =-" -ForegroundColor White -BackgroundColor Red
        Sleep 30

        Try {
            Restart-Computer -ComputerName $env:computername -ErrorAction Stop
            Write-Host "Rebooting Now!!" -ForegroundColor Green
            Add-Content $logfile "$($Timestamp) - Rebooting Now!!"
            Break
        } Catch {
            Write-Warning -Message $("Failed to restart the computer $($env:computername). Error: " + $_.Exception.Message)
            Break
        }
    } # Close 'IF ($secondcheck2)'
} # Close 'IF ($secondcheck1)'

# Add the second script complete to the logfile

# Check Script Progress via Logfile
$thirdcheck = Get-Content $logfile | Where-Object { $_.Contains("2-Build-Active-Directory-Complete") }

## 3-Build-Active-Directory ##

#------------
#- Settings -
#------------

# Add DNS Reverse Record
Timestamp
Try {
    Add-DnsServerPrimaryZone -NetworkId $globalsubnet -DynamicUpdate Secure -ReplicationScope Domain -ErrorAction Stop
    Write-Host "-= Successfully added in $($globalsubnet) as a reverse lookup within DNS =-" -ForegroundColor Green
    Add-Content $logfile "$($Timestamp) - Successfully added $($globalsubnet) as a reverse lookup within DNS"
} Catch {
    Write-Warning -Message $("Failed to create a reverse DNS lookups zone for network $($globalsubnet). Error: " + $_.Exception.Message)
    Break
}

# Add DNS Scavenging
Write-Host "-= Set DNS Scavenging =-" -ForegroundColor Yellow

Timestamp
Try {
    Set-DnsServerScavenging -ScavengingState $true -ScavengingInterval 7.00:00:00 -Verbose -ErrorAction Stop
    Set-DnsServerZoneAging $domainname -Aging $true -RefreshInterval 7.00:00:00 -NoRefreshInterval 7.00:00:00 -Verbose -ErrorAction Stop
    Set-DnsServerZoneAging $reversezone -Aging $true -RefreshInterval 7.00:00:00 -NoRefreshInterval 7.00:00:00 -Verbose -ErrorAction Stop
    Add-Content $logfile "$($Timestamp) - DNS Scavenging Complete"
} Catch {
    Write-Warning -Message $("Failed to enable DNS Scavenging. Error: " + $_.Exception.Message)
    Break
}

Get-DnsServerScavenging

Write-Host "-= DNS Scavenging Complete =-" -ForegroundColor Green

# Create Active Directory Sites and Services
Timestamp
Try {
    New-ADReplicationSubnet -Name $globalsubnet -Site "Default-First-Site-Name" -Location $subnetlocation -ErrorAction Stop
    Write-Host "-= Successfully added Subnet $($globalsubnet) with location $($subnetlocation) in AD Sites and Services =-" -ForegroundColor Green
    Add-Content $logfile "$($Timestamp) - Successfully added Subnet $($globalsubnet) with location $($subnetlocation) in AD Sites and Services"
} Catch {
    Write-Warning -Message $("Failed to create Subnet $($globalsubnet) in AD Sites and Services. Error: " + $_.Exception.Message)
    Break
}

# Rename Active Directory Site
Timestamp
Try {
    Get-ADReplicationSite Default-First-Site-Name | Rename-ADObject -NewName $sitename -ErrorAction Stop
    Write-Host "-= Successfully renamed Default-First-Site-Name to $sitename in AD Sites and Services =-" -ForegroundColor Green
    Add-Content $logfile "$($Timestamp) - Successfully renamed Default-First-Site-Name to $sitename in AD Sites and Services"
} Catch {
    Write-Warning -Message $("Failed to rename the site in AD Sites and Services. Error: " + $_.Exception.Message)
    Break
}

# Add NTP settings to PDC

Timestamp

$serverpdc = Get-AdDomainController -Filter * | Where {$_.OperationMasterRoles -contains "PDCEmulator"}

IF ($serverpdc) {
    Try {
        Start-Process -FilePath "C:\Windows\System32\w32tm.exe" -ArgumentList "/config /manualpeerlist:$($ntpserver1),$($ntpserver2) /syncfromflags:MANUAL /reliable:yes /update" -ErrorAction Stop
        Stop-Service w32time -ErrorAction Stop
        sleep 2
        Start-Service w32time -ErrorAction Stop
        Write-Host "-= Successfully set NTP Servers: $($ntpserver1) and $($ntpserver2) =-" -ForegroundColor Green
        Add-Content $logfile "$($Timestamp) - Successfully set NTP Servers: $($ntpserver1) and $($ntpserver2)"
    } Catch {
        Write-Warning -Message $("Failed to set NTP Servers. Error: " + $_.Exception.Message)
        Break
    }
}

# Continued...

```

**Conclusion:**
Utilizing PowerShell to create an Active Directory infrastructure on Windows Server 2022 brings significant benefits in terms of speed, efficiency, and consistency of administrative tasks. Throughout this article, we've explored the basics of Windows Server 2022, Active Directory, and PowerShell, and demonstrated the steps to quickly start creating an AD domain using a PowerShell script.

This post serves as an introduction to the wide range of possibilities that Windows Server 2022 and PowerShell offer. I hope this article helps you lay the foundation for further exploration and management of your server infrastructure.

**Note**: Before executing any scripts or administrative tasks in a production environment, it's always important to thoroughly test and understand the consequences of your actions.

Best of luck in creating your Active Directory infrastructure on Windows Server 2022 with the help of PowerShell!

🙋‍♂️💻[More about Autor](https://github.com/ekurtovic81) 🖱️💻