Jenkins REST API Create job - jenkins

I'm creating a new job in Jenkins using the REST API. I tried the below curl command lines, but they are throwing an error
curl -i -X POST --user "admin:<API token>" --data-binary "#C:\mylocalconfig.xml" -H "Content-Type: text/xml" http://localhost:8080/createItem?name=NewJob
curl -X POST -u <username>:<pass> -H "Content-Type:application/xml" -d "#C:\mylocalconfig.xml" "http://localhost:8080/createItem?name=AA_TEST_JOB3"
Error:
HTTP/1.1 403 No valid crumb was included in the request
Date: Fri, 01 Jul 2016 05:25:59 GMT
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=ISO-8859-1
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 360
Server: Jetty(9.2.z-SNAPSHOT)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Error 403 No valid crumb was included in the request</title>
</head>
<body><h2>HTTP ERROR 403</h2>
<p>Problem accessing /createItem. Reason:
<pre> No valid crumb was included in the request</pre></p><hr><i><small>Power
ed by Jetty://</small></i><hr/>
</body>
</html>

Jenkins by default has CSRF Protection enabled which prevents one-click attacks. To invoke the request, you need to obtain the crumb from /crumbIssuer/api/xml using your credentials and include it into your request.
For example:
CRUMB=$(curl -s 'http://USER:TOKEN#localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
Then you can create a job (by including the crumb into your header):
curl -X POST -H "$CRUMB" "http://USER:TOKEN#localhost:8080/createItem?name=NewJob"
If the above won't work, check your crumb (echo $CRUMB) or run curl with -u USER:TOKEN.
For a more detailed explanation, see: Running jenkins jobs via command line.

If you are using Postman to fire the requests, using #kenorb example above, get the crumb
To create a folder at root level using the createItem endpoint
To create a sub-folder inside the folder created above using the createItem endpoint

Related

Unable to trigger Jenkins job using API Token command-line curl

I'm new to this and not sure if I'm doing this right.
My requirement is to trigger(build) a jenkins job using command-line which I will invoke using ansible.
I'm following the instructions on this stackoverflow link.
I followed the below steps but Unfortunately the build does not get triggered.
Step 1:
I logged in Jenkins portal https://myjenkins.com:9043 using my user id user114 which is also the Jenkins administrator.
I then created API-token for my user id which is 118f32aa48601c136d29y11f3dd0e107f5.
Step 2:
I then selected Trigger Build Remotely option for job5 and gave the token name as 118f32aa48601c136d29y11f3dd0e107f5
Step 3: I then created Jenkins-Crumb using the below command:
`curl -s -k 'https://user114:118f32aa48601c136d29y11f3dd0e107f5#myjenkins.com:9043/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'
Jenkins-Crumb:5196c183ad95cf3c0482873e34236f3b78ab628ecba968086cd19s7430016a4e`
Then i tried the below commands with the intention of triggering the build for job5 but none of them triggered my Jenkins build.
Attemp 1:
$ curl -I -k -X POST https://user114:118f32aa48601c136d29y11f3dd0e107f5#myjenkins.com:9043/job/job5/build -H "Jenkins-Crumb:5196c183ad95cf3c0482873e34236f3b78ab628ecba968086cd19s7430016a4e"
HTTP/1.1 400 Bad Request
X-Content-Type-Options: nosniff
Cache-Control: must-revalidate,no-cache,no-store
Content-Type: text/html;charset=iso-8859-1
Content-Length: 481
Server: Jetty(NOTHING)
Attempt 2:
$ curl -k -X POST https://user114:118f32aa48601c136d29y11f3dd0e107f5#myjenkins.com:9043/job/job5/build -H "Jenkins-Crumb:5196c183ad95cf3c0482873e34236f3b78ab628ecba968086cd19s7430016a4e"
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 400 Nothing is submitted</title>
</head>
<body><h2>HTTP ERROR 400 Nothing is submitted</h2>
<table>
<tr><th>URI:</th><td>/job/job5/build</td></tr>
<tr><th>STATUS:</th><td>400</td></tr>
<tr><th>MESSAGE:</th><td>Nothing is submitted</td></tr>
<tr><th>SERVLET:</th><td>Stapler</td></tr>
</table>
<hr>Powered by Jetty:// NOTHING<hr/>
</body>
Attempt 3:
$ curl -k -X POST https://user114:118f32aa48601c136d29y11f3dd0e107f5#myjenkins.com:9043/job/job5/build?token=118f32aa48601c136d29y11f3dd0e107f5 -H "Jenkins-Crumb:5196c183ad95cf3c0482873e34236f3b78ab628ecba968086cd19s7430016a4e"
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 400 This page expects a form submission</title>
</head>
<body><h2>HTTP ERROR 400 This page expects a form submission</h2>
<table>
<tr><th>URI:</th><td>/job/job5/build</td></tr>
<tr><th>STATUS:</th><td>400</td></tr>
<tr><th>MESSAGE:</th><td>This page expects a form submission</td></tr>
<tr><th>SERVLET:</th><td>Stapler</td></tr>
</table>
<hr>Powered by Jetty:// NOTHING<hr/>
</body>
</html>
Further, I also intend to pass parameters to this jenkins job which i dont know how-to.
Can you please suggest ?
I started using the Generic Webhook Plugin for this. It takes away a lot of the hassle and allows you to parse any JSON/XML payload as you please.

Automatically allow-unauthenticated users to cloud run instances

Hi am developing a solution that creates and deploys services to Google cloud run using its REST API with OAuth as a service account created fot that purpose.
I am stuck at making the created services available publicly.
I was unable to find a corresponding --allow-unauthenticated parameter as with gcloud to use from the API.
The only way I found is to manually add allUsers as Cloud Run Invoker on each service I want publicly reachable. But, I would like all the services from that service-account to be automatically reacheable publicly.
I would like to know if there is a better(more automatic) way to achieve this.
Thanks in advance.
Firstly, you can't do this in only one command. You have to deploy the service and then to grant allUsers on the service. The CLI do this 2 steps conveniently for you.
Anyway, when you are stuck like this, there is a useful trick: add --log-http at your gcloud command. Like this, you will see all the HTTP API calls performed by the CLI.
if you do this when you deploy a new Cloud Run service, you will have tons of line and, at a moment, you have this
==== request start ====
uri: https://run.googleapis.com/v1/projects/gbl-imt-homerider-basguillaueb/locations/us-central1/services/predict2:setIamPolicy?alt=json
method: POST
== headers start ==
b'Authorization': --- Token Redacted ---
b'X-Goog-User-Project': b'gbl-imt-homerider-basguillaueb'
b'accept': b'application/json'
b'accept-encoding': b'gzip, deflate'
b'content-length': b'98'
b'content-type': b'application/json'
b'user-agent': b'google-cloud-sdk gcloud/299.0.0 command/gcloud.run.deploy invocation-id/61070d063a604fdda8e87ad63777e3ae environment/devshell environment-version/None interactive/True from-script/False python/3.7.3 term/screen (Linux 4.19.112+
)'
== headers end ==
⠹ Deploying new service...
{"policy": {"bindings": [{"members": ["allUsers"], "role": "roles/run.invoker"}], "etag": "ACAB"}}
== body end ==
⠹ Setting IAM Policy...
---- response start ----
status: 200
-- headers start --
-content-encoding: gzip
cache-control: private
content-length: 159
content-type: application/json; charset=UTF-8
date: Wed, 08 Jul 2020 11:37:11 GMT
server: ESF
transfer-encoding: chunked
vary: Origin, X-Origin, Referer
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 0
-- headers end --
-- body start --
{
"version": 1,
"etag": "BwWp7IdZGHs=",
"bindings": [
{
"role": "roles/run.invoker",
"members": [
"allUsers"
]
}
]
}
So, it's an addition API call that perform the CLI for you. You can find here the API definition
If you want to perform a call manually, you can do a request like this
curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "content-type: application/json" -X POST \
-d '{"policy": {"bindings": [{"members": ["allUsers"], "role": "roles/run.invoker"}]}}' \
"https://run.googleapis.com/v1/projects/<PROJECT_ID>/locations/<REGION>/services/<SERVICE_NAME>:setIamPolicy"

