Files
dms/Setup-ByteTrail-AD.ps1
T
2026-04-28 15:07:32 +02:00

407 lines
20 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================================
# ByteTrail GmbH Active Directory Setup Script
# Domäne: bytetrail.local
# Erstellt: Team 3 VZ | FH Burgenland | SS 2026
# Ausführen auf: SRV-DC01 als Domain Admin
# ============================================================
#region KONFIGURATION
$Domain = "byte.trail"
$DomainDN = "DC=byte,DC=trail"
$MailDomain = "byte.trail"
$DefaultPW = ConvertTo-SecureString "ByteTrail2026!" -AsPlainText -Force
#endregion
Write-Host "`n=== ByteTrail AD Setup gestartet ===" -ForegroundColor Cyan
# ============================================================
# DIAGNOSE - Pruefen ob AD bereit ist
# ============================================================
Write-Host "`n[0/4] AD-Diagnose..." -ForegroundColor Yellow
# ADWS-Dienst pruefen
$adws = Get-Service ADWS -ErrorAction SilentlyContinue
if ($adws) {
if ($adws.Status -ne 'Running') {
Write-Host " [!] ADWS-Dienst ist NICHT gestartet (Status: $($adws.Status)). Starte..." -ForegroundColor Red
try { Start-Service ADWS -ErrorAction Stop; Start-Sleep -Seconds 5 }
catch { Write-Host " [!] ADWS konnte nicht gestartet werden: $_" -ForegroundColor Red; exit 1 }
}
Write-Host " [OK] ADWS-Dienst laeuft" -ForegroundColor Green
} else {
Write-Host " [!] ADWS-Dienst nicht gefunden - ist AD DS installiert?" -ForegroundColor Red
exit 1
}
# AD erreichbar?
try {
$ADDomain = Get-ADDomain -ErrorAction Stop
Write-Host " [OK] AD-Domaene: $($ADDomain.DNSRoot)" -ForegroundColor Green
Write-Host " [OK] Naming Context: $($ADDomain.DistinguishedName)" -ForegroundColor Green
Write-Host " [OK] PDC Emulator: $($ADDomain.PDCEmulator)" -ForegroundColor Green
Write-Host " [OK] Infrastruktur Master: $($ADDomain.InfrastructureMaster)" -ForegroundColor Green
# RODC-Check
$dc = Get-ADDomainController -ErrorAction Stop
if ($dc.IsReadOnly) {
Write-Host " [!] ACHTUNG: Dieser DC ist ein READ-ONLY DC (RODC) - Schreiboperationen werden fehlschlagen!" -ForegroundColor Red
exit 1
}
Write-Host " [OK] DC: $($dc.HostName) (Beschreibbar)" -ForegroundColor Green
} catch {
Write-Host " [!] AD nicht erreichbar: $($_.Exception.Message)" -ForegroundColor Red
Write-Host " [!] InnerException: $($_.Exception.InnerException)" -ForegroundColor Red
Write-Host "`nMoegliche Loesungen:" -ForegroundColor Yellow
Write-Host " 1. Server neustarten (nach DC-Promotion noetig)" -ForegroundColor Yellow
Write-Host " 2. Restart-Service ADWS" -ForegroundColor Yellow
Write-Host " 3. dcdiag /v ausfuehren fuer Details" -ForegroundColor Yellow
exit 1
}
# Quick-Write-Test: Versuche ein Dummy-Objekt zu erstellen und loeschen
Write-Host " [..] Schreibtest..." -ForegroundColor Gray
try {
$testOUName = "_ByteTrailSetupTest"
$testOU = "OU=$testOUName,$DomainDN"
# Falls vom letzten Lauf noch vorhanden, erst loeschen
try {
Set-ADOrganizationalUnit -Identity $testOU -ProtectedFromAccidentalDeletion $false -ErrorAction Stop
Remove-ADOrganizationalUnit -Identity $testOU -Confirm:$false -Recursive -ErrorAction Stop
} catch { }
New-ADOrganizationalUnit -Name $testOUName -Path $DomainDN -ErrorAction Stop
Set-ADOrganizationalUnit -Identity $testOU -ProtectedFromAccidentalDeletion $false -ErrorAction Stop
Remove-ADOrganizationalUnit -Identity $testOU -Confirm:$false -Recursive -ErrorAction Stop
Write-Host " [OK] Schreibzugriff funktioniert" -ForegroundColor Green
} catch {
Write-Host " [!] SCHREIBTEST FEHLGESCHLAGEN!" -ForegroundColor Red
Write-Host " [!] Fehler: $($_.Exception.Message)" -ForegroundColor Red
if ($_.Exception.InnerException) {
Write-Host " [!] Detail: $($_.Exception.InnerException.Message)" -ForegroundColor Red
}
Write-Host "`nMoegliche Ursachen:" -ForegroundColor Yellow
Write-Host " 1. Server wurde nach DC-Promotion noch nicht neugestartet" -ForegroundColor Yellow
Write-Host " 2. AD DS Datenbank nicht bereit - 'Restart-Service NTDS' oder Server neustarten" -ForegroundColor Yellow
Write-Host " 3. Dieses Konto hat keine Schreibrechte (als Domain Admin ausfuehren)" -ForegroundColor Yellow
Write-Host " 4. dcdiag /v ausfuehren fuer Details" -ForegroundColor Yellow
$antwort = Read-Host "`nTrotzdem fortfahren? (j/n)"
if ($antwort -ne 'j') { exit 1 }
}
Write-Host ""
# ============================================================
# 1. OU-STRUKTUR
# ============================================================
Write-Host "[1/4] Erstelle OU-Struktur..." -ForegroundColor Yellow
$OUs = @(
"OU=Geschaeftsfuehrung,$DomainDN",
"OU=Sales,$DomainDN",
"OU=Marketing,$DomainDN",
"OU=Service,$DomainDN",
"OU=Server,$DomainDN",
"OU=Gruppen,$DomainDN"
)
$OUCreated = 0; $OUExists = 0; $OUError = 0
foreach ($OU in $OUs) {
$OUName = ($OU -split ",")[0] -replace "OU=", ""
try {
Get-ADOrganizationalUnit -Identity $OU -ErrorAction Stop | Out-Null
Write-Host " [~] OU existiert bereits: $OUName" -ForegroundColor Gray
$OUExists++
} catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
try {
New-ADOrganizationalUnit -Name $OUName -Path $DomainDN -ProtectedFromAccidentalDeletion $true -ErrorAction Stop
Write-Host " [+] OU erstellt: $OUName" -ForegroundColor Green
$OUCreated++
} catch {
Write-Host " [!] FEHLER OU '$OUName': $($_.Exception.Message)" -ForegroundColor Red
$OUError++
}
} catch {
# Anderer Fehler beim Pruefen (z.B. Berechtigung) - versuche trotzdem
try {
New-ADOrganizationalUnit -Name $OUName -Path $DomainDN -ProtectedFromAccidentalDeletion $true -ErrorAction Stop
Write-Host " [+] OU erstellt: $OUName" -ForegroundColor Green
$OUCreated++
} catch {
if ($_.Exception.Message -like "*already exists*" -or $_.Exception.Message -like "*existiert bereits*") {
Write-Host " [~] OU existiert bereits: $OUName" -ForegroundColor Gray
$OUExists++
} else {
Write-Host " [!] FEHLER OU '$OUName': $($_.Exception.Message)" -ForegroundColor Red
$OUError++
}
}
}
}
# ============================================================
# 2. AD-GRUPPEN
# ============================================================
Write-Host "`n[2/4] Erstelle AD-Gruppen..." -ForegroundColor Yellow
$Groups = @(
@{ Name = 'GRP-GF-VOLLZUGRIFF'; Description = 'Geschaeftsfuehrung - Vollzugriff' }
@{ Name = 'GRP-GF-VPN'; Description = 'Geschaeftsfuehrung - VPN-Zugang' }
@{ Name = 'GRP-GF-ERP'; Description = 'Geschaeftsfuehrung - ERP-Zugriff' }
@{ Name = 'GRP-SALES-ERP'; Description = 'Sales - ERP-Zugriff' }
@{ Name = 'GRP-SALES-VPN'; Description = 'Sales - VPN-Zugang' }
@{ Name = 'GRP-SALES-FILES'; Description = 'Sales - Dateifreigabe' }
@{ Name = 'GRP-MKT-FILES'; Description = 'Marketing - Dateifreigabe' }
@{ Name = 'GRP-SVC-FILES'; Description = 'Service/Technik - Dateifreigabe' }
@{ Name = 'GRP-SVC-ERP'; Description = 'Service/Technik - ERP-Zugriff (tlw.)' }
@{ Name = 'GRP-ALL-EMAIL'; Description = 'Alle Mitarbeiter - E-Mail' }
@{ Name = 'GRP-ADMINS'; Description = 'IT-Administratoren' }
)
$GrpCreated = 0; $GrpExists = 0; $GrpError = 0
foreach ($Group in $Groups) {
try {
Get-ADGroup -Identity $Group.Name -ErrorAction Stop | Out-Null
Write-Host " [~] Gruppe existiert bereits: $($Group.Name)" -ForegroundColor Gray
$GrpExists++
} catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
try {
New-ADGroup `
-Name $Group.Name `
-SamAccountName $Group.Name `
-GroupScope Global `
-GroupCategory Security `
-Description $Group.Description `
-Path "OU=Gruppen,$DomainDN" `
-ErrorAction Stop
Write-Host " [+] Gruppe erstellt: $($Group.Name)" -ForegroundColor Green
$GrpCreated++
} catch {
Write-Host " [!] FEHLER Gruppe '$($Group.Name)': $($_.Exception.Message)" -ForegroundColor Red
$GrpError++
}
} catch {
try {
New-ADGroup `
-Name $Group.Name `
-SamAccountName $Group.Name `
-GroupScope Global `
-GroupCategory Security `
-Description $Group.Description `
-Path "OU=Gruppen,$DomainDN" `
-ErrorAction Stop
Write-Host " [+] Gruppe erstellt: $($Group.Name)" -ForegroundColor Green
$GrpCreated++
} catch {
if ($_.Exception.Message -like "*already exists*" -or $_.Exception.Message -like "*existiert bereits*") {
Write-Host " [~] Gruppe existiert bereits: $($Group.Name)" -ForegroundColor Gray
$GrpExists++
} else {
Write-Host " [!] FEHLER Gruppe '$($Group.Name)': $($_.Exception.Message)" -ForegroundColor Red
$GrpError++
}
}
}
}
# ============================================================
# 3. BENUTZER
# ============================================================
Write-Host "`n[3/4] Erstelle Benutzer..." -ForegroundColor Yellow
# Schema: Vorname, Nachname, Abteilung, OU, Gruppen[]
$Users = @(
# --- Geschäftsführung (1 MA) ---
@{
Vorname = "Thomas"
Nachname = "Maier"
Abt = "Geschaeftsfuehrung"
OU = "OU=Geschaeftsfuehrung,$DomainDN"
Gruppen = @("GRP-GF-VOLLZUGRIFF","GRP-GF-VPN","GRP-GF-ERP","GRP-ALL-EMAIL")
Title = "Geschäftsführer"
},
# --- Sales / Vertrieb (2 MA) ---
@{
Vorname = "Anna"
Nachname = "Huber"
Abt = "Sales"
OU = "OU=Sales,$DomainDN"
Gruppen = @("GRP-SALES-ERP","GRP-SALES-VPN","GRP-SALES-FILES","GRP-ALL-EMAIL")
Title = "Vertriebsmitarbeiterin"
},
@{
Vorname = "Markus"
Nachname = "Reiter"
Abt = "Sales"
OU = "OU=Sales,$DomainDN"
Gruppen = @("GRP-SALES-ERP","GRP-SALES-VPN","GRP-SALES-FILES","GRP-ALL-EMAIL")
Title = "Vertriebsmitarbeiter"
},
# --- Marketing (2 MA) ---
@{
Vorname = "Julia"
Nachname = "Wagner"
Abt = "Marketing"
OU = "OU=Marketing,$DomainDN"
Gruppen = @("GRP-MKT-FILES","GRP-ALL-EMAIL")
Title = "Marketingmitarbeiterin"
},
@{
Vorname = "Stefan"
Nachname = "Bauer"
Abt = "Marketing"
OU = "OU=Marketing,$DomainDN"
Gruppen = @("GRP-MKT-FILES","GRP-ALL-EMAIL")
Title = "Marketingmitarbeiter"
},
# --- Service / Technik (25 MA) ---
# Techniker mit ERP-Zugriff (5 MA)
@{ Vorname="Klaus"; Nachname="Schneider"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-SVC-ERP","GRP-ALL-EMAIL"); Title="Techniker" },
@{ Vorname="Peter"; Nachname="Fischer"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-SVC-ERP","GRP-ALL-EMAIL"); Title="Techniker" },
@{ Vorname="Michael"; Nachname="Weber"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-SVC-ERP","GRP-ALL-EMAIL"); Title="Techniker" },
@{ Vorname="Andreas"; Nachname="Müller"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-SVC-ERP","GRP-ALL-EMAIL"); Title="Techniker" },
@{ Vorname="Christian";Nachname="Schmidt"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-SVC-ERP","GRP-ALL-EMAIL"); Title="Techniker" },
# Techniker ohne ERP (20 MA)
@{ Vorname="David"; Nachname="Hoffmann"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Felix"; Nachname="Schäfer"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Georg"; Nachname="Koch"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Hans"; Nachname="Becker"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Josef"; Nachname="Wolf"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Karl"; Nachname="Braun"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Leon"; Nachname="Schwarz"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Martin"; Nachname="Zimmermann";Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Nico"; Nachname="Krause"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Oliver"; Nachname="Richter"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Paul"; Nachname="Klein"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Robert"; Nachname="Werner"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Simon"; Nachname="Neumann"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Thomas"; Nachname="Lange"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Ulrich"; Nachname="Scholz"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Viktor"; Nachname="Peters"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Walter"; Nachname="Vogel"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Xaver"; Nachname="Keller"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" },
@{ Vorname="Yannick"; Nachname="Frank"; Abt="Service"; OU="OU=Service,$DomainDN"; Gruppen=@("GRP-SVC-FILES","GRP-ALL-EMAIL"); Title="Servicemitarbeiter" }
)
$UserCreatedCount = 0
$UserExistsCount = 0
$UserErrorCount = 0
foreach ($User in $Users) {
# Benutzername: vorname.nachname (Umlaute ersetzen)
$Sam = ($User.Vorname + "." + $User.Nachname).ToLower()
$Sam = $Sam -replace "ä","ae" -replace "ö","oe" -replace "ü","ue" -replace "ß","ss"
$UPN = "$Sam@$Domain"
$EmailAddr = "$Sam@$MailDomain"
$UserCreated = $false
try {
Get-ADUser -Identity $Sam -ErrorAction Stop | Out-Null
Write-Host " [~] User existiert bereits: $Sam" -ForegroundColor Gray
$UserExistsCount++
$UserCreated = $true # User existiert, Gruppen trotzdem zuweisen
} catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
try {
New-ADUser `
-SamAccountName $Sam `
-UserPrincipalName $UPN `
-GivenName $User.Vorname `
-Surname $User.Nachname `
-Name "$($User.Vorname) $($User.Nachname)" `
-DisplayName "$($User.Vorname) $($User.Nachname)" `
-Department $User.Abt `
-Title $User.Title `
-EmailAddress $EmailAddr `
-Path $User.OU `
-AccountPassword $DefaultPW `
-PasswordNeverExpires $false `
-ChangePasswordAtLogon $true `
-Enabled $true `
-ErrorAction Stop
Write-Host " [+] User erstellt: $Sam ($($User.Abt))" -ForegroundColor Green
$UserCreatedCount++
$UserCreated = $true
} catch {
Write-Host " [!] FEHLER User '$Sam': $($_.Exception.Message)" -ForegroundColor Red
$UserErrorCount++
}
} catch {
Write-Host " [!] FEHLER beim Pruefen von User '$Sam': $($_.Exception.Message)" -ForegroundColor Red
$UserErrorCount++
}
# Gruppen zuweisen - nur wenn User existiert oder gerade erstellt wurde
if ($UserCreated) {
foreach ($Gruppe in $User.Gruppen) {
try {
# User explizit im richtigen Domain-Kontext holen
$UserObj = Get-ADUser -Identity $Sam -ErrorAction Stop
Add-ADGroupMember -Identity $Gruppe -Members $UserObj -ErrorAction Stop
} catch {
if ($_.Exception.Message -like "*already a member*" -or $_.Exception.Message -like "*ist bereits Mitglied*" -or $_.Exception.Message -like "*member already exists*") {
# Stille Warnung - User ist schon in der Gruppe
} else {
Write-Warning " Gruppe '$Gruppe' -> '$Sam': $($_.Exception.Message)"
}
}
}
}
}
# ============================================================
# 4. SERVICE-ACCOUNT FÜR MAILSERVER (LDAP-Bind)
# ============================================================
Write-Host "`n[4/4] Erstelle Service-Account für Mailserver..." -ForegroundColor Yellow
$SvcSam = "svc-mailserver"
$SvcUPN = "$SvcSam@$Domain"
$SvcPW = ConvertTo-SecureString 'Mail$3rv!ceAcc2026' -AsPlainText -Force
try {
Get-ADUser -Identity $SvcSam -ErrorAction Stop | Out-Null
Write-Host " [~] Service-Account existiert bereits: $SvcSam" -ForegroundColor Gray
} catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
try {
New-ADUser `
-SamAccountName $SvcSam `
-UserPrincipalName $SvcUPN `
-Name "Mailserver Service Account" `
-DisplayName "Mailserver Service Account" `
-Description "Service-Account fuer Docker-Mailserver LDAP-Bind" `
-Path "OU=Server,$DomainDN" `
-AccountPassword $SvcPW `
-PasswordNeverExpires $true `
-ChangePasswordAtLogon $false `
-CannotChangePassword $true `
-Enabled $true `
-ErrorAction Stop
Write-Host " [+] Service-Account erstellt: $SvcSam" -ForegroundColor Green
} catch {
Write-Host " [!] FEHLER Service-Account '$SvcSam': $($_.Exception.Message)" -ForegroundColor Red
}
} catch {
Write-Host " [!] FEHLER beim Pruefen von Service-Account '$SvcSam': $($_.Exception.Message)" -ForegroundColor Red
}
# ============================================================
# ZUSAMMENFASSUNG
# ============================================================
Write-Host "`n=== Setup abgeschlossen ===" -ForegroundColor Cyan
Write-Host "OUs: $OUCreated neu, $OUExists vorhanden, $OUError Fehler" -ForegroundColor White
Write-Host "Gruppen: $GrpCreated neu, $GrpExists vorhanden, $GrpError Fehler" -ForegroundColor White
Write-Host "User: $UserCreatedCount neu erstellt, $UserExistsCount bereits vorhanden, $UserErrorCount Fehler (+ 1 Service-Account)" -ForegroundColor White
Write-Host "`nStandard-Passwort User: ByteTrail2026! (Benutzer muessen es beim ersten Login aendern)" -ForegroundColor Yellow
Write-Host "Service-Account Mailserver: $SvcSam / Mail`$3rv!ceAcc2026" -ForegroundColor Yellow
Write-Host "Mail-Domain: $MailDomain" -ForegroundColor White
Write-Host "AD-Domaene: $Domain" -ForegroundColor White
Write-Host ""