PoshCode Logo PowerShell Code Repository

Create AD Test Lab by Ted Wagner 4 years ago
embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1666"></script>download | new post

This script expands on Dmitry Sotnikov’s blog post on creating demo Active Directory environments. http://dmitrysotnikov.wordpress.com/2007/12/14/setting-demo-ad-environments/

I liked his script and used it often, but found I needed something a bit more substatial to save me time while doing tests. So, I used his script as a “base” and have highly modified it since last fall. In January I began to make much more substantial changes to it with the goal of adding it to poshcode.org. The comments in this script are more detailed. I will post updates as the script improves.

  1. # ---------------------------------------------------------------------------
  2. ### <Script>
  3. ### <Author>Ted Wagner</Author>
  4. ### <Version='2.4'>
  5. ### <Script Name='Create-ADTestLabContent.ps1'>
  6. ### <Derived From='Dmitry Sotnikov - http://dmitrysotnikov.wordpress.com/2007/12/14/setting-demo-ad-environments/'>
  7. ### <Description>
  8. ### This script design uses the original script (base script) written by Dmitry Sotnikov.  The script's
  9. ### original comments are included below.  I am referring to Dmitry's script as "version 1.0"
  10. ###
  11. ### My goal is to standardize variables, functions and libraries such that the script is portable.  
  12. ### This is so that I can place all files for PowerShell on an ISO file and re-use the content
  13. ### with as little modification as possible from test scenario to test scenario.
  14. ###
  15. ### My scripts folder is a directory copied from the ISO file.  When I build a virtual environment,
  16. ### I bring up a completely configured and empty AD domain.  I then attach the ISO to the VM and
  17. ### copy the "scripts" folder to the root of C:.  I then drop in a default profile.ps1 into the
  18. ### WindowsPowerShell directory (the default All Users profile) and run this script.
  19. ###
  20. ### There is more work, yet to do; I want to "pare down" the functions so that the functions could be added to
  21. ### a functions.ps1 "library" file.
  22. ###
  23. ### The labs I set up for testing use an OU structure similar to the following:
  24. ###
  25. ### OU=DeptName -
  26. ###             |- Computers
  27. ###             |- Groups
  28. ###             |- Users
  29. ###
  30. ### The profile.ps1 sets up the PSDrive and then creates a variable to the provider.  The profile.ps1
  31. ### script is in the root of the scripts directoy which is copied from the ISO file.
  32. ###
  33. ### Contents of the profile.ps1 file:
  34. ###
  35. ### New-PSDrive -name ScriptLib -psProvider FileSystem -root "C:\Scripts"
  36. ### $ScriptLib = 'ScriptLib:'
  37. ###
  38. ### The Scripts folder contains a subfolder named "LabSetup".  The LabSetup folder contains this script,
  39. ### titled "Create-ADTestLabContent.ps1" and all of the text files necessary for creating the user
  40. ### objects, OU's, etc.  You can create your own files and/or edit this script to match your file names.
  41. ### I've listed the contents of each file below.
  42. ###
  43. ### I deviated from the original text files from Dmitry's script.
  44. ### My goal was to have a "true" list of random names by utilizing the "select-random" written by
  45. ### Joel Bennett.  This can be downloaded from poshcode.org.  I found that the combination of the
  46. ### select-ramdom on the census files and parsing the extra data was extremely time consuming.
  47. ### I went to the census.org page for year 2000 and downloaded the top 1000 names spreadsheet.
  48. ### Then, I simply stripped off ALL of the extra data (first row and all columns after column A)
  49. ### and saved it as an ascii file called "surnames.txt".  The link to that page is:
  50. ### http://www.census.gov/genealogy/www/data/2000surnames/index.html
  51. ###
  52. ### Additionally, I did something similar with the first names.
  53. ### I downloaded common male and female names from http://infochimps.org/collections/moby-project-word-lists
  54. ### Those files are named fgivennames.txt and mgivennames.txt.  You can alternately download a text file
  55. ### of 21,000+ common given names from the same site instead of using the surnames from census.gov.
  56. ### However, for my testing, a sample of 1000 last names was sufficient for my needs.
  57. ###
  58. ### departments.txt - Name of each Department which will be both an OU, group, and the department
  59. ### property on user objects.
  60. ### ous.txt - Name of child-containers for each Department OU (Computers, Groups, Users).  
  61. ### cities.txt - Names of cities I will use on user properties
  62. ### dist.all.last.txt - ASCII file of last names downloaded from the Census.gov website
  63. ### dist.male.first.txt - ASCII file of male first names downloaded from the Census.gov website
  64. ### dist.female.first.txt - ASCII file of female first names downloaded from the Census.gov website
  65. ###
  66. ### The descriptions of the deparments match the OU name.  This differentiates them from the default
  67. ### containers created when AD is set up from those added by this script.  This allows for easily removing
  68. ### containers and all child items quickly during testing.
  69. ### </Description>
  70. ###
  71. ### <Dependencies>
  72. ### Requires ActiveRoles Management Shell for Active Directory.  This script will check
  73. ### for the snapin and add the snapin at runtime.
  74. ### </Dependencies>
  75. ###
  76. ### <History>
  77. ### changes 01/08/2010 - version 2.0
  78. ###     - Change Display name and full name properties to format of Lastname, Firstname
  79. ###     - Change password to p@ssw0rd
  80. ### Changes 01/11/2010 - version 2.1
  81. ###  - Assume base config of empty domain.  Create variable for root domain name
  82. ###  - make sure not attempt is made to duplicate usernames
  83. ###  - Create containers
  84. ### Changes 02/19/2010 - version 2.2
  85. ###  - added function to create empty departmental OUs and child containers for users, groups and computers
  86. ### Changes 02/22/2010 - version 2.3
  87. ###  - added computer account creation to occur when the user is added
  88. ###  - dot source functions.ps1
  89. ###  - added Joel Bennett's select-random v2.2 script to functions.ps1.  functions.ps1 in root of scripts folder
  90. ### Changes 02/23/2010
  91. ###  - Made script more readible by using word-wrap
  92. ###      - Cleaned up description and commenting
  93. ### Changes 02/24/2010 - Version 2.4
  94. ###  - Using new ascii files for first and given names (see notes)
  95. ###  - Removed original lines for parsing census.gov files
  96. ### Changes 02/25/2010
  97. ###  - added better description for containers added via script to differentiate them to account for
  98. ###  manually added containers
  99. ###      - fixed issue with computer object creation - computer objects weren't always getting created
  100. ###
  101. ### Original Script name:  demoprovision.ps1
  102. ##################################################
  103. ### Script to provision demo AD labs
  104. ### (c) Dmitry Sotnikov, xaegr
  105. ### Requires AD cmdlets
  106. ##################################################
  107. ###
  108. ### set folder in which the data files are located
  109. ### this folder should contain files from
  110. ### http://www.census.gov/genealogy/names/names_files.html
  111. ### as well as cities.txt and departments.txt with the
  112. ### lists of cities and departments for the lab
  113. ### </History>
  114. ### </Script>
  115. # ---------------------------------------------------------------------------
  116.  
  117. #Load Function Library
  118. . $ScriptLib\functions.ps1
  119.  
  120. # function to create empty OUs
  121. function create-LabOUs (){
  122.         # Create Each Dept OU
  123.         for ($i = 0; $i -le $DeptOUs.Length - 1; $i++){
  124.                 $OUName = "Test Lab Container - " + $DeptOUs[$i]
  125.                 $CreateDeptOU += @(new-QADObject -ParentContainer $RootDomain.RootDomainNamingContext `
  126.                 -type 'organizationalUnit' -NamingProperty 'ou' -name $DeptOUs[$i] -description $OUName )
  127.         }
  128.  
  129.         # Create Child OUs for each Dept
  130.         foreach ($DeptOU in $CreateDeptOU){
  131.                 for ($i = 0; $i -le $ChildOUs.Length - 1; $i++){
  132.                         new-qadObject -ParentContainer $DeptOU.DN -type 'organizationalUnit' -NamingProperty 'ou' `
  133.                         -name $ChildOUs[$i]
  134.                 }
  135.         }
  136. }
  137.  
  138. function New-RandomADUser (){
  139.         # set up random number generator
  140.         $rnd = New-Object System.Random
  141.  
  142.         # pick a male or a female first name
  143.         if($rnd.next(2) -eq 1) {
  144.                 $fn = $firstm[$rnd.next($firstm.length)]
  145.         } else {
  146.                 $fn = $firstf[$rnd.next($firstf.length)]
  147.         }
  148.         # random last name
  149.         $ln = $last[$rnd.next($last.length)]
  150.  
  151.         # Set proper caps
  152.         $ln = $ln[0] + $ln.substring(1, $ln.length - 1).ToLower()
  153.         $fn = $fn[0] + $fn.substring(1, $fn.length - 1).ToLower()
  154.  
  155.         # random city and department
  156.         $city = $cities[$rnd.next($cities.length)]
  157.         $dept = $depts[$rnd.next($depts.length)]
  158.  
  159.         $SName = ($fn.substring(0,1) + $ln)
  160.  
  161.         # set user OU variable
  162.         switch ($dept){
  163.                 $DeptContainers[0].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[0].DN | `
  164.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  165.                 $DeptContainers[1].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[1].DN | `
  166.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  167.                 $DeptContainers[2].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[2].DN | `
  168.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  169.                 $DeptContainers[3].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[3].DN | `
  170.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  171.                 $DeptContainers[4].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[4].DN | `
  172.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  173.                 $DeptContainers[5].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[5].DN | `
  174.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  175.                 $DeptContainers[6].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[6].DN | `
  176.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  177.                 $DeptContainers[7].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[7].DN | `
  178.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  179.                 $DeptContainers[8].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[8].DN | `
  180.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  181.                 $DeptContainers[9].name {$UserOU = Get-QADObject -SearchRoot $DeptContainers[9].DN | `
  182.                         where { $_.DN -match "Users" -and $_.Type -ne "user" }}
  183.         }
  184.  
  185.         # Check for account, if not exist, create account
  186.         if ((get-qaduser $SName) -eq $null){
  187.                 # Create and enable a user
  188.                 New-QADUser -Name "$ln`, $fn" -SamAccountName $SName -ParentContainer $UserOU -City $city `
  189.                 -Department $dept -UserPassword "p@ssw0rd" -FirstName $fn -LastName $ln -DisplayName "$ln`, $fn" `
  190.                 -Description "$city $dept" -Office $city | Enable-QADUser
  191.         }
  192.  
  193.         # set group OU variable
  194.         switch ($dept){
  195.                 $DeptContainers[0].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[0].DN | `
  196.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  197.                 $DeptContainers[1].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[1].DN | `
  198.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  199.                 $DeptContainers[2].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[2].DN | `
  200.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  201.                 $DeptContainers[3].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[3].DN | `
  202.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  203.                 $DeptContainers[4].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[4].DN | `
  204.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  205.                 $DeptContainers[5].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[5].DN | `
  206.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  207.                 $DeptContainers[6].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[6].DN | `
  208.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  209.                 $DeptContainers[7].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[7].DN | `
  210.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  211.                 $DeptContainers[8].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[8].DN | `
  212.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  213.                 $DeptContainers[9].name {$GroupOU = Get-QADObject -SearchRoot $DeptContainers[9].DN | `
  214.                         where { $_.DN -match "Groups" -and $_.Type -ne "group" }}
  215.         }
  216.  
  217.         # Create groups for each department, create group if it doesn't exist
  218.         if ((get-QADGroup $dept) -eq $null){
  219.                 New-QADGroup -Name $dept -SamAccountName $dept -ParentContainer $GroupOU -Description "$dept Users"
  220.         }
  221.  
  222.         # Add user to the group based on their department
  223.         Get-QADUser $SName -SearchRoot $UserOU | Add-QADGroupMember -Identity { $_.Department }
  224.        
  225.         # set computer OU variable
  226.         switch ($dept){
  227.                 $DeptContainers[0].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[0].DN | `
  228.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  229.                 $DeptContainers[1].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[1].DN | `
  230.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  231.                 $DeptContainers[2].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[2].DN | `
  232.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  233.                 $DeptContainers[3].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[3].DN | `
  234.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  235.                 $DeptContainers[4].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[4].DN | `
  236.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  237.                 $DeptContainers[5].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[5].DN | `
  238.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  239.                 $DeptContainers[6].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[6].DN | `
  240.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  241.                 $DeptContainers[7].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[7].DN | `
  242.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  243.                 $DeptContainers[8].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[8].DN | `
  244.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  245.                 $DeptContainers[9].name {$ComputerOU = Get-QADObject -SearchRoot $DeptContainers[9].DN | `
  246.                         where { $_.DN -match "Computers" -and $_.Type -ne "computer" }}
  247.         }
  248.  
  249.         # Create a computer account for the user
  250.         if ((get-qadcomputer "$SName-Computer") -eq $null){
  251.                 New-QADComputer -Name "$SName-Computer" -SamAccountName "$SName-Computer" -ParentContainer `
  252.                 $ComputerOU -Location "$city $dept"
  253.         }
  254. }
  255.  
  256. $TestQADSnapin = get-pssnapin | where { $_.Name -eq "Quest.ActiveRoles.ADManagement"}
  257. if($TestQADSnapin -eq $null){
  258.         add-pssnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue
  259. }
  260.  
  261. # number of accounts to generate - edit
  262. $num = 50
  263.  
  264. # Read root domain text
  265. $RootDomain = Get-QADRootDSE
  266.  
  267. # Read all text data
  268. # OU's to create
  269. $DeptOUs = @(Get-Content "$ScriptLib\LabSetup\Departments.txt")
  270. $ChildOUs = @(Get-Content "$ScriptLib\labsetup\ous.txt")
  271. # read department and city info
  272. $cities = Get-Content C:\scripts\LabSetup\Cities.txt
  273. $depts = Get-Content C:\scripts\LabSetup\Departments.txt
  274.  
  275. # read name files
  276. # randomly select names from census files
  277. # Use Joel Bennet's select-random v 2.2; saved in functions.ps1
  278. 1..$num | ForEach-Object {
  279.         $last += @(Get-Content C:\scripts\LabSetup\surnames.txt | select-random)
  280.         $firstm += @(Get-Content C:\scripts\LabSetup\mgivennames.txt | select-random)
  281.         $firstf += @(Get-Content C:\scripts\LabSetup\fgivennames.txt | select-random)
  282. }
  283.  
  284. # Let's do the work
  285.  
  286. # Create OUs first - call function
  287. create-LabOUs
  288.  
  289. # Retrieve all newly created OU DN's for use in next function
  290. $DeptContainers = @(Get-QADObject -Type "organizationalUnit" | where {$_.Name -ne "Computers" -and $_.Name `
  291.         -ne "Groups" -and $_.Name -ne "Users" -and $_.Description -match "Test Lab Container"})
  292.  
  293. foreach ($item in $DeptContainers){
  294.         $item.description
  295. }
  296. # Create users, create dept groups
  297. 1..$num | ForEach-Object { New-RandomADUser }
  298.  
  299. trap{
  300.         Write-Host "ERROR: script execution was terminated.`n" $_.Exception.Message
  301.         break
  302. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me