Подтвердить что ты не робот

Как запросить эмитента кролика для Дженкинса

Я хочу использовать Jenkins Remote API и ищу безопасное решение. Я столкнулся с Prevent Cross Site Request Forgery exploits и хочу их использовать, но где-то читал, что вам нужно сделать крошечный запрос.

Как получить запрос на крошку, чтобы заставить работать API?

Я нашел это https://github.com/entagen/jenkins-build-per-branch/pull/20, но все же я не знаю, как это исправить.

Моя версия Jenkins - 1.50.x.

Аутентифицированный удаленный запрос API отвечает 403 при использовании запроса POST

4b9b3361

Ответ 1

Я тоже не нашел это в документации. Этот код протестирован против старого Jenkins (1.466), но он все равно должен работать.

Для выпуска крошки используйте 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);

Это даст вам ответ вроде этого

{"crumb":"fb171d526b9cc9e25afe80b356e12cb7","crumbRequestField":".crumb"}

Это содержит две части информации, которые вам нужны

  • имя поля, с которым вам нужно передать крошку
  • сама крошка

Если вы хотите что-то получить от Дженкинса, добавьте крошку в качестве заголовка. В приведенном ниже примере я приведу последние результаты сборки.

HttpPost httpost = new HttpPost(jenkinsUrl + "rssLatest");
httpost.addHeader(crumbJson.crumbRequestField, crumbJson.crumb);

Вот пример кода в целом. Я использую gson 2.2.4 для анализа ответа и Apache httpclient 4.2.3 для остальных.

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;
    }

}

Ответ 2

Или вы можете использовать Python и requests вместо

req = requests.get('http://JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)', auth=(username, password))
print(req.text)

даст вам имя и крошку

Jenkins-Crumb:e2e41f670dc128f378b2a010b4fcb493

Ответ 3

Ответ пользователя cheffe помог 90%. Спасибо, что дали нам правильное направление.

Отсутствующие 10% связаны с аутентификацией имени пользователя и пароля HTTP.

Поскольку API-интерфейс Codenameone Java, который я использовал, не обладал классом аутентификации,

new UsernamePasswordCredentials(usernName, password));

Я использовал:

String apiKey = "yourJenkinsUsername:yourJenkinsPassword";
httpConnection.addRequestHeader("Authorization", "Basic " + Base64.encode(apiKey.getBytes()));

Ответ 4

Эта функция Python получает крошку и дополнительно использует крошку для отправки на конечную точку Jenkins. Это было протестировано с Jenkins 2.46.3 с включенной защитой CSRF:

import urllib.parse
import requests

def build_jenkins_job(url, username, password):
    """Post to the specified Jenkins URL.

    'username' is a valid user, and 'password' is the user password or
    (preferably) hex API token.
    """
    # Build the Jenkins crumb issuer URL
    parsed_url = urllib.parse.urlparse(url)
    crumb_issuer_url = urllib.parse.urlunparse((parsed_url.scheme,
                                                parsed_url.netloc,
                                                'crumbIssuer/api/json',
                                                '', '', ''))

    # Get the Jenkins crumb
    auth = requests.auth.HTTPBasicAuth(username, password)
    r = requests.get(crumb_issuer_url, auth=auth)
    json = r.json()
    crumb = {json['crumbRequestField']: json['crumb']}

    # POST to the specified URL
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    headers.update(crumb)
    r = requests.post(url, headers=headers, auth=auth)

username = 'jenkins'
password = '3905697dd052ad99661d9e9f01d4c045'
url = 'http://jenkins.example.com/job/sample/build'
build_jenkins_job(url, username, password)

Ответ 5

Пользовательский фрагмент кода cheffe Java отлично поработал для меня на Jenkins v2.89.3 (Eclipse.org) и другом экземпляре Jenkins, который я использую, в версии 2.60.3 (после включения 1).

Я добавил это к Maven mojo 2, который я использую для того, чтобы надавить локально редактируемые изменения config.xml обратно на сервер.

1 Защита CSRF
2 Плагин синхронизации работы Hudson