Lägg till support för autentiseringsuppgifter in PowerShell-funktioner
Kommentar
Den ursprungliga versionen av den här artikeln visades på bloggen skriven av @joshduffney. Den här artikeln har redigerats för inkludering på den här webbplatsen. PowerShell-teamet tackar Josh för att ha delat det här innehållet med oss. Kolla in hans blogg på duffney.io.
Den här artikeln visar hur du lägger till autentiseringsparametrar i PowerShell-funktioner och varför du vill det. En parameter för autentiseringsuppgifter är att du kan köra funktionen eller cmdleten som en annan användare. Den vanligaste användningen är att köra funktionen eller cmdleten som ett förhöjt användarkonto.
Cmdleten New-ADUser
har till exempel en parameter för autentiseringsuppgifter , som du kan ange autentiseringsuppgifter för domänadministratör för att skapa ett konto i en domän. Förutsatt att ditt normala konto som kör PowerShell-sessionen inte redan har den åtkomsten.
Skapa autentiseringsobjekt
PSCredential-objektet representerar en uppsättning säkerhetsautentiseringsuppgifter, till exempel användarnamn och lösenord. Objektet kan skickas som en parameter till en funktion som körs som användarkonto i det autentiseringsobjektet. Det finns några sätt att skapa ett autentiseringsobjekt. Det första sättet att skapa ett autentiseringsobjekt är att använda PowerShell-cmdleten Get-Credential
. När du kör utan parametrar uppmanas du att ange ett användarnamn och lösenord. Eller så kan du anropa cmdleten med några valfria parametrar.
Om du vill ange domännamnet och användarnamnet i förväg kan du använda parametrarna Autentiseringsuppgifter eller Användarnamn . När du använder parametern UserName måste du också ange ett meddelandevärde . Koden nedan visar hur du använder cmdleten. Du kan också lagra objektet för autentiseringsuppgifter i en variabel så att du kan använda autentiseringsuppgifterna flera gånger. I exemplet nedan lagras objektet för autentiseringsuppgifter i variabeln $Cred
.
$Cred = Get-Credential
$Cred = Get-Credential -Credential domain\user
$Cred = Get-Credential -UserName domain\user -Message 'Enter Password'
Ibland kan du inte använda den interaktiva metoden för att skapa autentiseringsobjekt som visas i föregående exempel. De flesta automatiseringsverktyg kräver en icke-interaktiv metod. Om du vill skapa en autentiseringsuppgift utan användarinteraktion skapar du en säker sträng som innehåller lösenordet. Skicka sedan den säkra strängen och användarnamnet System.Management.Automation.PSCredential()
till metoden.
Använd följande kommando för att skapa en säker sträng som innehåller lösenordet:
ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force
Både parametrarna AsPlainText och Force krävs. Utan dessa parametrar får du ett meddelande om att du inte ska skicka oformaterad text till en säker sträng. PowerShell returnerar den här varningen eftersom lösenordet för oformaterad text registreras i olika loggar. När du har skapat en säker sträng måste du skicka den till PSCredential()
metoden för att skapa objektet för autentiseringsuppgifter. I följande exempel innehåller variabeln $password
den säkra strängen $Cred
som innehåller autentiseringsobjektet.
$password = ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ("username", $password)
Nu när du vet hur du skapar autentiseringsobjekt kan du lägga till parametrar för autentiseringsuppgifter i dina PowerShell-funktioner.
Lägga till en parameter för autentiseringsuppgifter
Precis som andra parametrar börjar du med att lägga till den i funktionsblocket param
.
Vi rekommenderar att du namnger parametern $Credential
eftersom det är vad befintliga PowerShell-cmdletar använder. Parametertypen ska vara [System.Management.Automation.PSCredential]
.
I följande exempel visas parameterblocket för en funktion med namnet Get-Something
. Den har två parametrar: $Name
och $Credential
.
function Get-Something {
param(
$Name,
[System.Management.Automation.PSCredential]$Credential
)
Koden i det här exemplet räcker för att ha en fungerande parameter för autentiseringsuppgifter, men det finns några saker du kan lägga till för att göra den mer robust.
Lägg till verifieringsattributet
[ValidateNotNull()]
för att kontrollera att värdet skickas till autentiseringsuppgifter. Om parametervärdet är null förhindrar det här attributet att funktionen körs med ogiltiga autentiseringsuppgifter.Lägg till
[System.Management.Automation.Credential()]
. På så sätt kan du skicka in ett användarnamn som en sträng och ha en interaktiv fråga efter lösenordet.Ange ett standardvärde för parametern
$Credential
till[System.Management.Automation.PSCredential]::Empty
. Din funktion som du kanske skickar det här$Credential
objektet till befintliga PowerShell-cmdletar. Om du anger ett null-värde för cmdleten som anropas i funktionen uppstår ett fel. Om du anger ett tomt autentiseringsobjekt undviker du det här felet.
Dricks
Vissa cmdletar som accepterar en parameter för autentiseringsuppgifter stöder [System.Management.Automation.PSCredential]::Empty
inte som de ska. Se avsnittet Hantera äldre cmdletar för en lösning.
Använda parametrar för autentiseringsuppgifter
I följande exempel visas hur du använder parametrar för autentiseringsuppgifter. I det här exemplet visas en funktion med namnet Set-RemoteRegistryValue
, som inte finns i Pester-boken. Den här funktionen definierar parametern för autentiseringsuppgifter med hjälp av de tekniker som beskrivs i föregående avsnitt. Funktionen anropar Invoke-Command
med hjälp av variabeln $Credential
som skapats av funktionen. På så sätt kan du ändra användaren som kör Invoke-Command
. Eftersom standardvärdet $Credential
för är en tom autentiseringsuppgift kan funktionen köras utan att ange autentiseringsuppgifter.
function Set-RemoteRegistryValue {
param(
$ComputerName,
$Path,
$Name,
$Value,
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
$null = Invoke-Command -ComputerName $ComputerName -ScriptBlock {
Set-ItemProperty -Path $using:Path -Name $using:Name -Value $using:Value
} -Credential $Credential
}
I följande avsnitt visas olika metoder för att ange autentiseringsuppgifter till Set-RemoteRegistryValue
.
Fråga efter autentiseringsuppgifter
Att använda Get-Credential
inom parenteser ()
vid körning gör att körningen Get-credential
först. Du uppmanas att ange ett användarnamn och lösenord. Du kan använda parametrarna Get-credential
Credential eller UserName för för att fylla i användarnamnet och domänen i förväg. I följande exempel används en teknik som kallas splatting för att skicka parametrar till Set-RemoteRegistryValue
funktionen. Mer information om splatting finns i artikeln about_Splatting .
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams -Credential (Get-Credential)
Att använda (Get-Credential)
verkar besvärligt. När du använder parametern Credential med endast ett användarnamn uppmanas cmdleten automatiskt att ange lösenordet. Attributet [System.Management.Automation.Credential()]
aktiverar det här beteendet.
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams -Credential duffney
Kommentar
För att ange registervärdet som visas förutsätter dessa exempel att du har webbserverfunktionerna i Windows installerade. Kör Install-WindowsFeature Web-Server
och Install-WindowsFeature web-mgmt-tools
om det behövs.
Ange autentiseringsuppgifter i en variabel
Du kan också fylla i en variabel för autentiseringsuppgifter i förväg och skicka den till parametern Set-RemoteRegistryValue
Credential för funktionen. Använd den här metoden med CI/CD-verktyg (Continuous Integration/Continuous Deployment), till exempel Jenkins, TeamCity och Octopus Deploy. Ett exempel med Jenkins finns i Hodges blogginlägg Automatisera med Jenkins och PowerShell i Windows – del 2.
I det här exemplet används .NET-metoden för att skapa autentiseringsobjektet och en säker sträng för att skicka in lösenordet.
$password = ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ("duffney", $password)
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams -Credential $Cred
I det här exemplet skapas den säkra strängen med ett lösenord för klartext. Alla tidigare nämnda CI/CD har en säker metod för att ange lösenordet vid körning. När du använder dessa verktyg ersätter du lösenordet för oformaterad text med variabeln som definierats i CI/CD-verktyget som du använder.
Kör utan autentiseringsuppgifter
Eftersom $Credential
standardvärdet är ett tomt autentiseringsobjekt kan du köra kommandot utan autentiseringsuppgifter, som du ser i det här exemplet:
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams
Hantera äldre cmdletar
Alla cmdletar stöder inte autentiseringsobjekt eller tillåter tomma autentiseringsuppgifter. I stället vill cmdleten ha parametrar för användarnamn och lösenord som strängar. Det finns några sätt att kringgå den här begränsningen.
Använda if-else för att hantera tomma autentiseringsuppgifter
I det här scenariot accepterar inte den cmdlet som du vill köra ett tomt autentiseringsobjekt. Det här exemplet lägger bara till parametern Credential om Invoke-Command
den inte är tom. Annars körs parametern Invoke-Command
utan autentiseringsuppgifter .
function Set-RemoteRegistryValue {
param(
$ComputerName,
$Path,
$Name,
$Value,
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
if($Credential -ne [System.Management.Automation.PSCredential]::Empty) {
Invoke-Command -ComputerName:$ComputerName -Credential:$Credential {
Set-ItemProperty -Path $using:Path -Name $using:Name -Value $using:Value
}
} else {
Invoke-Command -ComputerName:$ComputerName {
Set-ItemProperty -Path $using:Path -Name $using:Name -Value $using:Value
}
}
}
Använda splatting för att hantera tomma autentiseringsuppgifter
I det här exemplet används parametersplatting för att anropa den äldre cmdleten. Objektet $Credential
läggs villkorligt till i hash-tabellen för splatting och undviker behovet av att upprepa skriptblocket Invoke-Command
. Mer information om att splatta inuti funktioner finns i blogginlägget Splatting Parameters Inside Advanced Functions (Splatting Parameters Inside Advanced Functions ).
function Set-RemoteRegistryValue {
param(
$ComputerName,
$Path,
$Name,
$Value,
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
$Splat = @{
ComputerName = $ComputerName
}
if ($Credential -ne [System.Management.Automation.PSCredential]::Empty) {
$Splat['Credential'] = $Credential
}
$null = Invoke-Command -ScriptBlock {
Set-ItemProperty -Path $using:Path -Name $using:Name -Value $using:Value
} @splat
}
Arbeta med stränglösenord
Cmdleten Invoke-Sqlcmd
är ett exempel på en cmdlet som accepterar en sträng som ett lösenord.
Invoke-Sqlcmd
gör att du kan köra enkla SQL-infognings-, uppdaterings- och borttagningsinstruktioner. Invoke-Sqlcmd
kräver ett användarnamn och lösenord i klartext i stället för ett säkrare autentiseringsobjekt. Det här exemplet visar hur du extraherar användarnamnet och lösenordet från ett autentiseringsobjekt.
Funktionen Get-AllSQLDatabases
i det här exemplet anropar cmdleten Invoke-Sqlcmd
för att fråga en SQL-server om alla dess databaser. Funktionen definierar en parameter för autentiseringsuppgifter med samma attribut som används i föregående exempel. Eftersom användarnamnet och lösenordet finns i variabeln $Credential
kan du extrahera dessa värden för användning med Invoke-Sqlcmd
.
Användarnamnet är tillgängligt från egenskapen UserName för variabeln $Credential
. För att få lösenordet måste du använda GetNetworkCredential()
-metoden för $Credential
objektet. Värdena extraheras till variabler som läggs till i en hash-tabell som används för att splatta parametrar till Invoke-Sqlcmd
.
function Get-AllSQLDatabases {
param(
$SQLServer,
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
$UserName = $Credential.UserName
$Password = $Credential.GetNetworkCredential().Password
$splat = @{
UserName = $UserName
Password = $Password
ServerInstance = 'SQLServer'
Query = "Select * from Sys.Databases"
}
Invoke-Sqlcmd @splat
}
$credSplat = @{
TypeName = 'System.Management.Automation.PSCredential'
ArgumentList = 'duffney',('P@ssw0rd' | ConvertTo-SecureString -AsPlainText -Force)
}
$Credential = New-Object @credSplat
Get-AllSQLDatabases -SQLServer SQL01 -Credential $Credential
Hantering av kontinuerlig inlärning av autentiseringsuppgifter
Det kan vara svårt att skapa och lagra autentiseringsobjekt på ett säkert sätt. Följande resurser kan hjälpa dig att underhålla PowerShell-autentiseringsuppgifter.