Powershell Invoke-Command远程工作,但不是来自Jenkins

时间:2018-04-09 19:29:53

标签: powershell jenkins windows-server-2012-r2 winrm

我有一个非常奇怪的情况,当从Windows Server 2012 R2手动运行时,同一命令可以正常工作,但不能从同一服务器上运行的Jenkins从属进程运行。

首先,手动运行的输出,一个管理PowerShell窗口:

PS C:\Users\Administrator> whoami
win-cm8utd1qfnc\administrator
PS C:\Users\Administrator> Invoke-Command -computername web.sandbox.MUNGED.com -scriptblock {iisreset /restart}
Attempting stop...
Internet services successfully stopped
Attempting start...
Internet services successfully restarted

大。现在,Jenkins管道代码的相关片段:

pipeline {
    stages {
        stage('Deploy web') {
            agent { label 'windows-server-2012' }
            environment {
                SERVER = 'web.sandbox.MUNGED.com'
            }
            steps {
                powershell """
                    whoami
                    Invoke-Command -computername ${SERVER} -scriptblock {iisreset /restart}
                """

            }
        }
    }
}

从Jenkins运行时的输出:

07:37:29 win-cm8utd1qfnc\administrator
07:37:29 [web.sandbox.MUNGED.com] Connecting to remote server web.sandbox.MUNGED.com failed with the following error message : Access is denied. For more information, see the 
07:37:29 about_Remote_Troubleshooting Help topic.
07:37:29     + CategoryInfo          : OpenError: (web.sandbox.MUNGED.com:String) [], PSRemotingTransportException
07:37:29     + FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken

Windows服务器(Jenkins从属服务器和Web服务器)不属于域,但具有相同的管理员密码,这似乎可以使身份验证工作正常。

对于它的价值,这里是Jenkins奴隶的winrm配置:

PS C:\Users\Administrator> winrm get winrm/config
Config
    MaxEnvelopeSizekb = 500
    MaxTimeoutms = 1800000
    MaxBatchItems = 32000
    MaxProviderRequests = 4294967295
    Client
        NetworkDelayms = 5000
        URLPrefix = wsman
        AllowUnencrypted = false
        Auth
            Basic = true
            Digest = true
            Kerberos = true
            Negotiate = true
            Certificate = true
            CredSSP = false
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        TrustedHosts = *
    Service
        RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
        MaxConcurrentOperations = 4294967295
        MaxConcurrentOperationsPerUser = 1500
        EnumerationTimeoutms = 240000
        MaxConnections = 300
        MaxPacketRetrievalTimeSeconds = 120
        AllowUnencrypted = true
        Auth
            Basic = true
            Kerberos = true
            Negotiate = true
            Certificate = false
            CredSSP = false
            CbtHardeningLevel = Relaxed
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        IPv4Filter = *
        IPv6Filter = *
        EnableCompatibilityHttpListener = false
        EnableCompatibilityHttpsListener = false
        CertificateThumbprint
        AllowRemoteAccess = true
    Winrs
        AllowRemoteShellAccess = true
        IdleTimeout = 7200000
        MaxConcurrentUsers = 10
        MaxShellRunTime = 2147483647
        MaxProcessesPerShell = 4096
        MaxMemoryPerShellMB = 8192
        MaxShellsPerUser = 30

来自网络服务器:

PS C:\Users\Administrator> winrm get winrm/config
Config
    MaxEnvelopeSizekb = 500
    MaxTimeoutms = 1800000
    MaxBatchItems = 32000
    MaxProviderRequests = 4294967295
    Client
        NetworkDelayms = 5000
        URLPrefix = wsman
        AllowUnencrypted = false
        Auth
            Basic = true
            Digest = true
            Kerberos = true
            Negotiate = true
            Certificate = true
            CredSSP = false
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        TrustedHosts = *
    Service
        RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
        MaxConcurrentOperations = 4294967295
        MaxConcurrentOperationsPerUser = 1500
        EnumerationTimeoutms = 240000
        MaxConnections = 300
        MaxPacketRetrievalTimeSeconds = 120
        AllowUnencrypted = true
        Auth
            Basic = true
            Kerberos = true
            Negotiate = true
            Certificate = false
            CredSSP = false
            CbtHardeningLevel = Relaxed
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        IPv4Filter = *
        IPv6Filter = *
        EnableCompatibilityHttpListener = false
        EnableCompatibilityHttpsListener = false
        CertificateThumbprint
        AllowRemoteAccess = true
    Winrs
        AllowRemoteShellAccess = true
        IdleTimeout = 7200000
        MaxConcurrentUsers = 10
        MaxShellRunTime = 2147483647
        MaxProcessesPerShell = 25
        MaxMemoryPerShellMB = 1024
        MaxShellsPerUser = 30

