Creating new Wireless Guest with PowerShell

Standard

Wireless access in the enterprise can be a huge PITA ! Because you have to find the correct balance between usability and security, you don’t want everyone contacting the help desk asking on how to connect, and based on your hardware, it can be tricky.

In my case, we are using Trapeze wireless controllers (Trapeze recently acquired by Juniper), it has all the functions we need to create a robust wireless access scheme.

I decided to go with 3 SSID’s:

  • A VIP SSID with 802.1x authentication, any user who is a member of the VIP Active Directory group can access this network, the associated VLAN has unrestricted access permissions
  • A Users SSID with 802.1x authentication, any user who is a domain member (a member of the “Domain Users” AD group) can access this network, the associated VLAN has normal employee access permissions
  • A Guest SSID with Web authentication and no encryption, any user who is member of “Wireless Guests” AD group can access this network, the associated VLAN has guest access permissions

Well the first two are static and easily managed by the IT department, but suppose that your company receives a lot of guests, it’s not practical to go to the IT  everytime and get a set of credentials.

Some uses Cisco’s ACS, some uses any type of NAC, even integrate them with AD via LDS and LDAP, but in our case we are using our Active Directory infrastructure as the main point of authentication.

So we need a way to let managers create guest accounts for their users, it seems that we need to call our savior: PowerShell !

Below is the full GUI script i made, it’s very dirty and unprofessional, but hey, that’s what scripting is all about 😀

#Load needed .NET GUI Assemblies into memory
[void] [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
[void] [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
[void] [System.Reflection.Assembly]::LoadWithPartialName('System.Drawing')

#This var will be used to create a pssession just once if you want to create several users
$firsttime="true"

#The Date/time selector function
function selectdate{
 $objForm = New-Object Windows.Forms.Form
 $objForm.Text = "Expiration Date"
 $objForm.Size = New-Object Drawing.Size @(240,200)
 $objForm.StartPosition = "CenterScreen"
 $objForm.KeyPreview = $True
 $objForm.Add_KeyDown({
 if ($_.KeyCode -eq "Enter")
 {
 $dtmDate=$objCalendar.SelectionStart
 $objForm.Close()
 }
 })
 $objCalendar = New-Object System.Windows.Forms.MonthCalendar
 $objCalendar.ShowTodayCircle = $False
 $objCalendar.MaxSelectionCount = 1
 $objForm.Controls.Add($objCalendar)
 $objForm.Topmost = $True
 $objForm.Add_Shown({$objForm.Activate()})
 [void] $objForm.ShowDialog()
 $dtmdate=$dtmdate.addDays("1")

 return ($dtmDate)
}

#create User Main loop
do{

#Global vars
 $first=[Microsoft.VisualBasic.Interaction]::InputBox("Enter First Name", "First Name", "")
 $last=[Microsoft.VisualBasic.Interaction]::InputBox("Enter Last name", "Last Name", "")
 $password=[Microsoft.VisualBasic.Interaction]::InputBox("Enter a Password", "Password", "")
 $aname=$first.SubString(0,1)+$last+".guest"
 $expdate=selectdate
 $desc="Account created on " + (get-date).tostring() + "`, expires by the end of " + $expdate.addDays("-1") + "`, created by "+ ((get-item env:username).value)
 $anotheruser="No"

#If this is the first time you enter in this loop, open a new PSsession with the domain controller
 if($firsttime -eq "true"){
 $session = new-pssession -comp dc -EA Stop
 invoke-command -command { import-module activedirectory } -session $session
 import-pssession -session $session -module activedirectory -prefix rem
 $firsttime="false"
 }

#Try to create a user, using implicit remoting for AD module commands
 try{
 new-remADuser -SamAccountName $aname -path "OU=Guests,OU=wireless,OU=Company,DC=domainname,DC=com" -Name ($first+" "+$last) -GivenName $first -surname $last -DisplayName ($first+" "+$last) -Description $desc -UserPrincipalName $aname -AccountExpirationDate $expdate -EA Stop
#-EA stop here is crucial, you can't catch errors when using implicit remoting without it

 Add-remADGroupMember -identity "Password Complexity Exceptions" -members $aname
 Set-remADAccountPassword -identity $aname -Reset -NewPassword (ConvertTo-SecureString -AsPlainText $password -Force)
 set-remadaccountcontrol -identity $aname -enabled 1
 Add-remADGroupMember -identity "Wireless Guests" -members $aname

 #Set the primary Group to be "wireless guests"
 invoke-command -session $session -scriptblock {
 param($username)
 $group = get-adgroup "Wireless Guests"
 $groupSid = $group.sid
 [int]$GroupID = $groupSid.Value.Substring($groupSid.Value.LastIndexOf("-")+1)
 Get-ADUser $username | Set-ADObject -Replace @{primaryGroupID=$GroupID } -server dc
 } -Args $aname

 #Remove the newly created user from "Domain Users"
 Remove-remADGroupMember -identity "domain users" -members $aname -confirm:$false

 #confirm the creation and ask for another one
 $anotheruser=[System.Windows.Forms.MessageBox]::Show("Account successfully created,`nUsername: " + $aname + "`nPassword: " + $password + "`nWould you like to create another user? " , "Account Creation Status" , 4)

 }catch {
 $anotheruser=[System.Windows.Forms.MessageBox]::Show("An error has occured,`nWould you like to try again ?" , "Error while creating the account" , 4)
 }

}while($anotheruser -eq "Yes")

$session | remove-pssession

The script will do the following in order:

  1. Load the necessary .NET GUI assemblies into memory so you can use Windows and Visualbasic forms
  2. Create a function for Date selection
  3. Prompts you for a First name, Last name, Password and an Expiration date, and save them in their relative variables
  4. Will check if this is the first user creation attempt, if it’s the first time, it will open a new PSsession with the domain controller
  5. It will use Implicit Remoting for the ActiveDirectory modules with the prefix of “rem” so you don’t have to install it locally
  6. It will try to create the user using the Add-ADuser cmdlet, but with the implicit remoting prefix so it will be Add-remADuser
  7. It will add the newly created user to a group i created called “Password complexity exceptions”, this group has fine grained password policy, because we don’t want to force guests to use complex passwords
  8. It sets the user’s password
  9. It enabled the user
  10. It add the user to the “wireless guests” group
  11. It will set the primary user’s group to be “wireless guests”, this step is important because we want to remove the “domain users” membership, and by default the “domain user” group is the primary group, you can’t remove the user’s membership from a primary group
  12. It will remove the user’s membership from “domain users”
  13. It will confirm the creation of the user and ask you if you want to create another one
  14. It will close the PSsession

As you can see it’s very dirty, no input validation, and it has a very obscure error handling, one way to improve errors and exception handling is to use the built-int $error array along with some “if” statements , but i’m too lazy to do it.

And of course there is the security side of the story, but it’s not our main point for today.

Now you (or your manager,in case you got hit by lightning the day before) can create new wireless guests in under 10 seconds !

One thought on “Creating new Wireless Guest with PowerShell

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s