LoginSignup
22
15

More than 3 years have passed since last update.

TerraformでAWS(EC2)のキーペアを作成する

Last updated at Posted at 2019-09-04

前提

  • Terraform 0.11系。

説明

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

tfファイル

キーペア作成

keygen.tf
/**
 * 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アカウント情報

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

EC2のキーペアとして登録

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

使い方

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

plan

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.

apply

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」で探すと良い。

参考モジュール

22
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
15