Dodawanie obsługi poświadczeń do funkcji programu PowerShellAdd Credential support to PowerShell functions

Uwaga

[Oryginalna wersja][] tego artykułu pojawiła się w blogu zapisanym przez program @joshduffney .The original version of this article appeared on the blog written by @joshduffney. Ten artykuł został zmodyfikowany w celu dołączenia do tej witryny.This article has been edited for inclusion on this site. Zespół programu PowerShell Dziękujemy za udostępnienie tej zawartości firmie Josh.The PowerShell team thanks Josh for sharing this content with us. Zapoznaj się z blogiem w witrynie duffney.IO.Please check out his blog at duffney.io.

W tym artykule opisano sposób dodawania parametrów poświadczeń do funkcji programu PowerShell i przyczyn.This article shows you how to add credential parameters to PowerShell functions and why you'd want to. Parametr Credential umożliwia uruchomienie funkcji lub polecenia cmdlet jako innego użytkownika.A credential parameter is to allow you to run the function or cmdlet as a different user. Najbardziej typowym zastosowaniem jest uruchomienie funkcji lub polecenia cmdlet jako konta użytkownika z podwyższonym poziomem uprawnień.The most common use is to run the function or cmdlet as an elevated user account.

Na przykład polecenie cmdlet New-ADUser ma parametr Credential , który można podać poświadczenia administratora domeny, aby utworzyć konto w domenie.For example, the cmdlet New-ADUser has a Credential parameter, which you could provide domain admin credentials to create an account in a domain. Zakładając, że normalne konto, na którym działa sesja programu PowerShell, nie ma już dostępu.Assuming your normal account running the PowerShell session doesn't have that access already.

Tworzenie obiektu poświadczeńCreating credential object

Obiekt PSCredential reprezentuje zestaw poświadczeń zabezpieczeń, takich jak nazwa użytkownika i hasło.The PSCredential object represents a set of security credentials such as a user name and password. Obiekt może być przesłany jako parametr do funkcji, która jest uruchamiana jako konto użytkownika w tym obiekcie poświadczeń.The object can be passed as a parameter to a function that runs as the user account in that credential object. Istnieje kilka sposobów tworzenia obiektu Credential.There are a few ways that you can create a credential object. Pierwszym sposobem utworzenia obiektu Credential jest użycie polecenia cmdlet programu PowerShell Get-Credential .The first way to create a credential object is to use the PowerShell cmdlet Get-Credential. Po uruchomieniu bez parametrów zostanie wyświetlony komunikat z prośbą o nazwę użytkownika i hasło.When you run without parameters, it prompts you for a username and password. Lub można wywołać polecenie cmdlet z niektórymi opcjonalnymi parametrami.Or you can call the cmdlet with some optional parameters.

Aby określić nazwy domeny i nazwę użytkownika przed czasem, możesz użyć poświadczeń lub parametrów username .To specify the domain name and username ahead of time you can use either the Credential or UserName parameters. W przypadku użycia parametru username należy również podać wartość komunikatu .When you use the UserName parameter, you're also required to provide a Message value. Poniższy kod ilustruje użycie polecenia cmdlet.The code below demonstrates using the cmdlet. Możesz również przechowywać obiekt Credential w zmiennej, aby można było używać poświadczeń wiele razy.You can also store the credential object in a variable so that you can use the credential multiple times. W poniższym przykładzie obiekt Credential jest przechowywany w zmiennej $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'

Czasami nie można użyć interaktywnej metody tworzenia obiektów poświadczeń pokazanych w poprzednim przykładzie.Sometimes, you can't use the interactive method of creating credential objects shown in the previous example. Większość narzędzi automatyzacji wymaga metody nieinteraktywnej.Most automation tools require a non-interactive method. Aby utworzyć poświadczenie bez interakcji z użytkownikiem, Utwórz bezpieczny ciąg zawierający hasło.To create a credential without user interaction, create a secure string containing the password. Następnie Przekaż bezpieczny ciąg i nazwę użytkownika do System.Management.Automation.PSCredential() metody.Then pass the secure string and user name to the System.Management.Automation.PSCredential() method.

Użyj następującego polecenia, aby utworzyć bezpieczny ciąg zawierający hasło:Use the following command to create a secure string containing the password:

ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force

