使用 Terraform 将文件传递给新创建的 ec2 实例而不共享 "connection" 部分中的私钥

using Terraform to pass a file to newly created ec2 instance without sharing the private key in "connection" section

我的设置是: 地形 --> AWS ec2

使用 Terraform 创建具有 SSH 访问权限的 ec2 实例。

resource "aws_instance" "inst1" {
  instance_type = "t2.micro"
  ami           = data.aws_ami.ubuntu.id
  key_name      = "aws_key"
  subnet_id     = ...
  user_data     = file("./deploy/templates/user-data.sh")

  vpc_security_group_ids = [
    ... ,
  ]
  provisioner "file" {
    source      = "./deploy/templates/ec2-caller.sh"
    destination = "/home/ubuntu/ec2-caller.sh"
  }

  provisioner "remote-exec" {
    inline = [
      "chmod +x /home/ubuntu/ec2-caller.sh",      
    ]
  }

  connection {
    type        = "ssh"
    host        = self.public_ip
    user        = "ubuntu"
    private_key = file("./keys/aws_key_enc")
    timeout     = "4m"
  }
}

上面的位有效,我可以看到供应商复制和执行'ec2-caller.sh。 我不想将我的私钥以明文形式传递给 Terraform 供应商。无论如何,我们可以在不使用配置器或不将私钥传递给配置器的情况下将文件复制到新创建的 ec2 吗?

干杯。

Terraform 文档部分 Provisioners are a Last Resort raises the need to provision and pass in credentials as one of the justifications for provisioners being a "last resort", and then goes on to suggest some other strategies for passing data into virtual machines and other compute resources

您似乎已经在使用 user_data 为 运行 指定一些其他脚本,因此要遵循该文档中的建议,需要将这些全部组合成一个 cloud-init配置。 (我假设您的 AMI 已安装 cloud-init,因为这通常负责将 user_data 解释为要执行的 shell 脚本。)

Cloud-init 支持 several different user_data formats, with the primary one being cloud-init's own YAML configuration file format, "Cloud Config". You can also use a multipart MIME message 将多个不同的 user_data 有效负载打包到一个 user_data 主体中,只要有效负载的组合大小符合 EC2 的上限user_data 大小限制,即 16kiB。

从您的配置来看,您似乎需要 cloud-init 处理两个步骤才能使用 cloud-init:

完全解决此问题
  • 运行 ./deploy/templates/user-data.sh 脚本。
  • /home/ubuntu/ec2-caller.sh 放在具有适当权限的磁盘上。

假设这两个步骤相互独立,您可以发送 cloud-init 多部分 MIME 消息,其中包括您最初单独使用的 user-data 脚本 一个 Cloud Config YAML 配置,用于将 ec2-caller.sh 文件放在磁盘上。 The Terraform provider hashicorp/cloudinit has a data source cloudinit_config 知道如何为 cloud-init 构造多部分 MIME 消息,您可以像这样使用它:

data "cloudinit_config" "example" {
  part {
    content_type = "text/x-shellscript"
    content      = file("${path.root}/deploy/templates/user-data.sh")
  }

  part {
    content_type = "text/cloud-config"
    content = yamlencode({
      write_files = [
        {
          encoding    = "b64"
          content     = filebase64("${path.root}/deploy/templates/ec2-caller.sh")
          path        = "/home/ubuntu/ec2-caller.sh"
          owner       = "ubuntu:ubuntu"
          permissions = "0755"
        },
      ]
    })
  }
}

resource "aws_instance" "inst1" {
  instance_type = "t2.micro"
  ami           = data.aws_ami.ubuntu.id
  key_name      = "aws_key"
  subnet_id     = ...
  user_data     = data.cloudinit_config.example.rendered

  vpc_security_group_ids = [
    ... ,
  ]
}

上面的第二个 part 块包含基于 cloud-init 示例的 YAML Writing out arbitrary files, which you could refer to in order to learn what other settings are possible. Terraform's yamlencode function 无法生成特殊的 !!binary该示例中某些文件中使用的标记,但设置 encoding: b64 允许将 base64 编码的文本作为普通字符串传递。