Building an Active Directory demo lab using Workflow to automatize the process

Hi,

I’m trying to join two articles from the “Hey, Scripting Guy!” website:

    * Building a demo Active Directory (http://blogs.technet.com/b/heyscriptingguy/archive/2013/10/28/building-a-demo-active-directory-part-1.aspx) * PowerShell Workflows: Restarting the Computer (http://blogs.technet.com/b/heyscriptingguy/archive/2013/01/23/powershell-workflows-restarting-the-computer.aspx)

In other words, I’m trying to make one script file only to:

    * Rename server and restart * Name network connection, change IP address, install AD components, change administrator password, create domain and restart * Create base OU, other OUs and random users

I’ve tried using only one file but, it isn’t working…
So I have to split it on 3 files.

Here are the codes:

FILE “Configura_Lab.ps1”

WorkFlow Configura_Lab {

Restart-Computer -Force -Wait

(InlineScript {C:\Configurar\Passo1.ps1})

}

$actionscript = '-NonInteractive -WindowStyle Normal -NoLogo -NoProfile -NoExit -Command "&''C:\Configurar\Workflow.ps1''"'
$pstart =  "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
Get-ScheduledTask -TaskName Continuar_Workflow -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false
$act = New-ScheduledTaskAction -Execute $pstart -Argument $actionscript
$trig = New-ScheduledTaskTrigger -AtLogOn
Register-ScheduledTask -TaskName Continuar_Workflow -Action $act -Trigger $trig -RunLevel Highest | Out-Null

#Renomear o servidor
$ServerName = Read-Host "Digite um nome para o servidor"
Rename-Computer $ServerName -Force -Passthru

Configura_Lab

FILE “Passo1.ps1”

WorkFlow Passo_2 {

(InlineScript {
Param(
$Empresa="Inventada LTDA",
$IPAddress="10.0.0.1",
$NetworkMask="24",
$Gateway="",
[string]$Password=’Secret321!’
)

#Configurar IP fixo
$NetAdaptersConnected = Get-NetAdapter | Where {$_.Status -eq "Up"}
$NetAdaptersConnected.Count
If ($NetAdaptersConnected.count){
Write-Host "Adaptadores conectados encontrados:"
$NetAdaptersConnected
$NetAdapterSelected = Read-Host "Digite o número da interface (ifIndex) que deseja utilizar"
}
else{
$NetAdapterSelected = $NetAdaptersConnected.ifIndex
}
Rename-NetAdapter -Name (Get-NetAdapter -ifIndex $NetAdapterSelected).name $Empresa
If ($Gateway){
New-NetIPAddress -AddressFamily IPv4 -IPAddress $IPAddress -PrefixLength $NetworkMask -DefaultGateway $Gateway -InterfaceIndex $NetAdapterSelected
}
else{
New-NetIPAddress -AddressFamily IPv4 -IPAddress $IPAddress -PrefixLength $NetworkMask -InterfaceIndex $NetAdapterSelected
}
Set-DnsClientServerAddress -ServerAddresses $IPAddress -InterfaceIndex $NetAdapterSelected -PassThru

#Instalar Domain Services no servidor
INSTALL-WindowsFeature AD-Domain-Services –IncludeManagementTools -IncludeAllSubFeature

#Alterar senha de administrador local
Net user Administrator $Password
})

Restart-Computer -Force -Wait

(InlineScript {C:\Configurar\Passo2.ps1})

}

Get-Job -command Configura_Lab | Stop-Job
Get-Job -command Configura_Lab | Remove-Job

Passo_2

FILE “Passo2.ps1”

WorkFlow Passo_3 {

(InlineScript {

Param(
[string]$DomainName=’Contoso.local’,
[string]$DomainNETBIOSName=’CONTOSO’,
[string]$Password=’Secret321!’
)

#Configurar o AD
Import-module ADDSDeployment

Install-ADDSForest –SkipPreChecks –CreateDnsDelegation:$False –DatabasePath ‘C:\Windows\NTDS’ –DomainMode ‘Win2012R2’ –DomainName $DomainName –DomainNetbiosname $DomainNETBIOSName –ForestMode ‘Win2012R2’ –InstallDns:$True –Logpath ‘C:\Windows\NTDS’ –NoRebootOnCompletion:$True –SysvolPath ‘C:\Windows\SYSVOL’ –SafeModeAdministratorPassword (CONVERTTO-SecureString $Password –asplaintext –force) –force:$true
})

Restart-Computer -Force -Wait

(InlineScript {C:\Configurar\Passo3.ps1})

}

Get-Job -command Passo_2 | Stop-Job
Get-Job -command Passo_2 | Remove-Job

Passo_3

FILE “Passo3.ps1”

Import-module ActiveDirectory

$ErrorActionPreference = "SilentlyContinue"

# Crude Random Password Generator 
Function GeneratePassword
{

# How many Characters Minimum?
$Length=15

# Create a password choosing everying from Character 34 to 127
1..$Length | foreach{ $Password+=([char]((Get-Random 93)+34))}

# Convert to a Secure String
$Password=Convertto-SecureString $Password -asplaintext -force
Return $Password
}

Function Get-GroupInfo()
{
Param(
$City,
$Division
)

$GroupName=$City.replace(" ","")+"-"+$Division.replace(" ","")
$GroupDescription="$Division in $City Access Group"

# Return the Results (This is a feature new to version 3)
[pscustomobject]@{Name=$Groupname;Description=$GroupDescription}
}

$BaseOU="Offices"
$CityOU=“Tokyo”,”Redmond”,”Ottawa”,”Madrid”,”New Orleans”,”Queensland”
$DivisionOU="Sales","Marketing","HR","Finance"
$Domain="DC=Contoso,DC=Local"
$CompanyPath="OU=$BaseOU,"+$Domain
$UPN="@contoso.local"

# Create BaseOU for Offices
NEW-ADOrganizationalUnit -name $BaseOU -path $Domain

# Gather through list of Cities
Foreach ($City in $CityOU) 
   {
    # Create OU for City
    NEW-ADOrganizationalUnit -path $CompanyPath -name $City

    # Gather through list of Divisions
    Foreach($Division in $DivisionOU)
    {

 # Create Division within City
 NEW-ADOrganizationalUnit -path "OU=$City,$CompanyPath" -name $Division

 # Create Group within Division and Description
 $Groupdata=Get-Groupinfo –City $City –Division $Division
 $GroupName=$Groupdata.Name
 $GroupDescription=$Groupdata.Description
 
 NEW-ADGroup -name $GroupName -GroupScope Global -Description $GroupDescription -Path "OU=$Division,OU=$City,$CompanyPath"
    }
}

# Pull together list of CSV raw data supplied from Generator
$Names=IMPORT-CSV C:\Configurar\Sample_names.csv

# Generate 150 Random Users from pulled Raw data
For ($x=0;$x -lt 150;$x++)
 {

 # Pick a Random First and Last Name
 $Firstname=GET-Random $Names.Firstname
 $Lastname=GET-Random $Names.Lastname
 $Displayname=$Lastname+” “+$Firstname
 
 # Pick a Random City
 $City=GET-RANDOM $Cityou

 # Pick a Random Division
 $Division=GET-RANDOM $DivisionOU
 $LoginID=$Firstname.substring(0,1)+$Lastname
 $UserPN=$LoginID+$UPN
 $Sam=$LoginID.padright(20).substring(0,20).trim()

 # Define their path in Active Directory
 $ADPath="OU=$Division,OU=$City,$CompanyPath"

 # Create the user in Active Directory
 New-ADUser -GivenName $Givenname -Surname $Surname -DisplayName $Displayname -UserPrincipalName $UserPN -Division $Division -City $City -Path $ADPath -name $Displayname -SamAccountName $Sam –AccountPassword (GENERATEPASSWORD)

 # Add User to appropriate Security Group
 $Groupname=(GET-GroupInfo –city $City –division $Division).Name
 ADD-ADGroupmember $Groupname –members $Sam

 # Enable the account for access
 ENABLE-ADAccount $Sam
 }

Get-ScheduledTask -TaskName Continuar_Workflow | Unregister-ScheduledTask -Confirm:$false

ADDITIONAL FILE “SampleNames.txt”


FirstName,LastName
Joe,Bloe
John,Smith
Mary,Jones
Marty,McFly
Johanna,Lopes
Jerry,Lewis
Terry,Williams
June,McCarthy
Louie,Adams
Giullermo,Andrade
Allan,Matthews
Richard,Marx
Tony,Bielfore
Taylor,Jameson
Phoebe,Cates

ADDITIONAL FILE “Workflow.txt”

Import-Module PSWorkflow
Get-Job | Resume-Job

Why using that kind of approach it just don’t work using one file?
Whats happened: Using one file the computer was renamed, restarted, configured IP address, restarted and didn’t installed Active Directory. Just gave me errors saying that it can’t create those OU or users because there was no domain.

Any ideas?

That was a great article, but these days I’d use Desired State Configuration instead. Much easier to write and maintain. Is that an option?

Well, I’m kinda new to PowerShell… Will give a look at DSC and I’ll post here my opinion.

Thanks a lot!

I’d second DSC - the downloads will give you AD building capability

powershell.org/wp/ebooks has an ebook on the subject - I’m using it to build my own lab environment, and I posted my scripts in a blog post here last week, I think. They’d probably be decent examples for you to start with. MUCH more straightforward. Good luck.

I’m going to do it right now! Thank you both for the replies.