はじめに
S3+CloudFront+Route53+ACMで静的Webサイトの記事があったのでリンクを追加。まずこの方法でサイトを構築するとMozilla ObservatoryだとF評価なので、セキュリティヘッダーを追加しよう、またSPAのルーティングの場合はどうするのが良いか。という記事です。
追記(2021/6/18)
セキュリティヘッダー
CloudFrontではセキュリティ系のヘッダーが指定されないのでこれらをCloudFront Functionsで追加すること。まずはAWS sampleの値をベースに厳しい方向へ。現実的にはバックエンドのAPIを呼び出すことが殆どだと思うので Content Security Policy (CSP) のconnect-src
にアクセス先を指定したり、SPAフレームワーク側などの実装に合わせてprefetch-src 'self';
の追加とかstyle-src 'self' 'unsafe-hashes' 'unsafe-inline';
への変更が必要。ここらへんは実際のアプリケーションの実装に合わせてデベロッパーツールを見ながら対処。
Google の Web Fundamentals 解説とChromeデベロッパーツールでの手順なんかが参考になる。
ルーティング(オプション)
多くの場合SPAでもルーティングさせることになると思うので、
Terraformでの設定
基本的なCloudFrontとS3の設定を除き、これらをTerraformで実現すると次の部分の追加になる。いや、viewer-response
とviewer-request
を間違って動かなかったのでそれをメモしときたかったのが本題。あとマネージメントコンソールで複数の関数を関連付けできるように、function_association
を並べればよい。
resource "aws_cloudfront_distribution" "example" {
# 省略
default_cache_behavior {
# 省略
function_association {
event_type = "viewer-response" # ヘッダーはresponse側で
function_arn = aws_cloudfront_function.security_headers.arn
}
function_association {
event_type = "viewer-request" # ルーティングはrequest時点で
function_arn = aws_cloudfront_function.spa_routing.arn
}
# 省略
}
#
# ヘッダーの追加
# security-headers.jsはaws-samplesの
# https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/add-security-headers
# をベースにカスタマイズ
#
resource "aws_cloudfront_function" "security_headers" {
name = "security-headers"
runtime = "cloudfront-js-1.0"
comment = "HTTP security headers"
publish = true
code = file("${path.module}/security-headers.js")
}
#
# SPAのルーティング
# spa-routing.jsはaws-samplesの
# https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/url-rewrite-single-page-apps
# をベースにカスタマイズ
resource "aws_cloudfront_function" "spa_routing" {
name = "spa-routing"
runtime = "cloudfront-js-1.0"
comment = "URI rewrite for SPA"
publish = true
code = file("${path.module}/spa-routing.js")
}