如何在terraform中创建SSH密钥?

Abe*_*Abe 31 amazon-web-services terraform

我需要为不同的用户启动一堆EC2盒子.每个用户都应该从所有其他用户沙箱中进行,因此每个EC2框都需要自己的SSH密钥.

在terraform中实现这一目标的最佳方法是什么?

我发现的几乎所有说明都要我手动创建SSH密钥并将其粘贴到terraform脚本中.

(坏)示例:

由于我需要以编程方式为许多用户生成唯一键,因此这是不切实际的.

这似乎不是一个困难的用例,但我无法在任何地方找到它的文档.

在紧要关头,我可以使用bash生成terraform脚本并动态注入SSH密钥.但这似乎就像terraform首先应该做的那样.

yda*_*coR 59

Terraform可以使用该tls_private_key资源生成SSL/SSH私钥.

因此,如果您想动态生成SSH密钥,您可以执行以下操作:

variable "key_name" {}

resource "tls_private_key" "example" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "aws_key_pair" "generated_key" {
  key_name   = "${var.key_name}"
  public_key = "${tls_private_key.example.public_key_openssh}"
}

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}

resource "aws_instance" "web" {
  ami           = "${data.aws_ami.ubuntu.id}"
  instance_type = "t2.micro"
  key_name      = "${aws_key_pair.generated_key.key_name}"

  tags {
    Name = "HelloWorld"
  }
}
Run Code Online (Sandbox Code Playgroud)

这将创建一个生活在Terraform状态的SSH密钥对(它不会写入除不使用远程状态时Terraform状态本身可能做的文件以外的文件中的磁盘),根据公钥创建AWS密钥对然后创建一个Ubuntu 14.04实例,ubuntu用户可以使用生成的私钥访问该实例.

然后,您必须从状态文件中提取私钥并将其提供给用户.output当应用Terraform时,您可以使用a 直接吐出到stdout.

我应该在这里指出,传递私钥通常是一个坏主意,让开发人员创建自己的密钥对并为您提供您(或他们)可以用来生成AWS密钥对的公钥会更好. (可能使用上例中使用的aws_key_pair资源),然后可以在创建实例时指定.

一般情况下,我只会使用类似于上述生成SSH密钥的方法来为您控制的非常临时的开发环境,因此您不需要将私钥传递给任何人.如果您确实需要将私钥传递给人员,则需要确保在安全通道中执行此操作,并确保Terraform状态(包含纯文本中的私钥)也得到适当保护.

  • 最初的问题不要求将其用作 exec 的一部分,因此您可能最好提出一个单独的问题,链接到其中的这个问题,并解释为什么这里的答案不适合您的特定用例,显示您的代码以及运行时遇到的错误。 (3认同)
  • 该答案仅生成一个私钥。如果您正在做一些不同的事情,那么可能值得创建一个新问题来显示您所做的事情并链接回此问题作为参考。 (2认同)

Oli*_*ver 20

对先前答案的扩展,不适合评论:

要将生成的密钥写入具有正确权限的私有文件:

resource "local_file" "pem_file" {
  filename = pathexpand("~/.ssh/${local.ssh_key_name}.pem")
  file_permission = "600"
  directory_permission = "700"
  sensitive_content = tls_private_key.ssh.private_key_pem
}
Run Code Online (Sandbox Code Playgroud)

然而,像这样保存文件的一个缺点是路径最终会处于 terraform 状态。如果只是 CI/CD 和/或一个人运行 terraform apply,那么没什么大不了的,但如果有更多“应用者”,则只要与上次 apply 不同的人运行 apply,tfstate 就会更新。这会产生一些“更新”噪音。没什么大不了的,但需要注意。

避免这种情况的另一种方法是将 pem 文件保存在 AWS Secrets Manager 中,或在 S3 中加密,并提供命令来获取它并创建本地文件。

2023 年 3 月更新:

local_sensitive_file自 2022 年 3 月起可用。请改用它:

resource "local_sensitive_file" "pem_file" {
  filename = pathexpand("~/.ssh/${local.ssh_key_name}.pem")
  file_permission = "600"
  directory_permission = "700"
  content = tls_private_key.ssh.private_key_pem
}
Run Code Online (Sandbox Code Playgroud)

感谢@kangkyud 指出如何改进这篇文章!


Sau*_*abh 10

添加凯的答案

variable "generated_key_name" {
  type        = string
  default     = "terraform-key-pair"
  description = "Key-pair generated by Terraform"
}

resource "tls_private_key" "dev_key" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "aws_key_pair" "generated_key" {
  key_name   = var.generated_key_name
  public_key = tls_private_key.dev_key.public_key_openssh

  provisioner "local-exec" {    # Generate "terraform-key-pair.pem" in current directory
    command = <<-EOT
      echo '${tls_private_key.dev_key.private_key_pem}' > ./'${var.generated_key_name}'.pem
      chmod 400 ./'${var.generated_key_name}'.pem
    EOT
  }

}

Run Code Online (Sandbox Code Playgroud)


Kai*_*Kai 6

下面的代码创建myKeytoAWSmyKey.pemtoyour computer和 createdmyKeymyKey.pem具有相同的私钥。(我用过Terraform v0.15.4

resource "tls_private_key" "pk" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "aws_key_pair" "kp" {
  key_name   = "myKey"       # Create "myKey" to AWS!!
  public_key = tls_private_key.pk.public_key_openssh

  provisioner "local-exec" { # Create "myKey.pem" to your computer!!
    command = "echo '${tls_private_key.pk.private_key_pem}' > ./myKey.pem"
  }
}
Run Code Online (Sandbox Code Playgroud)

不要忘记myKey.pem仅通过在 ssh 到您的 ec2 实例之前运行以下代码来使其可读。

chmod 400 myKey.pem
Run Code Online (Sandbox Code Playgroud)

否则会出现下面的错误。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0664 for 'myKey.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "myKey.pem": bad permissions
ubuntu@35.72.30.251: Permission denied (publickey).
Run Code Online (Sandbox Code Playgroud)