使用Terraform创建AWS(EC2)的密钥对

假设

    Terraform 0.11系。

解释

    以下のように「ssh-keygen」などで作成したものを利用しているのを、Terraformの方に作成までやらせてみる。
ssh-keygen -t rsa -b 4096 -C '' -N '' -f example.id_rsa

tf文件

生成密钥对 duì)

「TLS」プロバイダの「tls_private_key」リソースを利用して作成する。

https://www.terraform.io/docs/providers/tls/r/private_key.html

/**
 * require
 **/
terraform {
  required_version = ">= 0.11.0"
}

/**
 * variable
 **/
variable "key_name" {
  type        = "string"
  description = "keypair name"
  #default    = "example" # キー名を固定したかったらdefault指定。指定なしならインタラクティブにキー入力して決定。
}

# キーファイル
## 生成場所のPATH指定をしたければ、ここを変更するとよい。
locals {
  public_key_file  = "./${var.key_name}.id_rsa.pub"
  private_key_file = "./${var.key_name}.id_rsa"
}

/**
 * resource
 **/
# キーペアを作る
resource "tls_private_key" "keygen" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

/**
 * file
 **/
# 秘密鍵ファイルを作る
resource "local_file" "private_key_pem" {
  filename = "${local.private_key_file}"
  content  = "${tls_private_key.keygen.private_key_pem}"

  # local_fileでファイルを作ると実行権限が付与されてしまうので、local-execでchmodしておく。
  provisioner "local-exec" {
    command = "chmod 600 ${local.private_key_file}"
  }
}

resource "local_file" "public_key_openssh" {
  filename = "${local.public_key_file}"
  content  = "${tls_private_key.keygen.public_key_openssh}"

  # local_fileでファイルを作ると実行権限が付与されてしまうので、local-execでchmodしておく。
  provisioner "local-exec" {
    command = "chmod 600 ${local.public_key_file}"
  }
}

/**
 * output
 **/
# キー名
output "key_name" {
  value = "${var.key_name}"
}

# 秘密鍵ファイルPATH(このファイルを利用してサーバへアクセスする。)
output "private_key_file" {
  value = "${local.private_key_file}"
}

# 秘密鍵内容
output "private_key_pem" {
  value = "${tls_private_key.keygen.private_key_pem}"
}

# 公開鍵ファイルPATH
output "public_key_file" {
  value = "${local.public_key_file}"
}

# 公開鍵内容(サーバの~/.ssh/authorized_keysに登録して利用する。)
output "public_key_openssh" {
  value = "${tls_private_key.keygen.public_key_openssh}"
}

AWS账户信息

provider "aws" {
  profile = "example"
  region  = "ap-northeast-1"
}
    「profile」にはAWS CLIのプロファイル名を指定。

注册为EC2密钥对

「AWS」プロバイダの「aws_key_pair」リソースを利用。

https://www.terraform.io/docs/providers/aws/r/key_pair.html

resource "aws_key_pair" "key_pair" {
  key_name   = "${var.key_name}"
  public_key = "${tls_private_key.keygen.public_key_openssh}"
}

用法

    キーペア作成するだけなら、AWSプロバイダ関連の記述は不要(上記tfファイル群のうち「keygen.tf」だけで良い)。

计划

terraform plan
var.key_name
  keypair name

  Enter a value: 
    キーペア名を聞かれるので、「example」と入力すると、以下のように表示される。
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + local_file.private_key_pem
      id:                         <computed>
      content:                    "${tls_private_key.keygen.private_key_pem}"
      filename:                   "./example.id_rsa"

  + local_file.public_key_openssh
      id:                         <computed>
      content:                    "${tls_private_key.keygen.public_key_openssh}"
      filename:                   "./example.id_rsa.pub"

  + tls_private_key.keygen
      id:                         <computed>
      algorithm:                  "RSA"
      ecdsa_curve:                "P224"
      private_key_pem:            <computed>
      public_key_fingerprint_md5: <computed>
      public_key_openssh:         <computed>
      public_key_pem:             <computed>
      rsa_bits:                   "4096"


Plan: 3 to add, 0 to change, 0 to destroy.

申请

