Putting It All Together
One potential use for domain- and OU-manipulation scripts is to configure a test or pilot domain that resembles your production domain. By using a script, you can install a domain controller in a lab, and then quickly recreate aspects of your production environment, such as OU structure and user accounts.
Preload Domain
Listing 15.1 shows a script that preloads a domain with a specific OU structure. Just for fun, I've thrown in a couple of new methods that copy and move OUs around within the domain. See if you can figure out how they work before you read the line-by-line explanation.
Listing 15.1. PreLoad.vbs. Preloads a specific OU configuration into a domain via LDAP.
'bind to domain
Dim oDomain
Set oDomain = GetObject("LDAP://dc=domain,dc=com")
'Create top-level OUs
Dim oSales, oHR, oMIS
Set oSales = oDomain.Create("organizationalUnit", "Sales")
Set oHR = oDomain.Create("organizationalUnit", "HR")
Set oMIS = oDomain.Create("organizationalUnit", "MIS")
oDomain.SetInfo
'set descriptions
oSales.Put "description", "Sales OU"
oHR.Put "description", "HR OU"
oMIS.Put "description", "MIS OU"
'save
oSales.SetInfo
oHR.SetInfo
oMIS.SetInfo
'create child OUs for Sales
Dim oChild
Set oChild = oSales.Create("organizationalUnit", "Widgets")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", "Wodgets")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", "Worm Gears")
oChild.SetInfo
'create child OUs for HR
Set oChild = oSales.Create("organizationalUnit", "Recruiting")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", "Counseling")
oChild.SetInfo
'create child OUs for MIS
Set oChild = oSales.Create("organizationalUnit", "Engineering")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", "Desktop")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", _
"Configuration")
oChild.SetInfo
'set domain-wide password policy
oDomain.Put "minPwdLength", 10
oDomain.Put "maxPwdAge", 30
oDomain.Put "minPwdAge", 2
oDomain.SetInfo
'display contents of Users
Dim sContents, oUsers, oObject
Set oUsers = GetObject("LDAP://cn=Users,dc=domain,dc=com")
For Each oObject In oUsers
sContents = sContents & oObject.Name & ", "
Next
WScript.Echo "Users contains: " & sContents
'create another top-level OU
Dim oOU
Set oOU = oDomain.Create("organizationalUnit", "Management")
oDomain.SetInfo
'move the top-level OU into Sales
oSales.MoveHere "LDAP://ou=Management,dc=domain,dc=com"
'create a management OU in HR, too
Dim oCopy
oCopy = oHR.Create("organizationalUnit", "Management")
oCopy.SetInfo
'now we're going to copy the Sales Management OU
'attributes to the HR Management OU
Dim oTemplate, aAttributes, sAttribute, sValue
'use the Sales OU as a reference
Set oTemplate = GetObject( _
"LDAP://ou=Management,ou=Sales,dc=domain,dc=com")
aAttributes = Array("description", "location")
'copy each attribute from the source to the target
For Each sAttribute In aAttributes
sValue = oTemplate.Get(sAttribute)
oCopy.Put sAttribute, sValue
Next
'save the information
oCopy.SetInfo
Before you run this script, you obviously need to modify the LDAP connection strings to point to a domain in your environment. Of course, I highly recommend the use of a test domain, not your production domain!
Preload Domain-Explained
This script begins by binding to the domain itself.
'bind to domain
Dim oDomain
Set oDomain = GetObject("LDAP://dc=domain,dc=com")
Then, the script creates three top-level OUs: Sales, HR, and MIS. These are each referenced by their own object variables.
'Create top-level OUs
Dim oSales, oHR, oMIS
Set oSales = oDomain.Create("organizationalUnit", "Sales")
Set oHR = oDomain.Create("organizationalUnit", "HR")
Set oMIS = oDomain.Create("organizationalUnit", "MIS")
oDomain.SetInfo
The script then sets a description for each new OU.
'set descriptions
oSales.Put "description", "Sales OU"
oHR.Put "description", "HR OU"
oMIS.Put "description", "MIS OU"
Next, I save the information using the SetInfo method of each new OU.
'save
oSales.SetInfo
oHR.SetInfo
oMIS.SetInfo
Now, I create three child OUs under the Sales OU. After creating each, I save it, so that I can reuse the oChild object.
'create child OUs for Sales
Dim oChild
Set oChild = oSales.Create("organizationalUnit", "Widgets")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", "Wodgets")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", "Worm Gears")
oChild.SetInfo
Now the script creates two child OUs for HR, and three more under MIS. Again, notice the use of SetInfo after each call to Create.
'create child OUs for HR
Set oChild = oSales.Create("organizationalUnit", "Recruiting")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", "Counseling")
oChild.SetInfo
'create child OUs for MIS
Set oChild = oSales.Create("organizationalUnit", "Engineering")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", "Desktop")
oChild.SetInfo
Set oChild = oSales.Create("organizationalUnit", _
"Configuration")
oChild.SetInfo
Now I return to the top-level domain object to set a few domain-wide password policy attributes. I've used Put to set each one, and then called SetInfo to save the new configuration.
'set domain-wide password policy
oDomain.Put "minPwdLength", 10
oDomain.Put "maxPwdAge", 30
oDomain.Put "minPwdAge", 2
oDomain.SetInfo
Just for fun, I have the script iterate through each object in the built-in Users container. Remember: Although it looks like an OU, it isn't one, so it has to be accessed by using the CN component, not the OU component. The result should be a comma-separated list of the object names in the container.
'display contents of Users
Dim sContents, oUsers, oObject
Set oUsers = GetObject("LDAP://cn=Users,dc=domain,dc=com")
For Each oObject In oUsers
sContents = sContents & oObject.Name & ", "
Next
WScript.Echo "Users contains: " & sContents
Next, I create another top-level OU.
'create another top-level OU
Dim oOU
Set oOU = oDomain.Create("organizationalUnit", "Management")
oDomain.SetInfo
The script now moves the new OU to be a child OU of Sales. I could have created the OU directly under Sales, but that wouldn't have shown off the MoveHere method. Notice how this works: I use the MoveHere method of the parent object, specifying the LDAP string of the object to be moved. There's no need to call SetInfo in this case.
'move the top-level OU into Sales
oSales.MoveHere "LDAP://ou=Management,dc=domain,dc=com"
Now I want to copy the Sales/Management OU into HR, so that there will also be an HR/Management OU. I want the attributes of both OUs to be the same. I have to start by creating the new child OU under HR.
'create a management OU in HR, too
Dim oCopy
oCopy = oHR.Create("organizationalUnit", "Management")
oCopy.SetInfo
I need a reference to my template object, which is the Management OU that already exists under the Sales OU.
'now we're going to copy the Sales Management OU
'attributes to the HR Management OU
Dim oTemplate, aAttributes, sAttribute, sValue
'use the Sales OU as a reference
Set oTemplate = GetObject( _
"LDAP://ou=Management,ou=Sales,dc=domain,dc=com")
aAttributes = Array("description", "location")
Next, I can use a For Each…Next loop to copy each attribute from Sales/Management to HR/Management.
'copy each attribute from the source to the target
For Each sAttribute In aAttributes
sValue = oTemplate.Get(sAttribute)
oCopy.Put sAttribute, sValue
Next
When the attributes are copied, a call to SetInfo saves the changes.
'save the information
oCopy.SetInfo
Using this type of script to quickly load a domain is a valuable trick, and can save you many hours in the test lab. Unlike a backup, which always restores the same thing, this script can be easily tweaked to set up different test environments, or to reflect changes in your production domain.
|