How to POST with curl and not get HTTP error 422 'Unprocessable Entity'?

I am trying to send a POST request to an sign in endpoint. I keep getting HTTP error 422 'Unprocessable Entity'. How do I get past this error?
Here are some examples of commands I have tried:
curl -v -X POST -F 'user[email]=test#email.com' -F 'user[password]=password' https://example.com/users/sign_in
curl -v -H 'Accept: text/html,application/xhtml+xml,application/xml;' -H 'Content-Type: application/x-www-form-urlencoded' -d 'utf8=%E2%9C%93&authenticity_token=123456789123456789123456789123123123456456456789789789789VX4KgMBr6zgGjo123456789123456789njQ%3D%3D&user%5Bemail%5D=test%40sign_in.com&user%5Bpassword%5D=password&commit=Sign+in' https://example.com/users/sign_in
I want the request to send back a 200 or 301/302 response status, but instead I get this:
* upload completely sent off: 208 out of 208 bytes
< HTTP/1.1 422 Unprocessable Entity
< Server: nginx/1.12.2
< Date: Fri, 08 Feb 2019 12:08:07 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 0
< Connection: keep-alive
< X-Request-Id: 6ceb5baa-7740-448a-8105-6f67dd203fbb
< X-Runtime: 0.021676
Any help or advice is appreciated. Thanks
Update
I see now that the Rails log from such a request renders an InvalidAuthenticityToken Error
Started POST "/users/sign_in" for 127.0.0.1 at 2019-02-08 14:30:50 +0000
Processing by Users::SessionsController#create as */*
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)
ActionController::InvalidAuthenticityToken - ActionController::InvalidAuthenticityToken:
Any ideas on how to get past this? All I am seeking to do is ensure that routes which require authentication are returning 200/301/302 responses.
There are at least two ways to do this:
Option 1: get and use a token
One way to solve this is to actually capture and utilize the authenticity token that rails generates. To do this, we also need to capture and then send back cookies, to allow ourselves to utilize a session that is associated with the generated token. I was able to get this to work with something like the following incantation.
(Note: I'm assuming a scaffold has been created for "thing", creating a things_controller.rb, etc. Adapt this to your use case as needed.)
step 1: capture the token:
token=$(curl -s -c myjar https://example.com/things/new | \
sed -n 's/.*name="authenticity_token" value="\([^"]*\)".*/\1/p')
step 2: use it in the request:
cat myjar | \
curl -b - -s \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-d '{"thing": {"field1":"Test","field2":"Testing"},
"authenticity_token":"'"$token"'"}' \
https://example.com/things | jq .
This works, without any changes to the application. When I run that, I see a pretty rendering of the JSON from a successful object creation as output.
(Ignore the | jq . if you just want the raw JSON data, perhaps to send it along to something else.)
However, there is another option. With a small tweak to the controller, one can achieve a bit easier curl usage (no cookiejar required, fewer parameters, only a single curl command, and no strange nested quotes), as follows:
Option 2: disable token checking:
Another way to get past this is to disable the validity_token checking for the create action in any controller(s) you wish to allow this sort of thing from. For example, given my example of a scaffold called "thing", one might update the app/controllers/things_controller.rb file to add the second line shown here:
class ThingsController < ApplicationController # EXISTING LINE
skip_before_action :verify_authenticity_token, only: [:create] # NEW LINE
before_action :set_img, only: [:show, :edit, :update, :destroy] # EXISTING LINE
# ... additional content elided ...
And then rails simply won't do that check, so one can do a one-step requset something like:
curl -s \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-d '{"thing": {"field1":"Test","field2":"Testing"}}' \
http://example.com/things | jq .
Again, I see the jq-generated output, this time without having to capture cookies or a token or anything.

