Tag: Powershell Scripts

Zero to Windows Domain Controller in 4 reboots!

Hey there,

Yes, it’s time to wow and amaze you with my coding skills! Prepare to be amazed! Or, more appropriately, roll your eyes with my lame ability to hack other peoples code into what I need to get done, quickly. Writing code for me is painful. Oh, like high school physics I can follow what’s going on pretty well, but sitting down and writing? Yea, that’s a challenge.

I needed a Windows Domain Controller for what I’m working on in my work lab. Figuring that I’ll probably need more Domain Controllers for future labs, I thought it would be a good time to automate it. I looked online for a simple PowerShell script that would do what I want and to my amazement, I couldn’t find anything other than pointers to a lot of commands. And, in many cases, those commands were either wrong or broken.

Lots of Steps

Because I work at VMware and this Domain Controller will be running as a VM, I’ll be using VMware VM Templates to create the virtual machines. I built a Windows 2012 template using some simple best practices steps documented here. I wanted to be able to right-click on a template and simply deploy a Domain Controller using GuestOS customization.

Simple, right? Actually, not that difficult. It’s mainly about getting all the steps done in the right order and meeting the requirements of each step.

  1. First, you have deploy the VM with the guest OS customization.
  2. Reboot
  3. Then add the AD bits to your Windows 2012 system so that you can enable the appropriate roles going forward.
  4. You’ll probably want to rename the system.
  5. Reboot
  6. Then install the AD Forest
  7. Reboot
  8. Then add the roles and configure networking/AD/DNS/etc..
  9. Reboot

How do you automate all that?

RunOnce to the Rescue

RunOnce is a Windows registry setting that automatically sets up Windows to run certain tasks when a system starts up or a user logs in. vSphere Guest OS Customization uses this so that when you deploy from a template, you can set the Windows system to run further setup scripts to modify the OS. In this example, you see how I’ve set up my DC-Builder.PS1 script to run via RunOnce.

MF Win7-x64 2014-08-04 13-19-38

The command I’m running is:

%SystemRoot%\system32\WindowsPowershell\v.10\Powershell.exe -executionpolicy bypass -file “C:\dc-builder.ps1”

Let’s run that down so everyone gets what’s happening. After deploying from Template and choosing this Guest OS Customization Specification, Windows 2012 will do a sysprep. After that is completed, Windows will reboot and run the RunOnce command above. That sets the ball in motion.

In the command, we’re running the DC-Builder.PS1 script using PowerShell.exe and specifying that it be run with the execution policy of bypass. That’s because the DC-Builder.PS1 script is not signed. Otherwise, it wouldn’t run.

You’ll notice that I’m running DC-Builder.PS1 from C:\. That’s because I built my template with the file copied to that location. Why? Because I didn’t want to have to deal with floppy images or network locations. Oh, sure, you can and then you can just change the location, but for me, I found this was easier. You want to do it differently? By all means, knock yourself out. :)

Now you’re probably asking “Ok, how do you automate all the other reboots?” Well, I iteratively  use RunOnce! I just nest the hell out of it!

DC-Builder creates a couple of scripts and sets up the first one to run after it reboots the system the first time. Then that script calls the next one to run.  DC-Builder creates the files using the PowerShell “@” operator.

Here’s an abbreviated example. Don’t just cut and paste this.

 

$InstallForestbat = @"
REM -----------------------------InstallForest.BAT------------------------------
REM Creating a .BAT file to change to bypass, run the commands, then change
REM back to remote
Powershell.exe set-executionpolicy bypass -force
SET FileToDelete="c:\InstallForest-transcript.txt"
IF EXIST %FileToDelete% del /F %FileToDelete%
powershell -noprofile -file c:\InstallForest.ps1 > c:\InstallForest-transcript.txt
REM Powershell.exe set-executionpolicy RemoteSigned
"@
$InstallForestBat |Out-File -FilePath c:\InstallForest.bat -Force -encoding ASCII
$AdminKey = "HKLM:"
$RunOnceKey = $AdminKey + "\Software\Microsoft\Windows\CurrentVersion\RunOnce"
Set-ItemProperty -Path $RunOncekey -Name Foo -Value "C:\InstallForest.bat"

 

