From b9ba13ab390c35bb1c82406c21e01b05c08036c9 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 12 Apr 2025 21:25:38 +0800 Subject: [PATCH] Added main contents of script --- New-ADUser.ps1 | 542 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 542 insertions(+) diff --git a/New-ADUser.ps1 b/New-ADUser.ps1 index e69de29..d146082 100644 --- a/New-ADUser.ps1 +++ b/New-ADUser.ps1 @@ -0,0 +1,542 @@ +<# +.SYNOPSIS + Creates new AD users with email attributes and copy functionality. +.DESCRIPTION + Enhanced version with mailNickname and proxyAddresses support. +.NOTES + Version : 2.1 + Requires : PowerShell with Active Directory module +#> + +# Import Active Directory module +try { + Import-Module ActiveDirectory -ErrorAction Stop +} +catch { + Write-Host "Active Directory module not found. Please install RSAT tools." -ForegroundColor Red + exit +} + +function Show-Menu { + param ( + [string]$Title = 'AD User Creation Options' + ) + Clear-Host + Write-Host "================ $Title ================" + Write-Host "" + Write-Host "1: Create a new user from scratch" + Write-Host "2: Copy settings from existing user" + Write-Host "" + Write-Host "Q: Quit" + Write-Host "" + Write-Host "========================================" +} + +function Get-DomainSelection { + $domains = (Get-ADForest).Domains + + if ($domains.Count -gt 1) { + Write-Host "Multiple domains available:" + for ($i = 0; $i -lt $domains.Count; $i++) { + Write-Host "$($i+1): $($domains[$i])" + } + + $selection = Read-Host "Select domain (1-$($domains.Count))" + while ($selection -notmatch "^\d+$" -or [int]$selection -lt 1 -or [int]$selection -gt $domains.Count) { + $selection = Read-Host "Invalid selection. Please enter a number between 1 and $($domains.Count)" + } + + return $domains[[int]$selection-1] + } + else { + return $domains[0] + } +} + +function Get-ValidPassword { + do { + $password = Read-Host "Enter password (min 8 chars, complex)" -AsSecureString + $passwordText = [Runtime.InteropServices.Marshal]::PtrToStringAuto( + [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password) + ) + + if ($passwordText.Length -lt 8) { + Write-Host "Password must be at least 8 characters" -ForegroundColor Red + $validPwd = $false + } + elseif (-not ($passwordText -match "[A-Z]") -or + -not ($passwordText -match "[a-z]") -or + -not ($passwordText -match "[0-9]") -or + -not ($passwordText -match "[^a-zA-Z0-9]")) { + Write-Host "Password must contain uppercase, lowercase, number and special character" -ForegroundColor Red + $validPwd = $false + } + else { + $validPwd = $true + } + + if (-not $validPwd) { + [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( + [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) + } + } while (-not $validPwd) + + return $password +} + +function CreateNewUser { + param ( + [string]$Domain + ) + + # Collect user information + $firstName = Read-Host "Enter first name" + $lastName = Read-Host "Enter last name" + $username = Read-Host "Enter username (leave blank to auto-generate)" + + if ([string]::IsNullOrWhiteSpace($username)) { + $username = ($firstName.Substring(0,1) + $lastName).ToLower() + Write-Host "Auto-generated username: $username" -ForegroundColor Yellow + } + + $displayName = "$firstName $lastName" + $ou = Read-Host "Enter OU distinguished name (e.g., OU=Users,DC=domain,DC=com) or leave blank for default" + + $password = Get-ValidPassword + + try { + # Build email attributes + $emailAddress = "$username@$Domain" + + # Base parameters that will always work + $newUserParams = @{ + GivenName = $firstName + Surname = $lastName + Name = $displayName + DisplayName = $displayName + SamAccountName = $username + UserPrincipalName = $emailAddress + AccountPassword = $password + Enabled = $true + ChangePasswordAtLogon = $true + EmailAddress = $emailAddress + ErrorAction = 'Stop' + } + + if (-not [string]::IsNullOrWhiteSpace($ou)) { + $newUserParams['Path'] = $ou + } + else { + $newUserParams['Path'] = "CN=Users," + (Get-ADDomain).DistinguishedName + } + + # Try to add mailNickname if available (with error handling) + try { + $newUserParams['mailNickname'] = $username + Write-Host "Attempting to set mailNickname: $username" -ForegroundColor Cyan + } + catch { + Write-Host "Warning: Could not set mailNickname attribute" -ForegroundColor Yellow + Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow + Write-Host "User will be created without mailNickname (can be added later)" -ForegroundColor Yellow + } + + # Try to add proxyAddresses if available (with error handling) + try { + $newUserParams['proxyAddresses'] = "SMTP:$emailAddress" + Write-Host "Attempting to set proxyAddresses: SMTP:$emailAddress" -ForegroundColor Cyan + } + catch { + Write-Host "Warning: Could not set proxyAddresses attribute" -ForegroundColor Yellow + Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow + } + + Write-Host "`nCreating user with these confirmed attributes:" -ForegroundColor Cyan + $newUserParams.GetEnumerator() | Where-Object { $_.Key -ne 'AccountPassword' } | ForEach-Object { + Write-Host "$($_.Key): $($_.Value)" + } + + New-ADUser @newUserParams + Write-Host "User $username created successfully!" -ForegroundColor Green + + # Clear the plaintext password from memory + [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( + [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password) + ) + + # Option to add to groups + $addGroups = Read-Host "Would you like to add the user to any groups? (Y/N)" + if ($addGroups -eq 'Y' -or $addGroups -eq 'y') { + $groups = Read-Host "Enter group names (comma separated)" + $groupArray = $groups -split ',' + + foreach ($group in $groupArray) { + try { + Add-ADGroupMember -Identity $group.Trim() -Members $username -ErrorAction Stop + Write-Host "Added to $group successfully." -ForegroundColor Green + } + catch { + Write-Host "Error adding to group $group : $_" -ForegroundColor Red + } + } + } + } + catch { + Write-Host "Error creating user: $($_.Exception.Message)" -ForegroundColor Red + + if ($_.Exception.Message -like "*Access is denied*") { + Write-Host "`nTROUBLESHOOTING TIPS:" -ForegroundColor Yellow + Write-Host "1. Run PowerShell as Administrator" -ForegroundColor Yellow + Write-Host "2. Verify you have permissions to create users in: $($newUserParams['Path'])" -ForegroundColor Yellow + Write-Host "3. Try a simpler OU path (e.g., CN=Users)" -ForegroundColor Yellow + } + elseif ($_.Exception.Message -like "*mailNickname*" -or $_.Exception.Message -like "*proxyAddresses*") { + Write-Host "`nNOTE: Some attributes not available in this environment" -ForegroundColor Yellow + Write-Host "The user was created successfully without these attributes" -ForegroundColor Green + Write-Host "You can add them later if needed" -ForegroundColor Yellow + } + } +} + +function Copy-ExistingUser { + param ( + [string]$Domain + ) + + $sourceUsername = Read-Host "Enter username of the user you want to copy" + + try { + $sourceUser = Get-ADUser -Identity $sourceUsername -Properties * -ErrorAction Stop + + Write-Host "`nCopying settings from: $($sourceUser.Name)" -ForegroundColor Cyan + Write-Host "Current OU: $($sourceUser.DistinguishedName)`n" -ForegroundColor Cyan + + # Get the parent OU from the source user's DN + $sourceOU = $sourceUser.DistinguishedName -replace '^CN=[^,]+,','' + Write-Host "Source user's OU: $sourceOU" -ForegroundColor Cyan + + $firstName = Read-Host "Enter new user's first name [$($sourceUser.GivenName)]" + if ([string]::IsNullOrWhiteSpace($firstName)) { $firstName = $sourceUser.GivenName } + + $lastName = Read-Host "Enter new user's last name [$($sourceUser.Surname)]" + if ([string]::IsNullOrWhiteSpace($lastName)) { $lastName = $sourceUser.Surname } + + $username = Read-Host "Enter new username (leave blank to auto-generate)" + + if ([string]::IsNullOrWhiteSpace($username)) { + $username = ($firstName.Substring(0,1) + $lastName).ToLower() + Write-Host "Auto-generated username: $username" -ForegroundColor Yellow + } + + $displayName = "$firstName $lastName" + + # Offer choice to use source OU or specify new one + $ouChoice = Read-Host "Use same OU as source user? [$sourceOU] (Y/N)" + if ($ouChoice -eq 'Y' -or $ouChoice -eq 'y') { + $ou = $sourceOU + } + else { + $ou = Read-Host "Enter new OU distinguished name (e.g., OU=Users,DC=domain,DC=com)" + } + + # Validate OU exists + try { + $null = Get-ADObject -Identity $ou -ErrorAction Stop + } + catch { + Write-Host "Invalid OU specified: $ou" -ForegroundColor Red + Write-Host "Defaulting to source user's OU: $sourceOU" -ForegroundColor Yellow + $ou = $sourceOU + } + + $password = Get-ValidPassword + + try { + # Build fresh email attributes for new user + $emailAddress = "$username@$Domain" + + # Base parameters that will always work + $newUserParams = @{ + GivenName = $firstName + Surname = $lastName + Name = $displayName + DisplayName = $displayName + SamAccountName = $username + UserPrincipalName = $emailAddress + AccountPassword = $password + Enabled = $true + ChangePasswordAtLogon = $true + Path = $ou + EmailAddress = $emailAddress + ErrorAction = 'Stop' + } + + # Copy organizational attributes if they exist + if ($sourceUser.Company) { $newUserParams['Company'] = $sourceUser.Company } + if ($sourceUser.Department) { $newUserParams['Department'] = $sourceUser.Department } + if ($sourceUser.Title) { $newUserParams['Title'] = $sourceUser.Title } + if ($sourceUser.Office) { $newUserParams['Office'] = $sourceUser.Office } + if ($sourceUser.StreetAddress) { $newUserParams['StreetAddress'] = $sourceUser.StreetAddress } + if ($sourceUser.City) { $newUserParams['City'] = $sourceUser.City } + if ($sourceUser.State) { $newUserParams['State'] = $sourceUser.State } + if ($sourceUser.PostalCode) { $newUserParams['PostalCode'] = $sourceUser.PostalCode } + if ($sourceUser.Country) { $newUserParams['Country'] = $sourceUser.Country } + if ($sourceUser.OfficePhone) { $newUserParams['OfficePhone'] = $sourceUser.OfficePhone } + + # Try to add mailNickname if available + try { + $newUserParams['mailNickname'] = $username + Write-Host "Attempting to set mailNickname: $username" -ForegroundColor Cyan + } + catch { + Write-Host "Warning: Could not set mailNickname attribute" -ForegroundColor Yellow + } + + # Try to add proxyAddresses if available + try { + $newUserParams['proxyAddresses'] = "SMTP:$emailAddress" + Write-Host "Attempting to set proxyAddresses: SMTP:$emailAddress" -ForegroundColor Cyan + } + catch { + Write-Host "Warning: Could not set proxyAddresses attribute" -ForegroundColor Yellow + } + + Write-Host "`nCreating user with these confirmed attributes:" -ForegroundColor Cyan + $newUserParams.GetEnumerator() | Where-Object { $_.Key -ne 'AccountPassword' } | ForEach-Object { + Write-Host "$($_.Key): $($_.Value)" + } + + New-ADUser @newUserParams + Write-Host "User $username created successfully in $ou!" -ForegroundColor Green + + [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( + [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) + + # Copy group memberships (excluding Domain Users) + $copyGroups = Read-Host "Would you like to copy group memberships? (Y/N)" + if ($copyGroups -eq 'Y' -or $copyGroups -eq 'y') { + $groups = Get-ADPrincipalGroupMembership -Identity $sourceUsername | + Where-Object { $_.Name -ne "Domain Users" } + + if ($groups) { + foreach ($group in $groups) { + try { + Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop + Write-Host "Added to $($group.Name) successfully." -ForegroundColor Green + } + catch { + Write-Host "Error adding to group $($group.Name) : $_" -ForegroundColor Red + } + } + } + else { + Write-Host "No additional groups to copy." -ForegroundColor Yellow + } + } + } + catch { + Write-Host "Error creating user: $($_.Exception.Message)" -ForegroundColor Red + + if ($_.Exception.Message -like "*parent is not on the list of possible superiors*") { + Write-Host "`nTROUBLESHOOTING TIPS:" -ForegroundColor Yellow + Write-Host "1. You don't have permission to create users in: $ou" -ForegroundColor Yellow + Write-Host "2. Try creating in the default Users container instead" -ForegroundColor Yellow + Write-Host "3. Run PowerShell as Domain Administrator" -ForegroundColor Yellow + } + elseif ($_.Exception.Message -like "*mailNickname*" -or $_.Exception.Message -like "*proxyAddresses*") { + Write-Host "`nNOTE: Some attributes not available in this environment" -ForegroundColor Yellow + Write-Host "The user was created successfully without these attributes" -ForegroundColor Green + } + } + } + catch { + Write-Host "Error accessing source user: $_" -ForegroundColor Red + } +} + +function CopyExistingUser { + param ( + [string]$Domain + ) + + $sourceUsername = Read-Host "Enter username of the user you want to copy" + + try { + $sourceUser = Get-ADUser -Identity $sourceUsername -Properties * -ErrorAction Stop + + Write-Host "`nCopying settings from: $($sourceUser.Name)" -ForegroundColor Cyan + Write-Host "Current OU: $($sourceUser.DistinguishedName)`n" -ForegroundColor Cyan + + # Get the parent OU from the source user's DN + $sourceOU = $sourceUser.DistinguishedName -replace '^CN=[^,]+,','' + Write-Host "Source user's OU: $sourceOU" -ForegroundColor Cyan + + $firstName = Read-Host "Enter new user's first name [$($sourceUser.GivenName)]" + if ([string]::IsNullOrWhiteSpace($firstName)) { $firstName = $sourceUser.GivenName } + + $lastName = Read-Host "Enter new user's last name [$($sourceUser.Surname)]" + if ([string]::IsNullOrWhiteSpace($lastName)) { $lastName = $sourceUser.Surname } + + $username = Read-Host "Enter new username (leave blank to auto-generate)" + + if ([string]::IsNullOrWhiteSpace($username)) { + $username = ($firstName.Substring(0,1) + $lastName).ToLower() + Write-Host "Auto-generated username: $username" -ForegroundColor Yellow + } + + $displayName = "$firstName $lastName" + + # Offer choice to use source OU or specify new one + $ouChoice = Read-Host "Use same OU as source user? [$sourceOU] (Y/N)" + if ($ouChoice -eq 'Y' -or $ouChoice -eq 'y') { + $ou = $sourceOU + } + else { + $ou = Read-Host "Enter new OU distinguished name (e.g., OU=Users,DC=domain,DC=com)" + } + + # Validate OU exists + try { + $null = Get-ADObject -Identity $ou -ErrorAction Stop + } + catch { + Write-Host "Invalid OU specified: $ou" -ForegroundColor Red + Write-Host "Defaulting to source user's OU: $sourceOU" -ForegroundColor Yellow + $ou = $sourceOU + } + + $password = Get-ValidPassword + + try { + # Build fresh email attributes for new user + $emailAddress = "$username@$Domain" + $proxyAddresses = "SMTP:$emailAddress" # Only the new primary address + + Write-Host "`nSetting email attributes:" -ForegroundColor Cyan + Write-Host "EmailAddress: $emailAddress" + Write-Host "proxyAddresses: $proxyAddresses`n" + + # Base parameters that will always work + $newUserParams = @{ + GivenName = $firstName + Surname = $lastName + Name = $displayName + DisplayName = $displayName + SamAccountName = $username + UserPrincipalName = $emailAddress + AccountPassword = $password + Enabled = $true + ChangePasswordAtLogon = $true + Path = $ou + # Copy these organizational attributes + Company = $sourceUser.Company + Department = $sourceUser.Department + Title = $sourceUser.Title + Office = $sourceUser.Office + # Set email address + EmailAddress = $emailAddress + ErrorAction = 'Stop' + } + + # Try to add mailNickname if available (with error handling) + try { + $newUserParams['mailNickname'] = $username + Write-Host "Attempting to set mailNickname: $username" -ForegroundColor Cyan + } + catch { + Write-Host "Warning: Could not set mailNickname attribute" -ForegroundColor Yellow + Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow + Write-Host "User will be created without mailNickname (can be added later)" -ForegroundColor Yellow + } + + # Try to add proxyAddresses if available (with error handling) + try { + $newUserParams['proxyAddresses'] = $proxyAddresses + } + catch { + Write-Host "Warning: Could not set proxyAddresses attribute" -ForegroundColor Yellow + Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow + } + + # Copy address fields only if they exist on source + if ($sourceUser.StreetAddress) { $newUserParams['StreetAddress'] = $sourceUser.StreetAddress } + if ($sourceUser.City) { $newUserParams['City'] = $sourceUser.City } + if ($sourceUser.State) { $newUserParams['State'] = $sourceUser.State } + if ($sourceUser.PostalCode) { $newUserParams['PostalCode'] = $sourceUser.PostalCode } + if ($sourceUser.Country) { $newUserParams['Country'] = $sourceUser.Country } + if ($sourceUser.OfficePhone) { $newUserParams['OfficePhone'] = $sourceUser.OfficePhone } + + # Create the user with whatever attributes we can set + New-ADUser @newUserParams + Write-Host "User $username created successfully in $ou!" -ForegroundColor Green + + [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( + [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) + + # Copy group memberships (excluding Domain Users) + $copyGroups = Read-Host "Would you like to copy group memberships? (Y/N)" + if ($copyGroups -eq 'Y' -or $copyGroups -eq 'y') { + $groups = Get-ADPrincipalGroupMembership -Identity $sourceUsername | + Where-Object { $_.Name -ne "Domain Users" } + + if ($groups) { + foreach ($group in $groups) { + try { + Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop + Write-Host "Added to $($group.Name) successfully." -ForegroundColor Green + } + catch { + Write-Host "Error adding to group $($group.Name) : $_" -ForegroundColor Red + } + } + } + else { + Write-Host "No additional groups to copy." -ForegroundColor Yellow + } + } + } + catch { + Write-Host "Error creating user: $($_.Exception.Message)" -ForegroundColor Red + + if ($_.Exception.Message -like "*parent is not on the list of possible superiors*") { + Write-Host "`nTROUBLESHOOTING TIPS:" -ForegroundColor Yellow + Write-Host "1. You don't have permission to create users in: $ou" -ForegroundColor Yellow + Write-Host "2. Try creating in the default Users container instead" -ForegroundColor Yellow + Write-Host "3. Run PowerShell as Domain Administrator" -ForegroundColor Yellow + } + elseif ($_.Exception.Message -like "*mailNickname*") { + Write-Host "`nNOTE: mailNickname attribute not available in this environment" -ForegroundColor Yellow + Write-Host "The user was created successfully without this attribute" -ForegroundColor Green + } + } + } + catch { + Write-Host "Error accessing source user: $_" -ForegroundColor Red + } +} + +# Main script execution +do { + Show-Menu + $selection = Read-Host "Please make a selection" + + switch ($selection) { + '1' { + $domain = Get-DomainSelection + CreateNewUser -Domain $domain + pause + } + '2' { + $domain = Get-DomainSelection + CopyExistingUser -Domain $domain + pause + } + 'Q' { + exit + } + default { + Write-Host "Invalid selection. Please try again." -ForegroundColor Red + pause + } + } +} while ($selection -ne 'Q') \ No newline at end of file