您遇到了一個稱爲雙跳問題。在本質上,您要求遠程會話使用相同的Windows身份驗證訪問另一個外部資源。
由於安全原因,Microsoft默認情況下不允許這種情況。
如果您想了解更多關於它,請閱讀我的整個後PowerShell remoting caveats
的解決方案是不容易的,definetely不是唯一的,因爲它主要有Kerberos身份驗證以及如何做域控制器想要控制這個。例如,域控制器可以指定兩臺服務器之間允許使用特定的雙跳,否則您必須允許每臺服務器使用雙跳。
更好的解決方案是使用域配置,但您需要聯繫您的域管理員並說服他。
我將通過腳本參考顯示如何爲每個服務器執行此操作。例如從上面的圖片中,我們必須配置ServerA
以允許將憑證委託給ServerB
。
我必須解決這些問題,我已經構建了一個自動化存儲庫。自動化名稱爲ISHBootstrap,我將參考此存儲庫中的腳本。並非一切都適合這裏。請記住,所有腳本都可以在本地或遠程執行,這就是爲什麼您會注意到使用包裝程序cmdlet的原因:Invoke-Command
Invoke-CommandWrap。只需查看受尊重的腳本塊並提取代碼即可。
首先,我們需要在ServerA
上安裝一些前提條件。
我使用這個腳本Install-WinRMPrerequisites.ps1,但它是作爲此命令
Get-WindowsFeature |Where-Object -Property Name -EQ "WinRM-IIS-Ext"|Add-WindowsFeature
然後,我們需要啓用和配置WSManCredSSP一樣簡單。這需要一個安全的遠程會話,這就是爲什麼我們需要通過SSL設置winrm。此腳本運行整個過程Enable-WSManCredSSP.ps1
- 啓用WSManCredSSP。
- 安裝自簽名證書並使用安全端點配置WSMan。
- 重新啓動WSMan。
- 打開防火牆端口。
下面是從腳本中提取出代碼:
#region Enable WSManCredSSP
Enable-WSManCredSSP -Role Server -Force | Out-Null
#endregion
#region Configure a secure WinRMListener
$winRmListeners=& winrm enumerate winrm/config/listener
$httpsLine= $winRmListeners -match "HTTPS"
Write-Debug "httpsLine=$httpsLine"
if(-not $httpsLine)
{
$certificate=Get-ChildItem -Path Cert:\LocalMachine\My |Where-Object -Property Thumbprint -EQ $Thumbprint
$hostname=(($certificate.Subject -split ', ')[0] -split '=')[1]
Write-Debug "Adding winrm https listener"
& winrm create winrm/config/Listener?Address=*+Transport=HTTPS "@{Hostname=""$hostname"";CertificateThumbprint=""$Thumbprint""}"
Write-Verbose "Added winrm https listener"
Write-Debug "Configuring ACL"
# Specify the user, the permissions and the permission type
$permission = "NETWORK SERVICE","Read,FullControl","Allow"
$accessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permission;
$keyPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\";
$keyName = $certificate.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName;
$keyFullPath = Join-Path $keyPath $keyName;
# Get the current acl of the private key
# This is the line that fails!
$acl = Get-Acl -Path $keyFullPath;
# Add the new ace to the acl of the private key
$acl.AddAccessRule($accessRule);
# Write back the new acl
Set-Acl -Path $keyFullPath -AclObject $acl;
Write-Verbose "Configured ACL"
}
else
{
Write-Warning "winrm https listener detected. Skipped"
}
#endregion
#region restart WinRm service
Write-Debug "Restarting winrm service"
Get-Service -Name WinRM |Restart-Service| Out-Null
while((Get-Service -Name WinRM).Status -ne "Running")
{
Start-Sleep -Milliseconds 500
}
Write-Verbose "Restarted WINRM service"
#endregion
#region Configure windows firewall
$ruleName="WinRM-HTTPS"
$rulePort=5986
Write-Debug "Querying if firewall port for winrm https is open"
if(-not (Get-NetFirewallRule|Where-Object {($_.DisplayName -eq $ruleName) -and ($_.Direction -eq "Inbound")}))
{
Write-Verbose "Adding firewall port for winrm https is open"
New-NetFirewallRule -DisplayName $ruleName -Direction Inbound -Action Allow -Protocol "TCP" -LocalPort $rulePort|Out-Null
}
Write-Host "Winrm https firewall port is ok"
#endregion
此時ServerA
準備好您的授權委託給另一臺服務器,但客戶仍然需要明確指出的是,遠程會話必須能夠做到這一點。使用CredSSP
認證類型時這樣
$session=New-PSSession -ComputerName $Computer -Credential $Credential -UseSSL -Authentication Credssp
公告創建一個會話兩個重要的事情:
-Credentials
必須明確指定,即使他們是爲登錄同一用戶。
- 使用
-UseSSL
使用winrm安全。
現在使用$session
與你原來的代碼,它應該工作
Invoke-Command -ComputerName $vms -Session $session -ScriptBlock {
Import-Certificate `
-FilePath \\dc1\CertificateShare\17C37D0A655B89967398C9E7E8185F78541B1589.cer `
-CertStoreLocation 'Cert:\LocalMachine\Root'
}
- 固定雙躍點身份驗證問題「*什麼是需要克服這個錯誤*?」;可能重複的[Powershell服務器網絡驅動器](https://stackoverflow.com/questions/24903878/powershell-server-network-drive) – TessellatingHeckler