Delen via


Referentieondersteuning toevoegen aan PowerShell-functies

Notitie

De oorspronkelijke versie van dit artikel verscheen op het blog dat is geschreven door @joshduffney. Dit artikel is bewerkt voor opname op deze site. Het PowerShell-team bedankt Josh voor het delen van deze inhoud met ons. Bekijk zijn blog op duffney.io.

In dit artikel leest u hoe u referentieparameters toevoegt aan PowerShell-functies en waarom u dat wilt. Met een referentieparameter kunt u de functie of cmdlet als een andere gebruiker uitvoeren. Het meest voorkomende gebruik is het uitvoeren van de functie of cmdlet als een gebruikersaccount met verhoogde bevoegdheid.

De cmdlet New-ADUser heeft bijvoorbeeld een referentieparameter , waarmee u domeinbeheerdersreferenties kunt opgeven om een account in een domein te maken. Ervan uitgaande dat uw normale account waarop de PowerShell-sessie wordt uitgevoerd, nog geen toegang heeft.

Referentieobject maken

Het PSCredential-object vertegenwoordigt een set beveiligingsreferenties, zoals een gebruikersnaam en wachtwoord. Het object kan worden doorgegeven als een parameter aan een functie die wordt uitgevoerd als het gebruikersaccount in dat referentieobject. Er zijn een aantal manieren waarop u een referentieobject kunt maken. De eerste manier om een referentieobject te maken, is door de PowerShell-cmdlet Get-Credentialte gebruiken. Wanneer u zonder parameters uitvoert, wordt u gevraagd om een gebruikersnaam en wachtwoord. U kunt de cmdlet ook aanroepen met enkele optionele parameters.

Als u de domeinnaam en gebruikersnaam van tevoren wilt opgeven, kunt u de parameters Referentie of Gebruikersnaam gebruiken. Wanneer u de parameter UserName gebruikt, moet u ook een berichtwaarde opgeven. De onderstaande code laat zien hoe u de cmdlet gebruikt. U kunt het referentieobject ook opslaan in een variabele, zodat u de referentie meerdere keren kunt gebruiken. In het onderstaande voorbeeld wordt het referentieobject opgeslagen in de variabele $Cred.

$Cred = Get-Credential
$Cred = Get-Credential -Credential domain\user
$Cred = Get-Credential -UserName domain\user -Message 'Enter Password'

Soms kunt u de interactieve methode voor het maken van referentieobjecten die in het vorige voorbeeld worden weergegeven, niet gebruiken. Voor de meeste automatiseringshulpprogramma's is een niet-interactieve methode vereist. Als u een referentie wilt maken zonder tussenkomst van de gebruiker, maakt u een beveiligde tekenreeks met het wachtwoord. Geef vervolgens de beveiligde tekenreeks en gebruikersnaam door aan de System.Management.Automation.PSCredential() methode.

Gebruik de volgende opdracht om een beveiligde tekenreeks te maken die het wachtwoord bevat:

ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force

De parameters AsPlainText en Force zijn vereist. Zonder deze parameters ontvangt u een berichtwaarschuwing dat u geen tekst zonder opmaak moet doorgeven aan een beveiligde tekenreeks. PowerShell retourneert deze waarschuwing omdat het wachtwoord voor tekst zonder opmaak wordt vastgelegd in verschillende logboeken. Nadat u een beveiligde tekenreeks hebt gemaakt, moet u deze doorgeven aan de PSCredential() methode om het referentieobject te maken. In het volgende voorbeeld bevat de variabele $password de beveiligde tekenreeks $Cred het referentieobject.

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

Nu u weet hoe u referentieobjecten maakt, kunt u referentieparameters toevoegen aan uw PowerShell-functies.

Een referentieparameter toevoegen

Net als elke andere parameter begint u door deze toe te voegen aan het param blok van uw functie. Het is raadzaam om de parameter $Credential een naam te gegeven, omdat dat is wat bestaande PowerShell-cmdlets gebruiken. Het type van de parameter moet zijn [System.Management.Automation.PSCredential].

