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:
- Load the necessary .NET GUI assemblies into memory so you can use Windows and Visualbasic forms
- Create a function for Date selection
- Prompts you for a First name, Last name, Password and an Expiration date, and save them in their relative variables
- 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
- It will use Implicit Remoting for the ActiveDirectory modules with the prefix of “rem” so you don’t have to install it locally
- It will try to create the user using the Add-ADuser cmdlet, but with the implicit remoting prefix so it will be Add-remADuser
- 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
- It sets the user’s password
- It enabled the user
- It add the user to the “wireless guests” group
- 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
- It will remove the user’s membership from “domain users”
- It will confirm the creation of the user and ask you if you want to create another one
- 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 !
Dude i love your blog!!! keep it up.