0

I have jenkins setup, now I want to add node to jenkins, I am following the steps in How-to-Connect-to-Remote-SSH-Slaves.

There is step to create credential with slave node private key. I try to create that using jenkins api by ansible.

Tasks in playbook are

- name: Read private key file content of slave1
  slurp:
      src: "{{ ansible_env.HOME }}/.ssh/slave1"
  register: private_key_file
  tags:
      - credential

- name: Add credential to add node
  uri:
      body: |
          json={
              "": "0",
              "credentials": {
                "scope": "GLOBAL",
                "id": "jenkins_linux_slave1_auth",
                "username": "jenkins",
                "password": "",
                "privateKeySource": {
                  "stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource",
                  "privateKey": "{{ private_key_file['content'] | b64decode }}",
                },
                "description": "Jenkins Linux Slave1 Authentication",
                "stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
              }
            }
      force_basic_auth: yes
      method: POST
      password: "{{ jenkins_user_token }}"
      status_code: 302
      url: "{{ jenkins_url }}/credentials/store/system/domain/_/createCredentials"
      user: "{{ jenkins_user }}"
      validate_certs: no
  tags:
      - credential

But this failed as

$ ansible-playbook -i hosts jenkins_config.yaml --verbose -u root --ask-pass -b -e "jenkins_user=admin" -e "jenkins_user_token=admin" --tags credential
Using /root/ansible_playbooks/ansible.cfg as config file
SSH password:

PLAY [jenkins_servers] ***************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [jenkins_config : Read private key file content of slave1] **********************************************************************************************************************************************************************
ok: [localhost] => {"changed": false, "content": "Content", "encoding": "base64", "source": "/root/.ssh/slave1"}

TASK [jenkins_config : Add credential to add node] ***********************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"cache_control": "no-cache,no-store,must-revalidate", "changed": false, "connection": "close", "content": "\n\n\n\n\n  \n  <!DOCTYPE html><html><head resURL=\"/static/92560838\" data-rooturl=\"\" data-resurl=\"/static/92560838\">\n    \n\n    <title>Jenkins [Jenkins]</title><link rel=\"stylesheet\" href=\"/static/92560838/css/layout-common.css\" type=\"text/css\" /><link rel=\"stylesheet\" href=\"/static/92560838/css/style.css\" type=\"text/css\" /><link rel=\"stylesheet\" href=\"/static/92560838/css/color.css\" type=\"text/css\" /><link rel=\"stylesheet\" href=\"/static/92560838/css/responsive-grid.css\" type=\"text/css\" /><link rel=\"shortcut icon\" href=\"/static/92560838/favicon.ico\" type=\"image/vnd.microsoft.icon\" /><link color=\"black\" rel=\"mask-icon\" href=\"/images/mask-icon.svg\" /><script>var isRunAsTest=false; var rootURL=\"\"; var resURL=\"/static/92560838\";</script><script src=\"/static/92560838/scripts/prototype.js\" type=\"text/javascript\"></script><script src=\"/static/92560838/scripts/behavior.js\" type=\"text/javascript\"></script><script src='/adjuncts/92560838/org/kohsuke/stapler/bind.js' type='text/javascript'></script><script src=\"/static/92560838/scripts/yui/yahoo/yahoo-min.js\"></script><script src=\"/static/92560838/scripts/yui/dom/dom-min.js\"></script><script src=\"/static/92560838/scripts/yui/event/event-min.js\"></script><script src=\"/static/92560838/scripts/yui/animation/animation-min.js\"></script><script src=\"/static/92560838/scripts/yui/dragdrop/dragdrop-min.js\"></script><script src=\"/static/92560838/scripts/yui/container/container-min.js\"></script><script src=\"/static/92560838/scripts/yui/connection/connection-min.js\"></script>
"content_length": "27072", "content_type": "text/html;charset=utf-8", "date": "Mon, 22 Jan 2018 15:58:04 GMT", "expires": "Thu, 01 Jan 1970 00:00:00 GMT", "msg": "Status code was not [302]: HTTP Error 500: Server Error", "redirected": false, "server": "Jetty(9.4.z-SNAPSHOT)", "set_cookie": "JSESSIONID.8c551130=node0v7u4nqouxb1l1kcnd5139in7616.node0;Path=/;Secure;HttpOnly", "status": 500, "url": "http://localhost:8080/credentials/store/system/domain/_/createCredentials", "x_content_type_options": "nosniff", "x_frame_options": "sameorigin", "x_hudson": "1.395", "x_hudson_theme": "default", "x_instance_identity": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgORb1hlBOGx2LlN77veNlsGhwykedmrM+XqbHh0Fq4UGHQKhFicOXSPKiuOr4XpfWRZtYAy7jrY59cCF4So2qHionFUBjQespaALVC+aWQC3qIaZC4NlDgZXz+xQCFFrgW8G2iX2DA5kbPuwuIsv4WlgWvk8Z3kNmAxr16xhRq1R+RmdtVnmTaRyZiHdyQXdVpNHuYzITHfzUyIVIa8elbylS2CgDBMKRasxf7ewX++5Qp5rM5OzDbb5QLAueDhoyjAN2aA+jibUfYKoO7rwgpO3zMbIxuT9SKI7DMM7+TOEDQaH9SF0n+l/WXqpN6PLur9/o/10gsPghMXaV//KpQIDAQAB", "x_jenkins": "2.89.3", "x_jenkins_session": "92560838"}
    to retry, use: --limit @/root/ansible_playbooks/jenkins_config.retry