In het volgende voorbeeld ziet u het parameterblok voor een functie die wordt aangeroepen Get-Something. Het heeft twee parameters: $Name en $Credential.

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

De code in dit voorbeeld is voldoende om een werkende referentieparameter te hebben, maar er zijn een paar dingen die u kunt toevoegen om deze robuuster te maken.

  • Voeg het [ValidateNotNull()] validatiekenmerk toe om te controleren of de waarde die wordt doorgegeven aan referentie. Als de parameterwaarde null is, voorkomt dit kenmerk dat de functie wordt uitgevoerd met ongeldige referenties.

  • Toevoegen [System.Management.Automation.Credential()]. Hiermee kunt u een gebruikersnaam doorgeven als een tekenreeks en een interactieve prompt voor het wachtwoord hebben.

  • Stel een standaardwaarde voor de $Credential parameter in op [System.Management.Automation.PSCredential]::Empty. Uw functie geeft dit $Credential object mogelijk door aan bestaande PowerShell-cmdlets. Als u een null-waarde opgeeft voor de cmdlet die in uw functie wordt aangeroepen, wordt een fout veroorzaakt. Het opgeven van een leeg referentieobject voorkomt deze fout.

Tip

Sommige cmdlets die een referentieparameter accepteren, worden niet naar behoren ondersteund [System.Management.Automation.PSCredential]::Empty . Zie de sectie Omgaan met verouderde cmdlets voor een tijdelijke oplossing.

Referentieparameters gebruiken

In het volgende voorbeeld ziet u hoe u referentieparameters gebruikt. In dit voorbeeld ziet u een functie die uit the Pester Book is aangeroepenSet-RemoteRegistryValue. Deze functie definieert de referentieparameter met behulp van de technieken die in de vorige sectie worden beschreven. De functie roept Invoke-Command aan met behulp van de $Credential variabele die door de functie is gemaakt. Hiermee kunt u de gebruiker wijzigen die wordt uitgevoerd Invoke-Command. Omdat de standaardwaarde $Credential een lege referentie is, kan de functie worden uitgevoerd zonder referenties op te geven.

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
}

In de volgende secties ziet u verschillende methoden voor het opgeven van referenties.Set-RemoteRegistryValue

Vragen om referenties

Als Get-Credential u haakjes () gebruikt tijdens runtime, wordt de Get-credential uitvoering eerst uitgevoerd. U wordt gevraagd om een gebruikersnaam en wachtwoord. U kunt de parameters Get-credential Referentie of Gebruikersnaam gebruiken om de gebruikersnaam en het domein vooraf in te vullen. In het volgende voorbeeld wordt een techniek met de naam splatting gebruikt om parameters door te geven aan de Set-RemoteRegistryValue functie. Raadpleeg het about_Splatting artikel voor meer informatie over splatting.

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

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

Een referentie ophalen tijdens runtime

Het gebruik (Get-Credential) lijkt omslachtig. Normaal gesproken vraagt de cmdlet automatisch om het wachtwoord wanneer u de parameter Referentie gebruikt met alleen een gebruikersnaam. Met [System.Management.Automation.Credential()] het kenmerk wordt dit gedrag ingeschakeld.

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

Set-RemoteRegistryValue @remoteKeyParams -Credential duffney

Vragen om referenties

Notitie

Als u de weergegeven registerwaarde wilt instellen, wordt in deze voorbeelden ervan uitgegaan dat de webserverfuncties van Windows zijn geïnstalleerd. Uitvoeren Install-WindowsFeature Web-Server en Install-WindowsFeature web-mgmt-tools indien nodig.

Referenties opgeven in een variabele

