使用 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 编码的文本作为普通字符串传递。
我的设置是: 地形 --> 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 编码的文本作为普通字符串传递。