How to add crumb for CSRF in Jenkins via JSON / JS
Asked Answered
S

2

3

I wanna create via API jobs in Jenkins, but i can't connect couse of CSRF protection in Jenkins. I got a crumb but idk how to attach it to the url/request in JSON or JavaScript to get data pass by POST method. Any ideas? I wanna make it only with JS, without using JAVA. Thanks

Spark answered 10/4, 2017 at 11:3 Comment(0)
C
4

It should be easy enough. There are few things you are expected to do in order to get thru CSRF in Jenkins.

#1

Fetch an actual CSRF crumb that is valid and for that you should use "/crumbIssuer" endpoint. AFAIK, this is a protected endpoint and therefore you should make an authenticated call to it using either API Token or your credentials in the request. Here how would I do it in JavaScript:

// **** - is a placeholder for an auth token, replace it with yours
$.get({
    url: "https://my.jenkins.io/crumbIssuer/api/json",
    contentType: "application/json",
    headers: {
        "User-Agent": "my_js_script",
        "Authorization": "****"
    }
}).done(function(data) {
    // this is how you fetch valid & actual CSRF crumb
    console.log(data.crumbRequestField + " = " + data.crumb);
});

#2

Now, since you've got a handle on a valid & actual CSRF crumb, do send it with any request that modifies state in Jenkins. Lets say, your valid CSRF crumb JSON looks something like this:

{ "crumbRequestField": "Jenkins-Crumb", "crumb": "noop" }

and therefore your Ajax call would look somewhat like this (note an extra "Jenkins-Crumb" HTTP header):

// **** - is a placeholder for an auth token, replace it with yours
// simply activates a job in Jenkins, requirement for cloned jobs (aka. "Create-A-Copy-From")
$.post({
    url: "https://my.jenkins.io/job/my_job/description",
    contentType: "application/x-www-form-urlencoded; charset=UTF-8",
    headers: {
        "User-Agent": "my_js_script",
        "Authorization": "****",
        "Jenkins-Crumb": "noop" // makes CSRF filter in Jenkins happy
    },
    data: "description="
});

These JavaScript snippets unlikely perfect, but hopefully give you the right direction.

I'm working on a project that is Jenkins API library, but in Ruby. Here are some of the files that might be of interest in case you need to read some source code that actually does what you're looking for:

Cease answered 10/4, 2017 at 20:54 Comment(10)
How to generate the auth token?Glynas
I get Request header field Jenkins-Crumb is not allowed by Access-Control-Allow-Headers in preflight response. Any idea?Smashing
I found the problem, was a proxy inbetween which did not allow the headerSmashing
How do you set the Authorization? Been trying that for a while.Butterbur
@RutwickGangurde, as a Jenkins administrator (or any user for that matter), you can generate API tokens to allow programmatic access via Jenkins API. That token value is what goes into Authorization header. Looking at my scripts, I now recall Jenkins requires you to construct value of the header using the following format: Authorization: Basic base64(<username>:<API Token>) where base64(...) is a base64-encoding function in the programming/scripting language of your choice. Hope that answers your question.Cease
@RutwickGangurde, take a look at the following article how to generate API tokens in Jenkins: decodingdevops.com/…Cease
Thanks @pabloduo, I managed to do it myself after a lot of trial and errors. You need to set a cookie header as well. But I will check this article to learn.Butterbur
@RutwickGangurde, glad you figured it out and thanks for sharing your findings! It seems Jenkins API authentication requirements have changed a bit, I must say it is weird a REST API requires Cookie header to be set in favor of Authentication header which is usually the case for the most REST APIs.Cease
I agree, and there's not a lot of documentation around it. I spent hours trying to figure it out and finally found one article that had one tip around the topic, using that I spent a little more time to solve my issue.Butterbur
Check this thread. #57732318Butterbur
S
0

Remenber that the curl you get is associated with a session.. that means you have to get the cookie when asking for a crumb .. and then set the cookie when running a job

crumb=`curl -s -X GET "http://jenkins/crumbIssuer/api/json" --user usr:passwd --cookie-jar /tmp/crumcookie | tr ',' '\n' |grep '"crumb"' | sed 's/"//g' | awk -F ':' '{print $2}'`
echo "We got a crumb >> $crumb"
curl -X POST "http://jenkins/job/remoteTest/build" --user usr:passwd --cookie /tmp/crumcookie -H "Jenkins-Crumb:$crumb"
echo "Job has been launched"
Sapers answered 4/1, 2022 at 10:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.