Lägg till support för autentiseringsuppgifter in PowerShell-funktionerAdd Credential support to PowerShell functions

Anteckning

Den [ursprungliga versionen][] av den här artikeln visas på bloggen som skrivits av @joshduffney .The original version of this article appeared on the blog written by @joshduffney. Den här artikeln har redigerats för inkludering på den här webbplatsen.This article has been edited for inclusion on this site. PowerShell-teamet tack Josh för att dela det här innehållet med oss.The PowerShell team thanks Josh for sharing this content with us. Ta en titt på hans blogg på duffney.io.Please check out his blog at duffney.io.

Den här artikeln visar hur du lägger till parametrar för autentiseringsuppgifter till PowerShell-funktioner och varför du vill.This article shows you how to add credential parameters to PowerShell functions and why you'd want to. En parameter för autentiseringsuppgifter är att du ska kunna köra funktionen eller cmdleten som en annan användare.A credential parameter is to allow you to run the function or cmdlet as a different user. Den vanligaste användningen är att köra funktionen eller cmdleten som ett upphöjd användar konto.The most common use is to run the function or cmdlet as an elevated user account.

Till exempel har cmdleten New-ADUser en Credential -parameter, som du kan ange autentiseringsuppgifter för domän administratörer för att skapa ett konto i en domän.For example, the cmdlet New-ADUser has a Credential parameter, which you could provide domain admin credentials to create an account in a domain. Under förutsättning att det normala kontot som kör PowerShell-sessionen inte redan har den åtkomsten.Assuming your normal account running the PowerShell session doesn't have that access already.

Skapar Credential-objektCreating credential object

Objektet PSCredential representerar en uppsättning säkerhets referenser, till exempel användar namn och lösen ord.The PSCredential object represents a set of security credentials such as a user name and password. Objektet kan skickas som en parameter till en funktion som körs som användar konto i objektet Credential.The object can be passed as a parameter to a function that runs as the user account in that credential object. Det finns några sätt som du kan skapa ett Credential-objekt på.There are a few ways that you can create a credential object. Det första sättet att skapa ett Credential-objekt är att använda PowerShell-cmdleten Get-Credential .The first way to create a credential object is to use the PowerShell cmdlet Get-Credential. När du kör utan parametrar uppmanas du att ange ett användar namn och lösen ord.When you run without parameters, it prompts you for a username and password. Du kan också anropa cmdleten med några valfria parametrar.Or you can call the cmdlet with some optional parameters.

Om du vill ange domän namn och användar namn i förväg kan du antingen använda parametrarna Credential eller username .To specify the domain name and username ahead of time you can use either the Credential or UserName parameters. När du använder användar namns parametern måste du också ange ett meddelande värde.When you use the UserName parameter, you're also required to provide a Message value. Koden nedan visar hur du använder cmdleten.The code below demonstrates using the cmdlet. Du kan också lagra Credential-objektet i en variabel så att du kan använda autentiseringsuppgiften flera gånger.You can also store the credential object in a variable so that you can use the credential multiple times. I exemplet nedan lagras Credential-objektet i variabeln $Cred .In the example below, the credential object is stored in the variable $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 Credential-objekt som visas i föregående exempel.Sometimes, you can't use the interactive method of creating credential objects shown in the previous example. De flesta automatiserings verktyg kräver en icke-interaktiv metod.Most automation tools require a non-interactive method. Om du vill skapa en autentiseringsuppgift utan användar interaktion skapar du en säker sträng som innehåller lösen ordet.To create a credential without user interaction, create a secure string containing the password. Skicka sedan den säkra strängen och användar namnet till- System.Management.Automation.PSCredential() metoden.Then pass the secure string and user name to the System.Management.Automation.PSCredential() method.

Använd följande kommando för att skapa en säker sträng som innehåller lösen ordet:Use the following command to create a secure string containing the password:

ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force

Både egenskaperna för klartext och Force måste anges.Both the AsPlainText and Force parameters are required. Utan dessa parametrar får du en varning om att du inte ska skicka oformaterad text till en säker sträng.Without those parameters, you receive a message warning that you shouldn't pass plain text into a secure string. PowerShell returnerar denna varning eftersom lösen ordet för oformaterad text registreras i olika loggar.PowerShell returns this warning because the plain text password gets recorded in various logs. När du har skapat en säker sträng måste du skicka den till- PSCredential() metoden för att skapa Credential-objektet.Once you have a secure string created, you need to pass it to the PSCredential() method to create the credential object. I följande exempel innehåller variabeln $password den säkra strängen som $Cred innehåller objektet Credential.In the following example, the variable $password contains the secure string $Cred contains the credential object.