编辑:我在时尚之后开始工作了。首先,在詹金斯的奴隶上,我不得不跑:

winrm set winrm/config/client '@{AllowUnencrypted="true"}'

然后我将管道更改为:

powershell """
    \$creds = Import-CliXml \$home\\creds.xml
     Invoke-Command -computername ${SERVER} -scriptblock {iisreset /restart} -Authentication Basic -Credential \$creds
"""

其中creds.xml是先前使用Get-Credentials | Export-CliXml creds.xml生成的文件。

这仍然无法解释为什么手动PowerShell和Jenkins slave之间的行为有所不同。这有点令人讨厌,但至少我可以继续。

2 个答案:

答案 0 :(得分:0)

你可能正在从Jenkins遇到远程执行脚本限制(安全性是这里的原因)。您需要将Jenkins服务器配置为能够运行脚本"通常"但是你总是要添加凭证。

您从powershell命令行运行的脚本使用win-cm8utd1qfnc\administrator的默认凭据,因此以下内容将按您的说法运行:

PS C:\Users\Administrator> whoami
win-cm8utd1qfnc\administrator
PS C:\Users\Administrator> Invoke-Command -computername web.sandbox.MUNGED.com -scriptblock {iisreset /restart}
Attempting stop...
Internet services successfully stopped
Attempting start...
Internet services successfully restarted

然而,当从Jenkins运行Powershell时,就其性质而言,你正在达到设计安全性的限制。你不想跑#34;狂野"管理帐户的脚本。

我在这个主题上找到的最合理的指南是here(以下摘录自页面:

远程执行Powershell脚本/命令

  

他上面的工作在Jenkins服务器上创建了一个文本文件。至   设置远程Powershell脚本我们首先需要配置Jenkins   用于远程Powershell脚本执行的服务器。启用远程   Windows机器进入Jenkins服务器上的WS-Man可信列表。   在Jenkins服务器上的Powershell窗口上执行以下命令。该   命令会将所有远程计算机添加到可信列表中。

     

Set-Item WSMan:\localhost\Client\TrustedHosts *

     

除了命令之外,我们还需要启用远程脚本   执行也。启用远程执行Powershell脚本   在Jenkins服务器的Powershell窗口中执行以下命令。

     

Set-ExecutionPolicy RemoteSigned –Force

     

我们必须安装一个名为EnvInject Plugin的新插件   转移变量例如密码。

Login to Jenkins and navigate to Manage Jenkins > Manage Plugins
Click on the Available tab and Enter EnvInject in the filter box
Select the plugin showing by name PowerShell Plugin
Select Download now and install after restart
     

创建作业以重新启动Windows时间服务:

On Jenkins interface, click New Item
Enter Remote Powershell scripts for the job name. Select Freestyle project
Tick This build is parameterized. Create following parameters
    Type: String Parameter
    Name: ServerIp/Hostname
    Description: Remote machine’s IP address.
    Type: String Parameter
    Name: UserName
    Type: Password Parameter
    Name: Password
Now, Click Add Parameter list and select the Choice Parameter. Enter the options on new lines inside the Choices text box. Also,
     

提供所提及选项的说明:

以下脚本基于上面的链接,但我不喜欢使用的纯文本,因此我决定将其重写为使用Powershell SecureString

首先存储您的管理员密码:

read-host -AsSecureString | ConvertFrom-SecureString | Out-File C:\<your_path>\securestring.txt

然后有脚本:

# Configure build failure on errors on the remote machine similar to set -x on bash script 
$ErrorActionPreference = 'Stop'  

# Create a PSCredential Object using the "Username" and "Password" variables created on job 
$password = Get-Content 'C:\<your_path>\securestring.txt' | ConvertTo-SecureString
$creddentials = New-Object System.Management.Automation.PSCredential -ArgumentList $env:UserName, $password

# It depends on the type of job you are executing on the remote machine as to if you want to use "-ErrorAction Stop" on your Invoke-Command. 
Invoke-Command -ComputerName $env:Computer -Credential $credentials -ScriptBlock { Restart-Service -Name W32Time }

答案 1 :(得分:0)

看到这个问题:Remote Access with Powershell and Jenkins

需要将服务用户从本地系统更改为管理员。