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 requestを使用すると、認証済みのリモートAPI要求は403で応答します)
私もドキュメントでこれを見つけていません。このコードは古い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つの情報が含まれています
Jenkinsから何かを取得したい場合は、パンくずをヘッダーとして追加します。以下のサンプルでは、最新のビルド結果を取得します。
HttpPost httpost = new HttpPost(jenkinsUrl + "rssLatest");
httpost.addHeader(crumbJson.crumbRequestField, crumbJson.crumb);
これが全体のサンプルコードです。 gson 2.2.4 を使用して応答を解析し、 Apacheのhttpclient 4.2. を使用しています。
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;
}
}
または、代わりにPythonおよびrequests
を使用できます
req = requests.get('http://JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)', auth=(username, password))
print(req.text)
あなたに名前とパン粉を与えます:
Jenkins-Crumb:e2e41f670dc128f378b2a010b4fcb493
このPython関数はパンくずを取得し、さらにパンくずを使用してJenkinsエンドポイントに投稿します。これは CSRF保護 をオンにしてJenkins 2.46.3でテストされます。
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)
ユーザーシェフの回答 90%助けました。正しい方向性を与えてくれてありがとう。
欠落している10%は、HTTPユーザー名とパスワード認証に関連しています。
Codenameone Java私が使用していたAPIには認証クラスがなかったため、
new UsernamePasswordCredentials(usernName, password));
私が使用した:
String apiKey = "yourJenkinsUsername:yourJenkinsPassword";
httpConnection.addRequestHeader("Authorization", "Basic " + Base64.encode(apiKey.getBytes()));
一方、上記のソリューションで提供されるソースコードにパスワードを含める必要を防ぐために、APIトークンを生成できます。
https://wiki.jenkins.io/display/JENKINS/Authenticating+scripted+clients
ユーザーcheffeのJava snippet Jenkins v2.89.3(Eclipse.org)およびv2.60.3で使用する別のJenkinsインスタンス(有効にすると1回)1)。
これをMavenモジョに追加しました2 ローカルで編集されたconfig.xml
はサーバーに戻ります。