AD Bootstrap Scripts Reference
Automation scripts for managing the AD structure defined in AD Bootstrap.
1. Overview
| Script | Purpose | Flags |
|---|---|---|
|
Create all OUs and groups (idempotent) |
|
|
Delete all OUs, groups, and user |
|
2. ad-bootstrap-create.ps1
Creates the enterprise AD structure. Idempotent - safe to run multiple times, skips existing objects.
2.1. What It Creates
-
7 top-level OUs: Tier 0-2, User Accounts, Groups, Staging, Disabled
-
13 nested OUs: Service Accounts, Linux/Windows per tier, Workstations, etc.
-
8 security groups: GRP-Computers-, GRP-Servers-, GRP-Users-*
2.2. Source Code
# ad-bootstrap-create.ps1
# Creates all AD objects defined in ad-bootstrap.adoc
param(
[switch]$WhatIf
)
$ErrorActionPreference = "Stop"
$Domain = "DC=inside,DC=domusdigitalis,DC=dev"
Write-Host "=== AD Bootstrap Create ===" -ForegroundColor Cyan
if ($WhatIf) {
Write-Host "[WHATIF MODE] No changes will be made" -ForegroundColor Yellow
}
2.2.1. Phase 1: Top-Level OUs
# These are the root OUs following Microsoft's Enterprise Access Model
$topLevelOUs = @(
"Tier 0 - Identity", # DCs, PKI, identity infrastructure
"Tier 1 - Servers", # Application servers
"Tier 2 - Endpoints", # Workstations, mobile
"User Accounts", # All user objects (renamed from "Users" to avoid CN=Users conflict)
"Groups", # Security and distribution groups
"Staging", # New objects before production placement
"Disabled" # Decommissioned objects (retain for audit)
)
foreach ($ou in $topLevelOUs) {
try {
New-ADOrganizationalUnit -Name $ou -Path $Domain -ProtectedFromAccidentalDeletion $true
Write-Host " Created OU: $ou" -ForegroundColor Green
} catch {
Write-Host " OU exists: $ou" -ForegroundColor Yellow
}
}
2.2.2. Phase 2: Nested OUs
# Nested OUs for granular organization
# Order matters: parent OUs must exist before children
$nestedOUs = @(
# Tier 0 - Identity infrastructure service accounts
@{ Name = "Service Accounts"; Path = "OU=Tier 0 - Identity,$Domain" },
# Tier 1 - Servers by OS
@{ Name = "Linux"; Path = "OU=Tier 1 - Servers,$Domain" },
@{ Name = "Windows"; Path = "OU=Tier 1 - Servers,$Domain" },
# Tier 2 - Endpoints
@{ Name = "Workstations"; Path = "OU=Tier 2 - Endpoints,$Domain" },
@{ Name = "Mobile"; Path = "OU=Tier 2 - Endpoints,$Domain" },
# Workstations by OS (nested under Workstations)
@{ Name = "Linux"; Path = "OU=Workstations,OU=Tier 2 - Endpoints,$Domain" },
@{ Name = "Windows"; Path = "OU=Workstations,OU=Tier 2 - Endpoints,$Domain" },
@{ Name = "Mac"; Path = "OU=Workstations,OU=Tier 2 - Endpoints,$Domain" },
# User Accounts by role
@{ Name = "Admins"; Path = "OU=User Accounts,$Domain" },
@{ Name = "Standard"; Path = "OU=User Accounts,$Domain" },
@{ Name = "Service Accounts"; Path = "OU=User Accounts,$Domain" },
# Groups by type
@{ Name = "Security"; Path = "OU=Groups,$Domain" },
@{ Name = "Distribution"; Path = "OU=Groups,$Domain" }
)
foreach ($ou in $nestedOUs) {
New-ADOrganizationalUnit -Name $ou.Name -Path $ou.Path -ProtectedFromAccidentalDeletion $true
}
2.2.3. Phase 3: Security Groups
# Security groups for ISE authorization policies
# Naming: GRP-<ObjectType>-<OS/Role>
$groupPath = "OU=Security,OU=Groups,$Domain"
$groups = @(
# Computer groups - for 802.1X machine authentication
# ISE checks computer account's group membership (e.g., modestus-razer$)
@{ Name = "GRP-Computers-Linux-Admin"; Desc = "Linux admin workstations - Tier 2 privileged" },
@{ Name = "GRP-Computers-Linux-Standard"; Desc = "Linux standard workstations" },
@{ Name = "GRP-Computers-Windows"; Desc = "Windows workstations" },
@{ Name = "GRP-Computers-Mac"; Desc = "Mac workstations" },
# Server groups
@{ Name = "GRP-Servers-Linux"; Desc = "Linux servers - network access" },
@{ Name = "GRP-Servers-Windows"; Desc = "Windows servers - network access" },
# User groups - for user-based authorization
@{ Name = "GRP-Users-Admins"; Desc = "Admin users - privileged access" },
@{ Name = "GRP-Users-Standard"; Desc = "Standard users" }
)
foreach ($group in $groups) {
New-ADGroup -Name $group.Name `
-GroupScope Global `
-GroupCategory Security `
-Path $groupPath `
-Description $group.Desc
}
3. ad-bootstrap-reset.ps1
Removes all AD objects for testing. Destructive - use only in lab environments.
3.1. What It Removes
-
User account (
evanusmodestus) -
All 8 security groups (
GRP-*) -
All 21 OUs (nested first, then parents)
3.2. Key Concepts
3.2.1. Deletion Order
OUs must be deleted children first, parents last. If you try to delete a parent OU with children, it fails.
# WRONG order - will fail
Remove-ADOrganizationalUnit "OU=Tier 2 - Endpoints,$Domain" # Has children!
# CORRECT order - children first
Remove-ADOrganizationalUnit "OU=Linux,OU=Workstations,OU=Tier 2 - Endpoints,$Domain"
Remove-ADOrganizationalUnit "OU=Windows,OU=Workstations,OU=Tier 2 - Endpoints,$Domain"
Remove-ADOrganizationalUnit "OU=Mac,OU=Workstations,OU=Tier 2 - Endpoints,$Domain"
Remove-ADOrganizationalUnit "OU=Workstations,OU=Tier 2 - Endpoints,$Domain"
Remove-ADOrganizationalUnit "OU=Mobile,OU=Tier 2 - Endpoints,$Domain"
Remove-ADOrganizationalUnit "OU=Tier 2 - Endpoints,$Domain" # Now safe
3.2.2. Protection Flag
OUs are created with -ProtectedFromAccidentalDeletion $true. Must disable before deletion:
# This will fail
Remove-ADOrganizationalUnit "OU=Staging,$Domain"
# Error: "Access denied" or "Object is protected"
# Must disable protection first
Set-ADOrganizationalUnit -Identity "OU=Staging,$Domain" -ProtectedFromAccidentalDeletion $false
Remove-ADOrganizationalUnit "OU=Staging,$Domain" # Now works
3.3. Source Code
# ad-bootstrap-reset.ps1
# Removes all AD objects created by ad-bootstrap.adoc
param(
[switch]$WhatIf,
[switch]$Recreate # If set, recreates structure after deletion
)
$ErrorActionPreference = "SilentlyContinue"
$Domain = "DC=inside,DC=domusdigitalis,DC=dev"
3.3.1. Phase 1: Remove User
# User must be removed first (exists in an OU we're deleting)
$user = Get-ADUser -Filter 'SamAccountName -eq "evanusmodestus"'
if ($user) {
Remove-ADUser -Identity "evanusmodestus" -Confirm:$false
Write-Host "Removed user: evanusmodestus"
}
3.3.2. Phase 2: Remove Groups
# Groups must be removed before their container OU
$groups = @(
"GRP-Computers-Linux-Admin",
"GRP-Computers-Linux-Standard",
"GRP-Computers-Windows",
"GRP-Computers-Mac",
"GRP-Servers-Linux",
"GRP-Servers-Windows",
"GRP-Users-Admins",
"GRP-Users-Standard"
)
foreach ($group in $groups) {
$g = Get-ADGroup -Filter "Name -eq '$group'"
if ($g) {
Remove-ADGroup -Identity $group -Confirm:$false
Write-Host "Removed group: $group"
}
}
3.3.3. Phase 3: Remove OUs
# OUs in deletion order: deepest nested first, then parents
$ous = @(
# Level 3 (deepest) - Workstation OS types
"OU=Linux,OU=Workstations,OU=Tier 2 - Endpoints,$Domain",
"OU=Windows,OU=Workstations,OU=Tier 2 - Endpoints,$Domain",
"OU=Mac,OU=Workstations,OU=Tier 2 - Endpoints,$Domain",
# Level 2 - Nested OUs
"OU=Service Accounts,OU=Tier 0 - Identity,$Domain",
"OU=Linux,OU=Tier 1 - Servers,$Domain",
"OU=Windows,OU=Tier 1 - Servers,$Domain",
"OU=Workstations,OU=Tier 2 - Endpoints,$Domain",
"OU=Mobile,OU=Tier 2 - Endpoints,$Domain",
"OU=Admins,OU=User Accounts,$Domain",
"OU=Standard,OU=User Accounts,$Domain",
"OU=Service Accounts,OU=User Accounts,$Domain",
"OU=Security,OU=Groups,$Domain",
"OU=Distribution,OU=Groups,$Domain",
# Level 1 - Top-level OUs (deleted last)
"OU=Tier 0 - Identity,$Domain",
"OU=Tier 1 - Servers,$Domain",
"OU=Tier 2 - Endpoints,$Domain",
"OU=User Accounts,$Domain",
"OU=Groups,$Domain",
"OU=Staging,$Domain",
"OU=Disabled,$Domain"
)
foreach ($ouDN in $ous) {
$ou = Get-ADOrganizationalUnit -Filter "DistinguishedName -eq '$ouDN'"
if ($ou) {
# Disable protection, then delete
Set-ADOrganizationalUnit -Identity $ouDN -ProtectedFromAccidentalDeletion $false
Remove-ADOrganizationalUnit -Identity $ouDN -Confirm:$false -Recursive
Write-Host "Removed OU: $($ou.Name)"
}
}
4. Usage Examples
4.1. Fresh Deployment
# Preview what will be created
.\ad-bootstrap-create.ps1 -WhatIf
# Create everything
.\ad-bootstrap-create.ps1
# Manually create user (requires password)
New-ADUser -Name "Evan Rosado" -SamAccountName "evanusmodestus" `
-UserPrincipalName "evanusmodestus@inside.domusdigitalis.dev" `
-Path "OU=Admins,OU=User Accounts,DC=inside,DC=domusdigitalis,DC=dev" `
-AccountPassword (Read-Host -AsSecureString "Password") `
-Enabled $true -PasswordNeverExpires $true
Add-ADGroupMember -Identity "Domain Admins" -Members "evanusmodestus"
Add-ADGroupMember -Identity "GRP-Users-Admins" -Members "evanusmodestus"
4.2. Test Cycle
# Nuke everything
.\ad-bootstrap-reset.ps1
# Verify clean state
Get-ADOrganizationalUnit -Filter * | Select-Object Name
# Should only show "Domain Controllers"
# Rebuild
.\ad-bootstrap-create.ps1
# Verify
Get-ADOrganizationalUnit -Filter * | Select-Object Name
# Should show all 21 OUs
5. ISE Group Mapping
After creation, these groups map to ISE authorization policies:
| AD Group | Members | ISE Authorization Profile |
|---|---|---|
GRP-Computers-Linux-Admin |
modestus-razer$, modestus-p50$, modestus-aw$ |
Linux-Admin-VLAN10 |
GRP-Computers-Linux-Standard |
Standard Linux workstations |
Linux-Standard-VLAN10 |
GRP-Computers-Windows |
Windows computer objects |
Windows-Workstation-VLAN10 |
GRP-Computers-Mac |
Mac computer objects |
Mac-Workstation-VLAN10 |
GRP-Servers-Linux |
vault-01$, kvm-01$, nas-01$ |
Server-VLAN20 |
GRP-Servers-Windows |
home-dc01$, future Windows servers |
Server-VLAN20 |