既存 AWS IAM Identity Center ユーザーを Terraformにインポートする【import ブロックで超簡単】
どうも、ちゃだいん(@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ブロックを生成してみます。
#!/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__ 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インポート、やっていきましょう!