Spring Boot and XMLHttpRequest

I am having a hard time understanding how Spring Boot (v1.3.3) handles the X-Requested-With: XMLHttpRequest header. My understanding is that this header tells Spring Boot to return, for requests without an authenticated session, a 401-Unauthorized error rather than a 302-Found with a location to the login page.
I have set up my AngularJS client to send this header for any routing, and then configured an $http interceptor to act on the 401 error by displaying a dialog. Doesn't work for me, with a Spring Boot server with no additional security configuration.
With some investigation with CURL:
It seems that the -H "Accept: application/json" header also needs to be provided.
curl -v -H "X-Requested-With: XMLHttpRequest" localhost:9080/ returns a 302, while curl -v -H "X-Requested-With: XMLHttpRequest" -H "Accept: application/json" localhost:9080/ returns a 401.
Questions: Why is the application/json header required as well? Can I configure it differently (i.e. not require application/json header)? Should I configure it this way, or take another approach? The reason I don't want to require the application/json header is because I am not allowing public access to some resources, such as HTML templates and JS code, and want a 401 returned for these resources as well.
It seems that the JSESSIONID cookie may be affecting the response.
curl -v -H "X-Requested-With: XMLHttpRequest" -H "Accept: application/json" localhost:9080/ returns a 401, while curl -v -H "X-Requested-With: XMLHttpRequest" -H "Accept: application/json" -H "Cookie: JSESSIONID=63EA6E09F64B98938E4495DF9898323A" localhost:9080/' returns a 302.
Questions: Why does the presence of the (valid) JSESSIONID cookie make any difference?
I have looked at the source code for Spring Security and Spring Boot and I just cannot put together the pieces. Any help is much appreciated.

