Google Cloud Platform - 如何使用 terraform 将 ssh 密钥添加到 GCP 实例



所以我有一个在 Google Cloud Platform 中创建实例的 terraform 脚本,我希望能够让我的 terraform 脚本也将我的 ssh 密钥添加到我创建的实例中,以便我可以通过 ssh 配置它们。 这是我当前的地形脚本。

#PROVIDER INFO
provider "google" {
  credentials = "${file("account.json")}"
  project     = "myProject"
  region      = "us-central1"
}

#MAKING CONSUL SERVERS
resource "google_compute_instance" "default" {
  count    =  3
  name     =  "a-consul${count.index}"
  machine_type = "n1-standard-1"
  zone         = "us-central1-a"
  disk {
    image = "ubuntu-1404-trusty-v20160627"
  }
  # Local SSD disk
  disk {
    type    = "local-ssd"
    scratch = true
  }
  network_interface {
    network = "myNetwork"
    access_config {}
  }
}

我必须添加什么才能让我的地形脚本添加我的 ssh 密钥/Users/myUsername/.ssh/id_rsa.pub

我认为这样的事情应该有效:

  metadata = {
    ssh-keys = "${var.gce_ssh_user}:${file(var.gce_ssh_pub_key_file)}"
  }

https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys 描述了元数据机制,我在 https://github.com/hashicorp/terraform/issues/6678 中找到了此示例

仅供记录。 从 0.12 开始,该块似乎应如下所示:

resource "google_compute_instance" "default" {
  # ...
  metadata = {
    ssh-keys = join("n", [for user, key in var.ssh_keys : "${user}:${key}"])
  }
  # ...
}

(注意=符号后metadata令牌和ssh-keys vs. sshKeys(。

您可以使用以下内容

metadata = {
  ssh-keys = "username:${file("username.pub")}"
}

我一直在努力使用terraform使用ssh密钥创建一个实例,这个答案也经过测试和工作。

这是经过测试的。

  metadata {
    sshKeys = "${var.ssh_user}:${var.ssh_key} n${var.ssh_user1}:${var.ssh_key1}"
}

如果你想要多个键,你可以使用这样的heredoc

  metadata = {
    "ssh-keys" = <<EOT
<user>:<key>
<user>:<key>
EOT
  }

我在terraform fmt提供给我的帖子中保持了奇怪的格式。

只是在Terraform v0.15.4中更新多个键:

metadata = {
    ssh-keys = join("n", [for key in var.ssh_keys : "${key.user}:${key.publickey}"])
}

和相应的变量:

variable "ssh_keys" {
  type = list(object({
    publickey = string
    user = string
  }))
  description = "list of public ssh keys that have access to the VM"
  default = [
      {
        user = "username"
        publickey = "ssh-rsa yourkeyabc username@PC"
      }
  ]
}

我在下面为我工作:对于所有虚拟机,一个 SSH 密钥

resource "google_compute_project_metadata" "my_ssh_key" {
  metadata = {
    ssh-keys = <<EOF
      terakey:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICqaF7TqtimTUtqLdZIspKjuTXXXXnkbW7N9TQBPXazu terakey
      
    EOF
  }
}

我在下面测试了将ssh公钥注入谷歌计算实例及其对我工作的方法。

  metadata = {
    ssh-keys = "${var.ssh_user}:${file("./gcp_instance_ssh_key.pub")}"
  OR 
    ssh-keys  = "${var.ssh_user}:${file(var.public_key_path)}"
  OR
    ssh-keys  = "${var.ssh_user}:${file("${var.public_key_path}")}"
   
  }
variable "public_key_path" {
    default = "./gcp_instance_ssh_key.pub"   ##public key with path
}

请注意使用 ssh 键而不是 ssh_keys(带下划线(

首先,需要一个计算实例:

resource "google_compute_instance" "website_server" {
  name                      = "webserver"
  description               = "Web Server"
  machine_type              = "f1-micro"
  allow_stopping_for_update = true
  deletion_protection       = false
  tags = ["webserver-instance"]
  shielded_instance_config {
    enable_secure_boot          = true
    enable_vtpm                 = true
    enable_integrity_monitoring = true
  }
  scheduling {
    provisioning_model  = "STANDARD"
    on_host_maintenance = "TERMINATE"
    automatic_restart   = true
  }
  boot_disk {
    mode        = "READ_WRITE"
    auto_delete = true
    initialize_params {
      image = "ubuntu-minimal-2204-jammy-v20220816"
      type  = "pd-balanced"
    }
  }
  network_interface {
    network = "default"
    access_config {
      network_tier = "PREMIUM"
    }
  }
  metadata = {
    ssh-keys               = "${var.ssh_user}:${local_file.public_key.content}"
    block-project-ssh-keys = true
  }
  labels = {
    terraform = "true"
    purpose   = "host-static-files"
  }
  service_account {
    # Custom service account with restricted permissions
    email  = data.google_service_account.myaccount.email
    scopes = ["compute-rw"]
  }
}

请注意,metadata ssh-keys字段需要"授权密钥"格式的公钥数据,即打开的SSH公钥。这类似于执行pbcopy < ~/.ssh/id_ed25519.pub

您需要防火墙规则才能在(默认(端口 22 上允许 SSH:

resource "google_compute_firewall" "webserver_ssh" {
  name    = "webserver-firewall"
  network = "default"
  allow {
    protocol = "tcp"
    ports    = ["22"]
  }
  target_tags   = ["webserver-instance"]
  source_ranges = ["0.0.0.0/0"]
}

您的公钥和私钥可以是短暂的,以使事情更加无缝:

resource "tls_private_key" "webserver_access" {
  algorithm = "ED25519"
}
resource "local_file" "public_key" {
  filename        = "server_public_openssh"
  content         = trimspace(tls_private_key.webserver_access.public_key_openssh)
  file_permission = "0400"
}
resource "local_sensitive_file" "private_key" {
  filename = "server_private_openssh"
  # IMPORTANT: Newline is required at end of open SSH private key file
  content         = tls_private_key.webserver_access.private_key_openssh
  file_permission = "0400"
}

最后,要登录,您需要一个基于以下内容的连接字符串:

output "instance_connection_string" {
  description = "Command to connect to the compute instance"
  value       = "ssh -i ${local_sensitive_file.private_key.filename} ${var.ssh_user}@${google_compute_instance.website_server.network_interface.0.access_config.0.nat_ip} ${var.host_check} ${var.ignore_known_hosts}"
  sensitive   = false
}

其中变量文件可能如下所示:

variable "ssh_user" {
  type        = string
  description = "SSH user for compute instance"
  default     = "myusername"
  sensitive   = false
}
variable "host_check" {
  type        = string
  description = "Dont add private key to known_hosts"
  default     = "-o StrictHostKeyChecking=no"
  sensitive   = false
}
variable "ignore_known_hosts" {
  type        = string
  description = "Ignore (many) keys stored in the ssh-agent; use explicitly declared keys"
  default     = "-o IdentitiesOnly=yes"
  sensitive   = false
}

要知道的一件事是,如果有更高级别的项目,您可能需要在元数据中添加禁用操作系统登录的选项。

metadata = {
    "enable-oslogin" = false
    "ssh-keys"       = ...
}

只有这样authorized_keys才会创建文件

此外,您可能需要添加"can_ip_forward = true"选项以启用外部流量。

最新更新