Global Catalog Services - Design, Implementation, and Management
The Global Catalog (GC) is a critical component of Active Directory that provides forest-wide search capabilities and enables universal group membership authentication. Understanding its design, implementation, and management is essential for optimal Active Directory performance and functionality.
Overview of Global Catalog Services
What is a Global Catalog?
The Global Catalog is a distributed data repository that contains a searchable, partial representation of every object in every domain within an Active Directory forest. It serves as a centralized index that enables fast, cross-domain searches without requiring referrals to multiple domain controllers.
Key Characteristics
- Partial Replica: Contains a subset of attributes for all objects in the forest
- Multi-Master Replication: Distributed through standard AD replication mechanisms
- Read-Only: Objects from remote domains are read-only (except for Universal Group memberships)
- Performance Optimization: Eliminates cross-domain referrals for searches
- Authentication Support: Required for Universal Group membership evaluation
Global Catalog Architecture
┌─────────────────────────────────────────────────────────────┐
│ Active Directory Forest │
├─────────────────────────────────────────────────────────────┤
│ Domain A (Root) │ Domain B (Child) │
│ ┌─────────────────────┐ │ ┌─────────────────────┐ │
│ │ DC1 (GC) │ │ │ DC3 (GC) │ │
│ │ • Full Domain A │ │ │ • Full Domain B │ │
│ │ • Partial Domain B │ │ │ • Partial Domain A │ │
│ │ • Partial Domain C │ │ │ • Partial Domain C │ │
│ └─────────────────────┘ │ └─────────────────────┘ │
│ │ │
│ ┌─────────────────────┐ │ ┌─────────────────────┐ │
│ │ DC2 (Non-GC) │ │ │ DC4 (Infrastructure │ │
│ │ • Full Domain A │ │ │ Master) │ │
│ │ • No partial reps │ │ │ • Full Domain B │ │
│ └─────────────────────┘ │ │ • No GC role │ │
│ │ └─────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Domain C (Child) │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ DC5 (GC) │ │ DC6 (Non-GC) │ │
│ │ • Full Domain C │ │ • Full Domain C │ │
│ │ • Partial Domain A │ │ • No partial reps │ │
│ │ • Partial Domain B │ └─────────────────────┘ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Prerequisites and Planning
Planning Considerations
Before implementing Global Catalog services, evaluate the following factors:
Network Topology Assessment
- WAN link bandwidth and latency
- Site topology and replication schedules
- Network traffic patterns and peak usage times
- Available bandwidth for GC replication
Performance Requirements
- Expected query volume and complexity
- Authentication load and patterns
- Application dependencies on GC services
- Response time requirements
Capacity Planning
- Forest size and growth projections
- Attribute set size and customization
- Storage requirements for partial replicas
- Memory and CPU requirements
Hardware and Performance Requirements
Environment Size | CPU | Memory | Storage | Network |
---|---|---|---|---|
Small Forest (<10k objects) | 2+ cores | 4GB+ | Standard SSD | 1Gbps |
Medium Forest (10k-100k objects) | 4+ cores | 8GB+ | Fast SSD | 1Gbps+ |
Large Forest (100k-1M objects) | 8+ cores | 16GB+ | NVMe SSD | 10Gbps |
Enterprise Forest (>1M objects) | 16+ cores | 32GB+ | NVMe SSD RAID | 10Gbps+ |
Global Catalog Placement Strategies
Single Forest, Single Domain Configuration
In single-domain environments, Global Catalog placement is straightforward:
Recommendation: Configure ALL domain controllers as Global Catalogs
Benefits:
- No cross-domain referrals (since there's only one domain)
- Optimal authentication performance
- Simplified management
- No Infrastructure Master conflicts
# Configure all DCs as Global Catalogs in single domain
Get-ADDomainController -Filter * | ForEach-Object {
if (-not $_.IsGlobalCatalog) {
Write-Host "Enabling GC on $($_.Name)" -ForegroundColor Green
Set-ADObject -Identity $_.NTDSSettingsObjectDN -Replace @{options = $_.options -bor 1}
} else {
Write-Host "$($_.Name) is already a Global Catalog" -ForegroundColor Yellow
}
}
Single Forest, Multiple Domain Configuration
Multi-domain environments require strategic GC placement:
Standard Recommendation:
- Enable GC on most domain controllers
- Keep Infrastructure Masters as NON-GC servers (unless ALL DCs are GCs)
- Ensure at least one GC per site with significant user population
Placement Matrix for Multi-Domain Forests
Site Type | User Count | Recommended GC Placement |
---|---|---|
Hub Site | >1000 users | Multiple GCs for redundancy |
Regional Site | 100-1000 users | At least 1 GC |
Branch Site | 50-100 users | 1 GC (if sufficient bandwidth) |
Small Branch | <50 users | Evaluate based on WAN connectivity |
Advanced Placement Scenarios
Hub and Spoke Topology
┌─────────────────────────────────────────────────────────────┐
│ Hub Site (HQ) │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ DC1 (GC) │ │ DC2 (GC) │ │
│ │ • Primary hub │ │ • Backup hub │ │
│ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│ │
┌─────────┼──────────────────────┼─────────┐
│ │ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ┌───▼───┐
│Branch │ │Branch │ │Branch │ │Branch │
│Site A │ │Site B │ │Site C │ │Site D │
│ │ │ │ │ │ │ │
│DC3(GC)│ │DC4 │ │DC5(GC)│ │DC6 │
└───────┘ └───────┘ └───────┘ └───────┘
Regional Distribution Model
┌─────────────────────────────────────────────────────────────┐
│ Multi-Regional Forest │
├─────────────────────────────────────────────────────────────┤
│ Region 1 (Americas) │ Region 2 (EMEA) │ Region 3 (APAC) │
│ ┌─────────────────┐ │ ┌─────────────────┐ │ ┌─────────────────┐ │
│ │ DC1 (GC) │ │ │ DC3 (GC) │ │ │ DC5 (GC) │ │
│ │ DC2 (GC) │ │ │ DC4 (GC) │ │ │ DC6 (GC) │ │
│ └─────────────────┘ │ └─────────────────┘ │ └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Global Catalog Management
Enabling and Disabling Global Catalog
Using Active Directory Sites and Services
- Open Active Directory Sites and Services
- Navigate to Sites → [Site Name] → Servers → [Server Name] → NTDS Settings
- Right-click NTDS Settings → Properties
- Check/uncheck "Global Catalog" checkbox
- Restart the domain controller (recommended but not always required)
Using PowerShell (Recommended)
# Function to manage Global Catalog settings
function Set-GlobalCatalogStatus {
param(
[Parameter(Mandatory=$true)]
[string]$DomainController,
[Parameter(Mandatory=$true)]
[bool]$EnableGC,
[switch]$Force
)
try {
$dc = Get-ADDomainController -Identity $DomainController
$currentStatus = $dc.IsGlobalCatalog
if ($currentStatus -eq $EnableGC) {
Write-Host "$DomainController is already $(if($EnableGC){'enabled'}else{'disabled'}) as Global Catalog" -ForegroundColor Yellow
return
}
# Get NTDS Settings object
$ntdsPath = $dc.NTDSSettingsObjectDN
if ($EnableGC) {
# Enable Global Catalog
$options = (Get-ADObject -Identity $ntdsPath -Properties options).options
$newOptions = $options -bor 1
Set-ADObject -Identity $ntdsPath -Replace @{options = $newOptions}
Write-Host "Global Catalog enabled on $DomainController" -ForegroundColor Green
} else {
# Disable Global Catalog
if (-not $Force) {
Write-Warning "Disabling Global Catalog can impact authentication and searches. Use -Force to proceed."
return
}
$options = (Get-ADObject -Identity $ntdsPath -Properties options).options
$newOptions = $options -band (-bnot 1)
Set-ADObject -Identity $ntdsPath -Replace @{options = $newOptions}
Write-Host "Global Catalog disabled on $DomainController" -ForegroundColor Red
}
Write-Host "Note: Changes may take time to replicate. Restart recommended." -ForegroundColor Cyan
}
catch {
Write-Error "Failed to modify Global Catalog status: $($_.Exception.Message)"
}
}
# Examples:
# Enable GC on DC01
Set-GlobalCatalogStatus -DomainController "DC01.contoso.com" -EnableGC $true
# Disable GC on DC02 (with force)
Set-GlobalCatalogStatus -DomainController "DC02.contoso.com" -EnableGC $false -Force
Using Command Line Tools
# Using dsmod to enable GC
dsmod server "CN=NTDS Settings,CN=DC01,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=contoso,DC=com" -isgc yes
# Using repadmin to check GC status
repadmin /options DC01.contoso.com
# Verify GC status across all DCs
foreach ($dc in (Get-ADDomainController -Filter *)) {
Write-Host "$($dc.Name): GC=$($dc.IsGlobalCatalog)" -ForegroundColor $(if($dc.IsGlobalCatalog){'Green'}else{'Red'})
}
Global Catalog Attribute Management
Default Global Catalog Attribute Set
The Global Catalog includes essential attributes for common searches:
# View current Global Catalog attribute set
Get-ADObject -SearchBase (Get-ADRootDSE).SchemaNamingContext -Filter {isMemberOfPartialAttributeSet -eq $true} -Properties name,lDAPDisplayName |
Select-Object name,lDAPDisplayName |
Sort-Object name
Adding Custom Attributes to Global Catalog
# Function to add attribute to Global Catalog
function Add-AttributeToGlobalCatalog {
param(
[Parameter(Mandatory=$true)]
[string]$AttributeName
)
try {
$schemaPath = (Get-ADRootDSE).SchemaNamingContext
$attributePath = "CN=$AttributeName,$schemaPath"
# Check if attribute exists
$attribute = Get-ADObject -Identity $attributePath -Properties isMemberOfPartialAttributeSet -ErrorAction Stop
if ($attribute.isMemberOfPartialAttributeSet -eq $true) {
Write-Host "$AttributeName is already in the Global Catalog" -ForegroundColor Yellow
return
}
# Add to Global Catalog
Set-ADObject -Identity $attributePath -Replace @{isMemberOfPartialAttributeSet=$true}
Write-Host "$AttributeName added to Global Catalog" -ForegroundColor Green
Write-Warning "Schema changes require time to replicate and may need DC restart"
}
catch {
Write-Error "Failed to add $AttributeName to Global Catalog: $($_.Exception.Message)"
}
}
# Example: Add custom attribute to GC
# Add-AttributeToGlobalCatalog -AttributeName "employeeID"
Global Catalog Attribute Best Practices
- Minimize GC Attributes: Only add frequently searched attributes
- Impact Assessment: Each attribute increases replication traffic
- Testing: Test schema changes in development first
- Documentation: Maintain record of custom GC attributes
Monitoring and Performance
Global Catalog Health Monitoring
# Comprehensive Global Catalog health check
function Test-GlobalCatalogHealth {
param(
[string[]]$DomainControllers = @(),
[switch]$Detailed
)
if ($DomainControllers.Count -eq 0) {
$DomainControllers = (Get-ADDomainController -Filter {IsGlobalCatalog -eq $true}).Name
}
$results = @()
foreach ($dc in $DomainControllers) {
Write-Host "Testing Global Catalog on $dc..." -ForegroundColor Cyan
$result = [PSCustomObject]@{
DomainController = $dc
IsGlobalCatalog = $false
Port3268Responding = $false
Port3269Responding = $false
ReplicationStatus = "Unknown"
LastReplication = $null
PartialReplicaCount = 0
Status = "Unknown"
}
try {
# Check if DC is configured as GC
$dcInfo = Get-ADDomainController -Identity $dc
$result.IsGlobalCatalog = $dcInfo.IsGlobalCatalog
if ($result.IsGlobalCatalog) {
# Test GC ports
$result.Port3268Responding = (Test-NetConnection -ComputerName $dc -Port 3268 -WarningAction SilentlyContinue).TcpTestSucceeded
$result.Port3269Responding = (Test-NetConnection -ComputerName $dc -Port 3269 -WarningAction SilentlyContinue).TcpTestSucceeded
# Check replication status
try {
$replInfo = repadmin /showrepl $dc | Select-String "INBOUND NEIGHBORS"
$result.ReplicationStatus = if ($replInfo) { "Active" } else { "No Replication" }
}
catch {
$result.ReplicationStatus = "Error checking replication"
}
# Count partial replicas (approximate)
try {
$partitions = (Get-ADDomainController -Identity $dc).PartialReplicaDirectoryPartitions
$result.PartialReplicaCount = $partitions.Count
}
catch {
$result.PartialReplicaCount = -1
}
# Overall status
$result.Status = if ($result.Port3268Responding -and $result.Port3269Responding) { "Healthy" } else { "Warning" }
} else {
$result.Status = "Not a Global Catalog"
}
}
catch {
$result.Status = "Error: $($_.Exception.Message)"
}
$results += $result
}
return $results
}
# Run GC health check
$gcHealth = Test-GlobalCatalogHealth
$gcHealth | Format-Table -AutoSize
# Export results
$gcHealth | Export-Csv -Path "C:\Reports\GC-Health-$(Get-Date -Format 'yyyyMMdd-HHmm').csv" -NoTypeInformation
Performance Monitoring
# Global Catalog performance counters
$gcCounters = @(
"\NTDS\LDAP Searches/sec",
"\NTDS\LDAP Successful Binds/sec",
"\NTDS\LDAP Client Sessions",
"\NTDS\Address Book Client Sessions",
"\NTDS\DRA Inbound Full Sync Objects Remaining",
"\NTDS\DRA Outbound Bytes Total/sec",
"\NTDS\Database Cache % Hit"
)
# Collect performance data for GC servers
function Get-GlobalCatalogPerformance {
param(
[string[]]$GCServers,
[int]$SampleInterval = 60,
[int]$SampleCount = 10
)
$results = @()
foreach ($server in $GCServers) {
Write-Host "Collecting performance data from $server..." -ForegroundColor Green
try {
$perfData = Get-Counter -ComputerName $server -Counter $gcCounters -SampleInterval $SampleInterval -MaxSamples $SampleCount
$avgData = $perfData.CounterSamples | Group-Object Path | ForEach-Object {
[PSCustomObject]@{
Server = $server
Counter = ($_.Name -split '\\')[-1]
AverageValue = ($_.Group | Measure-Object CookedValue -Average).Average
MaxValue = ($_.Group | Measure-Object CookedValue -Maximum).Maximum
MinValue = ($_.Group | Measure-Object CookedValue -Minimum).Minimum
}
}
$results += $avgData
}
catch {
Write-Warning "Failed to collect performance data from $server`: $($_.Exception.Message)"
}
}
return $results
}
# Example usage
$gcServers = (Get-ADDomainController -Filter {IsGlobalCatalog -eq $true}).Name
$perfResults = Get-GlobalCatalogPerformance -GCServers $gcServers
$perfResults | Format-Table -AutoSize
Automated Monitoring Setup
# Create scheduled task for GC monitoring
function Install-GCMonitoring {
param(
[string]$ScriptPath = "C:\Scripts\Monitor-GlobalCatalog.ps1",
[string]$LogPath = "C:\Logs\GC-Monitor.log"
)
# Create monitoring script
$monitoringScript = @"
# Global Catalog Monitoring Script
Import-Module ActiveDirectory
`$gcHealth = Test-GlobalCatalogHealth
`$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
foreach (`$result in `$gcHealth) {
if (`$result.Status -ne "Healthy") {
`$message = "`$timestamp - WARNING: GC issue on `$(`$result.DomainController) - Status: `$(`$result.Status)"
Add-Content -Path "$LogPath" -Value `$message
# Send alert (customize as needed)
Write-EventLog -LogName Application -Source "GC Monitor" -EventId 1001 -EntryType Warning -Message `$message
}
}
"@
# Save monitoring script
$monitoringScript | Out-File -FilePath $ScriptPath -Encoding UTF8
# Create scheduled task
$taskAction = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File `"$ScriptPath`""
$taskTrigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(5) -RepetitionInterval (New-TimeSpan -Minutes 30)
$taskSettings = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable -StartWhenAvailable
$taskPrincipal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName "Global Catalog Health Monitor" -Action $taskAction -Trigger $taskTrigger -Settings $taskSettings -Principal $taskPrincipal -Description "Monitors Global Catalog server health and logs issues"
Write-Host "Global Catalog monitoring installed successfully" -ForegroundColor Green
Write-Host "Script: $ScriptPath" -ForegroundColor Yellow
Write-Host "Log: $LogPath" -ForegroundColor Yellow
}
# Install monitoring
# Install-GCMonitoring
Troubleshooting Common Issues
Issue 1: Global Catalog Not Responding
Symptoms:
- Authentication delays or failures
- Universal group membership issues
- Cross-domain searches failing
- Outlook/Exchange connectivity problems
Diagnosis:
# Comprehensive GC diagnostics
function Diagnose-GlobalCatalogIssues {
param([string]$DomainController)
Write-Host "Diagnosing Global Catalog issues on $DomainController" -ForegroundColor Cyan
# Test basic connectivity
Write-Host "`n1. Testing basic connectivity..." -ForegroundColor Yellow
$ping = Test-Connection -ComputerName $DomainController -Count 2 -Quiet
Write-Host " Ping: $(if($ping){'SUCCESS'}else{'FAILED'})" -ForegroundColor $(if($ping){'Green'}else{'Red'})
# Test GC ports
Write-Host "`n2. Testing Global Catalog ports..." -ForegroundColor Yellow
$port3268 = Test-NetConnection -ComputerName $DomainController -Port 3268 -WarningAction SilentlyContinue
$port3269 = Test-NetConnection -ComputerName $DomainController -Port 3269 -WarningAction SilentlyContinue
Write-Host " Port 3268 (GC LDAP): $(if($port3268.TcpTestSucceeded){'OPEN'}else{'CLOSED'})" -ForegroundColor $(if($port3268.TcpTestSucceeded){'Green'}else{'Red'})
Write-Host " Port 3269 (GC LDAPS): $(if($port3269.TcpTestSucceeded){'OPEN'}else{'CLOSED'})" -ForegroundColor $(if($port3269.TcpTestSucceeded){'Green'}else{'Red'})
# Check GC configuration
Write-Host "`n3. Checking Global Catalog configuration..." -ForegroundColor Yellow
try {
$dcInfo = Get-ADDomainController -Identity $DomainController
Write-Host " Is Global Catalog: $($dcInfo.IsGlobalCatalog)" -ForegroundColor $(if($dcInfo.IsGlobalCatalog){'Green'}else{'Red'})
if ($dcInfo.IsGlobalCatalog) {
Write-Host " Partial Replica Count: $($dcInfo.PartialReplicaDirectoryPartitions.Count)" -ForegroundColor Green
}
}
catch {
Write-Host " Error checking GC configuration: $($_.Exception.Message)" -ForegroundColor Red
}
# Check replication status
Write-Host "`n4. Checking replication status..." -ForegroundColor Yellow
try {
$replSummary = repadmin /replsummary $DomainController 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " Replication summary: SUCCESS" -ForegroundColor Green
} else {
Write-Host " Replication summary: ISSUES DETECTED" -ForegroundColor Red
Write-Host " Run 'repadmin /replsummary $DomainController' for details" -ForegroundColor Yellow
}
}
catch {
Write-Host " Error checking replication: $($_.Exception.Message)" -ForegroundColor Red
}
# Check event logs
Write-Host "`n5. Checking recent events..." -ForegroundColor Yellow
try {
$events = Get-WinEvent -ComputerName $DomainController -FilterHashtable @{LogName='Directory Service'; Level=1,2,3; StartTime=(Get-Date).AddHours(-24)} -MaxEvents 10 -ErrorAction SilentlyContinue
if ($events) {
Write-Host " Recent critical/error/warning events found: $($events.Count)" -ForegroundColor Yellow
$events | Select-Object TimeCreated, Id, LevelDisplayName, Message | Format-Table -Wrap
} else {
Write-Host " No recent critical events found" -ForegroundColor Green
}
}
catch {
Write-Host " Could not access event logs: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
# Run diagnostics
# Diagnose-GlobalCatalogIssues -DomainController "DC01.contoso.com"
Resolution Steps:
Verify GC Configuration:
# Re-enable Global Catalog if needed Set-GlobalCatalogStatus -DomainController "DC01.contoso.com" -EnableGC $true
Restart NetLogon Service:
Restart-Service -Name NetLogon -Force
Force Replication:
repadmin /syncall /AdeP
Check DNS Configuration:
nslookup -type=SRV _gc._tcp.contoso.com
Issue 2: Slow Global Catalog Performance
Symptoms:
- Slow authentication
- Delayed search results
- High CPU/memory usage on GC servers
- Network congestion
Diagnosis:
# Performance analysis for Global Catalog
function Analyze-GCPerformance {
param([string]$DomainController)
Write-Host "Analyzing Global Catalog performance on $DomainController" -ForegroundColor Cyan
# Check system resources
$cpu = Get-Counter "\Processor(_Total)\% Processor Time" -ComputerName $DomainController -SampleInterval 1 -MaxSamples 5
$memory = Get-Counter "\Memory\Available MBytes" -ComputerName $DomainController
$disk = Get-Counter "\PhysicalDisk(_Total)\% Disk Time" -ComputerName $DomainController -SampleInterval 1 -MaxSamples 5
Write-Host "`nSystem Resources:" -ForegroundColor Yellow
Write-Host " CPU Usage: $([math]::Round(($cpu.CounterSamples | Measure-Object CookedValue -Average).Average, 2))%" -ForegroundColor Green
Write-Host " Available Memory: $([math]::Round($memory.CounterSamples[0].CookedValue, 0)) MB" -ForegroundColor Green
Write-Host " Disk Usage: $([math]::Round(($disk.CounterSamples | Measure-Object CookedValue -Average).Average, 2))%" -ForegroundColor Green
# Check NTDS performance
$ntdsCounters = @(
"\NTDS\LDAP Searches/sec",
"\NTDS\LDAP Client Sessions",
"\NTDS\Database Cache % Hit"
)
Write-Host "`nNTDS Performance:" -ForegroundColor Yellow
foreach ($counter in $ntdsCounters) {
try {
$value = Get-Counter $counter -ComputerName $DomainController -MaxSamples 1
Write-Host " $($counter.Split('\')[-1]): $([math]::Round($value.CounterSamples[0].CookedValue, 2))" -ForegroundColor Green
}
catch {
Write-Host " $($counter.Split('\')[-1]): Unable to retrieve" -ForegroundColor Red
}
}
}
# Run performance analysis
# Analyze-GCPerformance -DomainController "DC01.contoso.com"
Resolution Steps:
Optimize Hardware Resources:
- Increase memory allocation
- Upgrade to faster storage (SSD/NVMe)
- Ensure adequate CPU resources
Database Optimization:
# Perform offline defragmentation (requires downtime) # esentutl /d C:\Windows\NTDS\ntds.dit # Online database optimization repadmin /showrepl ntdsutil "semantic database analysis" "go fixup" quit quit
Network Optimization:
- Optimize replication schedules
- Configure site links appropriately
- Consider additional GC servers in remote sites
Issue 3: Infrastructure Master and Global Catalog Conflicts
Symptoms:
- Stale cross-domain group memberships
- Inconsistent security descriptors
- Phantom objects not being cleaned up
Diagnosis and Resolution:
# Check for Infrastructure Master / GC conflicts
function Test-InfrastructureMasterConflict {
$forest = Get-ADForest
$conflicts = @()
foreach ($domain in $forest.Domains) {
$infraMaster = (Get-ADDomain $domain).InfrastructureMaster
$infraMasterDC = Get-ADDomainController -Identity $infraMaster
if ($infraMasterDC.IsGlobalCatalog) {
# Check if ALL DCs in domain are GCs
$allDCs = Get-ADDomainController -Filter * -Server $domain
$gcDCs = $allDCs | Where-Object {$_.IsGlobalCatalog}
if ($allDCs.Count -ne $gcDCs.Count) {
$conflicts += [PSCustomObject]@{
Domain = $domain
InfrastructureMaster = $infraMaster
IsGlobalCatalog = $true
AllDCsAreGC = $false
Recommendation = "Move Infrastructure Master to non-GC server OR make all DCs Global Catalogs"
}
} else {
# All DCs are GCs - this is acceptable
Write-Host "Domain $domain`: Infrastructure Master is GC, but all DCs are GCs - OK" -ForegroundColor Green
}
}
}
return $conflicts
}
# Check for conflicts
$conflicts = Test-InfrastructureMasterConflict
if ($conflicts) {
$conflicts | Format-Table -AutoSize
} else {
Write-Host "No Infrastructure Master / Global Catalog conflicts detected" -ForegroundColor Green
}
Security Considerations
Global Catalog Security Best Practices
Access Control and Authentication
# Audit Global Catalog access permissions
function Audit-GlobalCatalogSecurity {
Write-Host "Auditing Global Catalog security settings..." -ForegroundColor Cyan
# Check LDAP signing requirements
$gcServers = Get-ADDomainController -Filter {IsGlobalCatalog -eq $true}
foreach ($server in $gcServers) {
Write-Host "`nChecking $($server.Name):" -ForegroundColor Yellow
try {
# Check LDAP signing requirements
$ldapSigning = Invoke-Command -ComputerName $server.Name -ScriptBlock {
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -Name "LDAPServerIntegrity" -ErrorAction SilentlyContinue
}
$signingLevel = switch ($ldapSigning.LDAPServerIntegrity) {
0 { "None" }
1 { "Negotiate signing" }
2 { "Require signing" }
default { "Unknown" }
}
Write-Host " LDAP Signing: $signingLevel" -ForegroundColor $(if($ldapSigning.LDAPServerIntegrity -ge 1){'Green'}else{'Red'})
# Check SSL certificate for LDAPS
$sslTest = Test-NetConnection -ComputerName $server.Name -Port 636 -WarningAction SilentlyContinue
Write-Host " LDAPS Available: $($sslTest.TcpTestSucceeded)" -ForegroundColor $(if($sslTest.TcpTestSucceeded){'Green'}else{'Yellow'})
}
catch {
Write-Host " Error checking security settings: $($_.Exception.Message)" -ForegroundColor Red
}
}
}
# Run security audit
Audit-GlobalCatalogSecurity
Network Security
# Configure firewall rules for Global Catalog
function Configure-GCFirewallRules {
param([switch]$RemoveRules)
$gcRules = @(
@{ Name = "Global Catalog LDAP"; Port = 3268; Protocol = "TCP"; Description = "Global Catalog LDAP queries" },
@{ Name = "Global Catalog LDAPS"; Port = 3269; Protocol = "TCP"; Description = "Global Catalog LDAP over SSL" }
)
foreach ($rule in $gcRules) {
if ($RemoveRules) {
Remove-NetFirewallRule -DisplayName $rule.Name -ErrorAction SilentlyContinue
Write-Host "Removed firewall rule: $($rule.Name)" -ForegroundColor Yellow
} else {
New-NetFirewallRule -DisplayName $rule.Name -Direction Inbound -Protocol $rule.Protocol -LocalPort $rule.Port -Action Allow -Profile Domain -Description $rule.Description
Write-Host "Created firewall rule: $($rule.Name)" -ForegroundColor Green
}
}
}
# Configure GC firewall rules
# Configure-GCFirewallRules
Compliance and Auditing
# Enable Global Catalog auditing
function Enable-GCAuditing {
$gcServers = Get-ADDomainController -Filter {IsGlobalCatalog -eq $true}
foreach ($server in $gcServers) {
Write-Host "Enabling auditing on $($server.Name)..." -ForegroundColor Green
try {
Invoke-Command -ComputerName $server.Name -ScriptBlock {
# Enable directory service auditing
auditpol /set /subcategory:"Directory Service Access" /success:enable /failure:enable
auditpol /set /subcategory:"Directory Service Changes" /success:enable /failure:enable
# Configure security log size
wevtutil sl Security /ms:1073741824 # 1GB
wevtutil sl Security /rt:false # Archive when full
}
Write-Host " Auditing enabled successfully" -ForegroundColor Green
}
catch {
Write-Host " Error enabling auditing: $($_.Exception.Message)" -ForegroundColor Red
}
}
}
# Enable GC auditing
# Enable-GCAuditing
Best Practices Summary
Design and Planning
Strategic Placement:
- Place GCs close to users and applications
- Consider network topology and bandwidth
- Plan for redundancy and failover
Capacity Planning:
- Monitor storage growth for partial replicas
- Plan for increased network utilization
- Size hardware appropriately for query load
Forest Design:
- Minimize domains when possible
- Consider GC placement in multi-domain scenarios
- Plan for Infrastructure Master placement
Implementation and Management
Configuration Management:
- Use PowerShell for consistent configuration
- Document all GC placements and decisions
- Implement change management procedures
Monitoring and Maintenance:
- Regular health checks and performance monitoring
- Proactive capacity management
- Event log monitoring and alerting
Security:
- Implement LDAP signing and encryption
- Regular security audits
- Network segmentation and firewall rules
Operational Excellence
Automation:
- Automated health monitoring
- Scripted configuration management
- Performance trending and alerting
Documentation:
- Maintain current topology documentation
- Document custom attribute additions
- Keep troubleshooting procedures updated
Testing and Validation:
- Regular DR testing
- Performance baseline validation
- Security posture assessments