Dodawanie obsługi poświadczeń do funkcji programu PowerShell

Uwaga

Oryginalna wersja tego artykułu pojawiła się na blogu napisanym przez @joshduffney. Ten artykuł został edytowany w celu włączenia do tej witryny. Zespół programu PowerShell dziękuje Joshowi za udostępnienie tej zawartości. Zapoznaj się ze swoim blogiem na duffney.io.

W tym artykule pokazano, jak dodać parametry poświadczeń do funkcji programu PowerShell i dlaczego chcesz. Parametr poświadczeń umożliwia uruchamianie funkcji lub polecenia cmdlet jako inny użytkownik. Najczęstszym zastosowaniem jest uruchomienie funkcji lub polecenia cmdlet jako konta użytkownika z podwyższonym poziomem uprawnień.

Na przykład polecenie cmdlet New-ADUser ma parametr Credential , który można podać poświadczenia administratora domeny, aby utworzyć konto w domenie. Zakładając, że normalne konto z uruchomioną sesją programu PowerShell nie ma już tego dostępu.

Tworzenie obiektu poświadczeń

Obiekt PSCredential reprezentuje zestaw poświadczeń zabezpieczeń, takich jak nazwa użytkownika i hasło. Obiekt można przekazać jako parametr do funkcji uruchamianej jako konto użytkownika w tym obiekcie poświadczeń. Istnieje kilka sposobów tworzenia obiektu poświadczeń. Pierwszym sposobem utworzenia obiektu poświadczeń jest użycie polecenia cmdlet Get-Credentialprogramu PowerShell . Po uruchomieniu bez parametrów zostanie wyświetlony monit o podanie nazwy użytkownika i hasła. Możesz też wywołać polecenie cmdlet z kilkoma parametrami opcjonalnymi.

Aby określić nazwę domeny i nazwę użytkownika przed upływem czasu, możesz użyć parametrów Credential lub UserName . Jeśli używasz parametru UserName, musisz również podać wartość komunikatu. Poniższy kod demonstruje użycie polecenia cmdlet . Możesz również przechowywać obiekt poświadczeń w zmiennej, aby można było wielokrotnie używać poświadczeń. W poniższym przykładzie obiekt poświadczeń jest przechowywany w zmiennej $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ć metody interaktywnej tworzenia obiektów poświadczeń pokazanych w poprzednim przykładzie. Większość narzędzi automatyzacji wymaga metody nieinterakcyjnej. Aby utworzyć poświadczenia bez interakcji użytkownika, utwórz bezpieczny ciąg zawierający hasło. Następnie przekaż bezpieczny ciąg i nazwę użytkownika do System.Management.Automation.PSCredential() metody .

Użyj następującego polecenia, aby utworzyć bezpieczny ciąg zawierający hasło:

ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force

Wymagane są zarówno parametry AsPlainText, jak i Force. Bez tych parametrów zostanie wyświetlone ostrzeżenie o tym, że nie należy przekazywać zwykłego tekstu do bezpiecznego ciągu. Program PowerShell zwraca to ostrzeżenie, ponieważ hasło w postaci zwykłego tekstu jest rejestrowane w różnych dziennikach. Po utworzeniu bezpiecznego ciągu należy przekazać go do PSCredential() metody , aby utworzyć obiekt poświadczeń. W poniższym przykładzie zmienna $password zawiera bezpieczny ciąg $Cred zawierający obiekt poświadczeń.

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

Teraz, gdy już wiesz, jak tworzyć obiekty poświadczeń, możesz dodać parametry poświadczeń do funkcji programu PowerShell.

Dodawanie parametru poświadczeń

Podobnie jak każdy inny parametr, zacznij od dodania go do param bloku funkcji. Zaleca się nadanie parametrowi nazwy parametru $Credential , ponieważ są używane istniejące polecenia cmdlet programu PowerShell. Typ parametru powinien mieć wartość [System.Management.Automation.PSCredential].

W poniższym przykładzie przedstawiono blok parametrów dla funkcji o nazwie Get-Something. Ma dwa parametry: $Name i $Credential.

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

Kod w tym przykładzie wystarczy, aby mieć działający parametr poświadczeń, jednak istnieje kilka rzeczy, które można dodać, aby uczynić go bardziej niezawodnym.

  • Dodaj atrybut weryfikacji, [ValidateNotNull()] aby sprawdzić, czy wartość przekazywana do poświadczenia. Jeśli wartość parametru ma wartość null, ten atrybut uniemożliwia wykonywanie funkcji z nieprawidłowymi poświadczeniami.

  • Dodaj [System.Management.Automation.Credential()]element . Umożliwia to przekazanie nazwy użytkownika jako ciągu i wyświetlenie interakcyjnego monitu o hasło.

  • Ustaw wartość domyślną parametru $Credential na [System.Management.Automation.PSCredential]::Emptywartość . Twoja funkcja może przekazywać ten $Credential obiekt do istniejących poleceń cmdlet programu PowerShell. Podanie wartości null do polecenia cmdlet o nazwie wewnątrz funkcji powoduje błąd. Podanie pustego obiektu poświadczeń pozwala uniknąć tego błędu.

Napiwek

Niektóre polecenia cmdlet, które akceptują parametr poświadczeń, nie obsługują [System.Management.Automation.PSCredential]::Empty tak, jak powinny. Aby obejść ten problem, zobacz sekcję Obsługa starszych poleceń cmdlet .

Używanie parametrów poświadczeń

