Terraform为未创建的AWS Lambda配置可通过STS Assume的IAM角色
问题根因
你遇到的报错是因为IAM创建角色时会实时校验信任策略中的Principal是否真实存在,你写的arn:aws:sts::xxx:assumed-role/xxx/xxx是Lambda运行时生成的临时会话ARN,在IAM角色创建、Lambda还没部署的阶段这个ARN根本不存在,所以直接触发Principal无效的报错,本质是循环依赖+Principal类型使用错误。
正确配置方案
步骤1:拆分两个IAM角色
你需要明确拆分两类角色,不要混为一谈:
- Lambda执行角色:Lambda本身启动运行时用的角色,信任主体是
lambda.amazonaws.com服务,只需要给这个角色加允许assume目标角色的权限即可 - 业务目标角色:Lambda运行时通过STS Assume的角色,信任主体写Lambda执行角色的ARN,不需要写临时会话ARN
步骤2:编写Terraform配置示例
基础变量定义
locals { tms_rules_settings_lambda_func_name = "tms_rules_settings_lambda" lambda_exec_role_name = "tms_lambda_exec_role" target_assume_role_name = "tms_business_target_role" } # 调用当前账号信息 data "aws_caller_identity" "current" {}
第一步:创建Lambda执行角色
这个角色是Lambda启动时用的,信任主体固定为Lambda服务:
resource "aws_iam_role" "lambda_exec_role" { name = local.lambda_exec_role_name assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Principal = { Service = "lambda.amazonaws.com" } Effect = "Allow" } ] }) } # 给Lambda执行角色加允许Assume目标角色的权限 resource "aws_iam_role_policy" "allow_assume_target" { name = "allow_assume_target_role" role = aws_iam_role.lambda_exec_role.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Resource = aws_iam_role.target_assume_role.arn } ] }) }
第二步:创建Lambda要Assume的目标角色
信任主体直接写Lambda执行角色的ARN即可,不需要写运行时的临时会话ARN:
resource "aws_iam_role" "target_assume_role" { name = local.target_assume_role_name assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Principal = { AWS = aws_iam_role.lambda_exec_role.arn } Effect = "Allow" } ] }) # 这里添加目标角色需要的业务权限,比如操作S3、DynamoDB等 }
第三步:创建Lambda函数
直接关联Lambda执行角色即可:
resource "aws_lambda_function" "tms_rules_settings_lambda" { function_name = local.tms_rules_settings_lambda_func_name role = aws_iam_role.lambda_exec_role.arn # 其他Lambda配置:runtime、handler、代码包等 }
步骤3:Lambda代码适配
你的STS Assume代码不需要改,直接用原来的写法即可,运行时Lambda用执行角色的权限就能正常Assume到目标角色。
额外权限优化
如果需要严格限制只有指定的Lambda函数才能Assume目标角色,可以在目标角色的信任策略里加条件判断,不需要修改Principal配置即可实现最小权限:
assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Principal = { AWS = aws_iam_role.lambda_exec_role.arn } Effect = "Allow" Condition = { StringEquals = { "aws:userid" = "${aws_iam_role.lambda_exec_role.unique_id}:${local.tms_rules_settings_lambda_func_name}" } } } ] })
这个条件会校验运行时的userid后缀是否匹配指定的Lambda函数名称,不会让同一个执行角色下的其他Lambda也能Assume目标角色,同时完全避免循环依赖问题。
内容的提问来源于stack exchange,提问作者Black Dynamite
相关产品推荐
相关产品推荐

