Terraform创建API Gateway报AccessDeniedException异常排查
根因分析
- 本次报错的核心原因是执行Terraform操作的身份(本地配置的AK/SK、CI环境角色、实例角色等)缺少API Gateway相关操作的权限,和你代码中定义的IAM服务角色、Authorizer配置没有关系,也不需要额外在Terraform中定义
aws_iam_user资源。 - 你代码中编写的
aws_iam_role.invocation_role、Lambda执行角色等,属于AWS服务运行时使用的资源级角色,仅在API Gateway调用Lambda、授权器校验逻辑执行时生效;而Terraform调用AWS API创建资源时,使用的是你当前运行Terraform命令的身份凭证,这个身份权限不足时,会直接在创建最基础的aws_api_gateway_rest_api资源阶段就抛出403错误——如果是资源内角色配置错误,报错会出现在API创建完成后、配置集成/授权器的环节,不会卡在创建REST API的第一步。 - 除了权限问题外,你现有配置还有3处隐藏问题,就算执行权限修复后也会触发后续报错:
aws_api_gateway_integration.lambda_root配置错误,当前绑定的是/{proxy+}路径的POST方法,没有绑定API根路径,会导致根路径请求直接返回404。aws_api_gateway_authorizer的authorizer_uri格式错误,直接使用Lambda的invoke_arn不符合API Gateway授权器的调用规范,会导致授权器创建失败或无法正常调用。aws_api_gateway_deployment依赖项不全,没有关联Method、Resource、Authorizer资源,会出现资源创建完成但配置未发布到指定阶段的问题。
解决方案
1. 修复Terraform执行身份权限
给当前运行Terraform的IAM用户/角色附加包含以下权限的策略,即可解决创建REST API和自定义域名的403问题:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "apigateway:*", "acm:DescribeCertificate", "lambda:AddPermission", "lambda:RemovePermission" ], "Resource": "*" } ] }
注:如果需要遵循最小权限原则,可以按需收缩apigateway的操作范围,必须包含apigateway:POST(创建资源)、apigateway:GET/PUT/PATCH/DELETE(修改查询资源)权限;同时要确保该身份有权限读取你配置的var.domain_certificate_arn对应的ACM证书,否则自定义域名创建仍会报错。
2. 修正Terraform配置错误
修复根路径方法与集成
单独为API根路径创建POST方法,修正根路径集成的绑定关系:
# 根路径POST方法 resource "aws_api_gateway_method" "root_post" { rest_api_id = aws_api_gateway_rest_api.handler_gateway.id resource_id = aws_api_gateway_rest_api.handler_gateway.root_resource_id http_method = "POST" authorization = "NONE" } # 修正后的根路径Lambda集成 resource "aws_api_gateway_integration" "lambda_root" { rest_api_id = aws_api_gateway_rest_api.handler_gateway.id resource_id = aws_api_gateway_method.root_post.resource_id http_method = aws_api_gateway_method.root_post.http_method integration_http_method = "POST" type = "AWS_PROXY" uri = aws_lambda_function.handler_lambda.invoke_arn }
修正自定义授权器配置
调整authorizer_uri为API Gateway要求的标准格式,补充必填的授权器类型、身份来源参数:
resource "aws_api_gateway_authorizer" "demo" { name = "demo" rest_api_id = aws_api_gateway_rest_api.handler_gateway.id type = "REQUEST" # 可根据实际场景替换为TOKEN/COGNITO_USER_POOLS authorizer_uri = "arn:aws:apigateway:${var.aws_region}:lambda:path/2015-03-31/functions/${aws_lambda_function.handler_lambda.arn}/invocations" authorizer_credentials = aws_iam_role.invocation_role.arn identity_source = "method.request.header.Authorization" # 按实际鉴权字段调整 }
补全部署资源依赖
给Deployment资源补全所有关联资源的依赖,增加触发器保证配置变更时自动重新部署:
resource "aws_api_gateway_deployment" "handler" { depends_on = [ aws_api_gateway_integration.lambda, aws_api_gateway_integration.lambda_root, aws_api_gateway_method.events_post, aws_api_gateway_method.root_post, aws_api_gateway_resource.events_proxy, aws_api_gateway_authorizer.demo ] rest_api_id = aws_api_gateway_rest_api.handler_gateway.id stage_name = "default" triggers = { redeployment = sha1(jsonencode([ aws_api_gateway_resource.events_proxy.id, aws_api_gateway_method.events_post.id, aws_api_gateway_method.root_post.id, aws_api_gateway_integration.lambda.id, aws_api_gateway_integration.lambda_root.id, aws_api_gateway_authorizer.demo.id ])) } }
3. 验证修复
执行terraform plan确认配置无语法错误后,再运行terraform apply即可完成资源创建。
内容的提问来源于stack exchange,提问作者tjurkan
相关产品推荐
相关产品推荐

