どうも、ちゃだいん(@chazuke4649)です。
Terraform v1.5にて新たに import ブロックと既存リソースのHCL生成が追加され、config-driven import (手動ではなく設定ファイルが起点となるインポート) が可能となりました。
背景
今まで既存のAWSリソースをTerraformにインポートする方法といえば、
terraform import
コマンドによる地道な作業- Terraformer ツール頼み
でどちらも厳しい状況でした。
そんな中、v1.5では救世主とも呼べる新たな選択肢が誕生しました。
今回は試しに、マネコン あるいは CLI で作成していた既存の AWS IAM Identity Center ユーザーの Terraform コードを自動生成し、Terraform にインポートしてみます。
前提
- Terraform: v1.5.2 (v1.5の新機能が必須)
- AWS Provider: v5.7.0
手順
手順は以下となります。
- importブロックを生成する (シェルスクリプト)
- resourceブロックを生成する (コマンドオプション)
- applyしてインポートする
※importブロック自体の使い方は、先述のブログをご覧ください。
対象リソース
今回はIdentity Centerユーザーのみインポートします。
Identity Center グループや、ユーザーとグループの紐付けなどは対象としていません。が、実際全ての管理をTerraform化したい場合は必要となりますのでご注意ください。
1.importブロックを生成する
現時点ではimportブロックは、for_each
や count
などの機能をサポートしていません。
なので、importブロック自体はリソースの数だけ作成する必要があります。
Identity Center ユーザーが多い場合は、手動で全て記述するのは困難であるため、シェルスクリプトでimportブロックを生成してみます。
import_blocks_generator.sh
#!/bin/bash
STORE_ID=$(aws sso-admin list-instances --query "Instances[0].IdentityStoreId" --output text)
USER_NAME_AND_USER_ID=$(aws identitystore list-users --identity-store-id $STORE_ID --query "Users[*].[UserName,UserId]" --output text)
echo "$USER_NAME_AND_USER_ID" | while read -r line; do
USER_NAME=$(echo $line | awk '{print $1}')
# USER_NAMEに@が含まれている場合(主にメールアドレス)の場合は、@より前の部分をUSER_NAMEとする
# いずれの場合でも、USER_NAMEに含まれる記号は_に置換する
if [[ $USER_NAME == *"@"* ]]; then
USER_NAME=$(echo $USER_NAME | awk -F'@' '{print $1}' | sed 's/[^_0-9a-zA-Z]/_/g')
else
USER_NAME=$(echo $USER_NAME | sed 's/[^_0-9a-zA-Z]/_/g')
fi
USER_ID=$(echo $line | awk '{print $2}')
cat << EOF
import {
to = aws_identitystore_user.$USER_NAME
id = "${STORE_ID}/${USER_ID}"
}
EOF
done
補足
シェルスクリプトの補足をします。
1行目にて、IdentityStoreId
を取得します。
2行目にて、Identityストアから、Identity Centerユーザーの、 UserName
と UserId
を取得します。
UserId
はインポート対象リソースの判定のために必要なので、そのまま importブロックの to
に IdentityStoreId
と組み合わせてセットします。
UserName
は、resourceブロックのリソース名に使用します。
UserName
は、自分の環境だと、主に2パターン存在しました。
- いわゆる IAMユーザー名に設定するような一般的な文字列(例: chadain)のパターン
- メールアドレス(例: chadain@example.com)のパターン
これらどちらでも対応できるように、IF文にて条件分岐を入れています。
条件分岐内容としては、@が含まれるメールアドレスの場合、@より前の部分のみを利用します。
さらに、いずれの場合も記号が含まれる場合は、すべて _
に置換します。
理由としては、利用先であるresourceブロックのリソース名の制約として -
と _
以外の記号をサポートしていないためです。
ちなみに、置換は最小限にしておきたいため、アルファベットの大文字・小文字はそのままです。
実際にこのシェルスクリプトを実行すると 、importブロックが出力されます。
% ./import_blocks_generator.sh
import {
to = aws_identitystore_user.TestAdminUser
id = "d-9567example/95670080be-586dabeb-d327-4c15-a5a5-example1"
}
import {
to = aws_identitystore_user.TestReadOnlyUser
id = "d-9567example/95670080be-5e06c4ae-9465-4c64-a43d-example2"
}
import {
to = aws_identitystore_user.kurameso_ichiro
id = "d-9567example/87342ad8-30b1-xxxxxxx-example3"
}
import {
to = aws_identitystore_user.kurameso_jiro
id = "d-9567example/95670080be-60380f2a-066c-example4"
}
正常に出力されることが確認できたら、新しい構成ファイルに流し込みます。
% ./import_blocks_generator.sh > generated_imports.tf
2.resourceブロックを自動生成する
次に terraform plan
の -generate-config-out
オプション を使用して、先ほど生成された4つの import ブロックの resource ブロックを生成します。
% terraform plan -generate-config-out=generated_sso_users.tf
上記コマンドをたたくと、以下ファイルが生成されます。これは便利。
generated_sso_users.tf
# __generated__ by Terraform
# Please review these resources and move them into your main configuration files.
# __generated__ by Terraform from "d-d-9567example/87342ad8-30b1-xxxxxxx-example3"
resource "aws_identitystore_user" "kurameso_ichiro" {
display_name = ""
identity_store_id = "d-9567example"
locale = null
nickname = null
preferred_language = null
profile_url = null
timezone = null
title = null
user_name = "kurameso-ichiro@example.com"
user_type = null
addresses {
country = null
formatted = null
locality = null
postal_code = null
primary = false
region = null
street_address = null
type = "work"
}
emails {
primary = true
type = "work"
value = "kurameso-ichiro@example.com"
}
name {
family_name = "kurameso"
formatted = null
given_name = "ichiro"
honorific_prefix = null
honorific_suffix = null
middle_name = null
}
}
## 以下省略
## 本来はこのようなリソースブロックがあと3つ生成されます
3.applyしてインポートする
最後は、terraform apply してインポートを完了させます。
% terraform apply -auto-approve
data.aws_ssoadmin_instances.main: Reading...
## 間省略...
Apply complete! Resources: 4 imported, 0 added, 0 changed, 0 destroyed.
これでインポート完了です。
超簡単でしたね?
新機能を活用して既存リソースのTerraformインポート、やっていきましょう!