Exception while adding ssh credentials to Jenkins programmatically - jenkins

I have used a method mentioned here to add credential to Jenkins programmatically. It worked successfully for adding secret texts and secrets files. But it gives an exception while adding ssh private keys. Below is the curl command I used.
curl -X POST 'http://localhost:8080/jenkins/credentials/store/system/domain/_/createCredentials' \
--data-urlencode 'json={
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "temp",
"username": "temp",
"privateKeySource": {
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$FileOnMasterPrivateKeySource",
"privateKeyFile": "/home/udhan/private-key.pem",
},
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}'
Here is the exception I get.
A problem occurred while processing the request.
Please check our bug tracker to see if a similar problem has already been reported.
If it is already reported, please vote and put a comment on it to let us gauge the impact of the problem.
If you think this is a new issue, please file a new issue.
When you file an issue, make sure to add the entire stack trace, along with the version of Jenkins and relevant plugins.
The users list might be also useful in understanding what has happened.</p><h2>Stack trace</h2><pre style="margin:2em; clear:both">org.kohsuke.stapler.NoStaplerConstructorException: There's no #DataBoundConstructor on any constructor of class com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$FileOnMasterPrivateKeySource
at org.kohsuke.stapler.ClassDescriptor.loadConstructorParamNames(ClassDescriptor.java:265)
at org.kohsuke.stapler.RequestImpl.instantiate(RequestImpl.java:765)
at org.kohsuke.stapler.RequestImpl.access$200(RequestImpl.java:83)
at org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:678)

I've just bumped into this same problem right now. Rather than using a pem file, I ended up putting the SSH pem's value into a variable and passed it that way instead.
CRUMB=$(curl -s 'https://{{jenkins_admin_username}}:{{jenkins_admin_password}}#localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
SSH_KEY="$(cat /your/ssh/pem)"
curl -H $CRUMB -X POST 'https://{{jenkins_admin_username}}:{{jenkins_admin_password}}#localhost:8080/credentials/store/system/domain/_/createCredentials' --data-urlencode 'json={
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "'test-jenkins-id'",
"username": "'test-username'",
"password": "",
"privateKeySource": {
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource",
"privateKey": "$SSH_KEY",
},
"description": "test-jenkins-ssh description",
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}'
Not that I went with https instead of http here as we're passing things that should be secured.
I hope this helps.

Related

Is it possible to get git committer and author email with Travis API v3?

