httpd.conf → Lambda@Edge
私のサイト devel.keys.jp は、昼間は EC2 上の Apache httpd で動かしているんですが、夜中は S3 + CloudFront でホストするようにしています11。
というときに、S3 でも httpd と同じヘッダを加えたいなーと思って作りました。
EC2 の httpd の設定は次のようなものです:
Header set X-XSS-Protection "1; mode=block"
Header set X-Content-Type-Options nosniff
Header append X-Frame-Options SAMEORIGIN
Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
これを実現するには CloudFront の Lambda@Edge を使って、Viewer Response
と Origin Response
の両方をトリガー2にして動かす、次のような Python の Lambda を書きます。(JavaScriptで書く場合は、Amazon提供のチュートリアルを見てください)
def lambda_handler(event, context):
response = event['Records'][0]['cf']['response']
if int(response['status']) == 200:
response['headers']['strict-transport-security'] = [{'key': 'Strict-Transport-Security', 'value': 'max-age= 63072000; includeSubdomains; preload'}]
response['headers']['x-content-type-options'] = [{'key': 'X-Content-Type-Options', 'value': 'nosniff'}]
response['headers']['x-frame-options'] = [{'key': 'X-Frame-Options', 'value': 'SAMEORIGIN'}]
response['headers']['x-xss-protection'] = [{'key': 'X-XSS-Protection', 'value': '1; mode=block'}]
return response
一度設定したヘッダを変えることはほとんどないと思うんですが、せっかくなので3これを自動化する Perl スクリプトを書きました。
#!/usr/bin/perl
while (<>) {
s/^\s*(.*?)\s*$/$1/;
if ( /^Header\s+(set|append)\s+([\w-]+)\s+"?([^"]+)"?$/ ) {
my $h_key = lc($2);
print "response['headers']['$h_key'] = "[{'key': '$2', 'value': '$3'}]\n";
}
}
よくテストしていないので、実際に使ってみたいという人はテストをお忘れなく!
-
無料枠が月750時間までだと24時間動かしていると他のインスタンスを立てにくいので、1〜7時までインスタンスを落として無料枠をセーブしているのです ↩
-
CloudFront のキャッシュにヒットしたときは Viewer Response が、キャッシュミスした場合は Origin Response が、それぞれトリガーとして動くようになっている(らしい)です。参考: CloudFront Events That Can Trigger a Lambda Function ↩
-
最近 Perl のコードを書いてないので書きたくなって、理由を付けて書いてみました ↩