See how I’m using the “-encoding” qualifier? PS1 files don’t need it but .BAT files most definitely do.

DC-Builder creates four files to be run.

  1. InstallForest.BAT – This is set up to run via RunOnce after DC-Builder completes and the system reboots. It runs InstallForest.PS1.
  2. InstallForest.PS1 – This installs the AD Forest, sets up the running of Post-DCCleanup.Bat via RunOnce and reboots the system.
  3. Post-DCCleanup.BAT – It runs Post-DCCleanup.PS1.
  4. Post-DCCleanup.PS1 – This finishes off the rest of the steps that need to be run after installing the AD Forest and reboots the system.

DC-Builder.PS1, InstallForest.PS1 and Post-DCCleanupPS1 also create transaction files in C:\ so that you can check for errors.

Note: You’ll notice that DC-Builder.PS1 sets up the Administrator account to log in automatically. You need this, at least initially, to get all the scripts to run. They need to run under a user context. Because this is primarily for lab environments, I set up my VM’s to log in automatically just to save steps. Yea, the “security guy” said that. Whatever. :)

How do I get started?

  1. Edit DC-Builder.PS1 to set up your IP address, system name and any other custom setting you’d like.
  2. Create your Windows 2012 Template VM.
  3. Copy DC-Builder.PS1 to C:\
  4. Shutdown the Windows 2012 Template VM.
  5. Attach the Windows 2012 ISO image to the VM <This is key!
  6. Select “Convert to Template”
  7. Create a Windows Customization Specification as called out above (or Import the XML)
  8. Deploy a new VM from template using the Customization Specification
  9. The VM will reboot 4 times and you’ll be left with a Windows Domain Controller, ready to roll.

Download the script and guest OS customization XML

GuestOS XML:     https://dl.dropboxusercontent.com/u/10618705/DC%20Windows%202012.xml

DC-Builder.ps1     https://dl.dropboxusercontent.com/u/10618705/DC-Builder.ps1

These files have now been moved to GitHub. You can get them here:

https://github.com/mikefoley/DC-Builder

Give it a try and let me know what you think and what it’s missing. It could use some more documenting but if you’ve played around with PowerShell before, it should be all pretty straightforward. I’ve also credited where appropriate where I got some of the inspiration for the script and where I’ve blatantly copied code. Many thanks to some helpful hints from Brian @vTagion Graf, especially when dealing with variables embedded when using the “@” operator.

mike

Provisioning a LOT of RSA SecurID iPhone (and other) Tokens using Powershell

So, you can tell from my previous blog post that I kinda dig Powershell and that I enjoy the occasional challenge. It helps me feel like I haven’t lost my technical chops. :)

This challenge started off one afternoon at lunch when I was talking with an RSA Sales Engineer. One of his customers was moving over, en mass, to iPhones and they wanted to provision a bunch of RSA SecurID iPhone tokens. Unfortunately, the iPhone Token Converter tool wasn’t really designed for that. It’s a single use command line. Here’s an example from the documentation:

The following command uses the -mobile option to convert a password-protected token file. The -mobile option is currently used with the SecurID for iPhone application, 1.2 or later.

C:\path_name\TokenConverter user2-passwordtoken.sdtid -p t0kenpw1 -mobile –o tokenfile.txt

The converted token data looks similar to the following:

com.rsa.securid://ctf?ctfData=200002068164720663136011170432774461076477164632456201
026172115044046062716712650

When you install the RSA SecurID iPhone token from the App Store, this funky URL is registered to be opened exclusively by the token. That then provisions the token with the user record and off you go.

