3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TerraformでIAMユーザを一気に作る

Last updated at Posted at 2021-08-09

はじめに

  • 業務でTerraformを使う機会があり、とことん躓いたので備忘録を残します
  • 本稿ではTerraformでIAMユーザを一気に作る手順を記録します
  • 誤りの訂正・より良い方法のご助言、どしどしコメント頂ければ幸いです

参考とさせていただいた記事様

Terraform 実行環境

  • AWS Cloud9
    • Amazon Linux2
    • t2.micro
  • Cloud9を使う理由
    • 標準でTerraformが備わっているため
  • Cloud9の設定
    • AWS managed temporary credentialsをオフにする
      • オンだとIAMの一部機能にアクセスできないため
    • EC2インスタンスにAdministratorAccessポリシーを持つロールをアタッチしておく

アウトライン

  1. GPGで鍵の生成
  2. TerraformでIAMユーザの一括作成
  3. ワンライナーでIAMユーザパスワードの一括復号
  4. おまけ:一括復号ワンライナー完全理解

1.GPGで鍵の生成

鍵の生成

gpg --gen-key
  • 色々聞かれるが、基本デフォルト値(何も入力しないでエンター押すとそうなる)
  • Real Nameは必須
    • 今回はtaishi_oとする
  • パスワードは入力しなくてもいける
    • 今回はなしで

鍵を保存

gpg -o ./taishi_o.public.gpg  --export taishi_o
gpg -o ./taishi_o.private.gpg --export-secret-key taishi_o

公開鍵をBase64エンコードして保存

cat taishi_o.public.gpg | base64 | tr -d '\n' > taishi_o.public.gpg.base64
  • taishi_o.public.gpg.base64にエンコード済かつ改行コードが取り除かれた公開鍵が記録される

2. IAMユーザの作成

  • 下記の通りterraformのコードを書く
iam_user.tf
provider "aws" {
  region = "ap-northeast-1"
}

variable "pgp_key" {
  type    = string
  default = "mQ......Qz"  # taishi_o.public.gpg.base64 の中身
}

variable "aws_iam_user" {
  type = map(any)
  default = {
    member1 = {
      name   = "member1",
    },
    member2 = {
      name   = "member2",
    },
    member3 = {
      name   = "member3",
    },
  }
}

# IAM Userの作成
resource "aws_iam_user" "team_a" {
  for_each      = var.aws_iam_user
  name          = each.value.name
  path          = "/"
  force_destroy = true
}

# Login Profileの作成
resource "aws_iam_user_login_profile" "team_a" {
  for_each                = aws_iam_user.team_a
  user                    = each.value.name
  pgp_key                 = var.pgp_key
  password_reset_required = true
  password_length         = "20"
}


output "username" {
  value = aws_iam_user_login_profile.team_a
}
  • ターミナルでterraform apply
出力イメージ
username = {
  "member1" = {
    "encrypted_password" = "wc......A="
    "id" = "member1"
    "key_fingerprint" = "01...70"
    "password_length" = 20
    "password_reset_required" = true
    "pgp_key" = "mQ......Qz"
    "user" = "member1"
  }
  "member2" = {
    "encrypted_password" = "wc......A="
    "id" = "member2"
    "key_fingerprint" = "01...70"
    "password_length" = 20
    "password_reset_required" = true
    "pgp_key" = "mQ......Qz"
    "user" = "member2"
  }
  "member3" = {
    "encrypted_password" = "wc......A="
    "id" = "member3"
    "key_fingerprint" = "01...70"
    "password_length" = 20
    "password_reset_required" = true
    "pgp_key" = "mQ......Qz"
    "user" = "member3"
  }
}

3. IAMユーザパスワードの一括復号(ワンライナー)

  • 下記をターミナルで実行することで、作成したIAMユーザのパスワードを一括で標準出力できる
        - ご自身で作成されたgpgキーを使うところのみご変更ください(下記ではtaishi.oの部分)
