Sichere Automatisierung - Credentials in PowerShell verwalten
Einleitung - Die Herausforderung der Automatisierung
Hardcodierte Benutzernamen und Passwörter in Skripten stellen ein massives Sicherheitsrisiko dar (“Clear Text Passwords”). Während interaktive Skripte Anmeldedaten sicher via Get-Credential abfragen können, fehlt diese Möglichkeit bei automatisierten Aufgaben (z. B. im Task Scheduler).
Wie speichert man Credentials sicher, sodass ein Skript sie entschlüsseln kann, ein Unbefugter jedoch nicht? PowerShell bietet hierfür zwei Lösungswege.
Interaktive Skripte können natürlich zur Laufzeit die Anmeldedaten über Get-Credential vom Benutzer abfragen. Vorteil ist hier, dass die Daten nicht im Klartext im Skript hinterlegt werden müssen, für unbeaufsichtigt laufende Skripte funktioniert das leider so nicht. Automatisch ausgeführte Skripte benötigen einen Speicherort, an dem sie das Credential-Objekt sicher abrufen können. Idealerweise passiert das natürlich verschlüsselt.
PowerShell selbst bietet uns dafür sogar zwei mehr oder weniger nützliche Wege. Der erste und einfachste Weg ist das speichern der Credentials in einer externen XML Datei.
1
Get-Credential | Export-Clixml -Path "C:\temp\Credentials.xml"
Mit dem entsprechenden Import Kommando lassen sich die Credentials dann auch wieder in einem Skript nutzen.
1
2
3
$Cred = Import-Clixml -Path "C:\temp\Credentials.xml"
Write-Host "Benutzer: " $Cred.UserName
Write-Host "Password: " $Cred.GetNetworkCredential().Password
Vorteil:
- Super einfach anzuwenden und verschlüsselt.
Nachteil:
Export-Clixmlserialisiert das Objekt. Da der UserName ein einfacher String ist, bleibt er in der Datei im Klartext lesbar. Das Password ist ein SecureString und wird daher durch die DPAPI (Data Protection API von Windows) verschlüsselt. Damit kann nur der Benutzer der die Credentials exportiert hat und auch nur auf der Maschine auf der diese XML Datei exportiert wurde, das Passwort entschlüsseln.- Das macht die XML Datei relativ sicher, ohne sich um eine komplexe Kryptografie kümmern zu müssen. Allerdings kann die XML Datei auch nicht mehr mit anderen geteilt werden.
- Ein weiterer Nachteil aus der Praxis ist, dass ich für jedes Credential Objekt eine eigene XML Datei anlegen muss oder vor dem Export alles in eine Hashtable schreiben muss.
1
2
3
4
5
6
7
8
9
10
11
12
# Beispiel mit zwei Credentials
$cred1 = Get-Credential -Message "Bitte erstes Credential eingeben"
$cred2 = Get-Credential -Message "Bitte zweites Credential eingeben"
# In eine Hashtable speichern
$allCreds = @{
"SQL" = $cred1
"API" = $cred2
}
# Exportieren
$allCreds | Export-Clixml -Path "C:\temp\multiCredentials.xml"
In einem Skript lässt sich das dann wieder laden.
1
2
3
$allCreds = Import-Clixml -Path "C:\temp\multiCredentials.xml"
$allCreds["SQL"].UserName
$allCreds["API"].GetNetworkCredential().Password
Etwas praktikabler geht es mit einem Passwort Vault, welcher von Microsoft auch in einem entsprechenden Modul umgesetzt wurde.
Das PowerShell SecretManagement Modul bietet uns eine Abstraktionsschicht, um Benutzernamen und Passwörter sicher zu speichern und auch wieder sicher abzurufen und ist gerade für wiederkehrende Aufgaben (Task Scheduler) gedacht, da dort ja keine Benutzerinteraktion möglich ist.
Ähnlich wie vorher, wird dieser Vault über die in Windows enthaltene DPAPI verschlüsselt und ist ausschließlich von dem Benutzer und der Maschine die den Vault erstellt haben nutzbar (AES bzw. TripleDES abhängig von der Windows Version).
Das Modul Microsoft.PowerShell.SecretStore speichert die Credentials lokal. Für die automatische Ausführung z.B. über den Task Scheduler (Non-Interactive) müssen wir den Vault so konfigurieren, dass er kein Passwort zur Entsperrung verlangt, sondern den Kontext des ausführenden Benutzers (z.B. ein Service Account) nutzt. Standardmäßig wird der Vault sonst mit einem Master-Passwort geschützt, in diesem Fall lässt sich ein Skript natürlich wieder nur Interaktiv verwenden.
Das SecretManagement-Modul ist nur die Schnittstelle. Um Daten lokal zu speichern, benötigen wir zusätzlich einen Extension Vault wie den SecretStore.
1
2
3
4
5
6
7
8
9
10
11
12
13
# Installation der beiden benötigten Module
Install-Module Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore -Scope CurrentUser
# Registrierung des Vaults für den Task Scheduler
# WICHTIG: 'DoNotRequirePassword' nutzt DPAPI (User Context) zur Verschlüsselung
$VaultParams = @{
DoNotRequirePassword = $true
}
Register-SecretVault -Name "AutoTaskVault" -ModuleName Microsoft.PowerShell.SecretStore -VaultParameters $VaultParams
# Speichern des Geheimnisses (z.B. API-Key oder Passwort)
$SecureString = Read-Host -AsSecureString "Bitte Passwort eingeben"
Set-Secret -Name "DbAccess" -Secret $SecureString -Vault "AutoTaskVault"
Im Skript, das dann vom Task Scheduler ausgeführt wird, sind keine Credentials sichtbar. Und auch der Vault auf dem entsprechenden System ist nicht so einfach kopierbar.
1
2
3
4
5
6
7
8
# Abruf der Credentials zur Laufzeit
$Creds = Get-Secret -Name "DbAccess" -AsPSCredential -Vault "AutoTaskVault" -ErrorAction Stop
if ($Creds) {
# Connect-SQLServer ...
} else {
Write-Warning "Keine Credentials im Vault gefunden."
}
Vorteile:
- Skripte können damit auch einfach versioniert werden (Git), ohne Geheimnisse zu leaken.
- Der Backend-Speicher (Vault) kann getauscht werden, ohne das Skript zu ändern.
- Die Credentials lassen sich einfach verwalten. Es können sowohl zusätzliche Secrets hinzugefügt, aber auch Secrets gelöscht oder geändert werden.
1
2
3
4
5
6
7
8
9
# Secrets auflisten
Get-Secret
Get-SecretInfo
# Secret löschen
Remove-Secret -Name "Dbaccess"
# Secret ändern - bestehendes Secret einfach überschreiben
Set-Secret -Name "Dbaccess" -Secret (Get-Credential)
Nachteile & Risiken:
- DPAPI Abhängigkeit: Da wir
DoNotRequirePasswordnutzen, basiert die Sicherheit rein auf dem Windows-Benutzerprofil. Wenn ein Angreifer diesen Account kompromittiert, hat er Zugriff auf den Vault. Jeder Prozess, der unter diesem Benutzer läuft, kann das Passwort auslesen. Fängt man sich Schadcode ein, der unter diesem User läuft, ist der Vault offen. - User-Kontext: Der Task im Task Scheduler muss unter exakt demselben Account laufen, der den Vault erstellt hat. Der verschlüsselte Vault kann nur auf dem gleichen Rechner und unter dem gleichen Benutzerkonto wieder entschlüsselt werden.
Vergleich der Lösungen
| Kriterium | SecretManagement Modul | Export-Clixml |
|---|---|---|
| Skalierbarkeit | Sehr gut – geeignet für große Umgebungen und Automatisierung | Gering – eher für Einzelplatz oder kleine Skripte |
| Typen von Secrets | Strings, SecureStrings, PSCredentials, komplexe Objekte | PSCredentials und einfache Objekte |
| Verwaltung | Vollständig – Hinzufügen, Aktualisieren, Löschen, Auflisten | Nur Export und Import möglich |
| Integration | Nahtlos mit sicheren Vault und CI/CD-Pipelines | Keine native Integration mit externen Vaults |
| Einrichtung | Erfordert Installation des Moduls und Konfiguration eines Vault | Keine zusätzliche Einrichtung nötig |
| Best Practice | Für produktive Umgebungen und Automatisierung | Für einfache lokale Skripte oder Testzwecke |
Alternativen
- Nutzung eines Remote-Vaults: Z.B. Azure Key Vault oder Hshicorp Vault (Empfohlen für Enterprise). Sicherer, da Access Policies und Audit Logs existieren sowie Zertifikats-Authentifizierung für den Zugriff möglich ist. Damit sind diese Vaults universell im Team nutzbar, benötigen aber auch Zugriff auf das Internet.
- Passwordmanager: Diverse Passwort-Manager (z.B. KeePass) bieten auch eine API auf die mit PowerShell zugegriffen werden kann. Oft ist eine Implementierung aber deutlich komplexer als die vorher beschriebenen Varianten.
- GMSA (Group Managed Service Accounts): Für Server-zu-Server-Kommunikation oft die sicherste Methode, da Windows das Passwort-Management komplett übernimmt (kein
Get-Secretnötig). Für Skripte aber eher ungeeignet.
Fazit
Nutzen Sie Export-Clixml nur für temporäre lokale Tests. Stellen Sie für alle produktiven Task-Scheduler-Aufgaben auf das SecretManagement-Modul um. Es ist zukunftssicherer, da Sie das Backend (z. B. Wechsel zu Azure KeyVault) später austauschen können, ohne Ihr Skript umschreiben zu müssen.
