2017-10-11 52 views
0

我的網絡中的每個人都可以讀取包含需要安裝的證書的SMB共享。我也以域管理員身份執行此代碼。有什麼必要克服這個錯誤?調用命令導入證書訪問被拒絕

Access is denied. 0x80070005 (WIN32: 5 ERROR_ACCESS_DENIED) 

這是我想要在每臺服務器上安裝證書的代碼。

$vms = "App1","App2","App3" 

Invoke-Command -ComputerName $vms -ScriptBlock { 
    Import-Certificate ` 
     -FilePath \\dc1\CertificateShare\17C37D0A655B89967398C9E7E8185F78541B1589.cer ` 
     -CertStoreLocation 'Cert:\LocalMachine\Root' 

} 
+0

- 固定雙躍點身份驗證問題「*什麼是需要克服這個錯誤*?」;可能重複的[Powershell服務器網絡驅動器](https://stackoverflow.com/questions/24903878/powershell-server-network-drive) – TessellatingHeckler

回答

0

您遇到了一個稱爲雙跳問題。在本質上,您要求遠程會話使用相同的Windows身份驗證訪問另一個外部資源。

由於安全原因,Microsoft默認情況下不允許這種情況。

Double hop issue

如果您想了解更多關於它,請閱讀我的整個後PowerShell remoting caveats

的解決方案是不容易的,definetely不是唯一的,因爲它主要有Kerberos身份驗證以及如何做域控制器想要控制這個。例如,域控制器可以指定兩臺服務器之間允許使用特定的雙跳,否則您必須允許每臺服務器使用雙跳。

更好的解決方案是使用域配置,但您需要聯繫您的域管理員並說服他。

我將通過腳本參考顯示如何爲每個服務器執行此操作。例如從上面的圖片中,我們必須配置ServerA以允許將憑證委託給ServerB

我必須解決這些問題,我已經構建了一個自動化存儲庫。自動化名稱爲ISHBootstrap,我將參考此存儲庫中的腳本。並非一切都適合這裏。請記住,所有腳本都可以在本地或遠程執行,這就是爲什麼您會注意到使用包裝程序cmdlet的原因:Invoke-CommandInvoke-CommandWrap。只需查看受尊重的腳本塊並提取代碼即可。

首先,我們需要在ServerA上安裝一些前提條件。

我使用這個腳本Install-WinRMPrerequisites.ps1,但它是作爲此命令

Get-WindowsFeature |Where-Object -Property Name -EQ "WinRM-IIS-Ext"|Add-WindowsFeature 

然後,我們需要啓用和配置WSManCredSSP一樣簡單。這需要一個安全的遠程會話,這就是爲什麼我們需要通過SSL設置winrm。此腳本運行整個過程Enable-WSManCredSSP.ps1

  1. 啓用WSManCredSSP。
  2. 安裝自簽名證書並使用安全端點配置WSMan。
  3. 重新啓動WSMan。
  4. 打開防火牆端口。

下面是從腳本中提取出代碼:

#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' 

}