-
-
Save danimal141/45fa677efc3d8dd82a85338eb98b9b0e to your computer and use it in GitHub Desktop.
Lambda@Edge (origin-request) for CloudFront OAC with Lambda Function URL integration for POST/PUT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const crypto = require('crypto'); | |
exports.handler = (event, context, callback) => { | |
const request = event.Records[0].cf.request; | |
const headers = request.headers; | |
const method = request.method; | |
const body = Buffer.from(request.body.data, 'base64').toString(); | |
if (method != 'POST' && method != 'PUT') { | |
return callback(null, request); | |
} | |
const hash = crypto.createHash("sha256").update(body).digest("hex"); | |
console.log("hash", hash); | |
if (!headers["x-amz-content-sha256"]) { | |
headers["x-amz-content-sha256"] = [{ "key": "x-amz-content-sha256", "value": hash }]; | |
} | |
return callback(null, request); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module "cloudfront" { | |
source = "terraform-aws-modules/cloudfront/aws" | |
version = "~> 3.0" | |
# OAC is not supported for anything except GET requests out of the box: | |
# https://dev.to/vng_bach/resolve-lambda-url-error-signature-not-match-when-using-postput-44jm | |
# https://repost.aws/questions/QU7QethaVnTWKOF1JHGQggWg/lambda-url-with-x-amz-content-sha256-header | |
create_origin_access_control = true | |
origin_access_control = { | |
lambda_webhook_receiver = { | |
description = "CloudFront access to Lambda" | |
origin_type = "lambda" | |
signing_behavior = "always" | |
signing_protocol = "sigv4" | |
} | |
} | |
origin = { | |
lambda_webhook_receiver = { | |
domain_name = trimsuffix(trimprefix(module.webhook_receiver.lambda_function_url, "https://"), "/") | |
origin_access_control = "lambda_webhook_receiver" | |
custom_origin_config = { | |
http_port = 80 | |
https_port = 443 | |
origin_protocol_policy = "https-only" | |
origin_ssl_protocols = ["TLSv1.2"] | |
} | |
} | |
default = { # to disallow requests except to real webhook receiver | |
domain_name = "somethingnonexistent-just-to-disallow-requests.com" | |
custom_origin_config = { | |
http_port = 80 | |
https_port = 443 | |
origin_protocol_policy = "https-only" | |
origin_ssl_protocols = ["TLSv1.2"] | |
} | |
} | |
} | |
default_cache_behavior = { | |
target_origin_id = "default" | |
viewer_protocol_policy = "redirect-to-https" | |
allowed_methods = ["GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"] | |
cached_methods = ["GET", "HEAD"] | |
use_forwarded_values = false | |
compress = true | |
cache_policy_name = "Managed-CachingDisabled" | |
} | |
ordered_cache_behavior = [ | |
{ | |
path_pattern = local.webhook_path_pattern | |
target_origin_id = "lambda_webhook_receiver" | |
viewer_protocol_policy = "redirect-to-https" | |
allowed_methods = ["GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"] | |
cached_methods = ["GET", "HEAD"] | |
use_forwarded_values = false | |
compress = true | |
cache_policy_name = "Managed-CachingDisabled" | |
origin_request_policy_name = "Managed-AllViewerExceptHostHeader" | |
lambda_function_association = { | |
origin-request = { | |
lambda_arn = module.amz_content_sha256.lambda_function_qualified_arn | |
include_body = true | |
} | |
} | |
} | |
] | |
viewer_certificate = { | |
acm_certificate_arn = module.acm_us_east_1.acm_certificate_arn | |
ssl_support_method = "sni-only" | |
minimum_protocol_version = "TLSv1.2_2021" | |
} | |
geo_restriction = { | |
restriction_type = "blacklist" | |
locations = ["RU", "BY"] | |
} | |
} | |
# Lambda@Edge function which calculates the SHA256 hash of the request body | |
# and adds it as a custom header for CloudFront to be able to call Lambda function with OAC | |
module "amz_content_sha256" { | |
source = "terraform-aws-modules/lambda/aws" | |
version = "~> 7.0" | |
function_name = "amz-content-sha256" | |
description = "Lambda@Edge function which calculates the SHA256 hash of the request body and adds it as a custom header for CloudFront to be able to call Lambda function with OAC" | |
handler = "amz_content_sha256.handler" | |
runtime = "nodejs20.x" | |
architectures = ["x86_64"] | |
publish = true | |
lambda_at_edge = true | |
source_path = "${path.module}/amz_content_sha256.js" | |
create_current_version_allowed_triggers = true | |
create_unqualified_alias_allowed_triggers = true | |
allowed_triggers = { | |
cloudfront = { | |
service = "cloudfront" | |
source_arn = module.cloudfront.cloudfront_distribution_arn | |
}, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment