Edited at

Jenkinsのパラメータ付きビルドをAPI経由で実行しようとした時にCORSでハマった話


これ何?


  • Jenkinsのパラメータ付きビルドをAPI経由で実行しようとした時にCORSでハマった話です

  • ググったのですが、まとまった記事がなかなか見つからなかったので記事にまとめてみました

  • まぁ、CORSは常識ですよ!お前、勉強不足だよね!って言われてもしょうがない記事です


前提


curlでの実行は確認済み

以下、curlのコマンドです。

下記、コマンドにてJenkinsのパラメータビルドができることは確認済みでした。

http://hoge:8080/job/hoge_jobJenkinsのパラメータ付きビルドのURLです

$ curl -X POST \

-u JENKINS_USER:JENKINS_TOKEN \
http://hoge:8080/job/hoge_job/buildWithParameters?\
github_url=*

参考

JenkinsジョブをAPI経由でパラメータ付きビルドする


Node.jsのaxiosを採用

クライアントはNode.jsのaxiosを採用しました。

axiosはこちら

下記、postStartJobというメソッドを使って、jenkinsのjobを起動します。

// JenkinsのJobを開始する

postStartJob(data) {
return axios.post('http://hoge:8080/job/hoge_job/buildWithParameters', {}, {
params: {
github_url: data.GithubUrl,
},
auth: {
username: JENKINS_USER,
password: JENKINS_TOKEN,
},
});
}


現象😢

postStartJobメソッドを実行したところ下記エラーが発生しました。

うーん困った😓

Access to XMLHttpRequest at 

'http://hoge:8080/job/technical_analysis_staging/buildWithParameters?
github_url=*' from origin 'http://fuga:8082' has been blocked by CORS policy:
Request header field authorization is not allowed
by Access-Control-Allow-Headers in preflight response.


原因

原因は2つあります。


原因1. Same-Origin Policy

Jenkinsのデフォルト設定だと、Same-Origin Policy(日本語では同一生成元ポリシー)が適用されて、違うドメインからのアクセスを許可していないから。

CORSまとめを参考にしました。@tomoyukilabsさん、ありがとうございます!

Same-Origin Policyとは、1995年Netscape社によってJavaScriptと同時にウェブブラウザに導入されたセキュリティ上の考え方で、コンテンツがブラウザに来る源泉(origin)に基づいて整理して、外部からのアクセスを防ぐというポリシーです。

WIKI より参照

つまり、今回、Jenkinsはhttp://hoge でクライアントは http://fuga で違うドメインであることから、Jeninsはアクセスを拒否したっていうわけです。


原因2. pre-flight

ライブラリのaxiosは異なるドメインに対してリクエストする時に、OPTIONSメソッドでpre-flightのリクエストを送信します。

axiosはデフォルトでapplication/jsonフォーマットを使用しており、application/jsonの場合、常にpre-flightされる仕様になっているとのことです。

https://github.com/axios/axios/issues/475#issuecomment-253968037 を参考

pre-flightとは、 CORS プロトコルが理解されているかどうかを確認する CORS リクエストとのことです。つまり、自分の理解だと、CORSがちゃんと設定できているドメインか事前にチェックするよ! って確認する作業と理解しました。

https://developer.mozilla.org/ja/docs/Glossary/Preflight_request を参考


解決方法

Cors Filter PluginをJenkinsにインストールしてCORSの設定をする!

この解決方法で無事にJenkinsのパラメータビルドがAPI経由で実行できるようになりました:smile:


Cors Filter Pluginのインストール

プラグイン管理画面でcorsと検索してインストール

スクリーンショット 2019-04-12 9.04.59.png


CORSの設定

システム設定より以下、設定する。


  • Access-Control-Allow-Origins


    • *



  • Access-Control-Allow-Methods


    • GET, OPTIONS, POST



  • Access-Control-Allow-Headers


    • authorization, content-type



スクリーンショット 2019-04-12 9.08.45.png


Access-Control-Allow-Origins


  • 許可するドメインを指定します。* の場合は全てのドメインからアクセス可能ということです。

  • Jenkins側でアクセストークンが必要な設定になっているので特に問題ないかと思い、* を設定しました。本番環境では場合は、ちゃんと設定しようと思います。


Access-Control-Allow-Methods


  • 異なるドメインから許可するメソッドを指定します。

  • APIでメソッドは、GET, OPTIONS, POSTの3つなので、これらを許可します。
    OPTIONSは、pre-flightで使うメソッドなので必須です


Access-Control-Allow-Headers


  • 異なるドメインから許可するヘッダーを指定します。


  • authorizationは、認証情報のヘッダーです。これがあることで、JENKINS_USER:JENKINS_TOKENの認証を通すことができます。


まとめ


  • Same-Origin Policy があるので、同一ドメイン以外からAPIを実行する時にはCORSの設定が必要になる

  • Node.jsのaxiosは、pre-flightを実行するので、OPTIONSメソッドを許可する必要がある

  • Jenkinsの認証情報を送るには、authorizationヘッダーを許可する必要がある

あー、半日くらいハマったので疲れました :persevere:

でも解決できてよかったです。まだまだ未熟だ。。。