$password = ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ("username", $password)

Nu när du vet hur du skapar Credential-objekt kan du lägga till inloggnings parametrar till dina PowerShell-funktioner.Now that you know how to create credential objects, you can add credential parameters to your PowerShell functions.

Lägger till en Credential-parameterAdding a Credential Parameter

Precis som med andra parametrar börjar du med att lägga till den i param blockeringen av din funktion.Just like any other parameter, you start off by adding it in the param block of your function. Vi rekommenderar att du namnger parametern $Credential , eftersom det är det som befintliga PowerShell-cmdletar använder.It's recommended that you name the parameter $Credential because that's what existing PowerShell cmdlets use. Parameterns typ ska vara [System.Management.Automation.PSCredential] .The type of the parameter should be [System.Management.Automation.PSCredential].

I följande exempel visas parameter block för en funktion som kallas Get-Something .The following example shows the parameter block for a function called Get-Something. Det har två parametrar: $Name och $Credential .It has two parameters: $Name and $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 Credential-parameter, men det finns några saker som du kan lägga till för att göra den mer robust.The code in this example is enough to have a working credential parameter, however there are a few things you can add to make it more robust.

  • Lägg till [ValidateNotNull()] attributet verifiering för att kontrol lera att värdet skickas till autentiseringsuppgiften.Add the [ValidateNotNull()] validation attribute to check that the value being passed to Credential. Om parametervärdet är null förhindrar det här attributet funktionen från att köras med ogiltiga autentiseringsuppgifter.If the parameter value is null, this attribute prevents the function from executing with invalid credentials.

  • Lägg till [System.Management.Automation.Credential()] .Add [System.Management.Automation.Credential()]. På så sätt kan du skicka in ett användar namn som en sträng och ha en interaktiv prompt för lösen ordet.This allows you to pass in a username as a string and have an interactive prompt for the password.

  • Ange ett standardvärde för $Credential parametern till [System.Management.Automation.PSCredential]::Empty .Set a default value for the $Credential parameter to [System.Management.Automation.PSCredential]::Empty. Funktionen du kanske skickar det här $Credential objektet till befintliga PowerShell-cmdletar.Your function you might be passing this $Credential object to existing PowerShell cmdlets. Om du anger ett null-värde för cmdleten som anropas inuti funktionen uppstår ett fel.Providing a null value to the cmdlet called inside your function causes an error. Om du anger ett tomt Credential-objekt undviker du det här felet.Providing an empty credential object avoids this error.

Tips

Vissa cmdlets som accepterar en Credential-parameter stöder inte [System.Management.Automation.PSCredential]::Empty som de ska.Some cmdlets that accept a credential parameter do not support [System.Management.Automation.PSCredential]::Empty as they should. En lösning finns i avsnittet hantera med äldre cmdlets .See the Dealing with Legacy Cmdlets section for a workaround.

Använda Credential-parametrarUsing credential parameters

Följande exempel visar hur du använder Credential-parametrar.The following example demonstrates how to use credential parameters. I det här exemplet visas en funktion Set-RemoteRegistryValue som kallas, som ligger utanför pester-boken.This example shows a function called Set-RemoteRegistryValue, which is out of The Pester Book. Den här funktionen definierar Credential-parametern med hjälp av metoderna som beskrivs i föregående avsnitt.This function defines the credential parameter using the techniques describe in the previous section. Funktionen anropar Invoke-Command med $Credential variabeln som skapats av funktionen.The function calls Invoke-Command using the $Credential variable created by the function. På så sätt kan du ändra den användare som kör Invoke-Command .This allows you to change the user who's running Invoke-Command. Eftersom standardvärdet för $Credential är en tom autentiseringsuppgift kan funktionen köras utan att ange autentiseringsuppgifter.Because the default value of $Credential is an empty credential, the function can run without providing credentials.

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 för Set-RemoteRegistryValue .The following sections show different methods of providing credentials to Set-RemoteRegistryValue.

