Jenkins: dynamically connect slave to master without knowing node secret

I am trying to (dynamically) run a Jenkins slave from my dedicated slave (Windows 2012 R2 server). The Jenkins wizard (version 1.617), which I can upgrade if needed, but not downgrade [to 1.498, no credentials required]) is on a Windows 2012 R2 server . Security is enabled and configured through an Active Directory plugin and a project-based authorization strategy.

Due to active Active Directory, I cannot just add the system user for authentication (via -jnlpCredentials username:password

or -jnlpCredentials username:apitoken

). As a workaround, I'm using Jenkins service for this user, but I don't like the hardcoded API token in the script.
I am trying an alternative -secret secretKey

, but this secretKey is generated randomly when the slave node is registered with the master.

Since I am using the Azure Slave Plugin , slaves and associated virtual machines are created for me. Virtual machines are created from a predefined image that I can change in any way. In this predefined image, I have a PowerShell script executed at startup. It is derived from the example provided here . It doesn't have to be PowerShell, any other way would be fine too.

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

      

Downloading the JNLP file and reading the private key is not an option as I need proper HTTP authentication for the Jenkins master to do this.

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

      

  • How can I get the generated secret (without disabling security), or
  • What types of credentials can I use instead (without using an actual user - like my own or Jenkins service user)?
+3


source to share


2 answers


In an ideal world, the plugin creating the slave node and its VM would go into the VM that was created and execute a script similar to the one in my question - with the addition of the Jenkins Server URL entered, VM Name, and the generated secret. Since this is not the case for the current version of the Azure Slave Plugin , I am stuck with my workaround script - using my existing Jenkins service user.




I use this to allow the plugin to create a larger / faster VM on the fly which is only used for daily test runand automatically shuts down the rest of the time (and therefore incurs no cost when not in use ). If anyone is interested, this is the setup I ended up with:

  • Generic image of Azure VM (Windows 2012 R2, with JDK, Maven, Git installed). Through NSSM, I have set the PowerShell script (which starts the slave agent) as a Windows service to execute automatically when the machine boots (same as in the question):

    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
    
          

  • Jenkins master with Azure Slave plugin installed and configured to use this VM image after shutdown idle after five minutes.

  • Jenkins Maven (Job) project, which is only configured on Azure slave node, checks out my test project from Git and runs jUnit Selenium tests from there.

+1


source


I got into the same issue with Jenkins Openstack plugin.

They seem to be injecting the secret directly into the machine's metadata.



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

At the same time, I am using an SSH slave instead, which is more secure since only the pub key needs to be deployed to the slave.

+1


source







All Articles