In Travis API v2 I would get committer_email and author_email as described in the docs. However, in v3 I only get the name, as In this example:
$ curl -H "Authorization: token $TRAVIS_API_TOKEN" \
-H "travis-api-version: 3" \
'https://travis.example.com/api/repo/acme%my-app/builds?include=build.commit&limit=1'
{
"#type": "builds",
...
"builds": [
{
"#type": "build",
...
"id": 17771810,
"number": "26506",
...
"commit": {
"#type": "commit",
...
"message": "foo bar",
"committed_at": "2022-08-22T06:55:55Z",
"committer": {
"name": "John Doe",
"avatar_url": "https://0.gravatar.com/avatar/foobar"
},
"author": {
"name": "John Doe",
"avatar_url": "https://0.gravatar.com/avatar/foobar"
}
The commit and author data in the API is just defined as an Object without further definition:
committer Object Committer data.
author Object Committer data.
I'm testing this on an on-site install of Travis CI v3 Enterprise.
I got the answer from Travis CI support:
I have been discussing this with one of the Enterprise Engineers and it seems like it was intended not to expose the email information on the Travis CI API v3, in this case, the behaviour is expected, however, you will still have the author name and commuter name as you have mentioned.
Luckily Travis CI API v2 should still be available for the Travis CI Enterprise 3.x instance, so I'll be able to get the email for a while longer.

node-red upload attachment over http with token (multipart/form-data)

I am lost recreating curl POST request in node red.
My bank API documentation requires to form request like this:
multipart/form-data
curl -S -s --cacert GeoTrust_Primary_CA.pem -X POST -F "type=xml" -F "token=aGEMQB9Idh35fxxxxxxxxxxxxxQwyGlQ" -F "file=#C:\davka.xml" https://www.fio.cz/ib_api/rest/import/> result.xml 2>errorlog.txt type errorlog.txt
I really need just
curl -X POST -F "type=xml" -F "token=aGEMQB9Idh35fxxxxxxxxxxxxxQwyGlQ" -F "file=#C:\davka.xml" https://www.fio.cz/ib_api/rest/import/
However I am not able to pass the token to the form.
still get Required String parameter 'token' is not present
I failed with prefered http request or many node-red-contrib-send-form(...) variations.
My flow:
[{"id":"f0c84434.8907a8","type":"fileinject","z":"6012893b.689db8","name":"/share/result.xml","x":220,"y":300,"wires":[["690ae5f4.37b66c"]]},{"id":"690ae5f4.37b66c","type":"function","z":"6012893b.689db8","name":"","func":"msg.headers = {\n "content-type" : 'multipart/form-data'\n };\nlet databuffer = msg.payload;\n\nmsg.payload = {\n "KEY": {\n "value": databuffer,\n "options": {\n "filename": "data.xml",\n "type": "xml",\n "token": "aGEMQB9Idh35fxxxxxfakexxxxxxxxQwyGlQ"\n }\n }\n}\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":600,"y":220,"wires":[["6cca79ea.a45f28"]]},{"id":"6cca79ea.a45f28","type":"http request","z":"6012893b.689db8","name":"","method":"POST","ret":"txt","paytoqs":"ignore","url":"https://www.fio.cz/ib_api/rest/import/","tls":"","persist":false,"proxy":"","authType":"","x":760,"y":220,"wires":[["8ec9dd16.83be","3f347cc6.b9a114"]]},{"id":"8ec9dd16.83be","type":"debug","z":"6012893b.689db8","name":"File has been sent","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":980,"y":220,"wires":[]},{"id":"ba973765.11aa88","type":"inject","z":"6012893b.689db8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":220,"wires":[["e75f0fb7.fa71b"]]},{"id":"e75f0fb7.fa71b","type":"file in","z":"6012893b.689db8","name":"","filename":"/share/result.xml","format":"","chunk":false,"sendError":false,"encoding":"none","x":360,"y":220,"wires":[["690ae5f4.37b66c"]]},{"id":"3f347cc6.b9a114","type":"debug","z":"6012893b.689db8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"statusCode","targetType":"msg","statusVal":"","statusType":"auto","x":970,"y":280,"wires":[]}]
You should be able to do this with the core HTTP Request node. The issue is the format of the payload you are passing it.
If you change your Function node to structure the payload like this, I believe you should get further:
msg.payload = {
"file": {
"value": databuffer,
"options": {
"filename": "data.xml",
}
},
"type": "xml",
"token": "aGEMQB9Idh35fxxxxxfakexxxxxxxxQwyGlQ"
}

502 Bad Gateway nginx/1.13.12 on localhost while creating a new policy in ditto

I am new to docker, I'm using docker on windows 10 and am using Eclipse Ditto and Eclipse Mosquitto, I have to create a twin device. Before that I have to create a new policy via Postman,
While executing the policy am getting the following error:
The code to create the new policy is ass follow
curl -X put 'http://localhost:8080/api/2/policies/my.test:policy' -u 'ditto:ditto' -H 'Content-Type: application/json' -d '{
"entries": {
"owner": {
"subjects": {
"nginx:ditto": {
"type": "nginx basic auth user"
}
},
"resources": {
"thing:/": {
"grant": [
"READ","WRITE"
],
"revoke": []
},
"policy:/": {
"grant": [
"READ","WRITE"
],
"revoke": []
},
"message:/": {
"grant": [
"READ","WRITE"
],
"revoke": []
}
}
}
}
}'
I'm following the procedure given in this link
is there any solution to solve this kind of problem?
Seems that the Eclipse Ditto gateway service was not running correctly.
I'm confident that you figured out to look at the output of docker-compose ps and restarted the services.

Swagger Code generation error

Some help needed i was trying to generate the swagger client code using the command for an Expedia mobile API
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -i https://www.expedia.co.jp/static/mobile/swaggerui/swagger.json -l java -o samples/client/expedia
The code generation fails with the following error
[main] ERROR io.swagger.codegen.languages.JavaClientCodegen - No Type defined for Property null Exception in thread "main" java.lang.RuntimeException: Could not generate model
'detailedRentalFare'
The type attribute within the DetailedRentalFare is where it fails. I am not sure why this fails since the data type is defined. I am newbie to Swagger any help will be greatly appreciated
From #wing328's answer, even if this isn't your service to fix, you can still generate a client from it.
First, just download the JSON locally:
wget https://www.expedia.co.jp/static/mobile/swaggerui/swagger.json > expedia.json
Next, modify the value in the JSON that #wing328 pointed out
Finally, rerun your codegen using the static file as the source:
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i ./expedia.json \
-l java \
-o samples/client/expedia
It's always nice to let the service owner know about the issue, too, since fixing it will help with their adoption of the api.
Answer provided by #wing328
the issue is caused by incorrect type for array, e.g.
"detailedRentalFare": {
"properties": {
"rateTerm": {
"type": "string",
"description": "It can have the following values: HOURLY, DAILY, WEEKLY, WEEKEND, MONTHLY, TOTAL, TRIP"
},
"rate": {
"$ref": "mobilePrice"
},
"priceBreakdownOfTotalDueToday": {
"type": "array",
"items": {
"type": "rentalFareBreakdownItem"
}
},
It should be
"items": {
"$ref": "rentalFareBreakdownItem"
}
or even better
"items": {
"type": "object",
"$ref": "rentalFareBreakdownItem"
}
After correcting this i was able to generate the code.

How to create jenkins credentials via the REST API?

I need to create a jenkins credential ( https://wiki.jenkins-ci.org/display/JENKINS/Credentials+Plugin ) via a script. How can I do that using either the REST API or the cli ?
Note that I'm able to list the credentials using /credential-store/domain//api/json and /credential-store/domain//credential/8bd82461-e239-4db1-90bc-831ca3412e70/api/json etc.
This issue took me a while to figure, a lot of digging around, so I decided to let the solution here, if someone else needs it.
curl -X POST 'http://user:token#jenkins_server:8080/credentials/store/system/domain/_/createCredentials' \
--data-urlencode 'json={
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "identification",
"username": "manu",
"password": "bar",
"description": "linda",
"$class": "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"
}
}'
with latest jenkins you need a CRUMB to authenticate for this operation (ref https://stackoverflow.com/a/38314286)
CRUMB=$(curl -s 'http://user:token#jenkins_server:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
curl -H $CRUMB -X POST 'http://user:token#jenkins_server:8080/credentials/store/system/domain/_/createCredentials' \
--data-urlencode 'json={
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "identification",
"username": "manu",
"password": "bar",
"description": "linda",
"$class": "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"
}
}'
Otherwise you get
<body><h2>HTTP ERROR 403</h2>
<p>Problem accessing /credentials/store/system/domain/_/createCredentials. Reason:
<pre> No valid crumb was included in the request</pre></p><hr><i><small>Powered by Jetty://</small></i><hr/>
if you need to create credentials but with pem file path you can use this:
prerequisites: ssh-credentials plugin
CRUMB=$(curl -s 'http://{{jenkins_admin_username}}:{{jenkins_admin_password}}#localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
curl -H $CRUMB -X POST 'http://{{jenkins_admin_username}}:{{jenkins_admin_password}}#localhost:8080/credentials/store/system/domain/_/createCredentials' \
--data-urlencode 'json={
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "'{{ii.ssh_user}}'",
"username": "'{{ii.ssh_user}}'",
"password": "",
"privateKeySource": {
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$FileOnMasterPrivateKeySource",
"privateKeyFile": "'{{jenkins_home}}/{{ii.key_name}}.pem'",
},
"description": "'{{ii.ssh_user}}'",
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}'
this command used in ansible but you can replace the {{variables}} with your own variables
if you need to add all the pem file content you need to change the lines to:
....
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource",
"privateKey": "{{private_key_content}}",
},
"description": "{{user}}",
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
...
Just adding my 2 cents here: if you want to create the credentials for a specific folder, then use the following:
curl -H $CRUMB -X POST 'http://user:token#jenkins_server:8080/job/MY_FOLDER_NAME/credentials/store/folder/domain/_/createCredentials' \
...
So, you need to use /job/My_Folder at the beginning of the query part and replace the /store/system with /store/folder
There is no specific API call for this, but you can do it via cli commands to the jenkins jar.
echo 'jenkins.model.Jenkins.instance.securityRealm.createAccount("username", "password")' | java -jar jenkins-cli.jar -s http://localhost/ groovy =
For granting them permissions you can create a task in Jenkins which is running every N minutes and executing a groovy script as described here:
https://wiki.jenkins-ci.org/display/JENKINS/Grant+Cancel+Permission+for+user+and+group+that+have+Build+permission
I have a groovy script that also sets user permission using Matrix-based security. The script was posted at Creating user in Jenkins via API
Unable to point to ssh keys in ~/.ssh on Jenkins host
Means this no longer works,
"privateKeySource": {
"stapler-class": "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$FileOnMasterPrivateKeySource",
"privateKeyFile": "'{{jenkins_home}}/{{ii.key_name}}.pem'",
},
📌 Here is the official documentation for managing the Jenkins Credentials via REST API
https://github.com/jenkinsci/credentials-plugin/blob/master/docs/user.adoc#creating-a-credentials
Example of adding a deploy-key credential using the username wecoyote and the password secret123 in the testing domain of the /example-folder folder.
$ cat > credential.xml <<EOF
<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
<scope>GLOBAL</scope>
<id>deploy-key</id>
<description>Test User</description>
<usernameSecret>false</usernameSecret>
<username>wecoyote</username>
<password>secret123</password>
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
EOF
$ curl -X POST -u <username>:<password_or_token> -H content-type:application/xml -d #credential.xml \
https://jenkins.example.com/job/example-folder/credentials/store/folder/\
domain/testing/createCredentials
The expected responses are:
HTTP/200 Success, the credentials has been created.
HTTP/409 Failure, a credential with that id already exists.
HTTP/50x Could not parse the supplied domain XML body.

Resources