Terraform配置CloudFront关联Lambda@Edge的权限循环问题求助
解决Terraform中CloudFront与Lambda@Edge的依赖循环问题
核心问题分析
你遇到的是典型的Terraform资源依赖循环:CloudFront分发需要关联Lambda@Edge的ARN才能创建,但Lambda权限配置又需要CloudFront的ARN来限制调用方,导致两者互相依赖无法正常创建。
解决方案步骤
1. 先创建Lambda函数及对应IAM角色
首先单独定义Lambda函数和其所需的IAM角色,确保Lambda发布可用于Edge的版本:
resource "aws_iam_role" "lambda_edge_role" { name = "lambda-edge-cognito-auth-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = ["lambda.amazonaws.com", "edgelambda.amazonaws.com"] } }] }) } resource "aws_lambda_function" "edge_cognito_auth" { filename = "auth-lambda.zip" function_name = "edge-cognito-auth-handler" role = aws_iam_role.lambda_edge_role.arn handler = "index.handler" runtime = "nodejs18.x" publish = true # 强制发布版本,Lambda@Edge要求必须使用已发布版本 region = "us-east-1" # Lambda@Edge必须部署在us-east-1区域 }
2. 创建宽松的Lambda权限(避免依赖CloudFront)
暂时不指定CloudFront的ARN,而是允许CloudFront服务主体调用该Lambda,同时限制到你的AWS账户ID:
data "aws_caller_identity" "current" {} resource "aws_lambda_permission" "allow_cloudfront_invocation" { statement_id = "AllowCloudFrontService" action = "lambda:GetFunction,lambda:InvokeFunction" function_name = aws_lambda_function.edge_cognito_auth.function_name principal = "cloudfront.amazonaws.com" source_account = data.aws_caller_identity.current.account_id }
这里用当前账户ID限制调用方,既避免了依赖CloudFront资源,又防止其他账户的CloudFront调用你的Lambda。
3. 创建CloudFront分发并关联Lambda@Edge
现在可以安全创建CloudFront分发,关联Lambda的版本ARN,并通过depends_on确保权限先于CloudFront创建:
resource "aws_cloudfront_distribution" "main" { # 基础配置:域名、默认根对象等 enabled = true default_root_object = "index.html" # 其他必要配置:价格类、自定义域名、证书等... default_cache_behavior { target_origin_id = "your-origin-id" viewer_protocol_policy = "redirect-to-https" # 关联Lambda@Edge到viewer-request事件 lambda_function_association { event_type = "viewer-request" lambda_arn = aws_lambda_function.edge_cognito_auth.versioned_arn } } # 确保CloudFront在Lambda权限配置完成后再创建 depends_on = [aws_lambda_permission.allow_cloudfront_invocation] }
4. (可选)收紧Lambda权限到特定CloudFront分发
等CloudFront分发创建完成后,修改aws_lambda_permission资源,添加source_arn限制调用方为当前CloudFront分发:
resource "aws_lambda_permission" "allow_cloudfront_invocation" { statement_id = "AllowCloudFrontService" action = "lambda:GetFunction,lambda:InvokeFunction" function_name = aws_lambda_function.edge_cognito_auth.function_name principal = "cloudfront.amazonaws.com" source_account = data.aws_caller_identity.current.account_id source_arn = aws_cloudfront_distribution.main.arn # 添加这行限制特定分发 }
执行terraform apply即可完成权限收紧。
关键注意事项
- Lambda@Edge必须使用已发布的版本,因此Lambda函数必须设置
publish = true,并引用versioned_arn关联到CloudFront。 - Lambda函数必须部署在
us-east-1区域,即使你的CloudFront分发面向其他区域。 - IAM角色必须同时信任
lambda.amazonaws.com和edgelambda.amazonaws.com服务主体,否则Lambda@Edge无法正常执行。
内容的提问来源于stack exchange,提问作者Tomas Caetano
相关产品推荐
相关产品推荐