Download link (via API) to publicly accessible file on google docs returns 401

I've uploaded a (pgp) file via the documents API, and changed its
visibility to public. However, I'm unable to download it publicly
using the contents link for that file.
Here are the relevant bits of the xml for the meta-data for the file in
question.
$ curl -H "GData-Version: 3.0" -H "Authorization: Bearer ..." https://docs.google.com/feeds/default/private/full
...
<content type="application/pgp-encrypted" src="https://doc-0c-c0-docs.googleusercontent.com/docs/securesc/tkl8gnmcm9fhm6fec3160bcgajgf0i18/opa6m1tmj5cufpvrj89bv4dt0q6696a4/1336514400000/04627947781497054983/04627947781497054983/0B_-KWHz80dDXZ2dYdEZ0dGw3akE?h=16653014193614665626&e=download&gd=true"/>
...
<gd:feedLink rel="http://schemas.google.com/acl/2007#accessControlList" href="https://docs.google.com/feeds/default/private/full/file%3A0B_-KWHz80dDXZ2dYdEZ0dGw3akE/acl"/>
$ curl -H "GData-Version: 3.0" -H "Authorization: Bearer ..." https://docs.google.com/feeds/default/private/full/file%3A0B_-KWHz80dDXZ2dYdEZ0dGw3akE/acl
...
<entry gd:etag="W/"DUcNRns4eCt7ImA9WhVVFUw."">
<id>https://docs.google.com/feeds/id/file%3A0B_-KWHz80dDXZ2dYdEZ0dGw3akE/acl/default</id>
...
<gAcl:role value="reader"/>
<gAcl:scope type="default"/>
...
The role/scope returned for the file in question is reader/default, indicating
it is public. (It also shows up with public shared access in the web UI.)
However, accessing
the src attribute in the content element results in:
$ curl --verbose 'https://doc-0c-c0-docs.googleusercontent.com/docs/securesc/tkl8gnmcm9fhm6fec3160bcgajgf0i18/opa6m1tmj5cufpvrj89bv4dt0q6696a4/1336514400000/04627947781497054983/04627947781497054983/0B_-KWHz80dDXZ2dYdEZ0dGw3akE?h=16653014193614665626&e=download&gd=true'
< HTTP/1.1 401 Unauthorized
< Server: HTTP Upload Server Built on May 7 2012 18:16:42 (1336439802)
< WWW-Authenticate: GoogleLogin realm="http://www.google.com/accounts"
< Date: Tue, 08 May 2012 22:48:37 GMT
< Expires: Tue, 08 May 2012 22:48:37 GMT
< Cache-Control: private, max-age=0
< Content-Length: 0
< Content-Type: text/html
It seems like you are trying to publish a document: https://developers.google.com/google-apps/documents-list/#publishing_documents_by_publishing_a_single_revision
Once you publish it, the link with rel set to "http://schemas.google.com/docs/2007#publish" will point to the published document on the web.

Resources