web-dev-qa-db-fra.com

Comment demander l'émetteur de miettes pour Jenkins

Je souhaite utiliser l'API Jenkins Remote et je recherche une solution sûre. Je suis tombé sur Prevent Cross Site Request Forgery exploits et je veux l'utiliser, mais j'ai lu quelque part que vous devez faire une demande de miettes.

Comment obtenir une demande de miettes afin de faire fonctionner l'API?

J'ai trouvé ça https://github.com/entagen/jenkins-build-per-branch/pull/20, mais je ne sais toujours pas comment y remédier.

Ma version Jenkins est 1.50.x.

La demande d'API distante authentifiée répond par 403 lors de l'utilisation de POST

26
Satish

Je n'ai pas trouvé cela non plus dans la documentation. Ce code est testé par rapport à un Jenkins plus ancien (1.466), mais devrait toujours fonctionner.

Pour émettre la miette, utilisez le 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);

Cela vous donnera une réponse comme celle-ci

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

Il contient deux informations dont vous avez besoin

  1. le nom du champ avec lequel vous devez passer la miette
  2. la mie elle-même

Si vous voulez maintenant récupérer quelque chose de Jenkins, ajoutez la miette comme en-tête. Dans l'exemple ci-dessous, je récupère les derniers résultats de génération.

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

Voici l'exemple de code dans son ensemble. J'utilise gson 2.2.4 pour analyser la réponse et httpclient 4.2.3 d'Apache pour le reste.

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

}
31
cheffe

Ou vous pouvez utiliser Python et requests à la place

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

vous donnera le nom et la miette:

Jenkins-Crumb:e2e41f670dc128f378b2a010b4fcb493
5
JamesD

Cette fonction Python obtient la miette et utilise également la miette pour publier sur un point de terminaison Jenkins. Ceci est testé avec Jenkins 2.46.3 avec protection CSRF activé:

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's 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)
3
John McGehee

réponse de l'utilisateur cheffe a aidé 90%. Merci de nous avoir donné la bonne direction.

Les 10% manquants tournaient autour de l'authentification par nom d'utilisateur et mot de passe HTTP.

Étant donné que Codenameone Java que j'utilisais n'avait pas la classe d'authentification,

new UsernamePasswordCredentials(usernName, password));

J'ai utilisé:

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

Pendant ce temps, vous pouvez générer un jeton d'API afin d'éviter d'avoir à inclure votre mot de passe dans le code source fourni par les solutions ci-dessus:

https://wiki.jenkins.io/display/JENKINS/Authenticating+scripted+clients

3
Florian Straub

L'utilisateur cheffe's Java snippet a très bien fonctionné pour moi sur Jenkins v2.89.3 (Eclipse.org) et une autre instance Jenkins que j'utilise, à la v2.60.3 (une fois activée1).

Je l'ai ajouté à un mojo Maven2 J'utilise pour pousser les édités localement config.xml revient sur le serveur.

1Protection CSRF
2plug-in de synchronisation des tâches Hudson

1
nickboldt