Parametry AsPlainText i Force są wymagane.Both the AsPlainText and Force parameters are required. Bez tych parametrów zostanie wyświetlone ostrzeżenie informujące o tym, że nie należy przekazywać zwykłego tekstu do bezpiecznego ciągu.Without those parameters, you receive a message warning that you shouldn't pass plain text into a secure string. Program PowerShell zwraca to ostrzeżenie, ponieważ hasło w postaci zwykłego tekstu jest rejestrowane w różnych dziennikach.PowerShell returns this warning because the plain text password gets recorded in various logs. Po utworzeniu bezpiecznego ciągu musisz przekazać go do PSCredential() metody, aby utworzyć obiekt Credential.Once you have a secure string created, you need to pass it to the PSCredential() method to create the credential object. W poniższym przykładzie zmienna $password zawiera bezpieczny ciąg $Cred zawiera obiekt 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)

Teraz, gdy wiesz już, jak tworzyć obiekty poświadczeń, możesz dodać parametry poświadczeń do funkcji programu PowerShell.Now that you know how to create credential objects, you can add credential parameters to your PowerShell functions.

Dodawanie parametru CredentialAdding a Credential Parameter

Podobnie jak każdy inny parametr, możesz zacząć od dodania go w param bloku funkcji.Just like any other parameter, you start off by adding it in the param block of your function. Zaleca się, aby nazwać parametr, $Credential ponieważ są używane istniejące polecenia cmdlet programu PowerShell.It's recommended that you name the parameter $Credential because that's what existing PowerShell cmdlets use. Typ parametru powinien być typem [System.Management.Automation.PSCredential] .The type of the parameter should be [System.Management.Automation.PSCredential].

Poniższy przykład pokazuje Blok parametrów dla funkcji o nazwie Get-Something .The following example shows the parameter block for a function called Get-Something. Ma dwa parametry: $Name i $Credential .It has two parameters: $Name and $Credential.

function Get-Something {
    param(
        $Name,
        [System.Management.Automation.PSCredential]$Credential
    )

Kod w tym przykładzie wystarcza do posiadania działającego parametru poświadczeń, ale istnieje kilka rzeczy, które można dodać, aby zwiększyć jego niezawodność.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.

  • Dodaj [ValidateNotNull()] atrybut walidacji, aby sprawdzić, czy wartość jest przesyłana do poświadczenia.Add the [ValidateNotNull()] validation attribute to check that the value being passed to Credential. Jeśli parametr ma wartość null, ten atrybut uniemożliwia wykonywanie funkcji z nieprawidłowymi poświadczeniami.If the parameter value is null, this attribute prevents the function from executing with invalid credentials.

  • Dodaj [System.Management.Automation.Credential()] .Add [System.Management.Automation.Credential()]. Dzięki temu można przekazać nazwę użytkownika jako ciąg i uzyskać interaktywny monit o podanie hasła.This allows you to pass in a username as a string and have an interactive prompt for the password.

  • Ustaw wartość domyślną dla $Credential parametru na [System.Management.Automation.PSCredential]::Empty .Set a default value for the $Credential parameter to [System.Management.Automation.PSCredential]::Empty. Funkcja może przekazywać ten $Credential obiekt do istniejących poleceń cmdlet programu PowerShell.Your function you might be passing this $Credential object to existing PowerShell cmdlets. Podanie wartości null do polecenia cmdlet wywoływanego wewnątrz funkcji powoduje wystąpienie błędu.Providing a null value to the cmdlet called inside your function causes an error. Podawanie pustego obiektu poświadczeń pozwala uniknąć tego błędu.Providing an empty credential object avoids this error.

Porada

Niektóre polecenia cmdlet, które akceptują parametr poświadczeń, nie obsługują takich funkcji [System.Management.Automation.PSCredential]::Empty jak te.Some cmdlets that accept a credential parameter do not support [System.Management.Automation.PSCredential]::Empty as they should. Zapoznaj się z sekcją Rozwiązywanie problemów ze starszymi poleceniami cmdlet .See the Dealing with Legacy Cmdlets section for a workaround.

Korzystanie z parametrów poświadczeńUsing credential parameters

Poniższy przykład ilustruje sposób używania parametrów poświadczeń.The following example demonstrates how to use credential parameters. Ten przykład pokazuje funkcję o nazwie Set-RemoteRegistryValue , która znajduje się poza [książką szkodników][].This example shows a function called Set-RemoteRegistryValue, which is out of The Pester Book. Ta funkcja definiuje parametr Credential przy użyciu technik opisanych w poprzedniej sekcji.This function defines the credential parameter using the techniques describe in the previous section. Funkcja wywołuje Invoke-Command przy użyciu $Credential zmiennej utworzonej przez funkcję.The function calls Invoke-Command using the $Credential variable created by the function. Pozwala to na zmianę uruchomionego użytkownika Invoke-Command .This allows you to change the user who's running Invoke-Command. Ponieważ wartością domyślną $Credential jest puste poświadczenie, funkcja może zostać uruchomiona bez podawania poświadczeń.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
}

