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