PLAY RECAP ***************************************************************************************************************************************************************************************************************************
localhost : ok=2    changed=0    unreachable=0    failed=1

I check the jenkins log, it shows error to json parsing.

Jan 22, 2018 11:02:17 AM org.eclipse.jetty.server.handler.ContextHandler$Context log
WARNING: Error while serving http://localhost:8080/credentials/store/system/domain/_/createCredentials
java.lang.reflect.InvocationTargetException
    at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:347)
    at org.kohsuke.stapler.interceptor.RequirePOST$Processor.invoke(RequirePOST.java:52)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: javax.servlet.ServletException: Failed to parse JSON:{
    "": "0",
    "credentials": {
      "scope": "GLOBAL",
      "id": "jenkins_linux_slave1_auth",
      "username": "jenkins",
      "password": "",
      "privateKeySource": {
        "stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource",
        "privateKey": "-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
<MULTI LINE PRIVATE KEY>
-----END RSA PRIVATE KEY-----
",
      },
      "description": "Jenkins Linux Slave1 Authentication",
      "stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
    }
  }

    at org.kohsuke.stapler.RequestImpl.getSubmittedForm(RequestImpl.java:1021)
    at com.cloudbees.plugins.credentials.CredentialsStoreAction$DomainWrapper.doCreateCredentials(CredentialsStoreAction.java:832)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
    at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:343)
    ... 84 more
Caused by: net.sf.json.JSONException: Unterminated string at character 365 of {
    "": "0",
    "credentials": {
      "scope": "GLOBAL",
      "id": "jenkins_linux_slave1_auth",
      "username": "jenkins",
      "password": "",
      "privateKeySource": {
        "stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource",
        "privateKey": "-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
<MULTI LINE PRIVATE KEY>
-----END RSA PRIVATE KEY-----
",
      },
      "description": "Jenkins Linux Slave1 Authentication",
      "stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
    }
  }
    at net.sf.json.util.JSONTokener.syntaxError(JSONTokener.java:499)
    at net.sf.json.util.JSONTokener.nextString(JSONTokener.java:237)
    at net.sf.json.util.JSONTokener.nextValue(JSONTokener.java:345)
    at net.sf.json.JSONObject._fromJSONTokener(JSONObject.java:955)
    at net.sf.json.JSONObject.fromObject(JSONObject.java:156)
    at net.sf.json.util.JSONTokener.nextValue(JSONTokener.java:348)
    at net.sf.json.JSONObject._fromJSONTokener(JSONObject.java:955)
    at net.sf.json.JSONObject.fromObject(JSONObject.java:156)
    at net.sf.json.util.JSONTokener.nextValue(JSONTokener.java:348)
    at net.sf.json.JSONObject._fromJSONTokener(JSONObject.java:955)
    at net.sf.json.JSONObject._fromString(JSONObject.java:1145)
    at net.sf.json.JSONObject.fromObject(JSONObject.java:162)
    at net.sf.json.JSONObject.fromObject(JSONObject.java:132)
    at org.kohsuke.stapler.RequestImpl.getSubmittedForm(RequestImpl.java:1019)
    ... 87 more

If I copy content of private file manually to privateKey in payload, it works fine.

What is the difference between copy file content in and slurp['content]|b64decode ?

Nilesh
  • 255
  • 1
  • 6
  • 17

2 Answers2

1

I believe your JSON is invalid after it has been expanded by the template engine. Strings in JSON files may not contain newlines, and your private key string contains newlines. You may validate your JSON using a tool such as JSONLint.

jayhendren
  • 917
  • 4
  • 11
  • thanks, but what can I do to provide a valid json data to that ? if i past same key with new line (`\n`) character in that, then its working fine. – Nilesh Jan 23 '18 at 19:08
0

use sed -e 's/\n/\\n/g' privkey.rsa to change your priv key and it an be parsed

Michael Hampton
  • 237,123
  • 42
  • 477
  • 940
nayeem
  • 1