![在 jenkins 凭证 api 中,Ansible slurp 作为私钥进行 json 解析时出现错误?](https://linux22.com/image/716587/%E5%9C%A8%20jenkins%20%E5%87%AD%E8%AF%81%20api%20%E4%B8%AD%EF%BC%8CAnsible%20slurp%20%E4%BD%9C%E4%B8%BA%E7%A7%81%E9%92%A5%E8%BF%9B%E8%A1%8C%20json%20%E8%A7%A3%E6%9E%90%E6%97%B6%E5%87%BA%E7%8E%B0%E9%94%99%E8%AF%AF%EF%BC%9F.png)
我已经设置了 jenkins,现在我想将节点添加到 jenkins,我按照以下步骤操作如何连接远程 SSH 从属设备。
有一个使用slave node
私钥创建凭证的步骤。我尝试使用 ansible 的 jenkins api 创建该凭证。
剧本中的任务包括
- 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
但这失败了,因为
$ 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
我检查了詹金斯日志,它显示 json 解析错误。
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
如果我将私人文件的内容手动复制到privateKey
有效载荷中,它可以正常工作。
复制文件内容 和 有什么区别slurp['content]|b64decode
?
答案1
我认为您的 JSON 在模板引擎扩展后无效。JSON 文件中的字符串可能不包含换行符,而您的私钥字符串包含换行符。您可以使用以下工具验证您的 JSON:JSONLint。
答案2
用于sed -e 's/\n/\\n/g' privkey.rsa
更改你的私钥,并且可以对其进行解析