Jenkins:在不知道节点秘密的情况下动态地将奴隶连接到主人

Jenkins: dynamically connect slave to master without knowing node secret

我很难(动态地)从我的专用从属机器(Windows 2012 R2 服务器)启动 Jenkins 从属代理。 Jenkins master(版本 1.617 - 如果需要我可以升级,但不能降级 [在版本 1.498 之前不需要凭据])在 Windows 2012 R2 服务器上. 通过 Active Directory 插件和基于项目的矩阵授权策略启用和配置安全性。

由于涉及 Active Directory,我无法简单地添加系统用户进行身份验证(通过 -jnlpCredentials username:password-jnlpCredentials username:apitoken)。作为一种解决方法,我为此使用了我的 Jenkins 服务用户,但我不喜欢它是 API-脚本中硬编码的令牌。
我正在尝试使用替代方案 -secret secretKey,但是当从属节点在主节点上注册时,该 secretKey 是随机创建的。

由于我使用的是 Azure Slave Plugin,因此已为我创建从属节点和关联的虚拟机。 虚拟机是根据预定义的映像创建的,我可以根据需要以任何方式进行更改。
在这个预定义的图像中,我有一个在启动时执行的 PowerShell 脚本。它来自给定的样本 here。不一定是PowerShell,其他方式也可以。

Set-ExecutionPolicy Unrestricted

# base url to Jenkins master
$jenkinsserverurl = "https://jenkins.mycompany.com/"
# the azure-slave-plugin is creating VMs with names like 'Azure0807150842'
$vmname = (Get-Culture).TextInfo.ToTitleCase($env:computername.tolower())
# authenticate with Jenkins service user + API-token - since we don't know the '-secret'
$apiToken="jenkins_user:1234abcdefab56c7d890de1f2a345b67"

Write-Output "Downloading jenkins slave jar "
# in order to avoid updating it manually for Jenkins master updates
$slaveJarSource = $jenkinsserverurl + "jnlpJars/slave.jar"
$slaveJarLocal = "C:\jenkins_home\slave.jar"
$wc = New-Object System.Net.WebClient
$wc.DownloadFile($slaveJarSource, $slaveJarLocal)

Write-Output "Executing slave process "
$jnlpSource = $jenkinsserverurl+"computer/" + $vmname + "/slave-agent.jnlp"
# expect java.exe in the PATH, and use -noCertificateCheck to skip SSL validation
& java -jar $slaveJarLocal -jnlpCredentials $apiToken -jnlpUrl $jnlpSource -noCertificateCheck

下载 JNLP 文件并读取包含的秘密是不可能的,因为我也需要在 Jenkins master 上进行适当的 HTTP 身份验证。

Write-Output "Downloading jenkins slave jnlp "
$jnlpSource = $jenkinsserverurl+"computer/" + $vmname + "/slave-agent.jnlp"
$jnlpLocal = "C:\jenkins_home\slave-agent.jnlp"
$wc = New-Object System.Net.WebClient
$wc.DownloadFile($jnlpSource, $jnlpLocal)

Write-Output "Extracting secret from jenkins slave jnlp "
[xml]$jnlpFile = Get-Content $jnlpLocal
# the first argument in the generated JNLP contains the secret
$secret = Select-Xml "//jnlp/application-desc/argument[1]/text()" $jnlpFile
  1. 我怎样才能得到生成的秘密(不禁用安全性),或者
  2. 我可以使用哪种凭据(无需使用实际用户 - 例如我自己的用户或 Jenkins 服务用户)?

在理想情况下,创建从属节点及其 VM 的插件将登录到创建的 VM 并执行类似于我问题中的脚本 - 添加注入的 Jenkins 服务器 url、虚拟机名称和生成的秘密。由于当前 Azure Slave Plugin 版本不是这种情况,我 坚持使用我的解决方法脚本 - 使用我现有的 Jenkins 服务用户。


我用这个让插件动态创建一个 bigger/faster VM,它仅用于 日常测试 运行 并在其余时间自动关闭(因此 在未使用时不会产生任何费用 )。 如果有人感兴趣,这就是我最终得到的设置:

  1. 通用 Azure VM 映像(Windows 2012 R2,带有 JDK、Maven、Git 安装)。通过 NSSM,我安装了 PowerShell 脚本( 启动从属代理)作为 Windows 服务,将被执行 在机器启动时自动(与问题相同):

    Set-ExecutionPolicy Unrestricted
    
    # base url to Jenkins master
    $jenkinsserverurl = "https://jenkins.mycompany.com/"
    # the azure-slave-plugin is creating VMs with names like 'Azure0807150842'
    $vmname = (Get-Culture).TextInfo.ToTitleCase($env:computername.tolower())
    # authenticate with Jenkins service user + API-token - since we don't know the '-secret'
    $apiToken="jenkins_user:1234abcdefab56c7d890de1f2a345b67"
    
    Write-Output "Downloading jenkins slave jar "
    # in order to avoid updating it manually for Jenkins master updates
    $slaveJarSource = $jenkinsserverurl + "jnlpJars/slave.jar"
    $slaveJarLocal = "C:\jenkins_home\slave.jar"
    $wc = New-Object System.Net.WebClient
    $wc.DownloadFile($slaveJarSource, $slaveJarLocal)
    
    Write-Output "Executing slave process "
    $jnlpSource = $jenkinsserverurl+"computer/" + $vmname + "/slave-agent.jnlp"
    # expect java.exe in the PATH, and use -noCertificateCheck to skip SSL validation
    & java -jar $slaveJarLocal -jnlpCredentials $apiToken -jnlpUrl $jnlpSource -noCertificateCheck
    
  2. 安装并配置了 Azure 从属插件的 Jenkins master 使用此 VM 映像,五分钟后闲置关机。

  3. Jenkins Maven 项目(作业)配置为仅 运行 Azure 从节点,从 Git 检出我的测试项目,然后执行 jUnit Selenium 从那里开始测试。

我在使用 Jenkins Openstack 插件时遇到了同样的问题。

他们似乎会直接在机器的元数据中注入秘密。

https://github.com/jenkinsci/openstack-cloud-plugin/issues/104

与此同时,我将使用 SSH 从服务器,因为只需要在从服务器中部署 pub 密钥,所以更安全。