Fråga efter autentiseringsuppgifterPrompting for credentials

Get-CredentialAtt använda inom parentes () vid körningen gör Get-credential att körs först.Using Get-Credential in parentheses () at run time causes the Get-credential to run first. Du uppmanas att ange ett användar namn och lösen ord.You are prompted for a username and password. Du kan använda parametrarna Credential eller username för Get-credential att fylla i användar namnet och domänen i förväg.You could use the Credential or UserName parameters of Get-credential to pre-populate the username and domain. I följande exempel används en teknik som kallas ihopbuntning för att skicka parametrar till Set-RemoteRegistryValue funktionen.The following example uses a technique called splatting to pass parameters to the Set-RemoteRegistryValue function. Mer information om ihopbuntning finns i artikeln about_Splatting .For more information about splatting, check out the about_Splatting article.

$remoteKeyParams = @{
    ComputerName = $env:COMPUTERNAME
    Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
    Name = 'EnableRemoteManagement'
    Value = '1'
}

Set-RemoteRegistryValue @remoteKeyParams -Credential (Get-Credential)

Få en autentiseringsuppgift vid körning

Användningen (Get-Credential) verkar vara besvärlig.Using (Get-Credential) seems cumbersome. Normalt uppmanas du att ange lösen ordet när du använder parametern Credential med bara ett användar namn.Normally, when you use the Credential parameter with only a username, the cmdlet automatically prompts for the password. [System.Management.Automation.Credential()]Attributet aktiverar det här beteendet.The [System.Management.Automation.Credential()] attribute enables this behavior.

$remoteKeyParams = @{
    ComputerName = $env:COMPUTERNAME
    Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
    Name = 'EnableRemoteManagement'
    Value = '1'
}

Set-RemoteRegistryValue @remoteKeyParams -Credential duffney

Fråga efter autentiseringsuppgifter

Anteckning

Dessa exempel förutsätter att du har webb server funktionerna i Windows installerat för att ange registervärdet som visas.To set the registry value shown, these examples assume you have the Web Server features of Windows installed. Kör Install-WindowsFeature Web-Server och Install-WindowsFeature web-mgmt-tools om det behövs.Run Install-WindowsFeature Web-Server and Install-WindowsFeature web-mgmt-tools if required.

Ange autentiseringsuppgifter i en variabelProvide credentials in a variable

Du kan också fylla i en Credential-variabel i förväg och skicka den till parametern Credential för Set-RemoteRegistryValue funktionen.You can also populate a credential variable ahead of time and pass it to the Credential parameter of Set-RemoteRegistryValue function. Använd den här metoden med verktyg för kontinuerlig integrering/kontinuerlig distribution (CI/CD) som Jenkins, TeamCity och Octopus Deploy.Use this method with Continuous Integration / Continuous Deployment (CI/CD) tools such as Jenkins, TeamCity, and Octopus Deploy. Ett exempel på hur du använder Jenkins finns i blogg inlägget om att ta reda på Hodges blogg inlägg [med Jenkins och PowerShell på Windows-del 2][].For an example using Jenkins, check out Hodge's blog post Automating with Jenkins and PowerShell on Windows - Part 2.

I det här exemplet används .NET-metoden för att skapa Credential-objektet och en säker sträng för att skicka lösen ordet.This example uses the .NET method to create the credential object and a secure string to pass in the password.

$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 en säker sträng med ett lösen ord för klartext.For this example, the secure string is created using a clear text password. Alla tidigare angivna CI/CD-skivor har en säker metod för att ange lösen ordet vid körning.All of the previously mentioned CI/CD have a secure method of providing that password at run time. När du använder dessa verktyg ersätter du lösen ordet för klartext med den variabel som definierats i CI/CD-verktyget som du använder.When using those tools, replace the plain text password with the variable defined within the CI/CD tool you use.

Kör utan autentiseringsuppgifterRun without credentials

Eftersom $Credential standardvärdet är ett tomt Credential-objekt kan du köra kommandot utan autentiseringsuppgifter, som du ser i det här exemplet:Since $Credential defaults to an empty credential object, you can run the command without credentials, as shown in this example:

$remoteKeyParams = @{
    ComputerName = $env:COMPUTERNAME
    Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
    Name = 'EnableRemoteManagement'
    Value = '1'
}

