0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TerraformでLambda Function URLをCloudFront OACに設定する

Last updated at Posted at 2024-07-25

はじめに

CloudFrontのOrigin Access ControlでLambda Function URLを保護できるようになりました。

Lambda Function URLのアクセス制御は、PublicもしくはIAMによる認証しか選択できないため、この変更によりCloudFront + WAFでより細かくアクセス制御・保護が可能になります。

本記事ではこの設定をTerraformで作成します。

できたもの

variable "stage" { type = string }
variable "prefix" { type = string }
variable "generate_lambda_name" { type = string }
variable "generate_lambda_url" { type = string }

resource "aws_cloudfront_cache_policy" "lambda_origin" {
  name        = "${var.prefix}-cache-policy-${var.stage}"
  min_ttl     = 1
  max_ttl     = 100
  default_ttl = 50
  parameters_in_cache_key_and_forwarded_to_origin {
    cookies_config {
      cookie_behavior = "none"
    }
    headers_config {
      header_behavior = "none"
    }
    query_strings_config {
      query_string_behavior = "all"
    }
  }
}

resource "aws_cloudfront_origin_access_control" "lambda_origin" {
  name                              = "${var.prefix}-oac-${var.stage}"
  signing_protocol                  = "sigv4"
  signing_behavior                  = "always"
  origin_access_control_origin_type = "lambda"
}

resource "aws_cloudfront_distribution" "lambda_origin" {
  origin {
    domain_name              = replace(replace(var.lambda_function_url, "https://", ""), "/", "")
    origin_id                = "LambdaOrigin"
    origin_access_control_id = aws_cloudfront_origin_access_control.lambda_origin.id
    custom_origin_config {
      http_port                = 80
      https_port               = 443
      origin_protocol_policy   = "https-only"
      origin_ssl_protocols     = ["TLSv1.2"]
    }
  }

  enabled         = true
  is_ipv6_enabled = true

  default_cache_behavior {
    target_origin_id       = "LambdaOrigin"
    viewer_protocol_policy = "allow-all"
    allowed_methods        = ["HEAD", "DELETE", "POST", "GET", "OPTIONS", "PUT", "PATCH"]
    cached_methods         = ["HEAD", "GET", "OPTIONS"]
    cache_policy_id        = aws_cloudfront_cache_policy.lambda_origin.id
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

resource "aws_lambda_permission" "allow_cloudfront" {
  statement_id  = "AllowCloudFrontServicePrincipal"
  action        = "lambda:InvokeFunctionUrl"
  function_name = var.lambda_name
  principal     = "cloudfront.amazonaws.com"
  source_arn    = aws_cloudfront_distribution.lambda_origin.arn
}

ポイントなど

domain_nameについて

Lambda Function URLは

https://xxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/

の形式で取得できるので、domain_nameにはこれを整形して、

xxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws

を渡します。

PUT, POSTメソッドについて

Lambda Function URLでPUT, POSTリクエストを行う際は、x-amz-content-sha256ヘッダーにペイロードのsha256ハッシュ値を含める必要があります。

(IAM認証情報を使った署名は必要ありません:参考
今回のようにCloudFront経由でリクエストを行う際も、CloudFrontへのリクエストに同様のヘッダーを含める必要があります。

これがないと以下のように怒られます。

{
    "message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details."
}

API Gatewayと最大timeoutについて

今回このCloudFront + Lambda Function URLの構成を検討したきっかけとして、Lambdaの処理時間が長い場合にAPI Gatewayのtimeout制限を手っ取り早く回避したいというものがありました。
最大timeoutはそれぞれ

です。
CloudFrontのクォータはコンソールの「Service Quotas」からは引き上げリクエストできないので、サポートに問い合わせる必要があります。
CloudFrontのクォータ引き上げ時の最大timeoutの180秒について、これを明記しているドキュメントは見当たらなかったのですが、引き上げリクエスト時にサポートに聞いたら180秒がhard limitであると回答をもらいました。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?