├── README.md ├── Offboarding.ps1 ├── CUCM - Offboarding.ps1 ├── CUCM - Onboarding.ps1 └── Onboarding.ps1 /README.md: -------------------------------------------------------------------------------- 1 | # Public-Scripts 2 | Hi I'm Brad and this is my Public Script repo. I wanted to a place to share the scripts I've made while I learn PowerShell and automate various things. 3 | 4 | All scripts come with no warranty or guarantee they will work for you. The ones I use every day are extremely customized for my employer. These have been cut down and should work for most environments. 5 | 6 | Feel free to use them but please give me the credit. 7 | -------------------------------------------------------------------------------- /Offboarding.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Written by Brad Egberts. 3 | Free to use but give me the credit. 4 | 5 | 6 | Offboarding script to be used with my onboarding script. 7 | We disable the user, move their personal fileshare to an archive, then export all AD properties to a CSV for future reference. 8 | Also give the option to share the mailbox with a specified person. 9 | 10 | After we disable the user is moved into the disabled users OU and then add the ticket number and date in the description for reference. 11 | Licenses are removed automatically because we use group based licensing in Azure AD and remove the keyword. 12 | #> 13 | 14 | ############################### 15 | ##### Variables to Change ##### 16 | ############################### 17 | 18 | $Password = "Default password you give to new user accounts." 19 | $FileshareArchive = "Path to personal fileshare archive" 20 | $Fileshare = "Path to personal fileshare" 21 | $CSVpath = "Path to where you want the CSV to be saved. We save ours in the archived personal fileshare." 22 | $SharedMailboxOU = "OU where you put shared mailboxes is you have one." 23 | $DisabledUsersOU = "OU for disabled users" 24 | $Domain = "@yourdomain.here" 25 | 26 | # $Groups array is so we can add multiple groups we want the user to be removed from but not recorded in the CSV. 27 | 28 | ######################### 29 | ##### Prerequisites ##### 30 | ######################### 31 | 32 | #Start log 33 | Start-Transcript -Path $TranscriptPath -Append 34 | 35 | #Import required modules 36 | Import-Module ActiveDirectory 37 | 38 | ############################## 39 | ##### Gather Information ##### 40 | ############################## 41 | 42 | #Get needed variables and check is username is valid 43 | Do 44 | { 45 | $Username = Read-Host "Enter username of the person to offboard" 46 | $Username = $Username.Trim() 47 | If ($(Get-ADUser -Filter { SamAccountName -eq $Username })) 48 | { 49 | $Valid = $True 50 | } 51 | Else 52 | { 53 | $Valid = $False 54 | Write-Host "Username is invalid. Try again." -ForegroundColor:Yellow 55 | } 56 | } Until ($Valid -eq $True) 57 | $Inc = Read-Host "Enter ticket number" 58 | $Inc = $Inc.Trim() 59 | 60 | #Convert to shared mailbox prompt 61 | $Convert = Read-Host "Does the mailbox need to be shared? [y/n]" 62 | If ($Convert -eq "y") 63 | { 64 | #Connect to Exchange online console to convert the mailbox later 65 | Write-Host "Please provide your login credentials. Use your full email." -ForegroundColor:Yellow 66 | $Credential = Get-Credential 67 | $ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Credential -Authentication Basic -AllowRedirection 68 | Import-PSSession $ExchangeSession -DisableNameChecking | Out-Null 69 | 70 | If (Get-Mailbox $Username) 71 | { 72 | $MailboxDeligation = Read-Host "Enter the username of who will see the shared mailbox." 73 | } 74 | Else 75 | { 76 | Write-Host "User doesn't have a mailbox." 77 | $Convert = "No mailbox found." 78 | } 79 | } 80 | 81 | #Review 82 | Write-Host 83 | Write-Host "=======================================" 84 | Write-Host 85 | (Get-ADUser $Username | Format-List Name, SamAccountName, UserPrincipalName | Out-String).Trim() 86 | Write-Host "Incident : $Inc" 87 | Write-Host "Convert to shared : $Convert" 88 | Write-Host "Mailbox Deligation: $MailboxDeligation" 89 | Write-Host 90 | Write-Host "=======================================" 91 | Read-Host "Continuing will make permanent changes to the above account. Press ENTER to continue." 92 | 93 | ######################## 94 | ##### Disable User ##### 95 | ######################## 96 | 97 | #Disable account 98 | Write-Host "Disabling Account" 99 | Disable-ADAccount $Username 100 | 101 | #Reset password 102 | Write-Host "Resetting password" 103 | $Password = ConvertTo-SecureString -AsPlainText "$Password" -Force 104 | Set-ADAccountPassword -Identity $Username -Reset -NewPassword $Password 105 | 106 | #Check for fileshare. If not present then create the directory in the archive folder for the CSV to be stored. We user robocoby so that details of the transfer is saved in the log. 107 | $FileshareCheck = Test-Path $Fileshare 108 | If ($FileshareCheck -eq $True) 109 | { 110 | Write-Host "Moving I drive." -ForegroundColor:Green 111 | New-Item -Path "$FileshareArchive" -Name "$Username" -ItemType "Directory" | Out-Null 112 | Robocopy.exe "$Fileshare" "$FileshareArchive\$Username" /move /s /r:1 /w:10 113 | } 114 | Else 115 | { 116 | Write-Host "Unable to find fileshare. You might want to check manually." -ForegroundColor:Yellow 117 | New-Item -Path "$FileshareArchive" -Name "$Username" -ItemType "Directory" | Out-Null 118 | } 119 | 120 | #Remove groups that we don't want being exported in the CSV and possibly copied to new users 121 | $Groups = @( 122 | #Enter the groups you want to include here. Remove if you don't need this. 123 | ) 124 | Foreach ($Group in $Groups) 125 | { 126 | Remove-AdGroupMember -Identity $Group -Members $Username -Confirm:$False 127 | } 128 | 129 | #Get $Username AD attributes and export to CSV 130 | Write-Host "Exporting $Username's AD attributes. File can be found in the users archived fileshare." 131 | $User = Get-ADUser $Username -Properties * 132 | $Data = [PSCustomObject]@{ 133 | Title = $User.Title 134 | Department = $User.Department 135 | Description = $User.Description 136 | Office = $User.Office 137 | OFficePhone = $User.OfficePhone 138 | IpPhone = $User.IpPhone 139 | Fax = $User.Fax 140 | EmployeeNumber = $User.EmployeeNumber 141 | StreetAddress = $User.StreetAddress 142 | City = $User.City 143 | State = $User.State 144 | PostalCode = $User.PostalCode 145 | Company = $User.Company 146 | extensionAttribute1 = $User.extensionAttribute1 147 | extensionAttribute2 = $User.extensionAttribute2 148 | extensionAttribute3 = $User.extensionAttribute3 149 | extensionAttribute4 = $User.extensionAttribute4 150 | extensionAttribute5 = $User.extensionAttribute5 151 | extensionAttribute6 = $User.extensionAttribute6 152 | extensionAttribute7 = $User.extensionAttribute7 153 | extensionAttribute8 = $User.extensionAttribute8 154 | extensionAttribute9 = $User.extensionAttribute9 155 | extensionAttribute10 = $User.extensionAttribute10 156 | extensionAttribute11 = $User.extensionAttribute11 157 | extensionAttribute12 = $User.extensionAttribute12 158 | extensionAttribute13 = $User.extensionAttribute13 159 | extensionAttribute14 = $User.extensionAttribute14 160 | extensionAttribute15 = $User.extensionAttribute15 161 | OU = ($User.DistinguishedName -Split ",", 3)[2] 162 | Memberof = ((Get-ADPrincipalGroupMembership -Identity $Username | Where-Object { $_.Name -ine "Domain Users" } | Select-Object -ExpandProperty Name) -Join ',') 163 | } 164 | $Data | Export-Csv -Path $CSVpath -NoTypeInformation 165 | 166 | #Clear out AD attributes 167 | Write-Host "Clearing $Username's AD attributes." 168 | $Attributes = @( 169 | "Title" 170 | "Department" 171 | "Description" 172 | "physicalDeliveryOfficeName" #Office 173 | "StreetAddress" 174 | "L" #City 175 | "St" #State 176 | "PostalCode" 177 | "Company" 178 | "ipPhone" 179 | "telephoneNumber" 180 | "extensionAttribute1" 181 | "extensionAttribute2" 182 | "extensionAttribute3" 183 | "extensionAttribute4" 184 | "extensionAttribute5" 185 | "extensionAttribute6" 186 | "extensionAttribute7" 187 | "extensionAttribute8" 188 | "extensionAttribute9" 189 | "extensionAttribute10" 190 | "extensionAttribute11" 191 | "extensionAttribute12" 192 | "extensionAttribute13" 193 | "extensionAttribute14" 194 | "extensionAttribute15" 195 | ) 196 | ForEach ($A in $Attributes) 197 | { 198 | Set-ADuser -Identity $Username -Clear $A 199 | } 200 | 201 | #Add date/incident into description field 202 | $Date = Get-Date -Format "MM/dd/yyyy" 203 | Set-ADUser -Identity $Username -Description "Disabled $Date per $Inc" 204 | 205 | #Remove from groups. 206 | Write-Host "Removing from AD Groups" 207 | Get-AdPrincipalGroupMembership -Identity $Username | Where-Object -Property Name -NE -Value 'Domain Users' | Remove-AdGroupMember -Members $Username -Confirm:$False 208 | 209 | #Move to correct OU 210 | If ($Convert -eq "y") 211 | { 212 | #Move user to Shared Mailbox OU 213 | Write-Host "Moving to Shared Mailbox OU" 214 | Get-ADUser "$Username" | Move-ADObject -TargetPath $SharedMailboxOU 215 | } 216 | Else 217 | { 218 | #Move user to Disabled Users OU 219 | Write-Host "Moving to Disabled OU" 220 | Get-ADUser "$Username" | Move-ADObject -TargetPath $DisabledUsersOU 221 | } 222 | 223 | #Convert mailbox to shared. 224 | If ($Convert -eq "y") 225 | { 226 | $Email = "$Username + $Domain" 227 | 228 | #Re-add to O365 AD Sync Group (My org used group based Azure AD syncing) 229 | Get-ADUser $Username | Add-ADPrincipalGroupMembership -MemberOf "O365 AD Sync" 230 | 231 | #Convert to shared 232 | Set-Mailbox -Identity "$Email" -Type:Shared 233 | Write-Host "Mailbox has been converted." 234 | 235 | #Set Deligation if provided. 236 | If (![string]::IsNullOrWhiteSpace($MailboxDeligation)) 237 | { 238 | Add-MailboxPermission -Identity "$Email" -User $MailboxDeligation -AccessRights FullAccess -InheritanceType All 239 | Write-Host "$MailboxDeligation now has rights to $Email." 240 | } 241 | } 242 | 243 | #End session and end script 244 | If ($ExchangeSession -eq $True) 245 | { 246 | Remove-PSSession $ExchangeSession 247 | } 248 | Write-Host "Script finished." 249 | Stop-Transcript 250 | Read-Host "Press ENTER to close." -------------------------------------------------------------------------------- /CUCM - Offboarding.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Written by Brad Egberts. 3 | Free to use but give me the credit. 4 | 5 | 6 | Cisco onboarding script for CUCM 12.5 7 | Script will setup an existing phone and DN for a specific user and create a Jabber device. 8 | Voicemails in CUC will need to be added manually. 9 | This works by sending XML requests to the AXL API that is part of the CUCM server. An AXL API user will need to be created. 10 | For each of the requests the XML is stored into a variable then added to the function using the -XML parameter. The switch parameter is used to bypass the error catch for specific situations. 11 | You may need to use SOUPUI and the Cisco AXL Toolkit from your server to get the full XML that can be used in each request. 12 | 13 | *** NOTE *** 14 | This script only works for existing phones and DN's in CUCM. You will need to manually add them if they are not already present. 15 | There is an option to enter "none" for the physical phone 16 | A lot of this is specific to an environment so if you are going to try utilizing this you will need to go through and change some of the XML. 17 | #> 18 | 19 | ############################### 20 | ##### Variables to Change ##### 21 | ############################### 22 | 23 | $CiscoUsername = "Username for the AXL API user in CUCM" 24 | $Password = "Password for the AXK API user in CUCM" 25 | $URI = "https://ServerFQDN:8443/axl/" 26 | $TranscriptPath = "Place you want the logs to be saved if you want to keep them." 27 | 28 | ##################### 29 | ##### Functions ##### 30 | ##################### 31 | 32 | Function Send-APIRequest 33 | { 34 | Param ( 35 | [String] $XML, 36 | [Switch] $CatchBypass 37 | ) 38 | 39 | #Credentials 40 | $CiscoPassword = ConvertTo-SecureString $Password -AsPlainText -Force 41 | $Credentials = New-Object System.Management.Automation.PSCredential $CiscoUsername, $CiscoPassword 42 | 43 | #Other info 44 | $Headers = @{ 45 | SoapAction = "CUCM:DB ver=12.5"; 46 | Accept = "Accept: text/*"; 47 | } 48 | 49 | #Send the request. If the $CatchBypass parameter is present then it removes the try/catch. 50 | If ($CatchBypass.IsPresent) 51 | { 52 | $Response = Invoke-WebRequest -ContentType "text/xml;charset=UTF-8" -Headers $Headers -Body $XML -Uri $URI -Method Post -Credential $Credentials 53 | } 54 | Else 55 | { 56 | Try 57 | { 58 | $Response = Invoke-WebRequest -ContentType "text/xml;charset=UTF-8" -Headers $Headers -Body $XML -Uri $URI -Method Post -Credential $Credentials 59 | If ($Response.StatusCode -eq "200") 60 | { 61 | #Do nothing. This is only here to remove any unneeded info from the console. 62 | } 63 | } 64 | Catch 65 | { 66 | Write-Host "---An error occurred---" -ForegroundColor:Red 67 | Write-Host $_.ErrorDetails.Message -ForegroundColor:Red 68 | Pause 69 | } 70 | } 71 | } 72 | 73 | ############################## 74 | ##### Gather Information ##### 75 | ############################## 76 | 77 | #Start log 78 | Start-Transcript -Path $TranscriptPath -Append 79 | 80 | $Exists = $Null 81 | $Phone = $Null 82 | 83 | #Get user and check if they are valid 84 | Do 85 | { 86 | $Username = Read-Host "Enter the username to offboard" 87 | 88 | #Verify user exists 89 | If (Get-ADUser $Username) 90 | { 91 | $Exists = $True 92 | } 93 | Else 94 | { 95 | Write-Host "User doesn't exist. Please try again." 96 | $Exists = $False 97 | } 98 | } Until ($Exists -eq $True) 99 | 100 | #Get $Extension and determine route partition 101 | Do 102 | { 103 | $Extension = Read-Host "Enter an extension. If user has a 10 digit DN enter the full number including the \+." 104 | $Extension = $Extension.Trim() 105 | 106 | If ($Extension.Length -gt 4) 107 | { 108 | $RoutePT = "Global-ALL_PT" 109 | } 110 | Else 111 | { 112 | $RoutePT = "4DIGIT_PT" 113 | } 114 | 115 | #Verify extension 116 | Try 117 | { 118 | $GetLine = @" 119 | 120 | 121 | 122 | 123 | $Extension 124 | $RoutePT 125 | 126 | 127 | 128 | "@ 129 | Send-APIRequest -XML $GetLine -CatchBypass 130 | $Number = $True 131 | } 132 | Catch 133 | { 134 | Write-Host "Unable to find DN. Number might need to be created in Superman." 135 | $Number = $False 136 | } 137 | } until ($Number -eq $True) 138 | 139 | #Get phone name 140 | Do 141 | { 142 | $PhoneName = Read-Host "Enter the name of the physical phone the user has. This appears as SEP### in CUCM. Enter 'none' if no phone exists" 143 | $PhoneName = $PhoneName.Trim() 144 | 145 | If ($PhoneName -eq "none") 146 | { 147 | $Phone = $True 148 | } 149 | Else 150 | { 151 | Try 152 | { 153 | #Check if phone is valid 154 | $GetPhone = @" 155 | 156 | 157 | 158 | 159 | $PhoneName 160 | 161 | 162 | 163 | "@ 164 | Send-APIRequest -XML $GetPhone -CatchBypass 165 | $Phone = $True 166 | } 167 | Catch 168 | { 169 | Write-Host "Phone is invalid. Try again." 170 | $Phone = $False 171 | } 172 | } 173 | } Until ($Phone -eq $True) 174 | 175 | #Review 176 | Write-Host 177 | Write-Host "=======================================" 178 | Write-Host 179 | (Get-ADUser $Username -Properties * | Format-List Name, SamAccountName, UserPrincipalName | Out-String).Trim() 180 | Write-Host "Extension : $Extension" 181 | Write-Host "Phone : $PhoneName" 182 | Write-Host 183 | Write-Host "=======================================" 184 | Read-Host "Continuing will make changes to the above phone and user. Press ENTER to continue." 185 | 186 | ######################## 187 | ##### XML Requests ##### 188 | ######################## 189 | 190 | #Convert user to Local User in CUCM 191 | Write-Host "Converting user to a local user." 192 | $ConvertToLocal = @" 193 | 194 | 195 | 196 | 197 | $Username 198 | 199 | 200 | 201 | 202 | "@ 203 | Send-APIRequest -XML $ConvertToLocal 204 | 205 | #Delete User 206 | Write-Host "Deleting local user." 207 | $DeleteUser = @" 208 | 209 | 210 | 211 | 212 | $Username 213 | 214 | 215 | 216 | "@ 217 | Send-APIRequest -XML $DeleteUser 218 | 219 | #This loop searches for the three additional types of phone and deletes them if they are found. If they are not found then it will say it doesn't exist. 220 | Write-Host "Deleting unneeded devices." 221 | $Phones = "CSF$Username", "BOT$Username", "TCT$Username" 222 | Foreach ($Phone in $Phones) 223 | { 224 | Try 225 | { 226 | $RemovePhone = @" 227 | 228 | 229 | 230 | 231 | $Phone 232 | 233 | 234 | 235 | "@ 236 | 237 | Send-APIRequest -XML $RemovePhone -CatchBypass 238 | } 239 | Catch 240 | { 241 | Write-Host "$Phone does not exist" 242 | } 243 | } 244 | 245 | #Update phone line settings 246 | Write-Host "Updating phone settings." 247 | $UpdateLine = @" 248 | 249 | 250 | 251 | 252 | $Extension 253 | Vacant 254 | Vacant 255 | Vacant 256 | 257 | 258 | 259 | "@ 260 | Send-APIRequest -XML $UpdateLine 261 | 262 | #Update phone if needed 263 | If ($PhoneName -ine "none") 264 | { 265 | Write-Host "Updating Phone." 266 | $UpdatePhone = @" 267 | 268 | 269 | 270 | 271 | $PhoneName 272 | Vacant 273 | 274 | 275 | 1 276 | 277 | Vacant 278 | 279 | $Extension 280 | $RoutePT 281 | 282 | Vacant 283 | 284 | 285 | 286 | 287 | 288 | 289 | "@ 290 | Send-APIRequest -XML $UpdatePhone 291 | 292 | #Apply phone settings 293 | Write-Host "Applying phone settings." 294 | $ApplyPhone = @" 295 | 296 | 297 | 298 | 299 | $PhoneName 300 | 301 | 302 | 303 | "@ 304 | Send-APIRequest -XML $ApplyPhone 305 | } 306 | 307 | #Ending stuff 308 | Stop-Transcript 309 | Read-Host "Press ENTER to close." -------------------------------------------------------------------------------- /CUCM - Onboarding.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Written by Brad Egberts. 3 | Free to use but give me the credit. 4 | 5 | 6 | Cisco onboarding script for CUCM 12.5 7 | Script will setup an existing phone and DN for a specific user and create a Jabber device. 8 | Voicemails in CUC will need to be added manually. 9 | This works by sending XML requests to the AXL API that is part of the CUCM server. An AXL API user will need to be created. 10 | For each of the requests the XML is stored into a variable then added to the function using the -XML parameter. The switch parameter is used to bypass the error catch for specific situations. 11 | You may need to use SOUPUI and the Cisco AXL Toolkit from your server to get the full XML that can be used in each request. 12 | 13 | *** NOTE *** 14 | This script only works for existing phones and DN's in CUCM. You will need to manually add them if they are not already present. 15 | There is an option to enter "none" for the physical phone for Jabber and VM only users. 16 | A lot of this is specific to an environment so if you are going to try utilizing this you will need to go through and change some of the XML. 17 | #> 18 | 19 | ############################### 20 | ##### Variables to Change ##### 21 | ############################### 22 | 23 | $CiscoUsername = "Username for the AXL API user in CUCM" 24 | $Password = "Password for the AXK API user in CUCM" 25 | $URI = "https://ServerFQDN:8443/axl/" 26 | $TranscriptPath = "Place you want the logs to be saved if you want to keep them." 27 | $LDAPName = "Name of LDAP in CUCM" 28 | 29 | ##################### 30 | ##### Functions ##### 31 | ##################### 32 | 33 | Function Send-APIRequest 34 | { 35 | Param ( 36 | [String] $XML, 37 | [Switch] $CatchBypass 38 | ) 39 | 40 | #Credentials 41 | $CiscoPassword = ConvertTo-SecureString $Password -AsPlainText -Force 42 | $Credentials = New-Object System.Management.Automation.PSCredential $CiscoUsername, $CiscoPassword 43 | 44 | #Other info 45 | $Headers = @{ 46 | SoapAction = "CUCM:DB ver=12.5"; 47 | Accept = "Accept: text/*"; 48 | } 49 | 50 | #Send the request. If the $CatchBypass parameter is present then it removes the try/catch. 51 | If ($CatchBypass.IsPresent) 52 | { 53 | $Response = Invoke-WebRequest -ContentType "text/xml;charset=UTF-8" -Headers $Headers -Body $XML -Uri $URI -Method Post -Credential $Credentials 54 | } 55 | Else 56 | { 57 | Try 58 | { 59 | $Response = Invoke-WebRequest -ContentType "text/xml;charset=UTF-8" -Headers $Headers -Body $XML -Uri $URI -Method Post -Credential $Credentials 60 | If ($Response.StatusCode -eq "200") 61 | { 62 | #Do nothing. This is only here to remove any unneeded info from the console. 63 | } 64 | } 65 | Catch 66 | { 67 | Write-Host "---An error occurred---" -ForegroundColor:Red 68 | Write-Host $_.ErrorDetails.Message -ForegroundColor:Red 69 | Pause 70 | } 71 | } 72 | } 73 | 74 | ############################## 75 | ##### Gather Information ##### 76 | ############################## 77 | 78 | #Start log 79 | Start-Transcript -Path $TranscriptPath -Append 80 | 81 | $RoutePT = $Null 82 | $ShortExtension = $Null 83 | $Exists = $Null 84 | $Number = $Null 85 | $Phone = $Null 86 | $DP = $Null 87 | 88 | 89 | #Get information about user. 90 | Do 91 | { 92 | $Username = Read-Host "Enter the username of the new phone user" 93 | 94 | #Verify user exists in AD and get make a full name 95 | If ($(Get-ADUser -Filter { SamAccountName -eq $Username })) 96 | { 97 | #Get users AD properties 98 | $User = Get-ADUser $Username 99 | $FirstName = $User.GivenName 100 | $LastName = $User.Surname 101 | $FullName = "$FirstName $LastName" 102 | 103 | $Exists = $True 104 | } 105 | Else 106 | { 107 | Write-Host "User doesn't exist. Please try again." 108 | $Exists = $False 109 | } 110 | 111 | } Until ($Exists -eq $True) 112 | 113 | #Get $Extension and determine route partition 114 | Do 115 | { 116 | $Extension = Read-Host "Enter an extension. If user has a 10 digit DN enter the full number including the \+." 117 | $Extension = $Extension.Trim() 118 | 119 | If ($Extension.Length -gt 4) 120 | { 121 | $RoutePT = "Global-ALL_PT" 122 | 123 | #Get the last 4 digits for the label 124 | $ShortExtension = $Extension.Substring($Extension.Length - 4) 125 | } 126 | Else 127 | { 128 | $RoutePT = "4DIGIT_PT" 129 | $ShortExtension = $Extension 130 | } 131 | 132 | #Verify extension 133 | Try 134 | { 135 | $GetLine = @" 136 | 137 | 138 | 139 | 140 | $Extension 141 | $RoutePT 142 | 143 | 144 | 145 | "@ 146 | Send-APIRequest -XML $GetLine -CatchBypass 147 | $Number = $True 148 | 149 | $Label = "$FullName - $ShortExtension" 150 | } 151 | Catch 152 | { 153 | Write-Host "Unable to find DN." 154 | $Number = $False 155 | } 156 | } until ($Number -eq $True) 157 | 158 | #Get phone name 159 | Do 160 | { 161 | $PhoneName = Read-Host "Enter the name of the physical phone the user will have. This appears as SEP### in CUCM. Enter 'none' if no phone is needed" 162 | $PhoneName = $PhoneName.Trim() 163 | 164 | If ($PhoneName -eq "none") 165 | { 166 | $Phone = $True 167 | } 168 | Else 169 | { 170 | Try 171 | { 172 | #Check if phone is valid 173 | $GetPhone = @" 174 | 175 | 176 | 177 | 178 | $PhoneName 179 | 180 | 181 | 182 | "@ 183 | Send-APIRequest -XML $GetPhone -CatchBypass 184 | $Phone = $True 185 | } 186 | Catch 187 | { 188 | Write-Host "Phone is invalid. Try again." 189 | $Phone = $False 190 | } 191 | } 192 | } Until ($Phone -eq $True) 193 | 194 | #Get Device Pool 195 | Do 196 | { 197 | $DevicePool = Read-Host "Enter the Device Pool of phone. If no physical phone is needed this is still used to make a jabber phone." 198 | $DevicePool = $DevicePool.Trim() 199 | 200 | Try 201 | { 202 | #Check if device pool is valid 203 | $Request = @" 204 | 205 | 206 | 207 | 208 | $DevicePool 209 | 210 | 211 | 212 | "@ 213 | Send-APIRequest -XML $Request -CatchBypass 214 | $DP = $True 215 | } 216 | Catch 217 | { 218 | Write-Host "Device Pool is invalid. Try again." 219 | $DP = $False 220 | } 221 | } Until ($DP -eq $True) 222 | 223 | #Review 224 | Write-Host 225 | Write-Host "=======================================" 226 | Write-Host 227 | (Get-ADUser $Username -Properties * | Format-List Name, SamAccountName, UserPrincipalName | Out-String).Trim() 228 | Write-Host "Extension : $Extension" 229 | Write-Host "Phone : $PhoneName" 230 | Write-Host "Device Pool : $DevicePool" 231 | Write-Host "Phone Label : $Label" 232 | Write-Host 233 | Write-Host "=======================================" 234 | Read-Host "Continuing will make changes to the above phone and user. Press ENTER to continue." 235 | 236 | ######################## 237 | ##### XML Requests ##### 238 | ######################## 239 | 240 | #Initiate LDAP Sync. 241 | Write-Host "Forcing LDAP sync on Superman. Please wait." 242 | $LDAPSync = @" 243 | 244 | 245 | 246 | 247 | $LDAPName 248 | true 249 | 250 | 251 | 252 | "@ 253 | Send-APIRequest -XML $LDAPSync 254 | Start-Sleep -Seconds 12 #In my envirnment the 12 seconds is sometimes not long enough. If you get errors saying that the user isn't found increase this. 255 | 256 | #Update directory number 257 | Write-Host "Updating directory number." 258 | $UpdateLine = @" 259 | 260 | 261 | 262 | 263 | $Extension 264 | $RoutePT 265 | $FullName 266 | 267 | true 268 | Voicemail_CSS 269 | 270 | 271 | true 272 | Voicemail_CSS 273 | 274 | 275 | true 276 | Voicemail_CSS 277 | 278 | 279 | true 280 | Voicemail_CSS 281 | 282 | 283 | true 284 | Voicemail_CSS 285 | 286 | 287 | true 288 | Voicemail_CSS 289 | 290 | 291 | true 292 | Voicemail_CSS 293 | 294 | 295 | true 296 | Voicemail_CSS 297 | 298 | 299 | true 300 | Voicemail_CSS 301 | 302 | $FullName 303 | $FullName 304 | Voicemail 305 | 306 | 307 | 308 | "@ 309 | Send-APIRequest -XML $UpdateLine 310 | 311 | #Create Jabber device 312 | Write-Host "Creating Jabber device" 313 | $CreateJabber = @" 314 | 315 | 316 | 317 | 318 | 319 | CSF$Username 320 | $Fullname 321 | Cisco Unified Client Services Framework 322 | Phone 323 | SIP 324 | User 325 | Device_CSS 326 | $DevicePool 327 | Default 328 | $Username 329 | 330 | 331 | 1 332 | 333 | $Label 334 | 335 | $Extension 336 | $RoutePT 337 | 338 | $Label 339 | 340 | true 341 | true 342 | true 343 | true 344 | 345 | 346 | 347 | $Username 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | "@ 357 | Send-APIRequest -XML $CreateJabber 358 | 359 | #Update physical phone if needed 360 | If ($PhoneName -ine "None") 361 | { 362 | Write-Host "Updating phone." 363 | $UpdatePhone = @" 364 | 365 | 366 | 367 | 368 | $PhoneName 369 | $FullName 370 | 371 | 372 | 1 373 | 374 | $Label 375 | 376 | $Extension 377 | $RoutePT 378 | 379 | $Label 380 | 381 | true 382 | true 383 | true 384 | true 385 | 386 | 387 | 388 | $Username 389 | 390 | 391 | 392 | 393 | $Username 394 | 395 | 396 | 397 | "@ 398 | Send-APIRequest -XML $UpdatePhone 399 | 400 | #Apply phone settings 401 | Write-Host "Applying phone settings." 402 | $ApplyPhone = @" 403 | 404 | 405 | 406 | 407 | $PhoneName 408 | 409 | 410 | 411 | "@ 412 | Send-APIRequest -XML $ApplyPhone 413 | } 414 | 415 | 416 | #Update User. The XML changes depending on $PhoneName 417 | Write-Host "Updating User." 418 | If ($PhoneName -eq "none") 419 | { 420 | $UpdateUser = @" 421 | 422 | 423 | 424 | 425 | $Username 426 | 427 | CSF$Username 428 | 429 | 430 | $extension 431 | $RoutePT 432 | 433 | true 434 | true 435 | true 436 | 437 | 438 | 439 | "@ 440 | } 441 | Else 442 | { 443 | $UpdateUser = @" 444 | 445 | 446 | 447 | 448 | $Username 449 | 450 | $PhoneName 451 | CSF$Username 452 | 453 | 454 | $extension 455 | $RoutePT 456 | 457 | true 458 | true 459 | true 460 | 461 | 462 | 463 | "@ 464 | } 465 | Send-APIRequest -XML $UpdateUser 466 | 467 | #Ending stuff 468 | Stop-Transcript 469 | Read-Host "Press ENTER to close." -------------------------------------------------------------------------------- /Onboarding.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Written by Brad Egberts. 3 | Free to use but give me the credit. 4 | 5 | 6 | Onboarding script for Exchange Hybrid environment. Script is based on the New-RemoteMailbox cmdlet which will create a user in on-prem Exchange which adds it to AD and enables the remote mailbox. 7 | Special thanks to u/jimb2 on Reddit for the function to cycle through all the $CopiedUsers AD properties. Without it, the original script would error each time it copied a blank field from $CopiedUser. 8 | Microsoft licenses are applied by adding a key word into extensionAttribute1 which is used in a dynamic license group in Azure AD. In order for the license to be removed or changed, extensionAttribute1 must be cleared in AD. 9 | 10 | *** IMPORTANT NOTES *** 11 | In my organization we remove all attributes, groups, ect from users when we disable them. We export that info to a CSV that we then save to an archive of their personal fileshare. 12 | Because of this if the $CopiedUser is disabled we need to find the attributes.csv. 13 | 14 | In the Attribute Updates section, the IF statements are written in a way to be all inclusive to what type of copied user is being used is why I have the functions and call them in each instead of just running the code outside the statements once. 15 | 16 | # $Groups array is so we can add multiple groups we want the user to be removed from but not recorded in the CSV. 17 | #> 18 | 19 | ############################### 20 | ##### Variables to Change ##### 21 | ############################### 22 | 23 | $TranscriptPath = "Place you want the logs to be saved if you want to keep them." 24 | $ExchangeServerURI = "The URI used to connect to Exchange." 25 | $Domain = "Your email domain." 26 | $CSVpath = "Path to the $CopiedUsers archived personal fileshare." 27 | $Password = "Default password you give to new user accounts." 28 | $LicenseKeyWord = "Key word used for the dynamic license group in Azure AD." 29 | $Fileshare = "Location of users personal fileshare is going to be." 30 | 31 | ##################### 32 | ##### Functions ##### 33 | ##################### 34 | 35 | #Function gets all properties from the CopiedUser and then loops through them basically checking for empty values. This prevents errors when adding them. 36 | Function Add-Attributes 37 | { 38 | Write-Host "Adding AD Attributes" 39 | $PropertyString = 'Title,Department,physicalDeliveryOfficeName,Description,StreetAddress,L,St,PostalCode,Company,extensionAttribute2,extensionAttribute3,extensionAttribute4,extensionAttribute5,extensionAttribute6,extensionAttribute7,extensionAttribute8,extensionAttribute9,extensionAttribute10,extensionAttribute11,extensionAttribute12,extensionAttribute13,extensionAttribute14,extensionAttribute15' 40 | $Props = $PropertyString.Split(',') 41 | $Source = Get-ADUser -Identity $CopiedUser -Property $Props 42 | $Add = @{} 43 | $Ignore = @() 44 | Foreach ($P in $Props) 45 | { 46 | If ($Source.$P) 47 | { 48 | #Property exists 49 | $Add.$P = $Source.$P 50 | } 51 | Else 52 | { 53 | #Property does not exist 54 | $Ignore += $P 55 | } 56 | } 57 | Set-AdUser -Identity $Username -Replace $Add 58 | Set-ADUser -Identity $Username -Country "US" 59 | Start-Sleep 2 60 | } 61 | 62 | #Compares title of copied user to one entered at the start. If it's different, the title entered at the start replaces the copied one. 63 | Function Compare-Title 64 | { 65 | If (![string]::IsNullOrWhiteSpace($Title)) 66 | { 67 | $CopiedTitle = Get-ADUser -Identity $Username -Property Title 68 | If ($Title -ine $CopiedTitle) 69 | { 70 | Set-ADUser -Identity $Username -Replace @{title = "$Title" } 71 | } 72 | } 73 | } 74 | 75 | #Set Phone number 76 | Function Set-PhoneNumber 77 | { 78 | If (![string]::IsNullOrWhiteSpace($Extension)) 79 | { 80 | Set-ADuser -Identity $Username -Replace @{ipPhone = $Extension; telephoneNumber = $Extension } 81 | } 82 | } 83 | 84 | #Add to groups 85 | Function Add-Groups 86 | { 87 | Write-Host "Adding to groups" 88 | Foreach ($Group in $MemberOf) 89 | { 90 | Try 91 | { 92 | $GroupName = Get-ADGroup $Group | Select-Object -ExpandProperty DistinguishedName 93 | Get-ADUser $Username | Add-ADPrincipalGroupMembership -MemberOf $GroupName 94 | } 95 | Catch 96 | { 97 | Write-Host "Unable to find $Group. You may need to search AD and add them manually." -ForegroundColor:Yellow 98 | } 99 | } 100 | } 101 | 102 | ######################### 103 | ##### Prerequisites ##### 104 | ######################### 105 | 106 | #Start log 107 | Start-Transcript -Path $TranscriptPath -Append 108 | 109 | #Connect to Exchange Server. 110 | $UserCredential = Get-Credential 111 | $ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ExchangeServerURI -Authentication Kerberos -Credential $UserCredential 112 | 113 | #Import required modules. DisableNameChecking and Out-Null remove the warning and output for the module. 114 | Write-Output "Importing Required Modules..." 115 | Import-PSSession $ExchangeSession -AllowClobber -DisableNameChecking | Out-Null 116 | Import-Module ActiveDirectory 117 | Write-Host 118 | 119 | ####################################### 120 | ##### Gather New User Information ##### 121 | ####################################### 122 | 123 | #Gather new user information including if a license is needed. 124 | $FirstName = Read-Host "Enter the First Name" 125 | $FirstName = $FirstName.Trim() 126 | $PreferredName = Read-Host "Enter a Preferred name if provided" 127 | $PreferredName = $PreferredName.Trim() 128 | $MiddleInitial = Read-Host "Enter the Middle Initial" 129 | $MiddleInitial = $MiddleInitial.Trim() 130 | $LastName = Read-Host "Enter the Last Name" 131 | $LastName = $LastName.Trim() 132 | $Title = Read-Host "Enter the users Title" 133 | $Title = $Title.Trim() 134 | $Extension = Read-Host "Enter the users Extension" 135 | $Extension = $Extension.Trim() 136 | $License = Read-Host "Does the user need a 365 license? [y/n]" 137 | $License = $License.Trim() 138 | $CopiedUser = Read-Host "Enter a username to copy" 139 | $CopiedUser = $CopiedUser.Trim() 140 | $Welcome = Read-Host "Do you want to send a welcome email? [y/n]" 141 | 142 | #Sets full name depending on if a preferred name is given 143 | If (![string]::IsNullOrWhiteSpace($PreferredName)) 144 | { 145 | $FullName = "$LastName, $PreferredName" 146 | } 147 | Else 148 | { 149 | $FullName = "$LastName, $FirstName" 150 | } 151 | 152 | #Create Username using first initial of first name and last name 153 | $FirstInitial = $FirstName.Substring(0, 1) 154 | $Username = $FirstInitial + $LastName -Replace '[\W]', '' #The -Replace removes all special character. 155 | $I = 1 156 | Do 157 | { 158 | #Check if username exists 159 | Write-Host "Checking if username already exists..." -ForegroundColor:Green 160 | 161 | If ($(Get-ADUser -Filter { SamAccountName -eq $Username })) 162 | { 163 | Write-Host "WARNING: Logon name $Username already exists!!" -ForegroundColor:Yellow 164 | 165 | #If middle name is not provided, use additional letters of the first name until a valid username is found. 166 | If ([string]::IsNullOrWhiteSpace($MiddleInitial)) 167 | { 168 | $Taken = $True 169 | $I++ 170 | $Username = $FirstName.substring(0, $I) + $LastName 171 | } 172 | Else 173 | { 174 | $Taken = $True 175 | $Username = $FirstName.substring(0, 1) + $MiddleInitial + $LastName 176 | } 177 | $Email = $Username + $Domain 178 | Write-Host "Changing Logon name to" $Username -ForegroundColor:Yellow 179 | } 180 | Else 181 | { 182 | $Taken = $False 183 | Write-Host "No duplicates found." -ForegroundColor:Green 184 | } 185 | $Username = $Username.ToLower() 186 | } Until ($Taken -eq $False) 187 | 188 | #Trim for max length 189 | If ($Username.Length -gt 12) 190 | { 191 | $Username = $Username.Substring(0, 12) 192 | } 193 | 194 | #Create email 195 | $Email = $Username + $Domain 196 | 197 | #Check for $CopiedUser 198 | Do 199 | { 200 | Write-Host "Checking if $CopiedUser is a valid user..." -ForegroundColor:Green 201 | 202 | If ($(Get-ADUser -Filter { SamAccountName -eq $CopiedUser })) 203 | { 204 | Write-Host "$CopiedUser is valid" -ForegroundColor:Green 205 | } 206 | Else 207 | { 208 | Write-Host "Username doesn't exist." -ForegroundColor:Red 209 | $CopiedUser = Read-Host "Enter a username to copy" 210 | } 211 | } Until ($(Get-ADUser -Filter { SamAccountName -eq $CopiedUser })) 212 | 213 | #Variable review 214 | Write-Host 215 | Write-Host "=======================================" 216 | Write-Host 217 | Write-Host "First name: $FirstName" 218 | Write-Host "Preferred Name: $PreferredName" 219 | Write-Host "Middle Initial: $MiddleInitial" 220 | Write-Host "Last name: $LastName" 221 | Write-Host "Display name: $FullName" 222 | Write-Host "Username: $Username" 223 | Write-Host "Title: $Title" 224 | Write-Host "Phone Number: $Extension" 225 | Write-Host "Email: $Email" 226 | Write-Host "License: $License" 227 | Write-Host "Copied User: $CopiedUser" 228 | Write-Host "Welcome Email: $Welcome" 229 | Write-Host 230 | Write-Host "=======================================" 231 | Read-Host "If this is correct, press ENTER. Continuing will start creating the user. Press CTRL + C to cancel." 232 | 233 | ################################ 234 | ##### Classify $CopiedUser ##### 235 | ################################ 236 | 237 | #Checks to see if User is disabled or not. 238 | If ($(Get-ADUser $CopiedUser).enabled -eq $False) 239 | { 240 | $CopiedUserArchived = $True 241 | } 242 | Else 243 | { 244 | $CopiedUserArchived = $False 245 | } 246 | 247 | ############################ 248 | ##### Account Creation ##### 249 | ############################ 250 | 251 | #Create account using basic attributes 252 | Write-Host "Creating mailboxes, user and setting OU." 253 | $Password = ConvertTo-SecureString $Password -AsPlainText -Force 254 | $UserAttributes = @{ 255 | Name = "$FullName" 256 | FirstName = $FirstName 257 | LastName = $LastName 258 | DisplayName = $FullName 259 | Initials = $MiddleInitial 260 | UserPrincipalName = $Email 261 | Password = $Password 262 | resetpasswordonnextlogon = $true 263 | } 264 | New-RemoteMailbox @UserAttributes | Format-Table -Property DisplayName, PrimarySmtpAddress, SamAccountName 265 | 266 | #Check for user in AD before trying to make changes. Wait if not found. 267 | Do 268 | { 269 | If ($(Get-ADUser -Filter { SamAccountName -eq $Username })) 270 | { 271 | $Sync = $True 272 | } 273 | Else 274 | { 275 | $Sync = $False 276 | Start-Sleep 2 277 | } 278 | } Until ($Sync -eq $True) 279 | 280 | ############################# 281 | ##### Attribute Updates ##### 282 | ############################# 283 | 284 | Write-Host "Making changes in AD." 285 | 286 | #CopiedUser is disabled. All AD attributes are then pulled from a CSV created when the user is disabled 287 | If ($CopiedUserArchived -eq $True) 288 | { 289 | #Sanity check for easy troubleshooting. 290 | Write-Host "Copying from CSV" -ForegroundColor:Green 291 | 292 | #Import CSV and get all the values. 293 | $Datasheet = Import-Csv $CSVpath | Where-Object { $_.PSObject.Properties.Value -ne $null } 294 | ForEach ($User in $Datasheet) 295 | { 296 | $CopiedTitle = $User.Title 297 | $Department = $User.Department 298 | $Description = $User.Description 299 | $Office = $User.Office 300 | $StreetAddress = $User.StreetAddress 301 | $City = $User.City 302 | $State = $User.State 303 | $PostalCode = $User.PostalCode 304 | $Company = $User.Company 305 | $EA2 = $User.extensionAttribute2 306 | $EA3 = $User.extensionAttribute3 307 | $EA4 = $User.extensionAttribute4 308 | $EA5 = $User.extensionAttribute5 309 | $EA6 = $User.extensionAttribute6 310 | $EA7 = $User.extensionAttribute7 311 | $EA8 = $User.extensionAttribute8 312 | $EA9 = $User.extensionAttribute9 313 | $EA10 = $User.extensionAttribute10 314 | $EA11 = $User.extensionAttribute11 315 | $EA12 = $User.extensionAttribute12 316 | $EA13 = $User.extensionAttribute13 317 | $EA14 = $User.extensionAttribute14 318 | $EA15 = $User.extensionAttribute15 319 | $OU = $User.OU 320 | $MemberOf = ($User.Memberof -Split ",") 321 | } 322 | 323 | #IF statements only make changes is the CSV fields are not empty. This eliminates the errors that happen whenever you try adding $Null to AD. I don't honestly know how else to do this. 324 | If (![string]::IsNullOrWhiteSpace($CopiedTitle)) { Set-ADUser $Username -Title $CopiedTitle } 325 | If (![string]::IsNullOrWhiteSpace($Department)) { Set-ADUser $Username -Department $Department } 326 | If (![string]::IsNullOrWhiteSpace($Description)) { Set-ADUser $Username -Description $Description } 327 | If (![string]::IsNullOrWhiteSpace($Office)) { Set-ADUser $Username -Office $Office } 328 | If (![string]::IsNullOrWhiteSpace($StreetAddress)) { Set-ADUser $Username -StreetAddress $StreetAddress } 329 | If (![string]::IsNullOrWhiteSpace($City)) { Set-ADUser $Username -City $City } 330 | If (![string]::IsNullOrWhiteSpace($State)) { Set-ADUser $Username -State $State } 331 | If (![string]::IsNullOrWhiteSpace($PostalCode)) { Set-ADUser $Username -PostalCode $PostalCode } 332 | If (![string]::IsNullOrWhiteSpace($Company)) { Set-ADUser $Username -Company $Company } 333 | If (![string]::IsNullOrWhiteSpace($EA2)) { Set-ADUser $Username -Replace @{extensionAttribute2 = $EA2 } } 334 | If (![string]::IsNullOrWhiteSpace($EA3)) { Set-ADUser $Username -Replace @{extensionAttribute3 = $EA3 } } 335 | If (![string]::IsNullOrWhiteSpace($EA4)) { Set-ADUser $Username -Replace @{extensionAttribute4 = $EA4 } } 336 | If (![string]::IsNullOrWhiteSpace($EA5)) { Set-ADUser $Username -Replace @{extensionAttribute5 = $EA5 } } 337 | If (![string]::IsNullOrWhiteSpace($EA6)) { Set-ADUser $Username -Replace @{extensionAttribute6 = $EA6 } } 338 | If (![string]::IsNullOrWhiteSpace($EA7)) { Set-ADUser $Username -Replace @{extensionAttribute7 = $EA7 } } 339 | If (![string]::IsNullOrWhiteSpace($EA8)) { Set-ADUser $Username -Replace @{extensionAttribute8 = $EA8 } } 340 | If (![string]::IsNullOrWhiteSpace($EA9)) { Set-ADUser $Username -Replace @{extensionAttribute9 = $EA9 } } 341 | If (![string]::IsNullOrWhiteSpace($EA10)) { Set-ADUser $Username -Replace @{extensionAttribute10 = $EA10 } } 342 | If (![string]::IsNullOrWhiteSpace($EA11)) { Set-ADUser $Username -Replace @{extensionAttribute11 = $EA11 } } 343 | If (![string]::IsNullOrWhiteSpace($EA12)) { Set-ADUser $Username -Replace @{extensionAttribute12 = $EA12 } } 344 | If (![string]::IsNullOrWhiteSpace($EA13)) { Set-ADUser $Username -Replace @{extensionAttribute13 = $EA13 } } 345 | If (![string]::IsNullOrWhiteSpace($EA14)) { Set-ADUser $Username -Replace @{extensionAttribute14 = $EA14 } } 346 | If (![string]::IsNullOrWhiteSpace($EA15)) { Set-ADUser $Username -Replace @{extensionAttribute15 = $EA15 } } 347 | 348 | #Set Country 349 | Set-ADUser -Identity $Username -Country "US" 350 | 351 | #Set phone number 352 | Set-PhoneNumber 353 | 354 | #Confirm title is correct 355 | Compare-Title 356 | 357 | #Add to groups 358 | Add-Groups 359 | 360 | #Move to OU 361 | Write-Host "Moving to OU" 362 | Get-ADUser $Username | Move-ADObject -TargetPath $OU 363 | } 364 | 365 | #CopiedUser is currently enabled. Straight copy from one user to another. 366 | If ($CopiedUserArchived -eq $False) 367 | { 368 | #Sanity check for easy troubleshooting. 369 | Write-Host "Copy from enabled user" -ForegroundColor:Green 370 | 371 | #Add attributes with function 372 | Add-Attributes 373 | 374 | #Set phone number 375 | Set-PhoneNumber 376 | 377 | #Confirm title is correct 378 | Compare-Title 379 | 380 | #Add to groups 381 | $MemberOf = Get-ADPrincipalGroupMembership $CopiedUser | Where-Object { $_.Name -ine "Domain Users" } 382 | Add-Groups 383 | 384 | #Remove groups that shouldn't be copied over 385 | $Groups = @( 386 | #Add a list of groups that shouldn't be copied over to the new users. My org keeps a list of groups that can only be added by a directors explicit orders. 387 | ) 388 | Foreach ($Group in $Groups) 389 | { 390 | Remove-AdGroupMember -Identity $Group -Members $Username -Confirm:$False 391 | } 392 | 393 | #Move to OU 394 | Write-Host "Moving to OU" 395 | $CopiedUserOU = Get-ADUser $CopiedUser -Properties CanonicalName 396 | $OU = ($CopiedUserOU.DistinguishedName -Split ",", 3)[2] 397 | Get-ADUser $Username | Move-ADObject -TargetPath $OU 398 | } 399 | 400 | ############################# 401 | ##### Finishing Touches ##### 402 | ############################# 403 | 404 | #Add keyword for license if needed 405 | If ($License -eq 'y') 406 | { 407 | Set-ADUser $Username -Add @{extensionAttribute1 = "$LicenseKeyWord" } 408 | Write-Host "Microsoft 365 licenses will be applied after the next AD sync." 409 | } 410 | 411 | #Create personal fileshare. Out-Null hides the output of new-item. 412 | Write-Host "Creating personal fileshare." 413 | New-Item -Path $Fileshare -Name "$Username" -ItemType "Directory" | Out-Null 414 | Start-Sleep -Seconds 2 415 | $ACL = Get-Acl -Path "$Fileshare\$Username" 416 | $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("$Username", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow") 417 | $ACL.SetAccessRule($AccessRule) 418 | $ACL | Set-Acl -Path "$Fileshare\$Username" 419 | 420 | #Email info to requester 421 | If ($Welcome -eq "y") 422 | { 423 | #Generate $Phone info if provided 424 | If (![string]::IsNullOrWhiteSpace($Extension)) 425 | { 426 | $Phone = "Extension: $Extension
Voicemail PIN: 1234" 427 | } 428 | 429 | #Get requester username 430 | $Requester = Read-Host "Enter the username of the requester" 431 | $Requester = $Requester.Trim() 432 | $From = "Helpdesk@yourdomain.here " 433 | $To = "$Requester + $Domain" 434 | $Subject = "New User account - $FullName" 435 | $Body = " 436 | 437 | 438 |

A user account has been created as requested for:

439 |

Name: $FullName
440 | User ID: $Username
441 | Password: $Password
442 | Email Address: $Email
443 | $Phone

444 |

Body text that can be changed to fit what you need

445 | 446 | " 447 | 448 | #Send email 449 | Write-Host "Sending email." 450 | Send-MailMessage -To $To -From $From -Subject $Subject -Body $Body -BodyAsHtml -SmtpServer $ExchangeServer 451 | } 452 | 453 | #End session 454 | Remove-PSSession $ExchangeSession 455 | Write-Host "Exchange session ended." 456 | Write-Host "Script finished." 457 | Stop-Transcript 458 | Read-Host "Press ENTER to close." --------------------------------------------------------------------------------