まえがき
業務でCSPを設定してるサイトに広告を入れることになりまして。
CSPの設定自体がはじめてだったのでどうしていいのか分からず、結局人海戦術で対応しました。。。
で、その後でreport-uri
を知ったので、備忘として残します。
なお、そのサイトではまだ使っておらず、ローカルで試しただけです。。
ダメだったらゴメンね(´・ω・`)
ヤ、でも自分のPCでは動いたんだ(;´Д`)
あと、業務に関わるパラメータはテキトーに一括置換で書き換えてます。
たぶん大枠問題ないと思うんですが、なんか変になってても許してください(;´Д`)
2018/02/19 追記
わたくし、嘘をついておりました・・・・(´・ω・`)
いや、元々記述していた内容でも動くんですが、そんなまだるっこしいことしなくて良かったので、
記事の内容を直しておきます。
通常の設定
CSPを有効にするには、要はレスポンスヘッダーに入ればいいので、
Nginxの設定で入れてもよいし、プログラム側でヘッダーに出力してもよいです。
今回は、Nginxに add_header
で入れてます。
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com;"
・・・・ホントはscript_src
とかimage-src
とかも入れてるんですが、あまりにも長いのでdefault-src
のみ書いときます。
report-uriによる報告機能
問題のreport-uri
、設定は以下のようになります。
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com; report-uri https://local.izunak.com/csp/report;"
report-uri
に報告先へのURLを設定します。
報告の内容は、以下のようなJSONが、report-uri
に設定したURLへPOSTにより送られます。
{
"csp-report": {
"blocked-uri": "ブロックしたURL",
"column-number": 25,
"disposition": "report",
"document-uri": "https://local.izunak.com/",
"effective-directive": "default-src",
"line-number": 67042,
"original-policy": "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com; report-uri https://local.izunak.com/csp/report;",
"referrer": "",
"script-sample": "",
"source-file": "https://local.izunak.com/bundle-pc.js",
"status-code": 0,
"violated-directive": "default-src"
}
}
具体的な例
自分のローカル環境上で試した設定と、報告内容を記載します。
nginx.conf
http {
#・・・(略)・・・
log_format postdata '[$time_local] request_body: [$request_body]';
#・・・(略)・・・
}
ログの出力フォーマットを定義してます。
ゴチャゴチャ書いてあっても見づらいので、時間とPOSTパラメータだけ出力させています。
default.conf
server {
listen 443 default ssl;
ssl on;
server_name local.izunak.com;
#・・・(略)・・・
# CSP
# ちょっとだけ記述しやすいように変数化
set $default_src "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com;";
set $report_uri "report-uri https://local.izunak.com/csp/report;";
add_header Content-Security-Policy $default_src$report_uri;
# 報告を出力
location /csp/report {
access_log /var/log/nginx/postdata.log postdata;
fastcgi_pass unix:/run/php/php-fpm.sock;
}
#・・・(略)・・・
}
CSPの設定、1行で書くのがイヤになったので各変数つくって最後にくっつけてます。。
だって見づらいんだもん(´・ω・`)
report-uri
の報告先として自身の/csp/report
を指定し、location
で用意した受取先で直接ログ出力をしています。
ここでfastcgi_pass
を設定しているのは、location
内でPOSTパラメータを受け取れるようにするためです。
入れないとPOSTが空なので、なんの役にも立たないログファイルが出来上がるので気をつけて。
参考: Nginx で POST データのログをフィルタする
報告内容
ログに出力された報告内容は↓のように出力されます。
[08/Feb/2018:22:17:16 +0900] request_body: [{\x22csp-report\x22:{\x22blocked-uri\x22:\x22ブロックしたURL\x22,\x22column-number\x22:25,\x22disposition\x22:\x22report\x22,\x22document-uri\x22:\x22https://local.izunak.com/\x22,\x22effective-directive\x22:\x22default-src\x22,\x22line-number\x22:67042,\x22original-policy\x22:\x22default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com; report-uri https://local.izunak.com/csp/report;\x22,\x22referrer\x22:\x22\x22,\x22script-sample\x22:\x22\x22,\x22source-file\x22:\x22https://local.izunak.com/bundle-pc.js\x22,\x22status-code\x22:0,\x22violated-directive\x22:\x22default-src\x22}}]
ダブルクォーテーションが\x22
になってるけど・・・・だいたいOK。
JSONを使いやすくするプラグインがあるのは知ってるけど、
これにしか使わないならわざわざ入れる必要もないかな、と・・・・。
今回はCSPにはじかれたURLさえ分かればいいのでやりませんでしたが、
report-uri
の受取先としてプログラムを用意して処理することももちろん可能です。
プログラム側でCSPをヘッダー出力しているなら、
受け取った後にプログラムでワッショイワッショイした方が手間が省けるんですかねたぶん。
Content-Security-Policy-Report-Only
report-uri
でNGだったURLを報告してもらえる・・・・とはいえ。
許可していないばっかりに広告が表示されないと収入が減って困る、という場合、
Content-Security-Policy-Report-Only
を使用するとよいかも?
add_header Content-Security-Policy-Report-Only "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com; report-uri https://local.izunak.com/csp/report;"
Content-Security-Policy-Report-Only
で設定した場合、
このパラメータ上で設定されたルールに該当しないリクエストが来た場合、リクエストのブロックはされず、report-uri
に設定されたURLへ報告するだけとなります。
Content-Security-Policy
との併用も可能です。
server {
listen 443 default ssl;
ssl on;
server_name local.izunak.com;
#・・・(略)・・・
# CSP
# ちょっとだけ記述しやすいように変数化
set $default_src "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com;";
set $report_uri "report-uri https://local.izunak.com/csp/report;";
add_header Content-Security-Policy $default_src;
add_header Content-Security-Policy-Report-Only $default_src$report_uri;
# 報告を出力
location /csp/report {
access_log /var/log/nginx/postdata.log postdata;
fastcgi_pass unix:/run/php/php-fpm.sock;
}
#・・・(略)・・・
}
あとがき
まえがきに書いたとおり、まだ業務で設定した内容ではないので、
不正確だったり不備があるかもしれません。。
不備ありました・・・・orz
ごめんなさい・・・・記事にする前にローカルで動くことは確認していたんですが・・・・
修正したのは、Content-Security-Policy-Report-Only
でしかreport-uri
が使えないような記述をしていた個所です。
Content-Security-Policy
への追加も試していたんですが、
おそらく単純に書き方が悪かったせいで正常動作せず、
Content-Security-Policy-Report-Only
を試した際にたまたまその不備が解消されていたんではないかと。。
余談
ぜんぜんCSPとも関係ないんですが、コレ書いてるときに気になったので、、、
すぐ消すようなローカル環境をチャラっと作る際、だいたいドメインを***.izunak.com
にしてるんですが、これって一般的なものなんですかね・・・・?
何度か気になってググってみるも答えが見つからず・・・・orz
はじめてVirtualPCをつかうプロジェクトをやったとき、先輩からすでに用意されたのをもらったんですが、そのときに設定されてたのが***.izunak.com
だったんで、なんとなく自分の中でコレが標準になってます。