Search code examples
sshjenkinsautomationcredentialsslave

How do I automate Jenkins SSH credentials creation/assigning to nodes?


I am writing an automated Jenkins machine creation script, and I have encountered a problem with SSH credentials, namely:

In Jenkins there is a file called credentials.xml (in /var/lib/jenkins) which stored credentials for the nodes. Mine looks like so:

<?xml version='1.0' encoding='UTF-8'?>
<com.cloudbees.plugins.credentials.SystemCredentialsProvider plugin="[email protected]">
  <domainCredentialsMap class="hudson.util.CopyOnWriteMap$Hash">
    <entry>
      <com.cloudbees.plugins.credentials.domains.Domain>
        <specifications/>
      </com.cloudbees.plugins.credentials.domains.Domain>
      <java.util.concurrent.CopyOnWriteArrayList>
        <com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
          <scope>GLOBAL</scope>
          <id>8743cc14-bc2c-44a6-b6bb-c121bef4ae2d</id>
          <description>root_with_secret</description>
          <username>root</username>
          <password>2Xd4i7+8tjVXg2RHP6ggl/ZtWJp177ajXNajJxsj80o=</password>
        </com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
      </java.util.concurrent.CopyOnWriteArrayList>
    </entry>
  </domainCredentialsMap>

There is (are) also nodes (slaves) configuration file(s) (stored in /var/lib/jenkins/nodes/HOSTNAME/config.xml for each slave) which look(s) like:

<?xml version='1.0' encoding='UTF-8'?>
<slave>
  <name>HOSTNAME_OF_MY_SECRET_MACHINE</name>
  <description>HOSTNAME_OF_MY_SECRET_MACHINE</description>
  <remoteFS>/root</remoteFS>
  <numExecutors>1</numExecutors>
  <mode>NORMAL</mode>
  <retentionStrategy class="hudson.slaves.RetentionStrategy$Always"/>
  <launcher class="hudson.plugins.sshslaves.SSHLauncher" plugin="[email protected]">
    <host>10.0.10.1</host>
    <port>22</port>
    <credentialsId>8743cc14-bc2c-44a6-b6bb-c121bef4ae2d</credentialsId>
    <maxNumRetries>0</maxNumRetries>
    <retryWaitTime>0</retryWaitTime>
  </launcher>
  <label></label>
  <nodeProperties/>
  <userId>anonymous</userId>
</slave>

The problem is that after I create the jenkins machine, copy credentials.xml and config.xmls for each slave then the credentials wouldn't work. I get

[07/26/15 16:00:39] [SSH] Opening SSH connection to 10.0.10.1:22.
ERROR: Failed to authenticate as root. Wrong password. (credentialId:8743cc14-bc2c-44a6-b6bb-c121bef4ae2d/method:password)
[07/26/15 16:00:41] [SSH] Authentication failed.
hudson.AbortException: Authentication failed.
    at hudson.plugins.sshslaves.SSHLauncher.openConnection(SSHLauncher.java:1178)
    at hudson.plugins.sshslaves.SSHLauncher$2.call(SSHLauncher.java:701)
    at hudson.plugins.sshslaves.SSHLauncher$2.call(SSHLauncher.java:696)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
[07/26/15 16:00:41] Launch failed - cleaning up connection
[07/26/15 16:00:41] [SSH] Connection closed.

To solve this issue I can go to Jenkins -> Credentials -> and then update the credential with the same password that I would use anyway and it will work.

So the question is whether Jenkins uses kind of salting/hashing per installation so that the credentials.xml will not work if copied to a new machine?


Solution

  • OK, I have managed to solve this with (I believe) a workaround-ish solution, namely:

    To store a password in plain text in credentials.xml, copy it over to the Jenkins machine after installing and starting the service. Then Jenkins will encrypt it with its new secret (or whatever it uses for that purpose) and it will work :)

    EDIT

    A second option is to install Jenkins, start it, and then copy the credentials.xml with encrypted passwords together with secrets directory and secret.xml from previous installation. This will copy both encryption master key and the encrypted credentials that have been created using this master key.