But what if you want to provision 100 tokens? Or 1000 tokens? What a PITA that would that be! So, I thought “there’s gotta be a way to do this in Powershell”. And do it even better. Not only did I want to generate the token URL’s for all the users, but I wanted to generate a text file based on the username and the content being the token URL. THEN, I wanted to send out a custom email to each user with the token URL in it so they’d only have to download the app and click on the link! After all, it’s only a few extra lines of simple code, right? As you’ll see below, it really is just a few lines of actual code!

Challenges

To generate the URL for the token, you need a .SDTID file. This is the file that’s generated by RSA Authentication Manager when you marry a token record to a user. Thankfully, the format of this file is XML. Bonus! Powershell loves XML! Unfortunately, provisioning a ton of tokens from the Auth Man GUI isn’t straightforward. I know, I know, “Mike, we need Powershell cmdlets for Authentication Manager!!”

<Official Statement> Please provide that feedback to your RSA representative. <\Official Statement>

Create the files needed

Ok, so you’ve used whatever (supported) tools you needed to get a .SDTID file for every user. I recommend that each user be matched on a per file basis. Example: jsmith.stdid, mfoley.stdid, hsimpson.stdid, etc… Because you can link your Active Directory to your Authentication Manager, the names should be the same as your AD login name.

Note: Make sure all these files are all in one folder!

Now that you have all the files, you’ll need to get the Token Converter Tool we mentioned previously and the Powershell script below. In addition, I highly recommend getting the Quest AD cmdlets. Some BRILLIANT work here by your friends at Quest. Not only do they provide an amazing tool for working with Powershell and Active Directory, the cmdlets are also FREE! It’s almost a crime to download them. :)

Checklist

  1. Downloaded *.stdid files to an accessible location
  2. Downloaded the Token Converter Tool and put it in the same location as the script
  3. Downloaded the script
  4. IP/FQDN of your email server
  5. Downloaded and installed the Quest AD cmdlets

You’ll see in the script that all the Quest/email stuff is commented out. I tested it, but you’ll want to ensure it works for you before you start provisioning a ton of tokens.

Let’s step thru some of the code

Configure the IP address or FQDN of your email server by uncommenting and editing this variable

[sourcecode language=”powershell”]
# $smtpserver = 192.168.1.1

[/sourcecode]

Enable the Quest cmdlets and Connect to AD

[sourcecode language=”powershell”]
# Uncomment for using AD
#add-PSSnapin quest.activeroles.admanagement
#Connect-QADService

[/sourcecode]

Edit the variable that states where the .SDTID files are. Default is the same directory as the script.

[sourcecode language=”powershell”]
# $token_location is the directory that the sdtid files are located in.
# Current value is the same folder this script it.
$token_location = .
[/sourcecode]

Now, the script will read each file and parse information out of it

[sourcecode language=”powershell”]
$list_of_files = Get-ChildItem . -filter "$token_location\*.sdtid"
foreach ($file in $list_of_files)
{
Write-Host "Processing $file"
[/sourcecode]

Remember when I said the .SDTID file is XML at heart and that Powershell loves XML? When, let’s get the username associated with the token out of the file

[sourcecode language=”powershell” padlinenumbers=”true”]
Write-Host "Processing $file"
#Get the username out of the token file.
[xml]$list = get-content $file
$username = $list.TKNBatch.TKN.UserLogin
[/sourcecode]

So, why are we getting the username? Well, because with the AD cmdlets, we can use that to retrieve the email address!

[sourcecode language=”powershell”]
Write-Host "Generating Token for $username"
# Uncomment for using AD
#$AD_user = Get-QADUser $username
#$user_email = $AD_user.email
[/sourcecode]

Great, we’ve gathered up a bunch of info and now it’s time to run the token converter. But it’s an old-school CLI tool, right? How do I get the output that contains that funky URL? Easy.

[sourcecode language=”powershell” wraplines=”true”]
#Generate the token URL and output to a variable
$token_link = .\TokenConverter.exe $file -iphone
#Write out a file on a per-user basis with the iPhone Token URL inside it.
$filename = $username + "_Token.txt"
New-Item $filename -type file -Force -Value "URL for $username is $token_link"
#
[/sourcecode]

The output of the converter tool is now in the variable “$token_link”. Just to be safe, we’ll write out a text file with the contents of the URL.

Now, let’s send an email to the user with their custom URL for their token record.

[sourcecode language=”powershell” padlinenumbers=”true” wraplines=”true”]
# Uncomment for using AD and sending email.
#Send-MailMessage -SMTPserver $smtpserver -To $user_email -Subject "Your iPhone Token" -Body "Please click on the link provided $token_link to add the token to your iPhone"
}
[/sourcecode]

