Adicionar suporte de Credenciais a funções do PowerShell
Nota
A versão original deste artigo apareceu no blog escrito por @joshduffney. Este artigo foi editado para inclusão neste site. A equipe do PowerShell agradece a Josh por compartilhar esse conteúdo conosco. Por favor, confira seu blog em duffney.io.
Este artigo mostra como adicionar parâmetros de credenciais às funções do PowerShell e por que você deseja. Um parâmetro de credencial é permitir que você execute a função ou cmdlet como um usuário diferente. O uso mais comum é executar a função ou cmdlet como uma conta de usuário elevada.
Por exemplo, o cmdlet New-ADUser
tem um parâmetro Credential , que você pode fornecer credenciais de administrador de domínio para criar uma conta em um domínio. Supondo que sua conta normal executando a sessão do PowerShell ainda não tenha esse acesso.
Criando objeto de credencial
O objeto PSCredential representa um conjunto de credenciais de segurança, como um nome de usuário e senha. O objeto pode ser passado como um parâmetro para uma função que é executada como a conta de usuário nesse objeto de credencial. Há algumas maneiras de criar um objeto de credencial. A primeira maneira de criar um objeto de credencial é usar o cmdlet Get-Credential
do PowerShell. Quando você executa sem parâmetros, ele solicita um nome de usuário e senha. Ou você pode chamar o cmdlet com alguns parâmetros opcionais.
Para especificar o nome de domínio e o nome de usuário com antecedência, você pode usar os parâmetros Credential ou UserName . Quando você usa o parâmetro UserName , também é necessário fornecer um valor Message . O código abaixo demonstra o uso do cmdlet. Você também pode armazenar o objeto de credencial em uma variável para que possa usá-la várias vezes. No exemplo abaixo, o objeto de credencial é armazenado na variável $Cred
.
$Cred = Get-Credential
$Cred = Get-Credential -Credential domain\user
$Cred = Get-Credential -UserName domain\user -Message 'Enter Password'
Às vezes, você não pode usar o método interativo de criação de objetos de credencial mostrado no exemplo anterior. A maioria das ferramentas de automação requer um método não interativo. Para criar uma credencial sem interação do usuário, crie uma cadeia de caracteres segura contendo a senha. Em seguida, passe a cadeia de caracteres segura e o nome de usuário para o System.Management.Automation.PSCredential()
método.
Use o seguinte comando para criar uma cadeia de caracteres segura contendo a senha:
ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force
Os parâmetros AsPlainText e Force são necessários. Sem esses parâmetros, você recebe uma mensagem avisando que não deve passar texto sem formatação para uma cadeia de caracteres segura. O PowerShell retorna esse aviso porque a senha de texto sem formatação é registrada em vários logs. Depois de criar uma cadeia de caracteres segura, você precisa passá-la para o PSCredential()
método para criar o objeto de credencial. No exemplo a seguir, a variável $password
contém a cadeia de caracteres $Cred
segura que contém o objeto credential.
$password = ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ("username", $password)
Agora que você sabe como criar objetos de credencial, pode adicionar parâmetros de credenciais às suas funções do PowerShell.
Adicionando um parâmetro de credencial
Assim como qualquer outro parâmetro, você começa adicionando-o no param
bloco da sua função.
É recomendável nomear o parâmetro $Credential
porque é isso que os cmdlets existentes do PowerShell usam. O tipo do parâmetro deve ser [System.Management.Automation.PSCredential]
.
O exemplo a seguir mostra o bloco de parâmetros para uma função chamada Get-Something
. Tem dois parâmetros: $Name
e $Credential
.
function Get-Something {
param(
$Name,
[System.Management.Automation.PSCredential]$Credential
)
O código neste exemplo é suficiente para ter um parâmetro de credencial de trabalho, no entanto, há algumas coisas que você pode adicionar para torná-lo mais robusto.
Adicione o
[ValidateNotNull()]
atributo de validação para verificar se o valor que está sendo passado para Credential. Se o valor do parâmetro for null, esse atributo impedirá que a função seja executada com credenciais inválidas.Adicionar
[System.Management.Automation.Credential()]
. Isso permite que você passe um nome de usuário como uma cadeia de caracteres e tenha um prompt interativo para a senha.Defina um valor padrão para o
$Credential
parâmetro como[System.Management.Automation.PSCredential]::Empty
. Sua função você pode estar passando esse$Credential
objeto para cmdlets existentes do PowerShell. Fornecer um valor nulo para o cmdlet chamado dentro de sua função causa um erro. Fornecer um objeto de credencial vazio evita esse erro.
Gorjeta
Alguns cmdlets que aceitam um parâmetro de credencial não oferecem suporte [System.Management.Automation.PSCredential]::Empty
como deveriam. Consulte a seção Lidando com cmdlets herdados para obter uma solução alternativa.
Usando parâmetros de credencial
O exemplo a seguir demonstra como usar parâmetros de credencial. Este exemplo mostra uma função chamada Set-RemoteRegistryValue
, que está fora do The Pester Book. Esta função define o parâmetro de credencial usando as técnicas descritas na seção anterior. A função chama Invoke-Command
usando a $Credential
variável criada pela função. Isso permite que você altere o usuário que está executando Invoke-Command
o . Como o valor padrão de é uma credencial vazia, a função pode ser executada $Credential
sem fornecer credenciais.
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
}
As seções a seguir mostram diferentes métodos de fornecimento de credenciais para Set-RemoteRegistryValue
o .
Solicitando credenciais
Usar Get-Credential
entre parênteses ()
em tempo de execução faz com que o Get-credential
seja executado primeiro. Ser-lhe-á pedido um nome de utilizador e uma palavra-passe. Você pode usar os parâmetros Credential ou UserName do para preencher previamente o nome de Get-credential
usuário e o domínio. O exemplo a seguir usa uma técnica chamada splatting para passar parâmetros para a Set-RemoteRegistryValue
função. Para obter mais informações sobre splatting, confira o artigo about_Splatting.
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams -Credential (Get-Credential)
Usar (Get-Credential)
parece complicado. Normalmente, quando você usa o parâmetro Credential com apenas um nome de usuário, o cmdlet solicita automaticamente a senha. O [System.Management.Automation.Credential()]
atributo habilita esse comportamento.
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams -Credential duffney
Nota
Para definir o valor do Registro mostrado, esses exemplos pressupõem que você tenha os recursos do Servidor Web do Windows instalados. Execute Install-WindowsFeature Web-Server
e Install-WindowsFeature web-mgmt-tools
se necessário.
Fornecer credenciais em uma variável
Você também pode preencher uma variável de credencial com antecedência e passá-la para o parâmetro Credential da Set-RemoteRegistryValue
função. Use esse método com ferramentas de Integração Contínua / Implantação Contínua (CI/CD), como Jenkins, TeamCity e Octopus Deploy. Para obter um exemplo usando Jenkins, confira a postagem do blog de Hodge Automatizando com Jenkins e PowerShell no Windows - Parte 2.
Este exemplo usa o método .NET para criar o objeto de credencial e uma cadeia de caracteres segura para passar a senha.
$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
Neste exemplo, a cadeia de caracteres segura é criada usando uma senha de texto não criptografado. Todos os CI/CD mencionados anteriormente têm um método seguro de fornecer essa senha em tempo de execução. Ao usar essas ferramentas, substitua a senha de texto sem formatação pela variável definida na ferramenta CI/CD que você usa.
Executar sem credenciais
Como $Credential
o padrão é um objeto de credencial vazio, você pode executar o comando sem credenciais, conforme mostrado neste exemplo:
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams
Lidando com cmdlets herdados
Nem todos os cmdlets oferecem suporte a objetos de credenciais ou permitem credenciais vazias. Em vez disso, o cmdlet deseja parâmetros de nome de usuário e senha como cadeias de caracteres. Existem algumas maneiras de contornar essa limitação.
Usando if-else para lidar com credenciais vazias
Nesse cenário, o cmdlet que você deseja executar não aceita um objeto de credencial vazio. Este exemplo adiciona o parâmetro Credential somente Invoke-Command
se ele não estiver vazio. Caso contrário, ele executa o Invoke-Command
sem o parâmetro Credential .
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
}
}
}
Usando splatting para lidar com credenciais vazias
Este exemplo usa o splatting de parâmetros para chamar o cmdlet herdado. O $Credential
objeto é adicionado condicionalmente à tabela de hash para splatting e evita a necessidade de repetir o Invoke-Command
bloco de script. Para saber mais sobre o splatting dentro de funções, consulte a postagem do blog 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
}
Trabalhando com senhas de cadeia de caracteres
O Invoke-Sqlcmd
cmdlet é um exemplo de um cmdlet que aceita uma cadeia de caracteres como senha.
Invoke-Sqlcmd
permite que você execute instruções simples de inserção, atualização e exclusão de SQL. Invoke-Sqlcmd
requer um nome de usuário e senha de texto não criptografado em vez de um objeto de credencial mais seguro. Este exemplo mostra como extrair o nome de usuário e a senha de um objeto de credencial.
A Get-AllSQLDatabases
função neste exemplo chama o Invoke-Sqlcmd
cmdlet para consultar um servidor SQL para todos os seus bancos de dados. A função define um parâmetro Credential com o mesmo atributo usado nos exemplos anteriores. Como o nome de usuário e a senha existem dentro da variável, você pode extrair esses valores para uso com Invoke-Sqlcmd
o $Credential
.
O nome de usuário está disponível na propriedade UserName da $Credential
variável. Para obter a senha, você tem que usar o GetNetworkCredential()
método do $Credential
objeto. Os valores são extraídos em variáveis que são adicionadas a uma tabela de hash usada para splatting parâmetros para 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
Gestão de credenciais de aprendizagem contínua
Criar e armazenar objetos de credenciais com segurança pode ser difícil. Os recursos a seguir podem ajudá-lo a manter as credenciais do PowerShell.