U kunt een referentievariabele ook van tevoren invullen en doorgeven aan de parameter Referentie van Set-RemoteRegistryValue de functie. Gebruik deze methode met CI/CD-hulpprogramma's (Continuous Integration/ Continuous Deployment), zoals Jenkins, TeamCity en Octopus Deploy. Bekijk voor een voorbeeld van Jenkins het blogbericht van Hodge automatiseren met Jenkins en PowerShell in Windows - deel 2.

In dit voorbeeld wordt de .NET-methode gebruikt om het referentieobject en een beveiligde tekenreeks te maken om het wachtwoord door te geven.

$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

In dit voorbeeld wordt de beveiligde tekenreeks gemaakt met een wachtwoord voor duidelijke tekst. Alle eerder genoemde CI/CD hebben een veilige methode om dat wachtwoord op te geven tijdens runtime. Wanneer u deze hulpprogramma's gebruikt, vervangt u het wachtwoord voor tekst zonder opmaak door de variabele die is gedefinieerd in het CI/CD-hulpprogramma dat u gebruikt.

Uitvoeren zonder referenties

Aangezien $Credential standaard een leeg referentieobject is, kunt u de opdracht zonder referenties uitvoeren, zoals wordt weergegeven in dit voorbeeld:

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

Set-RemoteRegistryValue @remoteKeyParams

Omgaan met verouderde cmdlets

Niet alle cmdlets ondersteunen referentieobjecten of staan lege referenties toe. In plaats daarvan wil de cmdlet gebruikersnaam- en wachtwoordparameters als tekenreeksen. Er zijn een aantal manieren om deze beperking te omzeilen.

If-else gebruiken om lege referenties af te handelen

In dit scenario accepteert de cmdlet die u wilt uitvoeren geen leeg referentieobject. In dit voorbeeld wordt de referentieparameter alleen toegevoegd als Invoke-Command deze niet leeg is. Anders wordt de Invoke-Command parameter Referentie uitgevoerd zonder de referentieparameter .

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

Splatting gebruiken om lege referenties te verwerken

In dit voorbeeld wordt parameter-splatting gebruikt om de verouderde cmdlet aan te roepen. Het $Credential object wordt voorwaardelijk toegevoegd aan de hash-tabel voor splatting en voorkomt dat het Invoke-Command scriptblok moet worden herhaald. Zie het blogbericht Splatting Parameters Inside Advanced Functions voor meer informatie over het splatten van functies.

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
}

Werken met tekenreekswachtwoorden

De Invoke-Sqlcmd cmdlet is een voorbeeld van een cmdlet die een tekenreeks accepteert als een wachtwoord. Invoke-Sqlcmd hiermee kunt u eenvoudige INSTRUCTIES voor invoegen, bijwerken en verwijderen van SQL uitvoeren. Invoke-Sqlcmd vereist een duidelijke tekst gebruikersnaam en wachtwoord in plaats van een veiliger referentieobject. In dit voorbeeld ziet u hoe u de gebruikersnaam en het wachtwoord kunt extraheren uit een referentieobject.

Met Get-AllSQLDatabases de functie in dit voorbeeld wordt de cmdlet aangeroepen Invoke-Sqlcmd om een query uit te voeren op een SQL-server voor alle bijbehorende databases. De functie definieert een referentieparameter met hetzelfde kenmerk dat in de vorige voorbeelden wordt gebruikt. Aangezien de gebruikersnaam en het wachtwoord in de $Credential variabele bestaan, kunt u deze waarden extraheren voor gebruik met Invoke-Sqlcmd.

De gebruikersnaam is beschikbaar via de eigenschap UserName van de $Credential variabele. Als u het wachtwoord wilt ophalen, moet u de GetNetworkCredential() methode van het $Credential object gebruiken. De waarden worden geëxtraheerd in variabelen die worden toegevoegd aan een hash-tabel die wordt gebruikt voor het splatten van parameters.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

Voortgezet leerreferentiebeheer

Het veilig maken en opslaan van referentieobjecten kan lastig zijn. Met de volgende bronnen kunt u PowerShell-referenties onderhouden.