The closing “}” signifies that this is the end of the foreach loop we started with.

The script will chug thru each .SDTID file and generate the token URL and email to the user.

Wrap-up

The final script is here. I hope this was helpful. It shouldn’t take much to do the same thing for Android and other SecurID soft tokens. They all use the same Token Converter tool. I’ll leave it as an exercise for the reader to figure out how to make it work for them. RTFM :)

As always, read the EULA in the script and tread carefully. Most of all, I hope you enjoyed this as much as I did.

{UPDATE}
Line 43 below has a type due to the Syntax Highlighter I use. Replace with this line only changing the word “bracket” to the appropriate open and close brackets with no spaces.

bracket xml bracket $list = get-content $file

mike

The Script

[sourcecode language=”powershell”]
#
# Bulk iPhone Token creator
# Mike Foley, mfoley@rsa.com, 781-515-6391
# RSA, the Security Division of EMC
#——————————————————————————
# All information, statements, and descriptions herein are offered AS IS
# only and are provided for informational purposes only. EMC Corporation
# does not guarantee the performance of, or offer a warranty of any kind,
# whether express, implied, or statutory, regarding the information herein
# or the compatibility of the information herein with EMC Corporation software
# or hardware products or other products.
#——————————————————————————-
# Requirements:
# Windows Powershell – Run Windows Update and you’ll get it. Ships with Win7 and
# Win2008 by default
# Quest Active Directory cmdlets – Free download from
# http://www.quest.com/powershell/activeroles-server.aspx
#——————————————————————————-
# SMTP Server you can send email thru. If you are using Exchange and your CORP
# account, uncomment and point $smtpserver at a CORP Exchange server and the
# script will use your current AD credentials to automatically log in.
#
# $smtpserver = 192.168.1.1
#
# To take advantage of the Active Directory stuff, uncomment the code below and
# have a valid account that can browse the AD store
#
# Connect to any available domain controller with the credentials of the locally
# logged on user.
# See Help Connect-QADService -examples for more info
# Uncomment for using AD
#add-PSSnapin quest.activeroles.admanagement
#Connect-QADService
#
# $token_location is the directory that the sdtid files are located in.
# Current value is the same folder this script it.
$token_location = .
$list_of_files = Get-ChildItem . -filter "$token_location\*.sdtid"
foreach ($file in $list_of_files)
{
Write-Host "Processing $file"
#Get the username out of the token file.
[xml]$list = get-content $file
$username = $list.TKNBatch.TKN.UserLogin
Write-Host "Generating Token for $username"
# Uncomment for using AD
#$AD_user = Get-QADUser $username
#$user_email = $AD_user.email
#
#Generate the token URL and output to a variable
$token_link = .\TokenConverter.exe $file -iphone
#Write out a file on a per-user basis with the iPhone Token URL inside it.
$filename = $username + "_Token.txt"
New-Item $filename -type file -Force -Value "URL for $username is $token_link"
#
# Uncomment for using AD and sending email.
#Send-MailMessage -SMTPserver $smtpserver -To $user_email -Subject "Your iPhone Token" -Body "Please click on the link provided $token_link to add the token to your iPhone"
}
[/sourcecode]