You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Jenkins的PEM凭证传递给Terraform并等待EC2就绪复制文件

问题背景

基于GitHub托管的Terraform项目可实现在AWS上部署搭载Tomcat的EC2实例,并配置8080端口访问安全策略,当前需要落地两个需求:

  • 等待EC2实例完全启动激活后,再执行文件复制操作
  • 将index.html、jpg格式示例图片复制到Tomcat的ROOT部署目录

核心卡点为PEM私钥的安全传递:出于安全考虑不将PEM文件直接提交到Git仓库,已将PEM文件存储在Jenkins凭证中,需要明确服务器就绪后执行文件复制的正确实现逻辑,以及将Jenkins存储的PEM凭证安全传递给Terraform的方案。

现有配置片段

Jenkins 配置

environment {
    AWS_ACCESS_KEY_ID     = credentials('AWS_ACCESS_KEY_ID')
    AWS_SECRET_ACCESS_KEY = credentials('AWS_SECRET_ACCESS_KEY')
    USER_KEYPEM           = credentials("AWS_USER_KEY_PEM")
}

Terraform 配置

resource "aws_instance" "web1" {
  ami                    = "${lookup(var.ami_id, var.region)}"
  instance_type          = "t2.micro"
  vpc_security_group_ids = ["sg-XXXXXXXXX"]

  tags = {
    Name = "myFirstWebServer"
  }

  provisioner "remote-exec" {
    inline = [
      "cloud-init status --wait"
    ]
  }
  provisioner "file" {
    source      = "web/index.html"
    destination = "/path_to_tomcat_root/index.html"
  }
  provisioner "file" {
    source      = "web/img.jpg"
    destination = "/path_to_tomcat_root/img.jpg"
  }

  connection {
    user        = "ec2-user"
    private_key = "?????????"    # 待解决:如何从Jenkins凭证传入PEM内容
    host        = "${aws_instance.web1.public_ip}"
  }
}
实现方案

等待服务器就绪后执行文件复制的配置方法

现有配置中cloud-init status --wait的逻辑方向正确,但需要补充provisioner执行顺序控制和连接重试配置,避免SSH服务未启动、Tomcat目录未初始化时提前执行操作导致报错:

  • Terraform会按照代码中定义的顺序从上到下执行provisioner,必须将等待系统就绪的remote-exec块放在所有文件复制provisioner的最前面
  • 在connection块中添加超时、重试间隔配置,等待SSH服务正常监听后再建立连接
  • 补充Tomcat ROOT目录存在性判断,避免文件复制时目标路径不存在

修正后的核心配置参考:

resource "aws_instance" "web1" {
  # 省略原有AMI、实例类型、安全组、标签配置

  # 最先执行:等待系统和服务初始化完成
  provisioner "remote-exec" {
    inline = [
      "cloud-init status --wait",
      # 轮询等待Tomcat ROOT目录初始化完成
      "while [ ! -d /path_to_tomcat_root ]; do sleep 5; done",
      # 若目录为root权限,可按需添加权限配置,例如:chmod 777 /path_to_tomcat_root
    ]
  }

  # 初始化完成后再执行文件复制
  provisioner "file" {
    source      = "web/index.html"
    destination = "/path_to_tomcat_root/index.html"
  }
  provisioner "file" {
    source      = "web/img.jpg"
    destination = "/path_to_tomcat_root/img.jpg"
  }

  connection {
    user        = "ec2-user"
    private_key = var.aws_private_key
    host        = self.public_ip
    timeout     = "5m"
    retry_delay = "10s" # 连接失败后10秒重试
  }
}

Jenkins PEM凭证安全传递给Terraform的方法

全程不要将PEM内容硬编码到代码或提交到Git仓库,通过Terraform敏感变量+Jenkins环境变量的方式传递,避免密钥泄露:

  1. 在Terraform项目中新建variables.tf文件,定义接收私钥的敏感变量:
variable "aws_private_key" {
  description = "EC2实例登录私钥内容"
  type        = string
  sensitive   = true # 标记为敏感值,Terraform执行日志不会输出明文
}
  1. 修改Jenkins Pipeline配置,利用Terraform的TF_VAR_前缀环境变量自动传参特性,不需要将PEM写入本地磁盘文件:

Jenkins的credentials()方法读取密钥类凭证时,会直接将凭证内容赋值给环境变量,全程不需要明文落盘

environment {
    AWS_ACCESS_KEY_ID     = credentials('AWS_ACCESS_KEY_ID')
    AWS_SECRET_ACCESS_KEY = credentials('AWS_SECRET_ACCESS_KEY')
    USER_KEYPEM           = credentials("AWS_USER_KEY_PEM")
    // Terraform会自动读取TF_VAR_开头的环境变量,匹配同名变量赋值
    TF_VAR_aws_private_key = "$USER_KEYPEM"
}

stages {
  stage('Deploy') {
    steps {
      sh 'terraform init'
      sh 'terraform apply -auto-approve'
    }
  }
}
  1. 配置完成后,Terraform的connection块直接引用var.aws_private_key即可获取PEM内容,替换原有占位符即可。
注意事项
  • 私钥变量标记为敏感类型后,执行过程中不会在Jenkins控制台日志中输出明文,避免日志泄露
  • 不需要在Pipeline中额外将PEM内容写入临时文件,减少密钥残留泄露的风险
  • 若file provisioner执行时报权限不足错误,在等待就绪的remote-exec块中添加目标目录的权限修改命令,为登录用户分配写入权限即可。

内容的提问来源于stack exchange,提问作者user3442473

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 07:21:21