如何将null_resource生成的密钥内容传入Terraform其他资源?
解决方案:将EC2密钥对内容传入AWS SSM Parameter Store
问题根源
你遇到的所有错误本质都是Terraform规划阶段与执行阶段的时序冲突:
file()函数在terraform plan阶段就会尝试读取文件,而null_resource的local-exec要到terraform apply阶段才生成文件,导致规划时文件不存在。depends_on只能引用完整资源对象,无法指向资源内部的provisioner。- Terraform的
output是用于向外暴露结果的,不能在资源配置内部直接引用。
推荐方案:使用官方aws_key_pair资源(最符合Terraform规范)
直接用Terraform官方提供的aws_key_pair资源创建密钥对,无需手动调用AWS CLI,可直接获取密钥材料属性,完美规避时序问题:
resource "aws_key_pair" "ec2_key" { key_name = var.resource_prefix key_type = "rsa" } resource "aws_ssm_parameter" "private_key" { name = "/production/${var.resource_prefix}.pem" description = "Private key" type = "SecureString" value = aws_key_pair.ec2_key.private_key # 隐式依赖已通过属性引用实现,depends_on可省略,此处显式写出仅作说明 depends_on = [aws_key_pair.ec2_key] }
优势
- 完全遵循Terraform声明式编程模型,无需处理本地文件的时序问题。
- 密钥材料直接通过资源属性传递,无需本地存储(如需本地保存,可通过
output导出后手动写入文件)。 - 自动维护资源依赖关系,避免手动配置
depends_on的失误。
备选方案:在local-exec中直接完成密钥创建与SSM上传(兼容原有工作流)
如果必须保留local-exec调用AWS CLI的方式,可将密钥创建、本地保存、SSM上传合并到同一个local-exec命令中,一次性完成所有操作:
resource "null_resource" "generate_key_pair_and_upload_ssm" { provisioner "local-exec" { command = <<EOF # 创建密钥对并捕获密钥材料 KEY_MATERIAL=$(aws ec2 create-key-pair \ --profile ${var.profile} \ --region ${var.aws_region} \ --key-name "${var.resource_prefix}" \ --key-type rsa \ --key-format pem \ --query "KeyMaterial" \ --output text) # 保存到本地.pem文件(按需保留) echo "$KEY_MATERIAL" > ${var.resource_prefix}.pem # 直接上传到SSM Parameter Store aws ssm put-parameter \ --profile ${var.profile} \ --region ${var.aws_region} \ --name "/production/${var.resource_prefix}.pem" \ --description "Private key" \ --type "SecureString" \ --value "$KEY_MATERIAL" EOF } }
注意事项
- 确保执行Terraform的环境已配置好AWS CLI权限,能同时操作EC2密钥对和SSM参数。
- 若后续Terraform操作依赖该SSM参数,需通过
null_resource的triggers或显式depends_on维护依赖关系。
内容的提问来源于stack exchange,提问作者Mitchell Privett
相关产品推荐
相关产品推荐