W poniższych sekcjach przedstawiono różne metody przekazywania poświadczeń do programu Set-RemoteRegistryValue .The following sections show different methods of providing credentials to Set-RemoteRegistryValue.

Monitowanie o poświadczeniaPrompting for credentials

Użycie Get-Credential w nawiasach w () czasie wykonywania powoduje Get-credential pierwsze uruchomienie.Using Get-Credential in parentheses () at run time causes the Get-credential to run first. Zostanie wyświetlony monit o podanie nazwy użytkownika i hasła.You are prompted for a username and password. Możesz użyć poświadczeń lub parametrów username , Get-credential Aby wstępnie wypełnić nazwę użytkownika i domenę.You could use the Credential or UserName parameters of Get-credential to pre-populate the username and domain. W poniższym przykładzie zastosowano technikę o nazwie korzystając do przekazywania parametrów do Set-RemoteRegistryValue funkcji.The following example uses a technique called splatting to pass parameters to the Set-RemoteRegistryValue function. Aby uzyskać więcej informacji na temat korzystając, zapoznaj się z artykułem 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)

Pobierz poświadczenie w czasie wykonywania

Korzystanie z programu (Get-Credential) wygląda nieskomplikowanie.Using (Get-Credential) seems cumbersome. Zwykle w przypadku używania parametru Credential z tylko nazwą użytkownika polecenie cmdlet automatycznie poprosi o hasło.Normally, when you use the Credential parameter with only a username, the cmdlet automatically prompts for the password. [System.Management.Automation.Credential()]Ten atrybut umożliwia takie zachowanie.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

Monituj o poświadczenia

Uwaga

Aby ustawić pokazaną wartość rejestru, w poniższych przykładach założono, że masz zainstalowane funkcje serwera sieci Web systemu Windows.To set the registry value shown, these examples assume you have the Web Server features of Windows installed. Uruchom Install-WindowsFeature Web-Server i Install-WindowsFeature web-mgmt-tools Jeśli jest to wymagane.Run Install-WindowsFeature Web-Server and Install-WindowsFeature web-mgmt-tools if required.

Podaj poświadczenia w zmiennejProvide credentials in a variable

Możesz również wypełnić zmienną poświadczeń przed czasem i przekazać ją do parametru Credential Set-RemoteRegistryValue funkcji.You can also populate a credential variable ahead of time and pass it to the Credential parameter of Set-RemoteRegistryValue function. Użyj tej metody z narzędziami ciągłej integracji/ciągłego wdrażania (CI/CD), takimi jak Jenkins, TeamCity i Octopus Deploy.Use this method with Continuous Integration / Continuous Deployment (CI/CD) tools such as Jenkins, TeamCity, and Octopus Deploy. Aby zapoznać się z przykładem przy użyciu Jenkins, zapoznaj [się z wpisem w blogu Hodge Automatyzacja przy użyciu Jenkins i programu PowerShell w systemie Windows — część 2][].For an example using Jenkins, check out Hodge's blog post Automating with Jenkins and PowerShell on Windows - Part 2.

W tym przykładzie zastosowano metodę .NET do utworzenia obiektu Credential i bezpiecznego ciągu do przekazania hasła.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

W tym przykładzie bezpieczny ciąg jest tworzony przy użyciu hasła czystego tekstu.For this example, the secure string is created using a clear text password. Wszystkie wspomniane wyżej poprzednie metody CI/CD zapewniają bezpieczną metodę dostarczania tego hasła w czasie wykonywania.All of the previously mentioned CI/CD have a secure method of providing that password at run time. Korzystając z tych narzędzi, Zastąp hasło zwykłego tekstu zmienną zdefiniowaną w używanym narzędziu CI/CD.When using those tools, replace the plain text password with the variable defined within the CI/CD tool you use.

Uruchom bez poświadczeńRun without credentials

