WinRM und JEA¶
Siehe auch
- Verwandte Artikel
- Offizielle Dokumentation
- Linuxfabrik
Über Windows Remote Management (WinRM) lassen sich auf einem entfernten Windows-Host PowerShell-Sessions öffnen, Cmdlets ausführen und Ergebnisse zurückgeben. Für einen Linux System Engineer wird das Thema überall dort relevant, wo der eigene Linux-Host Zustände auf Windows-Seite abfragen oder verändern muss: Monitoring, Konfigurationsmanagement (Ansible), Backup-Status, Compliance-Checks.
Der einfache Weg, einen Windows-Host per WinRM anzusprechen, läuft über die Standard-Shell und bekommt dabei die vollen Rechte des verbindenden Accounts. Für Produktivumgebungen ist das meist zu viel. Die Gegenmassnahme heisst Just Enough Administration (JEA): eine eigene PowerShell-Session-Konfiguration, die nur eine explizit erlaubte Liste von Cmdlets sichtbar macht, freies Scripting unterbindet und die Session unter einem temporären virtuellen Account ausführt. Der verbindende User braucht keine Admin-Rechte mehr, und gekaperte Credentials wiegen entsprechend weniger schwer.
Architektur¶
Ein JEA-Endpoint auf Windows besteht aus fünf Teilen:
Der WinRM-Dienst auf dem Windows-Host, der die Sessions annimmt (TCP 5985 für HTTP, 5986 für HTTPS).
Ein reguläres PowerShell-Modul unter
C:\Program Files\WindowsPowerShell\Modules\, das die Role-Capability-Datei aufnimmt.Eine Role Capability (
.psrc) mit der Liste der sichtbaren Cmdlets und der zu importierenden Module. Ein Host kann mehrere Rollen haben.Eine Session Configuration (
.pssc), die den Session-Typ (RestrictedRemoteServer), den Sicherheitskontext (RunAsVirtualAccount) und die Zuordnung von Benutzern zu Rollen definiert.Die Registrierung der Session Configuration als PowerShell-Endpoint mit
Register-PSSessionConfiguration, über den sich der Benutzer danach verbindet.
Die Zugriffskontrolle läuft primär über die RoleDefinitions in der .pssc-Datei. Windows-ACLs auf den Endpoint kann man zusätzlich setzen, ein Deny-ACE schlägt dann wie immer jeden Allow-ACE, das ist aber nur zusätzliche Härtung, nicht der Hauptmechanismus.
Windows-Seite einrichten¶
Die folgenden Schritte laufen allesamt in einer elevated PowerShell auf dem Windows-Host.
WinRM aktivieren¶
Enable-PSRemoting -Force
Set-Service -Name WinRM -StartupType Automatic
Start-Service -Name WinRM
Enable-PSRemoting legt die Default-Listener an, setzt den Dienst auf Autostart und öffnet die nötigen Firewall-Regeln (5985/tcp, im Domain- und Private-Profil). ICMP hat mit WinRM nichts zu tun und muss nicht angefasst werden.
Für den produktiven Einsatz ist HTTPS (5986/tcp) Pflicht. Dafür wird ein gültiges Serverzertifikat auf Cert:\LocalMachine\My hinterlegt und daraus ein HTTPS-Listener erzeugt:
$cert = Get-ChildItem -Path Cert:\LocalMachine\My |
Where-Object { $_.Subject -like "*CN=winsrv.example.com*" }
New-Item -Path WSMan:\localhost\Listener `
-Transport HTTPS `
-Address * `
-CertificateThumbPrint $cert.Thumbprint `
-Force
Status prüfen:
Get-Service -Name WinRM
winrm enumerate winrm/config/listener
Benutzer anlegen¶
Ist der Windows-Host AD-Mitglied, gehört das Konto ins AD, damit Kerberos als Auth-Methode zur Verfügung steht. Für Stand-alone-Hosts genügt ein lokaler Account:
$pw = Read-Host -AsSecureString -Prompt "JEA-Account-Passwort"
New-LocalUser -Name 'jea_monitor' `
-Password $pw `
-FullName 'JEA Read-Only Account' `
-Description 'Zugang ausschliesslich zum JEA-Endpoint MonitoringJEA'
Der User muss nicht in die Administratoren-Gruppe. Den Admin-Kontext liefert später RunAsVirtualAccount. In RoleDefinitions wird die Identität voll qualifiziert angegeben:
lokal:
<ComputerName>\jea_monitorim AD:
<Domain>\jea_monitor
PowerShell-Modul anlegen¶
Die .psrc-Datei muss in einem gültigen Modul liegen. Verzeichnisstruktur:
C:\Program Files\WindowsPowerShell\Modules\
MonitoringJEA\
MonitoringJEA.psd1
RoleCapabilities\
Monitoring.psrc
Modul und Rolle anlegen:
$moduleRoot = 'C:\Program Files\WindowsPowerShell\Modules\MonitoringJEA'
New-Item -Path $moduleRoot -ItemType Directory -Force | Out-Null
New-Item -Path (Join-Path $moduleRoot 'RoleCapabilities') -ItemType Directory -Force | Out-Null
New-ModuleManifest -Path (Join-Path $moduleRoot 'MonitoringJEA.psd1') `
-ModuleVersion '1.0.0' `
-Description 'JEA Read-Only Endpoint'
Role Capability (.psrc) definieren¶
Die .psrc legt fest, welche Cmdlets der Benutzer in der JEA-Session sieht. Alles, was nicht auf der Liste steht, existiert in der Session nicht. Ein Read-Only-Endpoint kommt typischerweise mit wenigen lesenden Cmdlets aus:
$roleCapArgs = @{
Path = 'C:\Program Files\WindowsPowerShell\Modules\MonitoringJEA\RoleCapabilities\Monitoring.psrc'
VisibleCmdlets = @('Get-Service', 'Get-Process', 'Get-ComputerInfo', 'Get-Counter')
VisibleFunctions = @()
VisibleAliases = @()
ModulesToImport = @('Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility')
}
New-PSRoleCapabilityFile @roleCapArgs
Schreibende Cmdlets wie Stop-Service, Start-Service, Restart-Service und Stop-Process fehlen hier bewusst und sind in der Session damit nicht existent. Für konkrete Anwendungsfälle (Failover-Cluster, Exchange, SQL Server, Eventlog-Export) wird die Liste gezielt erweitert, niemals mit * abgekürzt.
Session Configuration (.pssc)¶
Die .pssc verklammert Rolle, User und Sicherheitskontext:
$sessionConfigArgs = @{
Path = 'C:\ProgramData\JEA\MonitoringJEA.pssc'
SessionType = 'RestrictedRemoteServer'
RunAsVirtualAccount = $true
LanguageMode = 'NoLanguage'
TranscriptDirectory = 'C:\ProgramData\JEA\Transcripts'
RoleDefinitions = @{
'COMPUTERNAME\jea_monitor' = @{ RoleCapabilities = 'Monitoring' }
}
}
New-Item -Path 'C:\ProgramData\JEA\Transcripts' -ItemType Directory -Force | Out-Null
New-PSSessionConfigurationFile @sessionConfigArgs
Die wichtigen Parameter:
SessionType = 'RestrictedRemoteServer'schaltet die klassische Remote-Shell ab und lässt nur explizit freigegebene Cmdlets zu.RunAsVirtualAccount = $trueführt die Session unter einem temporären lokalen Admin aus. Der verbindende User braucht keine Admin-Rechte auf dem Host.LanguageMode = 'NoLanguage'blockiert freies Scripting in der Session. Der Client darf nur die freigegebenen Cmdlets aufrufen, keine Variablen, keine Pipelines, die sich wie Skripte verhalten, keineInvoke-Expression-Umgehungen. Ohne diese Zeile ist ein RestrictedRemoteServer-Endpoint nicht dicht.TranscriptDirectorylegt ein Voll-Transcript jeder Session ab. Für hochfrequente Abfragen ist das oft zu laut, für Audit-Zwecke dagegen die beste freie Kontrolle, was der Endpoint tatsächlich ausgeführt hat.
Vor der Registrierung die .pssc validieren:
Test-PSSessionConfigurationFile -Path 'C:\ProgramData\JEA\MonitoringJEA.pssc'
Das Kommando gibt True bei sauberer Konfiguration zurück.
Endpoint registrieren¶
Register-PSSessionConfiguration -Name 'MonitoringJEA' `
-Path 'C:\ProgramData\JEA\MonitoringJEA.pssc' `
-Force
Restart-Service -Name WinRM
Nach dem Neustart des WinRM-Dienstes ist der Endpoint unter dem Namen MonitoringJEA erreichbar. Verifikation:
Get-PSSessionConfiguration | Select-Object Name, Enabled
Get-PSSessionConfiguration -Name MonitoringJEA | Select-Object Name, Enabled, Permission
Transports und Authentifizierung¶
Welche Transport-Methode ein Linux-Client gegenüber WinRM verwendet, hängt von der Umgebung ab. WinRM selbst kennt fünf Varianten. Sie unterscheiden sich in Vertraulichkeit, Setup-Aufwand auf der Windows-Seite und der Frage, ob der Linux-Host Teil eines Active Directory ist:
Transport |
Einsatz |
Windows-seitige Voraussetzung |
|---|---|---|
Kerberos |
AD-integriert, empfohlene Wahl in Domain-Umgebungen. Single-Sign-On nach |
funktioniert mit |
NTLM |
universeller Fallback für Domain und Workgroup, wenn Kerberos nicht zur Verfügung steht. |
funktioniert mit |
CredSSP |
Multi-Hop-Szenarien, in denen der Endpoint die Credentials an einen weiteren Host weiterreichen muss. |
|
Basic |
Testumgebungen oder explizites HTTPS-only. Ohne HTTPS Klartext-Credentials im Header. |
|
Plaintext |
wie Basic, aber explizit über HTTP. |
wie Basic. In Produktion nicht sinnvoll. |
Für Kerberos ist auf dem Linux-Host /etc/krb5.conf gegen die AD-Domain konfiguriert und ein Ticket im Credential-Cache aktiv:
kinit user@EXAMPLE.COM
klist
Für JEA-Endpoints gilt unabhängig vom Transport: der Client muss das PowerShell Remoting Protocol (PSRP) sprechen und den Namen der Session Configuration (-ConfigurationName MonitoringJEA) mitgeben. Linux-Clients erreichen das über die Python-Library pypsrp; die ältere pywinrm-Library bedient die klassische WinRM-Shell, unterstützt aber keine benannten JEA-Endpoints. Welches Tool die Auswahl hinter den Kulissen trifft, dokumentiert das jeweilige Tool.
Default-Endpunkte härten¶
Warnung
Nur ausführen, nachdem (1) ein alternativer administrativer Zugang gesichert ist und (2) der JEA-Endpoint von aussen erfolgreich getestet wurde. Ein falsch gesetztes Deaktivieren der Default-Endpunkte sperrt den gesamten Remote-PowerShell-Zugriff auf den Host aus.
Nach abgeschlossenem JEA-Setup lassen sich die offenen Default-Endpunkte abschalten, damit Angreifer mit gekapertem Admin-Konto nicht die Standard-Shell nutzen können:
Disable-PSSessionConfiguration -Name Microsoft.PowerShell -Force
Disable-PSSessionConfiguration -Name Microsoft.PowerShell32 -Force
Disable-PSSessionConfiguration -Name Microsoft.PowerShell.Workflow -Force
Disable-PSSessionConfiguration -Name Microsoft.Windows.ServerManagerWorkflow -Force
Restart-Service -Name WinRM
Rollback in derselben Logik:
Enable-PSSessionConfiguration -Name Microsoft.PowerShell -Force
Enable-PSSessionConfiguration -Name Microsoft.PowerShell32 -Force
Enable-PSSessionConfiguration -Name Microsoft.PowerShell.Workflow -Force
Enable-PSSessionConfiguration -Name Microsoft.Windows.ServerManagerWorkflow -Force
Restart-Service -Name WinRM
Status aller Endpunkte:
Get-PSSessionConfiguration | Select-Object Name, Enabled
Troubleshooting¶
Die Symptome treffen im Alltag unabhängig davon zu, welches Tool auf der Linux-Seite verwendet wird. Die konkreten Fehlermeldungs-Wordings sind Tool-abhängig, die Ursachen dieselben.
- HTTP 401 Unauthorized beim Verbinden
Authentifizierung schlägt fehl. Bei NTLM User im Format
user@DOMAINoderDOMAIN\usersenden. Bei Kerberosklistkontrollieren und bei Bedarfkiniterneuern. Auf der Windows-Seitewinrm get winrm/config/service/authliefert die aktivierten Auth-Methoden.- HTTP 400 Bad Request beim Verbinden
Meist ein Transport-Mismatch: der Listener akzeptiert die gewählte Auth-Methode nicht. Bei Basic-Versuchen über HTTP prüfen, ob
AllowUnencryptedundBasicserverseitig aktiv sind, und ob der Client wirklich über HTTPS-Port 5986 mit gültigem Zertifikat spricht.- Session verbindet sich, das gewünschte Cmdlet kommt als
CommandNotFoundExceptionzurück Das ist kein Bug, sondern die Kern-Semantik eines JEA-Endpoints: nur in
VisibleCmdletsgelistete Cmdlets existieren in der Session. Prüfen, ob der Cmdlet-Name korrekt in der.psrcsteht.Register-PSSessionConfigurationmeldet „Die Datei kann nicht verarbeitet werden, weil die Role Capability nicht gefunden werden kann“Modul-Layout prüfen: das
.psd1liegt direkt unterModules\<Modulname>\, die.psrcunterModules\<Modulname>\RoleCapabilities\. Der Rollenname inRoleDefinitionsist der Dateiname ohne Suffix und ohne Pfad.- In der Session kommt
The syntax is not supported by this runspacezurück Der gewollte Effekt von
LanguageMode = 'NoLanguage'. Der Client darf nur freigegebene Cmdlets aufrufen - keine Variablenzuweisungen, keineif- oderforeach-Konstrukte, keine Expressions. Entweder das Kommando auf reine Cmdlet-Aufrufe eindampfen oder die komplexere Logik als Funktion in der.psrcfreigeben und von aussen nur noch diese Funktion aufrufen.- Cmdlets tauchen nicht auf, obwohl sie in
VisibleCmdletsstehen Das zugehörige PowerShell-Modul ist nicht importiert. In der
.psrcdas Modul unterModulesToImportaufnehmen oder das Standard-ModulMicrosoft.PowerShell.Managementbzw.Microsoft.PowerShell.Utilityergänzen.