terraform plan
var.key_name
  keypair name

  Enter a value: 
    ここでもキーペア名を聞かれるので、「example」と入力すると、以下のように表示される。
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + local_file.private_key_pem
      id:                         <computed>
      content:                    "${tls_private_key.keygen.private_key_pem}"
      filename:                   "./example.id_rsa"

  + local_file.public_key_openssh
      id:                         <computed>
      content:                    "${tls_private_key.keygen.public_key_openssh}"
      filename:                   "./example.id_rsa.pub"

  + tls_private_key.keygen
      id:                         <computed>
      algorithm:                  "RSA"
      ecdsa_curve:                "P224"
      private_key_pem:            <computed>
      public_key_fingerprint_md5: <computed>
      public_key_openssh:         <computed>
      public_key_pem:             <computed>
      rsa_bits:                   "4096"


Plan: 3 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: 
    • 最終確認が入るので、「yes」と入力すると、キーペアが作成される。

AWSへのEC2キーペア登録もするなら、同時に登録される。

可以按照以下的方式指定变量。

terraform apply -var 'key_name=example'

请留意

    • ssh-keygenと同じような感覚で、このまま「キーペア生成ツール」としては利用できない。

「key_name」変数を変更すると、既に作成したキーペアファイルが削除(destroy)されてしまう。
lifecycleブロックで適切にignore_changes 指定してやればいける?(未検証)

以下で検証した通り、単にignore_changes指定しただけでは「キーペア生成ツール」として利用することはできない、ということが分かった。

【追記】关于ignore_changes的验证结果

    例えば以下のように、上記例「keygen.tf」のうち、秘密鍵(private_key_pem)、公開鍵(public_key_openssh)それぞれについて、lifecycleブロックで「filename」をignore_changes指定してやったところ、削除(destroy)はされなくなったものの、単にそれだけで、再生成自体が行われなくなった。
resource "local_file" "private_key_pem" {
  filename = "${local.private_key_file}"
  content  = "${tls_private_key.keygen.private_key_pem}"

  provisioner "local-exec" {
    command = "chmod 600 ${local.private_key_file}"
  }

  lifecycle {
    ignore_changes = [ 
      "filename",
    ]   
  }
}
    • 考えてみれば当たり前のことで、「ignore_changes」は変更を無視するということなんだから、ここに「filename」を指定すれば、「変数の値を変更してファイル名が変わったとしても、何もしない。」となるだけの、至って正常な挙動だった。

 

    • 「lifecycle」ブロックには、「ignore_changes」も含め、以下のような項目がある。(※ 詳細はマニュアル参照)

ignore_changes

指定した属性の変更を無視して何もしない。
属性名をlist指定

prevent_destroy

このリソースをdestroyしない。変更などの影響でdestroyが実行されるとエラーになる。
true/falseのbool指定

create_before_destroy

同名リソースを再生成(create)する時に、先に削除(destroy)する。

false指定すると、createしてからdestroyするようになるという、処理順制御の項目。(削除はされる)

true/falseのbool指定

暗黙のデフォルト値は「true」になっている。

因此,结论是“无法像ssh-keygen命令一样,只能生成密钥对的工具不能使用。”相反,如果不将密钥名称变为变量,那么删除或生成操作将与tf文件的描述内容相联动,可能可以将其作为“密钥管理工具”来使用。


参考资料等

关于模块

    • 外部モジュールとして指定してやれば、変数指定だけで利用できたりする。

 

    「Terraform Module Registry」で探すと良い。

One possible paraphrase in Chinese for “参考モジュール” is “参考模块” .

cloudposse/terraform-aws-key-pair: Terraform Module to Automatically Generate SSH Key Pairs (Public/Private Keys)

https://github.com/cloudposse/terraform-aws-key-pair
Terraform Module Registry URL

https://registry.terraform.io/modules/cloudposse/key-pair

様々なTerraformモジュールを作っている「Cloud Posse」謹製モジュール。色々指定できる。ガッツリ系。

cloudposse/terraform-tls-ssh-key-pair: Terraform module for generating an SSH public/private key file.

https://github.com/cloudposse/terraform-tls-ssh-key-pair
Terraform Module Registry URL

https://registry.terraform.io/modules/cloudposse/ssh-key-pair

上記モジュールからAWS部分を除外して、キーペア作成だけにしたもの。

mitchellh/terraform-aws-dynamic-keys: Terraform module that dynamically generates a public/private keypair.

https://github.com/mitchellh/terraform-aws-dynamic-keys
Terraform Module Registry URL

https://registry.terraform.io/modules/mitchellh/dynamic-keys

Terraformを作っているHashiCorp代表、ミッチェル・ハシモト氏(mitchellh)謹製モジュール。アッサリ系。分かりやすい。

今回の記事は、ほぼこのモジュール内容のパクリ。

广告
将在 10 秒后关闭
bannerAds