I want to use the Jenkins Remote API, and I am looking for safe solution. I came across Prevent Cross Site Request Forgery exploits
and I want to use it, but I read somewhere that you have to make a crumb request.
How do I get a crumb request in order to get the API working?
I found this https://github.com/entagen/jenkins-build-per-branch/pull/20
, but still I don't know how to fix it.
My Jenkins version is 1.50.x.
Authenticated remote API request responds with 403 when using POST request
The web session ID was added in Jenkins 2.176. 2 and 2.186 to cause crumb to expire. See security advisory and upgrade guide. Plugins may provide other crumb issuers that use other criteria to determine whether a crumb is valid.
Jenkins provides machine-consumable remote access API to its functionalities. Currently it comes in three flavors: XML. JSON with JSONP support.
I haven't found this in the documentation either. This code is tested against an older Jenkins (1.466), but should still work.
To issue the crumb use the crumbIssuer
// left out: you need to authenticate with user & password -> sample below HttpGet httpGet = new HttpGet(jenkinsUrl + "crumbIssuer/api/json"); String crumbResponse = toString(httpclient, httpGet); CrumbJson crumbJson = new Gson().fromJson(crumbResponse, CrumbJson.class);
This will get you a response like this
{"crumb":"fb171d526b9cc9e25afe80b356e12cb7","crumbRequestField":".crumb"}
This contains two pieces of information you need
If you now want to fetch something from Jenkins, add the crumb as header. In the sample below I fetch the latest build results.
HttpPost httpost = new HttpPost(jenkinsUrl + "rssLatest"); httpost.addHeader(crumbJson.crumbRequestField, crumbJson.crumb);
Here is the sample code as a whole. I am using gson 2.2.4 to parse the response and Apache's httpclient 4.2.3 for the rest.
import org.apache.http.auth.*; import org.apache.http.client.*; import org.apache.http.client.methods.*; import org.apache.http.impl.client.*; import com.google.gson.Gson; public class JenkinsMonitor { public static void main(String[] args) throws Exception { String protocol = "http"; String host = "your-jenkins-host.com"; int port = 8080; String usernName = "username"; String password = "passwort"; DefaultHttpClient httpclient = new DefaultHttpClient(); httpclient.getCredentialsProvider().setCredentials( new AuthScope(host, port), new UsernamePasswordCredentials(usernName, password)); String jenkinsUrl = protocol + "://" + host + ":" + port + "/jenkins/"; try { // get the crumb from Jenkins // do this only once per HTTP session // keep the crumb for every coming request System.out.println("... issue crumb"); HttpGet httpGet = new HttpGet(jenkinsUrl + "crumbIssuer/api/json"); String crumbResponse= toString(httpclient, httpGet); CrumbJson crumbJson = new Gson() .fromJson(crumbResponse, CrumbJson.class); // add the issued crumb to each request header // the header field name is also contained in the json response System.out.println("... issue rss of latest builds"); HttpPost httpost = new HttpPost(jenkinsUrl + "rssLatest"); httpost.addHeader(crumbJson.crumbRequestField, crumbJson.crumb); toString(httpclient, httpost); } finally { httpclient.getConnectionManager().shutdown(); } } // helper construct to deserialize crumb json into public static class CrumbJson { public String crumb; public String crumbRequestField; } private static String toString(DefaultHttpClient client, HttpRequestBase request) throws Exception { ResponseHandler<String> responseHandler = new BasicResponseHandler(); String responseBody = client.execute(request, responseHandler); System.out.println(responseBody + "\n"); return responseBody; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With