Ponieważ $Credential Domyślnie jest to pusty obiekt poświadczeń, można uruchomić polecenie bez poświadczeń, jak pokazano w tym przykładzie: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

Obsługa starszych poleceń cmdletDealing with legacy cmdlets

Nie wszystkie polecenia cmdlet obsługują obiekty Credential lub zezwalają na puste poświadczenia.Not all cmdlets support credential objects or allow empty credentials. Zamiast tego polecenie cmdlet chce, aby parametry nazwy użytkownika i hasła były ciągami.Instead, the cmdlet wants username and password parameters as strings. Istnieje kilka sposobów na obejście tego ograniczenia.There are a few ways to work around this limitation.

Używanie polecenia if-else do obsługi pustych poświadczeńUsing if-else to handle empty credentials

W tym scenariuszu polecenie cmdlet, które chcesz uruchomić, nie akceptuje pustego obiektu Credential.In this scenario, the cmdlet you want to run doesn't accept an empty credential object. Ten przykład dodaje parametr Credential do Invoke-Command tylko wtedy, gdy nie jest pusty.This example adds the Credential parameter to Invoke-Command only if it's not empty. W przeciwnym razie zostanie uruchomione Invoke-Command bez parametru 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
        }
    }
}

Obsługa pustych poświadczeń przy użyciu korzystającUsing splatting to handle empty credentials

W tym przykładzie do wywołania starszego polecenia cmdlet jest wykorzystywany parametr korzystając.This example uses parameter splatting to call the legacy cmdlet. $CredentialObiekt jest warunkowo dodawany do tabeli skrótów dla korzystając i pozwala uniknąć konieczności powtarzania Invoke-Command bloku skryptu.The $Credential object is conditionally added to the hash table for splatting and avoids the need to repeat the Invoke-Command script block. Aby dowiedzieć się więcej na temat korzystając w funkcjach, zobacz [korzystając Parameters in the Advanced Functions][] post.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
}

Praca z hasłami ciągówWorking with string passwords

Invoke-SqlcmdPolecenie cmdlet jest przykładem polecenia cmdlet, które akceptuje ciąg jako hasło.The Invoke-Sqlcmd cmdlet is an example of a cmdlet that accepts a string as a password. Invoke-Sqlcmd umożliwia uruchamianie prostych instrukcji INSERT, Update i DELETE języka SQL.Invoke-Sqlcmd allows you to run simple SQL insert, update, and delete statements. Invoke-Sqlcmd wymaga nazwy użytkownika i hasła w postaci zwykłego tekstu, a nie bardziej bezpiecznego obiektu Credential.Invoke-Sqlcmd requires a clear-text username and password rather than a more secure credential object. Ten przykład pokazuje, jak wyodrębnić nazwę użytkownika i hasło z obiektu Credential.This example shows how to extract the username and password from a credential object.

Get-AllSQLDatabasesFunkcja w tym przykładzie wywołuje Invoke-Sqlcmd polecenie cmdlet w celu wysyłania zapytań do programu SQL Server dla wszystkich jego baz danych.The Get-AllSQLDatabases function in this example calls the Invoke-Sqlcmd cmdlet to query a SQL server for all its databases. Funkcja definiuje parametr Credential z tym samym atrybutem, który jest używany w poprzednich przykładach.The function defines a Credential parameter with the same attribute used in the previous examples. Ponieważ nazwa użytkownika i hasło istnieją w $Credential zmiennej, można wyodrębnić te wartości do użycia z Invoke-Sqlcmd .Since the username and password exist within the $Credential variable, you can extract those values for use with Invoke-Sqlcmd.

Nazwa użytkownika jest dostępna z właściwości username $Credential zmiennej.The user name is available from the UserName property of the $Credential variable. Aby uzyskać hasło, należy użyć GetNetworkCredential() metody $Credential obiektu.To obtain the password, you have to use the GetNetworkCredential() method of the $Credential object. Wartości są wyodrębniane do zmiennych, które są dodawane do tabeli skrótów używanej dla parametrów korzystając do 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

Dalsze uczenie zarządzania poświadczeniamiContinued learning credential management

Bezpieczne tworzenie i przechowywanie obiektów poświadczeń może być trudne.Creating and storing credential objects securely can be difficult. Poniższe zasoby mogą ułatwić zachowanie poświadczeń programu PowerShell.The following resources can help you maintain PowerShell credentials.