Co-authored-by: tg95 <tg95@noreply.localhost> Co-authored-by: Taarly <lownslow.music@gmail.com> Co-authored-by: taarly <lownslow.music@gmail.com> Co-authored-by: ViperioN1339 <stezel1989@outlook.de> Co-authored-by: MuchenTuchen31 <yasin.mine31@gmail.com> Reviewed-on: https://git.eckertplayground.de/taarly/PHP_AdminTool_Projekt/pulls/28 Co-authored-by: blaerf <blaerf@gmx.de> Co-committed-by: blaerf <blaerf@gmx.de>
154 lines
4.8 KiB
PowerShell
154 lines
4.8 KiB
PowerShell
param(
|
||
[Parameter(Mandatory=$true)]
|
||
[string]$InputFile
|
||
)
|
||
|
||
# Read input JSON
|
||
try {
|
||
$json = Get-Content -Raw -Path $InputFile -ErrorAction Stop
|
||
$payload = $json | ConvertFrom-Json
|
||
} catch {
|
||
$err = $_.Exception.Message
|
||
Write-Output (@{ success = $false; message = "Failed to read/parse input JSON: $err" } | ConvertTo-Json -Compress)
|
||
exit 1
|
||
}
|
||
|
||
# Default result
|
||
$actor = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
|
||
$result = @{ success = $false; message = "Unspecified error"; actor = $actor }
|
||
|
||
# Validate
|
||
if (-not $payload.samaccountname -or -not $payload.password) {
|
||
$result.message = "Required fields: samaccountname and password"
|
||
Write-Output ($result | ConvertTo-Json -Compress)
|
||
exit 1
|
||
}
|
||
|
||
# Convert to strings
|
||
$sam = [string]$payload.samaccountname
|
||
$display = [string]($payload.displayname)
|
||
$mail = [string]($payload.mail)
|
||
$pass = [string]$payload.password
|
||
$ou = [string]($payload.ou)
|
||
$groups = [string]($payload.groups)
|
||
$dryRun = [bool]($payload.dry_run -as [bool])
|
||
# Password hint and validation helper (German)
|
||
$passwordHint = @"
|
||
Das sollten die Anforderungen an das Passwort sein:
|
||
|
||
- mindestens 7 Zeichen
|
||
- darf den Benutzer-/Accountnamen nicht enthalten (bzw. keine zu großen Teile davon)
|
||
- muss Zeichen aus mindestens 3 von 4 Kategorien enthalten:
|
||
1) Großbuchstaben (A–Z)
|
||
2) Kleinbuchstaben (a–z)
|
||
3) Ziffern (0–9)
|
||
4) Sonderzeichen (alles, was kein Buchstabe/Zahl ist, z. B. ! ? # _ - . , usw.)
|
||
"@
|
||
|
||
function Test-PasswordRequirements {
|
||
param(
|
||
[string]$Password,
|
||
[string]$SamAccountName
|
||
)
|
||
|
||
$errors = @()
|
||
|
||
if ([string]::IsNullOrEmpty($Password) -or $Password.Length -lt 7) {
|
||
$errors += 'Passwort muss mindestens 7 Zeichen lang sein.'
|
||
}
|
||
|
||
$categories = 0
|
||
if ($Password -match '[A-Z]') { $categories++ }
|
||
if ($Password -match '[a-z]') { $categories++ }
|
||
if ($Password -match '\d') { $categories++ }
|
||
if ($Password -match '[^A-Za-z0-9]') { $categories++ }
|
||
if ($categories -lt 3) {
|
||
$errors += 'Passwort muss Zeichen aus mindestens 3 von 4 Kategorien enthalten (Groß, Klein, Ziffern, Sonderzeichen).'
|
||
}
|
||
|
||
if (-not [string]::IsNullOrEmpty($SamAccountName)) {
|
||
$pwLower = $Password.ToLowerInvariant()
|
||
$samLower = $SamAccountName.ToLowerInvariant()
|
||
|
||
if ($pwLower -like "*${samLower}*") {
|
||
$errors += 'Passwort darf den Benutzernamen nicht enthalten.'
|
||
} else {
|
||
$minLen = 4
|
||
if ($samLower.Length -ge $minLen) {
|
||
for ($len = $minLen; $len -le $samLower.Length; $len++) {
|
||
for ($start = 0; $start -le $samLower.Length - $len; $start++) {
|
||
$sub = $samLower.Substring($start, $len)
|
||
if ($pwLower -like "*${sub}*") {
|
||
$errors += 'Passwort darf keine größeren Teile des Benutzernamens enthalten.'
|
||
break 2
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return $errors
|
||
}
|
||
# Ensure ActiveDirectory module available
|
||
try {
|
||
Import-Module ActiveDirectory -ErrorAction Stop
|
||
} catch {
|
||
$result.message = "ActiveDirectory PowerShell module not available: $($_.Exception.Message)"
|
||
Write-Output ($result | ConvertTo-Json -Compress)
|
||
exit 1
|
||
}
|
||
|
||
# Build New-ADUser parameters
|
||
$props = @{
|
||
Name = if ($display -and $display -ne '') { $display } else { $sam }
|
||
SamAccountName = $sam
|
||
Enabled = $true
|
||
}
|
||
|
||
if ($mail -and $mail -ne '') { $props['EmailAddress'] = $mail }
|
||
if ($ou -and $ou -ne '') { $props['Path'] = $ou }
|
||
|
||
# Validate password before continuing
|
||
$pwErrors = Test-PasswordRequirements -Password $pass -SamAccountName $sam
|
||
if ($pwErrors.Count -gt 0) {
|
||
$result.message = 'Invalid password: ' + ($pwErrors -join ' | ')
|
||
$result.hint = $passwordHint
|
||
Write-Output ($result | ConvertTo-Json -Compress)
|
||
exit 1
|
||
}
|
||
|
||
# Build secure password
|
||
$securePass = ConvertTo-SecureString $pass -AsPlainText -Force
|
||
$props['AccountPassword'] = $securePass
|
||
|
||
# Execute
|
||
if ($dryRun) {
|
||
$result.success = $true
|
||
$result.message = "DRY RUN: would create user $($sam)"
|
||
Write-Output ($result | ConvertTo-Json -Compress)
|
||
exit 0
|
||
}
|
||
|
||
try {
|
||
# Create the AD user
|
||
New-ADUser @props -ErrorAction Stop
|
||
|
||
# Add to groups, if provided
|
||
if ($groups -and $groups -ne '') {
|
||
$groupList = $groups -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' }
|
||
foreach ($g in $groupList) {
|
||
Add-ADGroupMember -Identity $g -Members $sam -ErrorAction Stop
|
||
}
|
||
}
|
||
|
||
$result.success = $true
|
||
$result.message = "User $($sam) created successfully"
|
||
Write-Output ($result | ConvertTo-Json -Compress)
|
||
exit 0
|
||
} catch {
|
||
$result.message = "Error creating user $($sam): $($_.Exception.Message)"
|
||
Write-Output ($result | ConvertTo-Json -Compress)
|
||
exit 1
|
||
}
|