Set-RemoteRegistryValue @remoteKeyParams

Hantera äldre cmdletsDealing with legacy cmdlets

Alla cmdlets stöder inte Credential-objekt eller Tillåt tomma autentiseringsuppgifter.Not all cmdlets support credential objects or allow empty credentials. I stället vill cmdleten användar namn och lösen ord parametrar som strängar.Instead, the cmdlet wants username and password parameters as strings. Det finns några sätt att kringgå den här begränsningen.There are a few ways to work around this limitation.

Använda if-else för att hantera tomma autentiseringsuppgifterUsing if-else to handle empty credentials

I det här scenariot accepterar inte den cmdlet som du vill köra ett tomt Credential-objekt.In this scenario, the cmdlet you want to run doesn't accept an empty credential object. I det här exemplet läggs parametern Credential till Invoke-Command endast om den inte är tom.This example adds the Credential parameter to Invoke-Command only if it's not empty. Annars körs den Invoke-Command utan parametern Credential .Otherwise, it runs the Invoke-Command without the Credential parameter.

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 ihopbuntning för att hantera tomma autentiseringsuppgifterUsing splatting to handle empty credentials

I det här exemplet används parametern ihopbuntning för att anropa den äldre cmdleten.This example uses parameter splatting to call the legacy cmdlet. $CredentialObjektet läggs villkorligt till i hash-tabellen för ihopbuntning och gör att du inte behöver upprepa Invoke-Command skript blocket.The $Credential object is conditionally added to the hash table for splatting and avoids the need to repeat the Invoke-Command script block. Mer information om ihopbuntning inuti Functions finns i [ihopbuntning-parametrarna inuti avancerade funktioner][] blogg inlägg.To learn more about splatting inside functions, see the Splatting Parameters Inside Advanced Functions blog post.

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äng lösen ordWorking with string passwords

Invoke-SqlcmdCmdlet är ett exempel på en cmdlet som accepterar en sträng som ett lösen ord.The Invoke-Sqlcmd cmdlet is an example of a cmdlet that accepts a string as a password. Invoke-Sqlcmd gör att du kan köra enkla SQL INSERT-, Update-och Delete-instruktioner.Invoke-Sqlcmd allows you to run simple SQL insert, update, and delete statements. Invoke-Sqlcmd kräver ett användar namn och lösen ord i klartext i stället för ett säkrare Credential-objekt.Invoke-Sqlcmd requires a clear-text username and password rather than a more secure credential object. Det här exemplet visar hur du extraherar användar namnet och lösen ordet från ett Credential-objekt.This example shows how to extract the username and password from a credential object.

Get-AllSQLDatabasesFunktionen i det här exemplet anropar Invoke-Sqlcmd cmdleten för att fråga en SQL-Server för alla dess databaser.The Get-AllSQLDatabases function in this example calls the Invoke-Sqlcmd cmdlet to query a SQL server for all its databases. Funktionen definierar en Credential -parameter med samma attribut som användes i föregående exempel.The function defines a Credential parameter with the same attribute used in the previous examples. Eftersom användar namnet och lösen ordet finns i $Credential variabeln kan du extrahera dessa värden för användning med Invoke-Sqlcmd .Since the username and password exist within the $Credential variable, you can extract those values for use with Invoke-Sqlcmd.

Användar namnet är tillgängligt från egenskapen username för $Credential variabeln.The user name is available from the UserName property of the $Credential variable. För att få lösen ordet måste du använda- GetNetworkCredential() metoden för $Credential objektet.To obtain the password, you have to use the GetNetworkCredential() method of the $Credential object. Värdena extraheras till variabler som läggs till i en hash-tabell som används för ihopbuntning-parametrar till Invoke-Sqlcmd .The values are extracted into variables that are added to a hash table used for splatting parameters to 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
ConvertTo-SecureString -AsPlainText -Force)

Get-AllSQLDatabases -SQLServer SQL01 -Credential $Credential

Hantering av fortsatt inlärning av autentiseringsuppgifterContinued learning credential management

Det kan vara svårt att skapa och lagra Credential-objekt på ett säkert sätt.Creating and storing credential objects securely can be difficult. Följande resurser kan hjälpa dig att underhålla PowerShell-autentiseringsuppgifter.The following resources can help you maintain PowerShell credentials.