パスワード一括復号ワンライナー
terraform output -json | ruby -rjson -e 'json = JSON.load(ARGF); values = json["username"]["value"]; keys = %w(id encrypted_password); puts [keys, *keys.map{|key| values.map{|value| v = value[1][key].split; key == "encrypted_password" ? v.map{|s| `echo #{s} | base64 -di | gpg -r taishi_o`.chomp} : v}}.transpose].map{|a| a.join(",")}'
出力イメージ
gpg: encrypted with 2048-bit RSA key, ID 2E35ECDD, created 2021-08-06
      "taishi_o"
gpg: encrypted with 2048-bit RSA key, ID 2E35ECDD, created 2021-08-06
      "taishi_o"
gpg: encrypted with 2048-bit RSA key, ID 2E35ECDD, created 2021-08-06
      "taishi_o"
id,encrypted_password
member1,+B......Bk
member2,a#......MS
member3,Xz......i{
  • これらidencrypted_passwordでサインインすることができる

4. おまけ:一括復号ワンライナー完全理解


terraform output -json

|(パイプ)

  • command a| command bcommand aの結果をcommand bに渡せる

ruby -rjson -e '...'

  • ruby: Rubyコマンド
  • -rjson: rubyでjsonを扱えるJSONライブラリを読み込む
  • -e...に記述されたスクリプトを実行する
    • スクリプト内の;は改行を表す

json = JSON.load(ARGF);

  • パイプされたterraform output -jsonの出力をjson形式で読み込んで、json変数に入れる

    • ARGFは渡されたものを1つの仮想ファイルにするオブジェクト
  • 備考:渡されたjsonは下記で見れる

    terraform output -json | ruby -rjson -e 'json = JSON.load(ARGF); puts [JSON.pretty_generate(json)];'
    
    • putsは標準出力
    • JSON.pretty_generate(json)はjsonを可読性出力するものっぽい(Pythonで言うならpprint?)

terraform output -json | ruby -rjson -e 'json = JSON.load(ARGF); puts [json["username"]["value"]];'

values = json["username"]["value"];

  • データ部を抽出し、values変数に格納

keys = %w(username encrypted_password);

  • usernameencrypted_passwordという要素をもつ1次元配列keysを宣言
    • Rubyでは%w(a b c)["a","b","c"]が作れる

puts["char1", "char2"]

  • 出力
char1
char2
  • 要素を改行しながら表示してくれる

*keys.map{|key| values.map{|value| v = value[1][key].split;

  • Rubyではlist.mapで要素ごとに処理を追加できる
    • keysの要素(username, encrypted_password)をjsonのキーに指定し、値を変数vに格納している
    • splitは文字列を空白区切りで配列に変換している
  • 備考: *は配列展開
    • *keysはkeys[0], keys[1]と要素ごとに出力してくれる
    • *があるおかげで最終結果を見やすく改行できている

key == "encrypted_password" ? v.map{|s| `echo #{s} | base64 -di | gpg -r taishi_o`.chomp} : v}

  • 三項演算子
  • 条件:key"encrypted_password"か否か
    • True: v.map{|s| echo #{s} | base64 -di | gpg -r taishi_o.chomp}の結果を出力
    • False: v をそのまま出力

v.map{|s| `echo #{s} | base64 -di | gpg -r taishi_o`.chomp}

  • encrypted_passwordのリストvの各要素sに対して秘密鍵(?)taishi_oで復号している
  • chompは文字列から改行コードを除いて返すメソッド

transpose

  • 配列の転置
  • transposeの実行でmemberとそのパスワードをセットで表示できる
member1 password1
member2 password2

list.map{|a| a.join","}

  • listの要素を,区切りの文字列として連結
  • これにより下記のようなcsv形式になる
member1,password1
member2,password2

おわりに

  • 無事IAMユーザを一気に作り、ログインパスワードを一括で表示できました
  • 余談: countを使ってresourceを一括作成する方法もありますが、こちらは変更に弱くなってしまいます(詳しくは下記リンク様参照)
  • 苦しめられますが非常に便利なので、ネタがあれば引き続きTerraformの検証記事を書いていく予定です
3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?