CloudFrontディストリビューションにセキュリティヘッダーを追加する方法
AWS CloudFrontは、世界中のエッジロケーションでコンテンツをキャッシュし、高速に配信できるCDNサービスです。クラウドフロントを使用してS3バケットなどのオリジンから配信されるコンテンツに対し、セキュリティヘッダーを付与することで、Webサイトのセキュリティを強化できます。この記事では、CloudFormationを利用してLambda@EdgeでCloudFrontにセキュリティヘッダーを追加する方法を説明します。
前提条件
- CloudFrontディストリビューション:S3をオリジンとして設定します。
- Lambda@Edge:CloudFrontディストリビューションのレスポンスに対してカスタムセキュリティヘッダーを追加するためにLambda関数を作成し、Edgeでの実行を設定します。
セキュリティヘッダーとは?
セキュリティヘッダーは、ブラウザがWebページをより安全にレンダリングするための指示を含むHTTPレスポンスヘッダーです。以下のヘッダーをCloudFrontディストリビューションに追加することで、Webアプリケーションのセキュリティを高めます。
-
Strict-Transport-Security (HSTS)
- 指示:ブラウザに対し、指定された期間中、HTTPS接続を強制する。
- 例:
Strict-Transport-Security: max-age=63072000; includeSubdomains; preload
- 効果:HTTPからHTTPSへのリダイレクトにより、通信内容の傍受や中間者攻撃を防ぎます。
- 属性:
max-age
: 有効期限(秒単位)。例えば「63072000」は2年間を意味します。includeSubdomains
: サブドメインも含む。preload
: HSTSプリロードリストへの登録用のオプション。
-
X-Content-Type-Options
- 指示:ブラウザに対し、MIMEタイプの宣言を無視しないよう指示する。
- 例:
X-Content-Type-Options: nosniff
- 効果:コンテンツのMIMEタイプが正確に宣言されていない場合でも、ブラウザが独自にファイルタイプを判別することを防ぎます。これにより、クロスサイトスクリプティング(XSS)やMIMEスニッフィング攻撃のリスクを低減します。
-
X-Frame-Options
- 指示:ブラウザに対し、指定したページをフレーム内でレンダリングしないよう指示する。
- 例:
X-Frame-Options: DENY
- 効果:ページをフレーム内に表示することを禁止するため、クリックジャッキング攻撃を防止します。
-
X-XSS-Protection
- 指示:XSS(クロスサイトスクリプティング)フィルターを有効化。
- 例:
X-XSS-Protection: 1; mode=block
- 効果:ブラウザのXSSフィルターをオンにし、攻撃が検知された場合にページのレンダリングを停止します。
CloudFormationでLambda@Edgeを設定してセキュリティヘッダーを追加
以下のCloudFormationテンプレート例では、Lambda関数を定義し、CloudFrontディストリビューションのビヘイビアにセキュリティヘッダーを追加する処理を行います。
CloudFormationテンプレート例
Resources:
# Lambda関数の作成 (セキュリティヘッダーを追加)
EdgeLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: InsertSecurityHeaders
Handler: index.handler
Role: !GetAtt LambdaExecutionRole.Arn
Code:
ZipFile: |
exports.handler = async (event) => {
const response = event.Records[0].cf.response;
const headers = response.headers;
headers['strict-transport-security'] = [{key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload'}];
headers['x-content-type-options'] = [{key: 'X-Content-Type-Options', value: 'nosniff'}];
headers['x-frame-options'] = [{key: 'X-Frame-Options', value: 'DENY'}];
headers['x-xss-protection'] = [{key: 'X-XSS-Protection', value: '1; mode=block'}];
return response;
};
Runtime: nodejs14.x
MemorySize: 128
Timeout: 5
# Lambdaの実行ロール
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: LambdaEdgePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: '*'
# CloudFrontディストリビューションの作成
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName: your-s3-bucket.s3.amazonaws.com
Id: S3Origin
S3OriginConfig: {}
DefaultCacheBehavior:
TargetOriginId: S3Origin
ViewerProtocolPolicy: redirect-to-https
LambdaFunctionAssociations:
- EventType: origin-response
LambdaFunctionARN: !GetAtt EdgeLambdaFunction.Arn
Enabled: true
設定のポイント
- LambdaFunctionAssociations の
EventType: origin-response
:この設定により、レスポンスの際にLambda関数が実行され、セキュリティヘッダーが追加されます。 - ViewerProtocolPolicy の
redirect-to-https
:HTTP接続をHTTPSにリダイレクトして、すべてのトラフィックが安全なHTTPS経由で配信されるようにしています。
これで、CloudFormationテンプレートを利用して、CloudFrontディストリビューションにセキュリティヘッダーを追加する設定が完了です。セキュリティヘッダーを適切に設定することで、クロスサイトスクリプティングやクリックジャッキングといったさまざまな攻撃からWebサイトを保護できます。
このコードはCloudFrontレスポンスにセキュリティヘッダーを追加するLambda関数を作成するCloudFormationテンプレートの一部です。
以下で各セクションの詳細を説明します。
CloudFormationでレスポンスヘッダーポリシー (AWS::CloudFront::ResponseHeadersPolicy
) を作成し、セキュリティヘッダーを追加する基本的なテンプレート例を以下に示します。
このテンプレートでは、Content Security Policy、HSTS、XSS Protection、Frame Options など、よく使用されるセキュリティヘッダーを設定します。
Resources:
MyResponseHeadersPolicy:
Type: AWS::CloudFront::ResponseHeadersPolicy
Properties:
ResponseHeadersPolicyConfig:
Name: SecurityHeadersPolicy
Comment: "Response Headers Policy with Security Headers"
# セキュリティヘッダーの設定
SecurityHeadersConfig:
ContentSecurityPolicy:
ContentSecurityPolicy: "default-src 'self'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'; frame-ancestors 'none';"
Override: true
ContentTypeOptions:
Override: true # X-Content-Type-Options: nosniff
FrameOptions:
FrameOption: DENY # X-Frame-Options: DENY
Override: true
ReferrerPolicy:
ReferrerPolicy: no-referrer # Referrer-Policy: no-referrer
Override: true
StrictTransportSecurity:
AccessControlMaxAgeSec: 63072000 # HSTS (max-age 2 years)
IncludeSubdomains: true
Preload: true
Override: true
XSSProtection:
Protection: true
ModeBlock: true # X-XSS-Protection: 1; mode=block
Override: true
# カスタムヘッダーの設定 (任意)
CustomHeadersConfig:
Items:
- Header: X-Custom-Header
Value: CustomValue
Override: true
各プロパティの説明
- ContentSecurityPolicy:
default-src 'self';
などのポリシーにより、スクリプトやスタイル、画像などのソース制限を設定します。 - ContentTypeOptions:
X-Content-Type-Options
ヘッダーを「nosniff」に設定し、ブラウザによるMIMEタイプの推測を防ぎます。 - FrameOptions:
X-Frame-Options: DENY
により、クリックジャッキング攻撃を防止します。 - ReferrerPolicy:
no-referrer
に設定し、リファラ情報が外部に漏れないようにします。 - StrictTransportSecurity: HSTSの設定で、HTTPSの強制を行い、キャッシュの有効期間やサブドメインへの適用、プリロードを指定します。
- XSSProtection:
X-XSS-Protection: 1; mode=block
により、ブラウザのXSSフィルターを有効化します。
使用方法
このテンプレートをCloudFormationスタックにデプロイすることで、SecurityHeadersPolicy
という名前のレスポンスヘッダーポリシーが作成され、CloudFrontディストリビューションで再利用可能になります。このポリシーをCloudFrontディストリビューションに関連付けることで、指定したセキュリティヘッダーがレスポンスに追加されます
レスポンスヘッダーポリシー (ResponseHeadersPolicy)
CloudFrontに直接設定でき、CORSやセキュリティヘッダーの追加が簡単に行えます。
複数のCloudFrontディストリビューションで共有・再利用可能なため、設定が一貫します。
設定可能なヘッダーが限定されており、細かい条件での追加や動的な制御には制限があります。
メンテナンスや運用が簡単なため、基本的なセキュリティヘッダーを一貫して追加する場合に便利です。
Lambda@Edgeを使用すると、レスポンスヘッダーを動的に追加・変更できます。
レスポンス内容に応じたカスタマイズや、特定の条件下でのみヘッダーを追加するなどの柔軟な制御が可能です。
Lambda実行の追加コストが発生します。
複雑なヘッダー処理が必要な場合や、CloudFrontの標準設定だけでは対応できない場合に役立ちます。
基本的なセキュリティヘッダーのみであれば、レスポンスヘッダーポリシーを作成する方が簡単で管理も楽です。しかし、条件によって異なるヘッダーを設定したい場合や、動的にヘッダーを追加する必要がある場合は、Lambda@Edgeの活用が効果的です。