Introduction
Every enterprise network needs a centralized identity and access management system. Active Directory Domain Services (AD DS) remains the foundation of enterprise IT infrastructure, managing user identities, computer accounts, security policies, and resource access for millions of organizations worldwide.
In this comprehensive guide, you'll master Active Directory from installation through advanced enterprise scenarios. You'll learn domain architecture design, Group Policy administration, security hardening, disaster recovery, and hybrid cloud integration with Azure Active Directory.
What You'll Learn:
- Active Directory architecture and components
- Installing and configuring AD DS
- Creating and managing domains, forests, and trusts
- User, group, and computer object management
- Group Policy design and implementation
- Active Directory security hardening
- Backup, restore, and disaster recovery
- Monitoring and troubleshooting
- Hybrid identity with Azure AD Connect
- PowerShell automation for AD administration
Time to Complete: 120-180 minutes
Skill Level: Intermediate to Advanced
Active Directory Architecture
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Active Directory Domain Services Architecture β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Forest Root Domain β
β (contoso.com) β
β β β
β ββββββββββββββββββββββββββΌβββββββββββββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β βββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Domain β β Domain β β Domain β β
β β Controller βββββββββββ€ Controller ββββββββββ€ Controller β β
β β (DC01) β Repl. β (DC02) β Repl. β (DC03) β β
β β Primary β β Secondary β β Replication β β
β β β β β β β β
β ββββββββ¬βββββββ ββββββββ¬ββββββββ ββββββββ¬ββββββββ β
β β β β β
β β β β β
β βββββββββββββ¬ββββββββββββ΄βββββββββββββββββββββββββ β
β β β
β βββββββββββΌβββββββββββ β
β β Directory Data β β
β ββββββββββββββββββββββ€ β
β β β β
β β β’ Schema β (Object definitions) β
β β β’ Configuration β (Forest-wide settings) β
β β β’ Domain Data β (Users, groups, computers) β
β β β’ Application β (DNS, DHCP, Certificate Services) β
β β Partitions β β
β β β β
β ββββββββββββββββββββββ β
β β β
β βββββββββββββΌββββββββββββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β βββββββββββ ββββββββββββ ββββββββββββ β
β β Users β β Groups β βComputers β β
β βββββββββββ€ ββββββββββββ€ ββββββββββββ€ β
β β jdoe β β Domain β β WKS001 β β
β β jsmith β β Admins β β WKS002 β β
β β alee β β IT Team β β SRV001 β β
β β ... β β Finance β β ... β β
β βββββββββββ ββββββββββββ ββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Organizational Units (OUs) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β
β β β β
β β contoso.com β β
β β ββ IT β β
β β β ββ Servers β β
β β β ββ Workstations β β
β β β ββ Users β β
β β ββ HR β β
β β ββ Finance β β
β β ββ Sales β β
β β ββ North Region β β
β β ββ South Region β β
β β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Group Policy Objects (GPOs) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β
β β β β
β β β’ Default Domain Policy β Password policy, Kerberos β β
β β β’ Default Domain β Desktop settings, drive maps β β
β β Controllers Policy β β
β β β’ IT Security Policy β Software restrictions, firewall β β
β β β’ Desktop Configuration β Wallpaper, screen saver β β
β β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Key Services: β
β β’ LDAP (389/636) - Directory queries β
β β’ Kerberos (88) - Authentication β
β β’ DNS (53) - Name resolution β
β β’ SMB (445) - File sharing & SYSVOL replication β
β β’ Global Catalog (3268/3269) - Cross-domain searches β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Prerequisites
Required Hardware
- Processor: 1.4 GHz 64-bit processor
- RAM: 2 GB minimum (4 GB+ recommended)
- Disk Space: 32 GB minimum (60 GB+ recommended)
- Network: Static IP address required
Required Software
- Windows Server 2022 (Standard or Datacenter)
- Windows Admin Center (optional, for GUI management)
- Remote Server Administration Tools (RSAT) (for remote management)
Required Permissions
- Local Administrator on the server
- Enterprise Admin (for forest installation)
- Domain Admin (for domain operations)
Verify Prerequisites
# Check Windows Server version
Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, OsArchitecture
# Check available RAM
Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum |
ForEach-Object {"{0:N2} GB" -f ($_.sum / 1GB)}
# Check disk space
Get-Volume | Where-Object {$_.DriveLetter -eq 'C'} |
Select-Object DriveLetter,
@{Name="SizeGB";Expression={[math]::Round($_.Size/1GB,2)}},
@{Name="FreeGB";Expression={[math]::Round($_.SizeRemaining/1GB,2)}}
# Verify static IP configuration
Get-NetIPAddress -AddressFamily IPv4 |
Where-Object {$_.IPAddress -notlike "169.254.*" -and $_.IPAddress -ne "127.0.0.1"} |
Select-Object InterfaceAlias, IPAddress, PrefixLength
# Check network connectivity
Test-NetConnection -ComputerName "8.8.8.8" -Port 53
Step 1: Prepare Server for AD DS Installation
Set Static IP Address and Configure DNS
# Get network adapter name
$adapter = Get-NetAdapter | Where-Object {$_.Status -eq "Up"}
$adapterName = $adapter.Name
Write-Host "Network Adapter: $adapterName" -ForegroundColor Cyan
# Configure static IP
$ipConfig = @{
InterfaceAlias = $adapterName
IPAddress = "10.0.0.10" # Your DC IP
PrefixLength = 24 # Subnet mask (/24 = 255.255.255.0)
DefaultGateway = "10.0.0.1" # Your gateway
}
New-NetIPAddress @ipConfig
Write-Host "β Static IP configured" -ForegroundColor Green
# Configure DNS (point to itself and secondary DNS)
Set-DnsClientServerAddress -InterfaceAlias $adapterName `
-ServerAddresses "127.0.0.1", "8.8.8.8"
Write-Host "β DNS servers configured" -ForegroundColor Green
# Verify configuration
Get-NetIPConfiguration | Select-Object InterfaceAlias, IPv4Address, IPv4DefaultGateway, DNSServer
Rename Computer and Set Time Zone
# Rename computer to DC01
Rename-Computer -NewName "DC01" -Force
Write-Host "β Computer renamed to DC01 (restart required)" -ForegroundColor Green
# Set time zone (adjust for your location)
Set-TimeZone -Id "Eastern Standard Time"
# Verify time zone
Get-TimeZone
# Configure Windows Update settings (optional but recommended)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" `
-Name "NoAutoUpdate" -Value 0
Write-Host "β Time zone configured" -ForegroundColor Green
# Restart to apply changes
Write-Host "`nβ Restart required. Restarting in 10 seconds..." -ForegroundColor Yellow
Start-Sleep -Seconds 10
Restart-Computer -Force
Step 2: Install Active Directory Domain Services
Install AD DS Role
# Install AD DS role and management tools
Write-Host "Installing Active Directory Domain Services..." -ForegroundColor Cyan
Install-WindowsFeature -Name AD-Domain-Services `
-IncludeManagementTools `
-IncludeAllSubFeature
Write-Host "β AD DS role installed" -ForegroundColor Green
# Verify installation
Get-WindowsFeature | Where-Object {$_.Name -like "*AD-Domain*"} |
Select-Object Name, InstallState, DisplayName | Format-Table
# Check for required modules
$requiredModules = @("ActiveDirectory", "ADDSDeployment", "GroupPolicy")
foreach ($module in $requiredModules) {
if (Get-Module -ListAvailable -Name $module) {
Write-Host "β Module available: $module" -ForegroundColor Green
} else {
Write-Host "β Module missing: $module" -ForegroundColor Red
}
}
Promote Server to Domain Controller (New Forest)
# Define forest and domain parameters
$domainName = "contoso.com"
$netBiosName = "CONTOSO"
$forestMode = "WinThreshold" # Windows Server 2016 forest functional level
$domainMode = "WinThreshold" # Windows Server 2016 domain functional level
$dsrmPassword = ConvertTo-SecureString "P@ssw0rd123!DSRM" -AsPlainText -Force
Write-Host "`nβββββββββββββββββββββββββββββββββββββββββ" -ForegroundColor Cyan
Write-Host "Promoting Server to Domain Controller" -ForegroundColor Cyan
Write-Host "βββββββββββββββββββββββββββββββββββββββββ`n" -ForegroundColor Cyan
Write-Host "Domain Name: $domainName" -ForegroundColor Yellow
Write-Host "NetBIOS Name: $netBiosName" -ForegroundColor Yellow
Write-Host "Forest Mode: $forestMode" -ForegroundColor Yellow
Write-Host "Domain Mode: $domainMode`n" -ForegroundColor Yellow
# Test prerequisites
Write-Host "Testing prerequisites..." -ForegroundColor Cyan
try {
Test-ADDSForestInstallation -DomainName $domainName `
-DomainNetbiosName $netBiosName `
-ForestMode $forestMode `
-DomainMode $domainMode `
-SafeModeAdministratorPassword $dsrmPassword `
-InstallDns `
-NoRebootOnCompletion `
-Force
Write-Host "β Prerequisites check passed" -ForegroundColor Green
} catch {
Write-Host "β Prerequisites check failed: $($_.Exception.Message)" -ForegroundColor Red
exit
}
# Promote to domain controller
Write-Host "`nPromoting to domain controller..." -ForegroundColor Cyan
Write-Host "β This will take 5-15 minutes..." -ForegroundColor Yellow
try {
Install-ADDSForest -DomainName $domainName `
-DomainNetbiosName $netBiosName `
-ForestMode $forestMode `
-DomainMode $domainMode `
-SafeModeAdministratorPassword $dsrmPassword `
-InstallDns `
-DatabasePath "C:\Windows\NTDS" `
-LogPath "C:\Windows\NTDS" `
-SysvolPath "C:\Windows\SYSVOL" `
-NoRebootOnCompletion:$false `
-Force
Write-Host "β Domain controller promotion initiated" -ForegroundColor Green
Write-Host "β Server will restart automatically" -ForegroundColor Green
} catch {
Write-Host "β Promotion failed: $($_.Exception.Message)" -ForegroundColor Red
}
Verify Domain Controller Installation
# After server restarts, login with domain administrator
# Verify domain controller status
Write-Host "Verifying Domain Controller Status..." -ForegroundColor Cyan
# Check AD DS service
$addsService = Get-Service -Name "NTDS"
Write-Host " AD DS Service: $($addsService.Status)" -ForegroundColor $(if($addsService.Status -eq "Running"){"Green"}else{"Red"})
# Check DNS service
$dnsService = Get-Service -Name "DNS"
Write-Host " DNS Service: $($dnsService.Status)" -ForegroundColor $(if($dnsService.Status -eq "Running"){"Green"}else{"Red"})
# Check Netlogon service
$netlogonService = Get-Service -Name "Netlogon"
Write-Host " Netlogon Service: $($netlogonService.Status)" -ForegroundColor $(if($netlogonService.Status -eq "Running"){"Green"}else{"Red"})
# Get domain information
$domain = Get-ADDomain
Write-Host "`nDomain Information:" -ForegroundColor Yellow
Write-Host " Domain Name: $($domain.DNSRoot)" -ForegroundColor White
Write-Host " NetBIOS Name: $($domain.NetBIOSName)" -ForegroundColor White
Write-Host " Domain Mode: $($domain.DomainMode)" -ForegroundColor White
# Get forest information
$forest = Get-ADForest
Write-Host "`nForest Information:" -ForegroundColor Yellow
Write-Host " Forest Name: $($forest.Name)" -ForegroundColor White
Write-Host " Forest Mode: $($forest.ForestMode)" -ForegroundColor White
Write-Host " Schema Master: $($forest.SchemaMaster)" -ForegroundColor White
Write-Host " Domain Naming Master: $($forest.DomainNamingMaster)" -ForegroundColor White
# List domain controllers
Write-Host "`nDomain Controllers:" -ForegroundColor Yellow
Get-ADDomainController -Filter * |
Select-Object Name, IPv4Address, OperatingSystem, IsGlobalCatalog |
Format-Table -AutoSize
# Verify DNS zones
Write-Host "DNS Zones:" -ForegroundColor Yellow
Get-DnsServerZone | Select-Object ZoneName, ZoneType, IsAutoCreated | Format-Table -AutoSize
Step 3: Create Organizational Unit Structure
Design OU Hierarchy
# Define OU structure
$ouStructure = @{
"IT" = @(
"Servers",
"Workstations",
"Users",
"Groups",
"Service Accounts"
)
"HR" = @(
"Users",
"Groups"
)
"Finance" = @(
"Users",
"Groups",
"Workstations"
)
"Sales" = @(
"North Region",
"South Region",
"Users",
"Groups"
)
"Marketing" = @(
"Users",
"Groups"
)
}
$domainDN = (Get-ADDomain).DistinguishedName
Write-Host "Creating Organizational Unit Structure..." -ForegroundColor Cyan
Write-Host "Domain: $domainDN`n" -ForegroundColor Yellow
# Create parent OUs
foreach ($parentOU in $ouStructure.Keys) {
try {
$ouPath = "OU=$parentOU,$domainDN"
# Check if OU exists
$existingOU = Get-ADOrganizationalUnit -Filter "DistinguishedName -eq '$ouPath'" -ErrorAction SilentlyContinue
if ($existingOU) {
Write-Host " β OU exists: $parentOU" -ForegroundColor Yellow
} else {
# Create OU
New-ADOrganizationalUnit -Name $parentOU `
-Path $domainDN `
-ProtectedFromAccidentalDeletion $true
Write-Host " β Created: $parentOU" -ForegroundColor Green
}
# Create child OUs
foreach ($childOU in $ouStructure[$parentOU]) {
$childPath = "OU=$childOU,OU=$parentOU,$domainDN"
$existingChildOU = Get-ADOrganizationalUnit -Filter "DistinguishedName -eq '$childPath'" -ErrorAction SilentlyContinue
if ($existingChildOU) {
Write-Host " β Child OU exists: $parentOU\$childOU" -ForegroundColor Yellow
} else {
New-ADOrganizationalUnit -Name $childOU `
-Path "OU=$parentOU,$domainDN" `
-ProtectedFromAccidentalDeletion $true
Write-Host " β Created: $parentOU\$childOU" -ForegroundColor Green
}
}
} catch {
Write-Host " β Error creating $parentOU: $($_.Exception.Message)" -ForegroundColor Red
}
}
Write-Host "`nβ OU structure created" -ForegroundColor Green
# Display OU tree
Write-Host "`nOrganizational Unit Tree:" -ForegroundColor Yellow
Get-ADOrganizationalUnit -Filter * -Properties CanonicalName |
Sort-Object CanonicalName |
Select-Object @{Name="OU Path";Expression={$_.CanonicalName}}, DistinguishedName |
Format-Table -AutoSize
Step 4: Create Users and Groups
Create Security Groups
# Define security groups
$groups = @(
@{Name = "IT Administrators"; Description = "IT Department Administrators"; OU = "IT"},
@{Name = "IT Users"; Description = "IT Department Users"; OU = "IT"},
@{Name = "HR Administrators"; Description = "HR Department Administrators"; OU = "HR"},
@{Name = "HR Users"; Description = "HR Department Users"; OU = "HR"},
@{Name = "Finance Administrators"; Description = "Finance Department Administrators"; OU = "Finance"},
@{Name = "Finance Users"; Description = "Finance Department Users"; OU = "Finance"},
@{Name = "Sales Users"; Description = "Sales Department Users"; OU = "Sales"},
@{Name = "Marketing Users"; Description = "Marketing Department Users"; OU = "Marketing"},
@{Name = "Remote Users"; Description = "Users with VPN access"; OU = "IT"}
)
Write-Host "Creating Security Groups..." -ForegroundColor Cyan
foreach ($group in $groups) {
$ouPath = "OU=Groups,OU=$($group.OU),$domainDN"
# Check if Groups OU exists, create if not
$groupsOU = Get-ADOrganizationalUnit -Filter "DistinguishedName -eq '$ouPath'" -ErrorAction SilentlyContinue
if (-not $groupsOU) {
New-ADOrganizationalUnit -Name "Groups" -Path "OU=$($group.OU),$domainDN" -ProtectedFromAccidentalDeletion $true
}
try {
# Check if group exists
$existingGroup = Get-ADGroup -Filter "Name -eq '$($group.Name)'" -ErrorAction SilentlyContinue
if ($existingGroup) {
Write-Host " β Group exists: $($group.Name)" -ForegroundColor Yellow
} else {
# Create group
New-ADGroup -Name $group.Name `
-GroupScope Global `
-GroupCategory Security `
-Description $group.Description `
-Path $ouPath
Write-Host " β Created: $($group.Name)" -ForegroundColor Green
}
} catch {
Write-Host " β Error creating $($group.Name): $($_.Exception.Message)" -ForegroundColor Red
}
}
Write-Host "`nβ Security groups created" -ForegroundColor Green
Create User Accounts (Bulk)
# Define users
$users = @(
@{FirstName="John"; LastName="Doe"; Department="IT"; Title="IT Manager"; Username="jdoe"},
@{FirstName="Jane"; LastName="Smith"; Department="IT"; Title="System Administrator"; Username="jsmith"},
@{FirstName="Alice"; LastName="Lee"; Department="HR"; Title="HR Manager"; Username="alee"},
@{FirstName="Bob"; LastName="Johnson"; Department="Finance"; Title="Financial Analyst"; Username="bjohnson"},
@{FirstName="Charlie"; LastName="Brown"; Department="Sales"; Title="Sales Representative"; Username="cbrown"},
@{FirstName="Diana"; LastName="Williams"; Department="Marketing"; Title="Marketing Specialist"; Username="dwilliams"}
)
$defaultPassword = ConvertTo-SecureString "P@ssw0rd123!" -AsPlainText -Force
Write-Host "Creating User Accounts..." -ForegroundColor Cyan
foreach ($user in $users) {
$ouPath = "OU=Users,OU=$($user.Department),$domainDN"
$upn = "$($user.Username)@$domainName"
$displayName = "$($user.FirstName) $($user.LastName)"
$email = "$($user.Username)@$domainName"
try {
# Check if user exists
$existingUser = Get-ADUser -Filter "SamAccountName -eq '$($user.Username)'" -ErrorAction SilentlyContinue
if ($existingUser) {
Write-Host " β User exists: $($user.Username)" -ForegroundColor Yellow
} else {
# Create user
New-ADUser -Name $displayName `
-GivenName $user.FirstName `
-Surname $user.LastName `
-SamAccountName $user.Username `
-UserPrincipalName $upn `
-DisplayName $displayName `
-EmailAddress $email `
-Department $user.Department `
-Title $user.Title `
-Path $ouPath `
-AccountPassword $defaultPassword `
-Enabled $true `
-ChangePasswordAtLogon $true `
-PasswordNeverExpires $false
Write-Host " β Created: $displayName ($($user.Username))" -ForegroundColor Green
# Add to department group
$groupName = "$($user.Department) Users"
Add-ADGroupMember -Identity $groupName -Members $user.Username
Write-Host " β Added to group: $groupName" -ForegroundColor Green
}
} catch {
Write-Host " β Error creating $($user.Username): $($_.Exception.Message)" -ForegroundColor Red
}
}
Write-Host "`nβ User accounts created" -ForegroundColor Green
# Display created users
Write-Host "`nCreated Users:" -ForegroundColor Yellow
Get-ADUser -Filter * -SearchBase "OU=IT,DC=contoso,DC=com" -Properties Department, Title |
Select-Object Name, SamAccountName, Department, Title, Enabled |
Format-Table -AutoSize
Import Users from CSV
# Create sample CSV file
$csvContent = @"
FirstName,LastName,Department,Title,Username
Michael,Scott,Sales,Regional Manager,mscott
Dwight,Schrute,Sales,Assistant Regional Manager,dschrute
Pam,Beesly,Sales,Receptionist,pbeesly
Jim,Halpert,Sales,Sales Representative,jhalpert
"@
$csvPath = "C:\Temp\NewUsers.csv"
$csvContent | Out-File -FilePath $csvPath -Encoding UTF8
Write-Host "Created sample CSV: $csvPath" -ForegroundColor Green
# Import users from CSV
Write-Host "`nImporting users from CSV..." -ForegroundColor Cyan
$importedUsers = Import-Csv -Path $csvPath
foreach ($user in $importedUsers) {
$ouPath = "OU=Users,OU=$($user.Department),$domainDN"
$upn = "$($user.Username)@$domainName"
$displayName = "$($user.FirstName) $($user.LastName)"
try {
$existingUser = Get-ADUser -Filter "SamAccountName -eq '$($user.Username)'" -ErrorAction SilentlyContinue
if ($existingUser) {
Write-Host " β User exists: $($user.Username)" -ForegroundColor Yellow
} else {
New-ADUser -Name $displayName `
-GivenName $user.FirstName `
-Surname $user.LastName `
-SamAccountName $user.Username `
-UserPrincipalName $upn `
-DisplayName $displayName `
-EmailAddress "$($user.Username)@$domainName" `
-Department $user.Department `
-Title $user.Title `
-Path $ouPath `
-AccountPassword $defaultPassword `
-Enabled $true `
-ChangePasswordAtLogon $true
Write-Host " β Imported: $displayName" -ForegroundColor Green
}
} catch {
Write-Host " β Error importing $($user.Username): $($_.Exception.Message)" -ForegroundColor Red
}
}
Write-Host "`nβ CSV import completed" -ForegroundColor Green
Step 5: Configure Group Policy
Create and Link GPO for Password Policy
# Import Group Policy module
Import-Module GroupPolicy
Write-Host "Creating Group Policy Objects..." -ForegroundColor Cyan
# Create password policy GPO
$gpoName = "Corporate Password Policy"
try {
# Check if GPO exists
$existingGPO = Get-GPO -Name $gpoName -ErrorAction SilentlyContinue
if ($existingGPO) {
Write-Host " β GPO exists: $gpoName" -ForegroundColor Yellow
$passwordGPO = $existingGPO
} else {
# Create GPO
$passwordGPO = New-GPO -Name $gpoName -Comment "Corporate password policy settings"
Write-Host " β Created GPO: $gpoName" -ForegroundColor Green
}
# Configure password policy settings
Write-Host " Configuring password settings..." -ForegroundColor Cyan
# Minimum password length: 12 characters
Set-GPRegistryValue -Name $gpoName -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "MinimumPasswordLength" -Type DWord -Value 12
# Password complexity: Enabled
Set-GPRegistryValue -Name $gpoName -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "PasswordComplexity" -Type DWord -Value 1
# Password history: 24 passwords
Set-GPRegistryValue -Name $gpoName -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "PasswordHistorySize" -Type DWord -Value 24
# Maximum password age: 90 days
Set-GPRegistryValue -Name $gpoName -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "MaximumPasswordAge" -Type DWord -Value 90
Write-Host " β Password settings configured" -ForegroundColor Green
# Link GPO to domain
New-GPLink -Name $gpoName -Target $domainDN -LinkEnabled Yes -ErrorAction SilentlyContinue
Write-Host " β GPO linked to domain" -ForegroundColor Green
} catch {
Write-Host " β Error: $($_.Exception.Message)" -ForegroundColor Red
}
Create GPO for Desktop Configuration
# Create desktop configuration GPO
$desktopGPO = "Corporate Desktop Configuration"
try {
$gpo = New-GPO -Name $desktopGPO -Comment "Standard desktop configuration for all users"
Write-Host " β Created GPO: $desktopGPO" -ForegroundColor Green
# Set wallpaper
Set-GPRegistryValue -Name $desktopGPO `
-Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "Wallpaper" -Type String `
-Value "\\dc01\netlogon\wallpaper.jpg"
# Disable screen saver password
Set-GPRegistryValue -Name $desktopGPO `
-Key "HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop" `
-ValueName "ScreenSaveTimeOut" -Type String -Value "900"
# Configure screen saver
Set-GPRegistryValue -Name $desktopGPO `
-Key "HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop" `
-ValueName "ScreenSaverIsSecure" -Type String -Value "1"
# Link to domain
New-GPLink -Name $desktopGPO -Target $domainDN -LinkEnabled Yes
Write-Host " β Desktop configuration GPO created and linked" -ForegroundColor Green
} catch {
Write-Host " β Error: $($_.Exception.Message)" -ForegroundColor Red
}
Create Security Baseline GPO
# Create security hardening GPO
$securityGPO = "Security Baseline"
try {
$gpo = New-GPO -Name $securityGPO -Comment "Security hardening for all computers"
Write-Host " β Created GPO: $securityGPO" -ForegroundColor Green
# Disable SMBv1
Set-GPRegistryValue -Name $securityGPO `
-Key "HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" `
-ValueName "SMB1" -Type DWord -Value 0
# Enable Windows Firewall
Set-GPRegistryValue -Name $securityGPO `
-Key "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\DomainProfile" `
-ValueName "EnableFirewall" -Type DWord -Value 1
# Disable guest account
Set-GPRegistryValue -Name $securityGPO `
-Key "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" `
-ValueName "DisableCAD" -Type DWord -Value 0
# Enable audit policy
Set-GPRegistryValue -Name $securityGPO `
-Key "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" `
-ValueName "SCENoApplyLegacyAuditPolicy" -Type DWord -Value 1
# Link to domain
New-GPLink -Name $securityGPO -Target $domainDN -LinkEnabled Yes
Write-Host " β Security baseline GPO created and linked" -ForegroundColor Green
} catch {
Write-Host " β Error: $($_.Exception.Message)" -ForegroundColor Red
}
Write-Host "`nβ Group Policy configuration completed" -ForegroundColor Green
# Display all GPOs
Write-Host "`nConfigured GPOs:" -ForegroundColor Yellow
Get-GPO -All | Select-Object DisplayName, GpoStatus, CreationTime | Format-Table -AutoSize
Force Group Policy Update
# Force GP update on domain controller
Write-Host "Forcing Group Policy update..." -ForegroundColor Cyan
gpupdate /force
Write-Host "β Group Policy updated" -ForegroundColor Green
# Check GP replication status
Write-Host "`nGroup Policy Replication Status:" -ForegroundColor Yellow
Get-GPOReport -All -ReportType Html -Path "C:\Temp\GPOReport.html"
Write-Host "β GPO report generated: C:\Temp\GPOReport.html" -ForegroundColor Green
Step 6: Active Directory Backup and Recovery
Configure Windows Server Backup
# Install Windows Server Backup feature
Write-Host "Installing Windows Server Backup..." -ForegroundColor Cyan
Install-WindowsFeature -Name Windows-Server-Backup -IncludeManagementTools
Write-Host "β Windows Server Backup installed" -ForegroundColor Green
# Create backup policy
$backupPolicy = New-WBPolicy
# Add System State to backup
Add-WBSystemState -Policy $backupPolicy
# Add bare metal recovery
Add-WBBareMetalRecovery -Policy $backupPolicy
# Set backup target (external drive or network share)
$backupLocation = "E:\" # Adjust to your backup drive
$backupTarget = New-WBBackupTarget -VolumePath $backupLocation
Add-WBBackupTarget -Policy $backupPolicy -Target $backupTarget
# Schedule daily backup at 11 PM
$backupTime = (Get-Date).Date.AddHours(23)
Set-WBSchedule -Policy $backupPolicy -Schedule $backupTime
# Save policy
Set-WBPolicy -Policy $backupPolicy
Write-Host "β Backup policy configured (daily at 11 PM)" -ForegroundColor Green
# Start immediate backup
Write-Host "`nStarting backup (this may take 30-60 minutes)..." -ForegroundColor Yellow
Start-WBBackup -Policy $backupPolicy -Async
Write-Host "β Backup initiated" -ForegroundColor Green
Backup Active Directory (System State)
# Backup System State (includes AD database)
Write-Host "Backing up Active Directory System State..." -ForegroundColor Cyan
$backupPath = "E:\ADBackup\$(Get-Date -Format 'yyyyMMdd_HHmmss')"
New-Item -ItemType Directory -Path $backupPath -Force
# Perform system state backup
wbadmin start systemstatebackup -backupTarget:$backupPath -quiet
Write-Host "β System State backup completed: $backupPath" -ForegroundColor Green
# List backups
Write-Host "`nAvailable Backups:" -ForegroundColor Yellow
wbadmin get versions
Restore Active Directory (Authoritative Restore)
# IMPORTANT: This is for reference only. DO NOT RUN on production!
# Authoritative restore procedure:
<#
# 1. Restart DC in Directory Services Restore Mode (DSRM)
bcdedit /set {default} safeboot dsrepair
Restart-Computer
# 2. After restart, login with DSRM password
# 3. Restore System State from backup
wbadmin start systemstaterecovery -version:MM/DD/YYYY-HH:MM -backupTarget:E:\ADBackup
# 4. Mark restored objects as authoritative (so they replicate to other DCs)
ntdsutil
activate instance ntds
authoritative restore
restore database
# Or restore specific subtree:
restore subtree "OU=IT,DC=contoso,DC=com"
quit
quit
# 5. Restart in normal mode
bcdedit /deletevalue {default} safeboot
Restart-Computer
#>
Write-Host "β AD restore procedures documented above" -ForegroundColor Yellow
Write-Host "β Always test restores in lab environment first!" -ForegroundColor Yellow
Step 7: Monitoring and Troubleshooting
Create AD Health Check Script
function Get-ADHealthStatus {
Write-Host "`nβββββββββββββββββββββββββββββββββββββββββ" -ForegroundColor Cyan
Write-Host "Active Directory Health Check" -ForegroundColor Cyan
Write-Host "βββββββββββββββββββββββββββββββββββββββββ`n" -ForegroundColor Cyan
# Check 1: Domain Controller Services
Write-Host "1. Domain Controller Services:" -ForegroundColor Yellow
$services = @("NTDS", "DNS", "Netlogon", "W32Time", "DFSR")
foreach ($service in $services) {
$svc = Get-Service -Name $service -ErrorAction SilentlyContinue
if ($svc) {
$status = if ($svc.Status -eq "Running") { "β" } else { "β" }
$color = if ($svc.Status -eq "Running") { "Green" } else { "Red" }
Write-Host " $status $($svc.DisplayName): $($svc.Status)" -ForegroundColor $color
}
}
# Check 2: Replication Status
Write-Host "`n2. Replication Status:" -ForegroundColor Yellow
try {
$replStatus = Get-ADReplicationPartnerMetadata -Target $env:COMPUTERNAME -Scope Server
$replicationOK = $true
foreach ($partner in $replStatus) {
if ($partner.LastReplicationSuccess) {
$timeSince = (Get-Date) - $partner.LastReplicationSuccess
if ($timeSince.TotalHours -gt 1) {
Write-Host " β Replication delayed: $($partner.Partner)" -ForegroundColor Red
$replicationOK = $false
}
}
}
if ($replicationOK) {
Write-Host " β All replication partners healthy" -ForegroundColor Green
}
} catch {
Write-Host " β Unable to check replication: $($_.Exception.Message)" -ForegroundColor Yellow
}
# Check 3: FSMO Roles
Write-Host "`n3. FSMO Roles:" -ForegroundColor Yellow
$forest = Get-ADForest
$domain = Get-ADDomain
Write-Host " Schema Master: $($forest.SchemaMaster)" -ForegroundColor White
Write-Host " Domain Naming Master: $($forest.DomainNamingMaster)" -ForegroundColor White
Write-Host " PDC Emulator: $($domain.PDCEmulator)" -ForegroundColor White
Write-Host " RID Master: $($domain.RIDMaster)" -ForegroundColor White
Write-Host " Infrastructure Master: $($domain.InfrastructureMaster)" -ForegroundColor White
# Check 4: DNS Health
Write-Host "`n4. DNS Configuration:" -ForegroundColor Yellow
$dnsZones = Get-DnsServerZone | Where-Object {$_.ZoneName -like "*$domainName*"}
foreach ($zone in $dnsZones) {
Write-Host " β Zone: $($zone.ZoneName) ($($zone.ZoneType))" -ForegroundColor Green
}
# Check 5: SYSVOL and NETLOGON Shares
Write-Host "`n5. Critical Shares:" -ForegroundColor Yellow
$shares = @("SYSVOL", "NETLOGON")
foreach ($share in $shares) {
$smbShare = Get-SmbShare -Name $share -ErrorAction SilentlyContinue
if ($smbShare) {
Write-Host " β Share exists: \\$env:COMPUTERNAME\$share" -ForegroundColor Green
} else {
Write-Host " β Share missing: $share" -ForegroundColor Red
}
}
# Check 6: Disk Space
Write-Host "`n6. Disk Space:" -ForegroundColor Yellow
$volumes = Get-Volume | Where-Object {$_.DriveLetter -ne $null}
foreach ($vol in $volumes) {
$percentFree = ($vol.SizeRemaining / $vol.Size) * 100
$color = if ($percentFree -lt 10) { "Red" } elseif ($percentFree -lt 20) { "Yellow" } else { "Green" }
$status = if ($percentFree -lt 10) { "β" } elseif ($percentFree -lt 20) { "β " } else { "β" }
Write-Host " $status Drive $($vol.DriveLetter): $([math]::Round($vol.SizeRemaining/1GB, 2)) GB free ($([math]::Round($percentFree, 1))%)" -ForegroundColor $color
}
# Check 7: Event Log Errors (last 24 hours)
Write-Host "`n7. Event Log Errors (Last 24 Hours):" -ForegroundColor Yellow
$startTime = (Get-Date).AddHours(-24)
$errorEvents = Get-WinEvent -FilterHashtable @{
LogName = 'Directory Service', 'DNS Server', 'System'
Level = 2 # Error
StartTime = $startTime
} -ErrorAction SilentlyContinue
if ($errorEvents) {
$errorCount = $errorEvents.Count
Write-Host " β Found $errorCount error events" -ForegroundColor Yellow
$errorEvents | Group-Object Id | Sort-Object Count -Descending | Select-Object -First 5 | ForEach-Object {
Write-Host " Event ID $($_.Name): $($_.Count) occurrences" -ForegroundColor Gray
}
} else {
Write-Host " β No critical errors in last 24 hours" -ForegroundColor Green
}
Write-Host "`nβββββββββββββββββββββββββββββββββββββββββ" -ForegroundColor Green
Write-Host "Health Check Complete!" -ForegroundColor Green
Write-Host "βββββββββββββββββββββββββββββββββββββββββ`n" -ForegroundColor Green
}
# Run health check
Get-ADHealthStatus
# Schedule daily health check
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -File C:\Scripts\ADHealthCheck.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "8:00AM"
$principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName "AD Health Check" `
-Action $action `
-Trigger $trigger `
-Principal $principal `
-Description "Daily Active Directory health check"
Write-Host "β Scheduled daily health check at 8:00 AM" -ForegroundColor Green
Best Practices Summary
DO:
- β Use strong DSRM passwords and store securely
- β Implement regular backups (daily minimum)
- β Deploy multiple domain controllers for redundancy
- β Create OU structure before adding users/computers
- β Use security groups for permissions (not direct user assignment)
- β Enable auditing for sensitive actions
- β Implement least privilege principle
- β Document all changes and configurations
- β Test restores regularly in lab environment
- β Monitor replication and event logs
DON'T:
- β Use weak passwords for any accounts
- β Run single domain controller in production
- β Skip backups or disaster recovery planning
- β Modify schema without thorough testing
- β Disable security features without justification
- β Ignore replication errors
- β Grant everyone domain admin rights
- β Forget to patch and update regularly
- β Skip monitoring and health checks
- β Make changes without change control process
Key Takeaways
- Active Directory is mission-critical - Plan deployment carefully with redundancy
- OU structure drives administration - Design logical hierarchy before deploying
- Group Policy centralizes management - Use GPOs for configuration and security
- Backups save businesses - Test system state backups and restore procedures
- Monitoring prevents disasters - Regular health checks catch issues early
- Security requires layers - Password policy, auditing, least privilege
- Replication ensures availability - Multiple DCs prevent single point of failure
- Documentation is essential - Record configurations, changes, and procedures
- Automation scales management - PowerShell reduces errors and saves time
- Hybrid identity is future - Integrate with Azure AD for cloud services
Additional Resources
- Active Directory Domain Services Overview
- AD DS Deployment Guide
- Group Policy Documentation
- AD PowerShell Module
- Best Practices Analyzer
Next Steps
- Deploy secondary DC: Add redundancy with second domain controller
- Implement Azure AD Connect: Enable hybrid identity for Microsoft 365
- Configure Certificate Services: Deploy PKI for enhanced security
- Set up RADIUS/NPS: Centralize network authentication
- Implement LAPS: Manage local administrator passwords
- Deploy MFA: Add multi-factor authentication with Azure MFA
- Create disaster recovery plan: Document and test recovery procedures
- Implement privileged access management: Protect administrative accounts
Ready to build enterprise identity infrastructure? Start with a lab environment to practice these proceduresβActive Directory skills are foundational for any Windows system administrator!