# ============================================================ # 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 = "bytetrail.local" $DomainDN = "DC=bytetrail,DC=local" $MailDomain = "bytetrail.at" $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 ""