0
0

【AWS×Webアプリ】CloudFrontのキャッシュ削除(Terraform)

Last updated at Posted at 2024-06-02

目的

・AWS上の静的Webサイトホスティングを有効にしたS3をCloudFrontで公開。
・S3のコンテンツを更新した際に、CloudFrontのキャッシュ削除を行うLambdaを実装。

前提条件

・Terraformを使用してAWS上にリソースを作成する。
・Pythonを使用してLambdaを実装する。
・作成する内容は以下と同様

TFファイル

aws_s3.tf(前回からの追加箇所のみ抜粋)
resource "aws_s3_bucket_notification" "WebBucket_notification" {
  bucket = aws_s3_bucket.WebBucket.id

  lambda_function {
    lambda_function_arn = aws_lambda_function.DeleteCache.arn
    events              = ["s3:ObjectCreated:*","s3:ObjectRemoved:*"]
    filter_suffix       = "index.html"
  }
}
aws_lambda.tf
data "archive_file" "lambda_delete_cache" {
  type        = "zip"
  source_file = "${path.module}/lambda/delete_cache.py"
  output_path = "${path.module}/lambda_zip/delete_cache.zip"
}

resource "aws_lambda_function" "DeleteCache" {
  filename         = "${path.module}/lambda_zip/delete_cache.zip"
  function_name    = "delete_cache"
  role             = aws_iam_role.delete_cache_lambda_role.arn
  handler          = "delete_cache.lambda_handler"
  runtime          = "python3.11"
  source_code_hash = filebase64sha256("${path.module}/lambda/delete_cache.py")

  environment {
    variables = {
      DISTRIBUTION_ID = aws_cloudfront_distribution.WebBucketDistribution.id
    }
  }
}

resource "aws_lambda_permission" "allow_s3_to_invoke" {
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.DeleteCache.function_name
  principal     = "s3.amazonaws.com"
  source_account = data.aws_caller_identity.self.account_id
  source_arn    = aws_s3_bucket.WebBucket.arn
}
aws_iam.tf
data "aws_iam_policy_document" "allow_access_to_WebBucket" {
  statement {
    principals {
      type        = "Service"
      identifiers = ["cloudfront.amazonaws.com"]
    }

    effect = "Allow"
    actions = ["s3:GetObject"]
    resources = ["${aws_s3_bucket.WebBucket.arn}/*"]

    condition {
      test     = "StringEquals"
      variable = "aws:SourceArn"
      values   = [aws_cloudfront_distribution.WebBucketDistribution.arn]
    }
  }
}

resource "aws_iam_role" "delete_cache_lambda_role" {
  name = "DeleteCacheLambdaRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "lambda.amazonaws.com"
        }
      },
    ]
  })
}

resource "aws_iam_role_policy" "delete_cache_lambda_policy" {
  role = aws_iam_role.delete_cache_lambda_role.id

  policy = jsonencode({
    Statement = [
      {
        Action = ["cloudfront:CreateInvalidation","cloudfront:ListDistributions"]
        Effect = "Allow"
        Resource = "*"
      },
      {
        Action = ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"]
        Effect = "Allow"
        Resource = ["arn:aws:logs:*:*:*"]
      },
    ]
  })
}

◆aws_s3.tf
・WebBucket_notification:WebBucketでindex.htmlが作成・削除された際にLambda関数を呼び出すS3通知

◆aws_lambda.tf
・lambda_delete_cache:Lambda関数用のPythonファイルをZip圧縮
・DeleteCache:Lambda関数定義
 a. source_code_hash:TerraformがLambda関数のソースコードが変更を検出するために使用するハッシュ値
 b. environment:ディストリビューションIDを環境変数として設定
・allow_s3_to_invoke:Lambdaに付与するリソースベースのポリシー

◆aws_iam.tf
・allow_access_to_WebBucket:aws_s3.tfより移管したもの(前回記事より)
・delete_cache_lambda_role:キャッシュ削除Lambda用IAMロール
・delete_cache_lambda_policy:「delete_cache_lambda_role」に付与するポリシー

Lambda

delete_cache.py
import os
import boto3

def lambda_handler(event, context): 
    cloudfront_client = boto3.client('cloudfront')
                                     
    distribution_id = os.environ['DISTRIBUTION_ID']
    paths_to_invalidate = ['/index.html']
    
    #CloudFrontのキャッシュ削除
    cloudfront_client.create_invalidation(
        DistributionId=distribution_id,
        InvalidationBatch={
            'Paths': {
                'Quantity': len(paths_to_invalidate),
                'Items': paths_to_invalidate
            },
            'CallerReference': str(context.aws_request_id)
        }
    )

動作確認

①作成されたS3バケットへ「index.html」をアップロードする

index.html
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>My Website Home Page</title>
</head>
<body>
  <h1>Welcome to my website(CloudFront)</h1>
  <p>Now hosted on Amazon S3 using Terraform(Before)!</p>
</body>
</html>

②Webサイトへアクセス
・正常にアクセスできることを確認
image.png

③S3バケットへ「index.html」をアップロードする(更新)

index.html
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>My Website Home Page</title>
</head>
<body>
  <h1>Welcome to my website(CloudFront)</h1>
  <p>Now hosted on Amazon S3 using Terraform(After)!</p>
</body>
</html>

④ブラウザの更新
・表示される画面が更新され最新のコンテンツが配信されていることを確認
image.png

⑤ログ(CloudWatch)にエラーが出ていないことの確認
image.png

参考(前回記事)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0