Recently i have been labing a lot, and most of the labs requires me to have an Active directory for various stuff like authentication with Cisco ISE and ASA VPN also been into System Center Configuration Manager.
In the midst of all this i had to automate and make it easy for me to spin up an Active directory server, this all made me turn back to Powershell which is an awesome tool from Microsoft. With my knowldge on coding never thought it will be that tough, with google and Powershell documentation as my friend there will be no mountain to high for me to climb.
Luckily i came across an this article that was describing how to do that excatly.
How to create your Active Directory Lab with Powershell. We are working with the latest Windows Server 2019 version aka 1809, We use Standard version with GUI, but you can run all this step in a Windows Server Core this is more secure to my mind, but you need have a remote Windows 10 with RSAT.
In my Lab I use free API https://randomuser.me/
for create random user in my Active Directory.
1. Configure Windows Server 2019
1.1 Networking
How to configure networking with powershell.
#Find the Interface Index for your NIC with the name Ethernet $InterfaceIndex = $(Get-NetIPAddress | Where-Object {$_.InterfaceAlias -like "Ethernet*"}).InterfaceIndex #Assign Address IPv4 New-NetIPAddress -InterfaceIndex $InterfaceIndex -AddressFamily IPv4 -IPAddress “172.17.0.1” –PrefixLength 16 -DefaultGateway 172.17.255.254 #Assign Server DNS Set-DnsClientServerAddress -InterfaceIndex $InterfaceIndex -ServerAddresses 172.17.0.1
1.2 ComputerName
Rename-Computer -NewName DC -Restart
1.3 Install WindowsFeature
- The first step is to install Ad-Domain-Services.
Get-WindowsFeature -Name *AD-Domain*
- Install the Feature with all subfeatures
Install-WindowsFeature -Name AD-Domain-services -IncludeAllSubFeature -IncludeManagementTools
- Verify all the Feature installed
Get-WindowsFeature | Where-Object {$_. installstate -eq "installed"} | Format-List Name,Installstate | more
The Output :
Name : AD-Domain-Services InstallState : Installed Name : FileAndStorage-Services InstallState : Installed Name : File-Services InstallState : Installed Name : FS-FileServer InstallState : Installed Name : Storage-Services InstallState : Installed Name : NET-Framework-45-Features InstallState : Installed Name : NET-Framework-45-Core InstallState : Installed Name : NET-WCF-Services45 InstallState : Installed Name : NET-WCF-TCP-PortSharing45 InstallState : Installed Name : GPMC InstallState : Installed Name : RSAT InstallState : Installed Name : RSAT-Role-Tools InstallState : Installed Name : RSAT-AD-Tools InstallState : Installed Name : RSAT-AD-PowerShell InstallState : Installed Name : RSAT-ADDS InstallState : Installed Name : RSAT-AD-AdminCenter InstallState : Installed Name : RSAT-ADDS-Tools InstallState : Installed Name : WoW64-Support InstallState : Installed Name : Windows-Defender InstallState : Installed Name : PowerShellRoot InstallState : Installed Name : PowerShell InstallState : Installed Name : PowerShell-ISE InstallState : Installed Name : XPS-Viewer InstallState : Installed
2. Create Active Directory Forest
For Create Forest you have one powershell cmdlet `Install-ADDSforest’. the full documentation is available here. The function accept many parameters in my Lab, I use the minimal parameter to quickly promote my domain controller.
#Secure my password $Password ="123+aze" $SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force # Promote the domain controller Install-ADDSForest -DomainName JM2K69.pwsh -SafeModeAdministratorPassword $SecurePassword -Force
The Output 👩💻:
WARNING: Windows Server 2019 domain controllers offer a default security setting named "Allow encryption algorithms compatible with Windows NT 4.0". This setting prevents the use of weak encryption algorithms when establishing secure channel sessions. For more information on this setting, see Knowledge Base article 942564 (http://go.microsoft.com/fwlink/?LinkId=1 04751). WARNING: It is not possible to create a delegation for this DNS server because the authoritative parent zone cannot be found or it is not running the Windows DNS server. If you are integrating with an existing DNS infrastructure, you must manually create a delegation with this DNS server in the parent zone to enable reliable name resolution outside of the "JM2K69.pwsh" domain. Otherwise, no action is required. WARNING: Windows Server 2019 domain controllers provide a default security setting named "Allow encryption algorithms compatible with Windows NT 4.0". This setting prevents the use of weak encryption algorithms when establishing secure channel sessions. For more information on this setting, see Knowledge Base article 942564 (http://go.microsoft.com/fwlink/?LinkId=1 04751).
Then you computer restart.
3. Create your Organizational Unit (OU)
Now that the domain controller is up and running, you can start creating OUs. they allow to organize the objects of your company (Users, Computers, Printers …). On these organizational units will be positioned the GPOs.

3.1 PowerShell Time
At first, the script must be able to work on any ADDS. This code below allows us to retrieve all the information needed to create objects in active directory.
$fqdn = Get-ADDomain $fulldomain = $fqdn.DNSRoot $domain = $fulldomain.split(".") $Dom = $domain[0] $Ext = $domain[1]
3.2 Create one OU
Th powershell Cmdlet for create OU is very simple :
New-ADOrganizationalUnit -Name Test -Description Test
In your Lab Only and not in Production you can add the -parameter
-ProtectedFromAccidentalDeletion $false you can easily remove the OU.
3.3 My Script
# Informations $Sites = ("Lyon","New-York","London") $Services = ("Production","Marketing","IT","Direction","Helpdesk") $Materiel = ("Computer","Server","Printers") $FirstOU ="Sites" New-ADOrganizationalUnit -Name $FirstOU -Description $FirstOU -Path "DC=$Dom,DC=$EXT" -ProtectedFromAccidentalDeletion $false foreach ($S in $Sites) { New-ADOrganizationalUnit -Name $S -Description "$S" -Path "OU=$FirstOU,DC=$Dom,DC=$EXT" -ProtectedFromAccidentalDeletion $false foreach ($Serv in $Services) { New-ADOrganizationalUnit -Name $Serv -Description "$S $Serv" -Path "OU=$S,OU=$FirstOU,DC=$Dom,DC=$EXT" -ProtectedFromAccidentalDeletion $false } }
4. Create User
I Create a function to use a free API
.
function New-RandomUser { <# .SYNOPSIS Generate random user data from Https://randomuser.me/. .DESCRIPTION This function uses the free API for generating random user data from https://randomuser.me/ .EXAMPLE Get-RandomUser 10 .EXAMPLE Get-RandomUser -Amount 25 -Nationality us,gb .LINK https://randomuser.me/ #> [CmdletBinding()] param ( [Parameter(Position = 0)] [ValidateRange(1,500)] [int] $Amount, [Parameter()] [ValidateSet('Male','Female')] [string] $Gender, # Supported nationalities: AU, BR, CA, CH, DE, DK, ES, FI, FR, GB, IE, IR, NL, NZ, TR, US [Parameter()] [string[]] $Nationality, [Parameter()] [ValidateSet('json','csv','xml')] [string] $Format = 'json', # Fields to include in the results. # Supported values: gender, name, location, email, login, registered, dob, phone, cell, id, picture, nat [Parameter()] [string[]] $IncludeFields, # Fields to exclude from the the results. # Supported values: gender, name, location, email, login, registered, dob, phone, cell, id, picture, nat [Parameter()] [string[]] $ExcludeFields ) $rootUrl = "http://api.randomuser.me/?format=$($Format)" if ($Amount) { $rootUrl += "&results=$($Amount)" } if ($Gender) { $rootUrl += "&gender=$($Gender)" } if ($Nationality) { $rootUrl += "&nat=$($Nationality -join ',')" } if ($IncludeFields) { $rootUrl += "&inc=$($IncludeFields -join ',')" } if ($ExcludeFields) { $rootUrl += "&exc=$($ExcludeFields -join ',')" } Invoke-RestMethod -Uri $rootUrl }
4.1 How to use the function
How to :
$users = New-RandomUser -Amount 30 -Nationality us -IncludeFields name,dob,phone,cell -ExcludeFields picture | Select-Object -ExpandProperty results foreach ($user in $users) { $newUserProperties = @{ Name = "$($user.name.first) $($user.name.last)" City = "City" GivenName = $user.name.first Surname = $user.name.last Path = $adPath title = "Director" department="IT" OfficePhone = $user.phone MobilePhone = $user.cell Company="JM2K69" EmailAddress="$($user.name.first).$($user.name.last)@$($adDomain)" AccountPassword = (ConvertTo-SecureString $userPassword -AsPlainText -Force) SamAccountName = $($user.name.first).Substring(0,1)+$($user.name.last) UserPrincipalName = "$(($user.name.first).Substring(0,1)+$($user.name.last))@$($adDomain)" Enabled = $true } try {New-ADUser @newUserProperties} catch {} }
5. The final Script
All the part combined in one. For The different site I change the -parameter
Nationality. In this example I create 20 Employees and 5 Directors / Sites / Services.
$fqdn = Get-ADDomain $fulldomain = $fqdn.DNSRoot $domain = $fulldomain.split(".") $Dom = $domain[0] $Ext = $domain[1] $userPassword = '123+aze' $Sites = ("Dar-Es-Salaam", "Arusha", "Dodoma", "Zanzibar", "Mwanza") $Services = ("Production", "Marketing", "IT", "Direction", "Helpdesk") $Material = ("Computer", "Server", "Printers") $FirstOU = "Sites" New-ADOrganizationalUnit -Name $FirstOU -Description $FirstOU -Path "DC=$Dom,DC=$EXT" -ProtectedFromAccidentalDeletion $false foreach ($S in $Sites) { New-ADOrganizationalUnit -Name $S -Description "$S" -Path "OU=$FirstOU,DC=$Dom,DC=$EXT" -ProtectedFromAccidentalDeletion $false foreach ($Serv in $Services) { New-ADOrganizationalUnit -Name $Serv -Description "$S $Serv" -Path "OU=$S,OU=$FirstOU,DC=$Dom,DC=$EXT" -ProtectedFromAccidentalDeletion $false switch ($S) { 'Dar-Es-Salaam' { $Employees = New-RandomUser -Amount 20 -Nationality fr -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results $Directors = New-RandomUser -Amount 5 -Nationality fr -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results } 'Arusha' { $Employees = New-RandomUser -Amount 20 -Nationality us -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results $Directors = New-RandomUser -Amount 5 -Nationality us -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results } 'Dodoma' { $Employees = New-RandomUser -Amount 20 -Nationality gb -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results $Directors = New-RandomUser -Amount 5 -Nationality gb -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results } 'Zanzibar' { $Employees = New-RandomUser -Amount 20 -Nationality us -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results $Directors = New-RandomUser -Amount 5 -Nationality us -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results } 'Mwanza' { $Employees = New-RandomUser -Amount 20 -Nationality gb -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results $Directors = New-RandomUser -Amount 5 -Nationality gb -IncludeFields name, dob, phone, cell -ExcludeFields picture | Select-Object -ExpandProperty results } Default { } } foreach ($user in $Employees) { $newUserProperties = @{ Name = "$($user.name.first) $($user.name.last)" City = "$S" GivenName = $user.name.first Surname = $user.name.last Path = "OU=$Serv,OU=$S,OU=$FirstOU,dc=$Dom,dc=$EXT" title = "Employees" department = "$Serv" OfficePhone = $user.phone MobilePhone = $user.cell Company = "$Dom" EmailAddress = "$($user.name.first).$($user.name.last)@$($fulldomain)" AccountPassword = (ConvertTo-SecureString $userPassword -AsPlainText -Force) SamAccountName = $($user.name.first).Substring(0, 1) + $($user.name.last) UserPrincipalName = "$(($user.name.first).Substring(0,1)+$($user.name.last))@$($fulldomain)" Enabled = $true } Try { New-ADUser @newUserProperties } catch { } } foreach ($user in $Directors) { $newUserProperties = @{ Name = "$($user.name.first) $($user.name.last)" City = "$S" GivenName = $user.name.first Surname = $user.name.last Path = "OU=$Serv,OU=$S,OU=$FirstOU,dc=$Dom,dc=$EXT" title = "Directors" department = "$Serv" OfficePhone = $user.phone MobilePhone = $user.cell Company = "$Dom" EmailAddress = "$($user.name.first).$($user.name.last)@$($fulldomain)" AccountPassword = (ConvertTo-SecureString $userPassword -AsPlainText -Force) SamAccountName = $($user.name.first).Substring(0, 1) + $($user.name.last) UserPrincipalName = "$(($user.name.first).Substring(0,1)+$($user.name.last))@$($fulldomain)" Enabled = $true } Try { New-ADUser @newUserProperties } catch { } } } }
Written by Jérôme Bezet-Torres @JM2K69.