W poniższym przykładzie pokazano, jak używać parametrów poświadczeń. W tym przykładzie pokazano funkcję o nazwie Set-RemoteRegistryValue, która znajduje się poza książką Pester. Ta funkcja definiuje parametr poświadczeń przy użyciu technik opisanych w poprzedniej sekcji. Funkcja wywołuje Invoke-Command zmienną utworzoną $Credential przez funkcję. Umożliwia to zmianę użytkownika, który jest uruchomiony Invoke-Command. Ponieważ wartość $Credential domyślna to puste poświadczenie, funkcja może działać bez podawania poświadczeń.

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 podawania poświadczeń do Set-RemoteRegistryValueusługi .

Monitowanie o poświadczenia

Użycie Get-Credential w nawiasach () w czasie wykonywania powoduje Get-credential , że polecenie jest uruchamiane jako pierwsze. Zostanie wyświetlony monit o podanie nazwy użytkownika i hasła. Możesz użyć parametrów Credential lub UserName polecenia Get-credential , aby wstępnie wypełnić nazwę użytkownika i domenę. W poniższym przykładzie użyto techniki o nazwie splatting w celu przekazania parametrów do Set-RemoteRegistryValue funkcji. Aby uzyskać więcej informacji na temat splattingu, zapoznaj się z artykułem about_Splatting .

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

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

Pobieranie poświadczeń w czasie wykonywania

Używanie (Get-Credential) wydaje się kłopotliwe. Zwykle, gdy używasz parametru Credential tylko z nazwą użytkownika, polecenie cmdlet automatycznie wyświetla monit o hasło. Atrybut [System.Management.Automation.Credential()] umożliwia to zachowanie.

$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 tych przykładach założono, że masz zainstalowane funkcje serwera sieci Web systemu Windows. Uruchom polecenie Install-WindowsFeature Web-Server i Install-WindowsFeature web-mgmt-tools , jeśli jest to wymagane.

Podawanie poświadczeń w zmiennej

Możesz również wypełnić zmienną poświadczeń z wyprzedzeniem i przekazać ją do parametru Set-RemoteRegistryValue Credential funkcji. 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. Aby zapoznać się z przykładem użycia narzędzia Jenkins, zapoznaj się z wpisem w blogu Hodge Automating with Jenkins and PowerShell on Windows - Part 2 (Automatyzacja za pomocą narzędzia Jenkins i programu PowerShell w systemie Windows — część 2).

W tym przykładzie użyto metody .NET, aby utworzyć obiekt poświadczeń i bezpieczny ciąg do przekazania hasła.

$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 zwykłego tekstu. Wszystkie wymienione wcześniej ciągła integracja/ciągłe wdrażanie mają bezpieczną metodę zapewniania tego hasła w czasie wykonywania. W przypadku korzystania z tych narzędzi zastąp hasło zwykłego tekstu zmienną zdefiniowaną w używanym narzędziu ciągłej integracji/ciągłego wdrażania.

Uruchamianie bez poświadczeń

Ponieważ $Credential domyślnie jest to pusty obiekt poświadczeń, można uruchomić polecenie bez poświadczeń, jak pokazano w tym przykładzie:

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

Set-RemoteRegistryValue @remoteKeyParams

Obsługa starszych poleceń cmdlet

Nie wszystkie polecenia cmdlet obsługują obiekty poświadczeń lub zezwalają na puste poświadczenia. Zamiast tego polecenie cmdlet chce użyć parametrów nazwy użytkownika i hasła jako ciągów. Istnieje kilka sposobów obejścia tego ograniczenia.

Używanie instrukcji if-else do obsługi pustych poświadczeń

W tym scenariuszu polecenie cmdlet, które chcesz uruchomić, nie akceptuje pustego obiektu poświadczeń. W tym przykładzie dodano parametr Credential tylko Invoke-Command wtedy, gdy nie jest pusty. W przeciwnym razie uruchamia Invoke-Command parametr bez poświadczeń .

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
        }
    }
}

Używanie splattingu do obsługi pustych poświadczeń

W tym przykładzie użyto splattingu parametrów w celu wywołania starszego polecenia cmdlet. $Credential Obiekt jest warunkowo dodawany do tabeli skrótów w celu splatania i unika konieczności powtarzania bloku skryptuInvoke-Command. Aby dowiedzieć się więcej na temat splattingu wewnątrz funkcji, zobacz wpis w blogu Splatting Parameters Inside Advanced Functions (Parametryplatting 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
}

Praca z hasłami ciągów

Polecenie Invoke-Sqlcmd cmdlet jest przykładem polecenia cmdlet, które akceptuje ciąg jako hasło. Invoke-Sqlcmd umożliwia uruchamianie prostych instrukcji wstawiania, aktualizowania i usuwania sql. Invoke-Sqlcmd wymaga nazwy użytkownika i hasła w postaci zwykłego tekstu, a nie bezpieczniejszego obiektu poświadczeń. W tym przykładzie pokazano, jak wyodrębnić nazwę użytkownika i hasło z obiektu poświadczeń.

Funkcja Get-AllSQLDatabases w tym przykładzie Invoke-Sqlcmd wywołuje polecenie cmdlet, aby wysłać zapytanie do serwera SQL dla wszystkich jego baz danych. Funkcja definiuje parametr Credential z tym samym atrybutem używanym w poprzednich przykładach. Ponieważ nazwa użytkownika i hasło istnieją w zmiennej $Credential , możesz wyodrębnić te wartości do użycia z Invoke-Sqlcmd.

Nazwa użytkownika jest dostępna we właściwości UserName zmiennej $Credential . Aby uzyskać hasło, należy użyć GetNetworkCredential() metody $Credential obiektu . Wartości są wyodrębniane do zmiennych, które są dodawane do tabeli skrótów używanej do splatting parametrów do 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

Ciągłe uczenie się zarządzania poświadczeniami

Bezpieczne tworzenie i przechowywanie obiektów poświadczeń może być trudne. Poniższe zasoby mogą pomóc w utrzymywaniu poświadczeń programu PowerShell.