35

Jenkins Remote API を使用したいので、安全なソリューションを探しています。出会っPrevent Cross Site Request Forgery exploitsて使いたいのですが、クラムリクエストをしなければならないことをどこかで読みました。

API を機能させるためにクラム リクエストを取得するにはどうすればよいですか?

これを見つけましたhttps://github.com/entagen/jenkins-build-per-branch/pull/20が、まだ修正方法がわかりません。

私の Jenkins のバージョンは 1.50.x です。

POST リクエストを使用すると、認証されたリモート API リクエストが 403 で応答する

4

8 に答える 8

44

ドキュメントでもこれを見つけられませんでした。このコードは古い 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"}

これには、必要な 2 つの情報が含まれています

  1. クラムを渡す必要があるフィールド名
  2. クラム自体

Jenkins から何かをフェッチする場合は、クラムをヘッダーとして追加します。以下のサンプルでは、​​最新のビルド結果を取得しています。

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

}
于 2013-08-21T14:59:09.920 に答える
3

ユーザー Cheffe の回答は 90% 役に立ちました。正しい方向性を教えてくれてありがとう。

不足している 10% は、HTTP ユーザー名とパスワード認証に関連していました。

私が使っていたCodenameoneのJava APIにはAuthentication Classがなかったので、

new UsernamePasswordCredentials(usernName, password));

私が使用した:

String apiKey = "yourJenkinsUsername:yourJenkinsPassword";
httpConnection.addRequestHeader("Authorization", "Basic " + Base64.encode(apiKey.getBytes()));
于 2017-02-12T21:15:36.813 に答える