私はCloudFormationテンプレートが苦手です。CloudFormationが悪いツールだとは思いませんが、どうも慣れないというかなんというか。Terraformの方が簡単に書ける印象です。書くのが苦手ならば、もちろん読むのも苦手でして。たまにCFnテンプレートを渡されて、Terraformにしといてちょっと言われるのですが、よくわからないので渡されたテンプレートからCFnスタックを作成し、それをTerraformのimportでTerraform化していました。が、ちょっと検索するとcf2tfなるツールが・・・
cf2tf
CFnテンプレートをTerraformのコードにコンバートしてくれるツールです。できることはそれだけですが大変便利。
試す
簡単なCFnテンプレートを用意しました。
--- Resources: IAMUser: Type: AWS::IAM::User Properties: Path: / UserName: "test-user" IAMUserAccessKey: Type: AWS::IAM::AccessKey Properties: UserName: !Ref IAMUser IAMUserAccessKeySecret: Type: AWS::SecretsManager::Secret Properties: Name: !Sub credentials/${IAMUser} SecretString: !Sub "{\"accessKeyId\":\"${IAMUserAccessKey}\",\"secretAccessKey\":\"${IAMUserAccessKey.SecretAccessKey}\"}"
このコードでは、IAMユーザーを作成し、そのIAMユーザーで発行したクレデンシャルをSecrets Managerに登録します。
このコードをiam.aml
というファイルに保存し、cf2tfに食わせてみましょう。
$ cf2tf iam.yaml // Converting iam.yaml to Terraform! // Existing Terraform src code found at /var/folders/ys/ql50h491259ft68p_sf6qfjc0000gn/T/terraform_src. resource "aws_iam_user" "iam_user" { path = "/" name = "test-user" } resource "aws_iam_access_key" "iam_user_access_key" { user = aws_iam_user.iam_user.arn } resource "aws_secretsmanager_secret" "iam_user_access_key_secret" { name = "credentials/${aws_iam_user.iam_user.arn}" force_overwrite_replica_secret = "{"accessKeyId":"${aws_iam_access_key.iam_user_access_key.create_date}","secretAccessKey":"${aws_iam_access_key.iam_user_access_key.secret}"}" }
見事にTerraformのコードが生成されました。
デフォルトの動作では、コンバートしたHCLが標準出力されます。cf2tfに-o
オプションで出力先のディレクトリを指定してあげると、指定のディレクトリに出力できます。
$ cf2tf iam.yaml -o test // Converting iam.yaml to Terraform! // Existing Terraform src code found at /var/folders/ys/ql50h491259ft68p_sf6qfjc0000gn/T/terraform_src. Saving converted terraform objects to /path/to/test $ ls test resource.tf
今回はresource.tf
しかありませんが、変数を使っていればvariable.tf
、データソースを使用する場面があればdata.tf
など、いい感じにファイルを分割してくれます。
terraform validate
コマンドを実行してみると微妙にエラーが出ました。
$ terraform validate ╷ │ Error: Missing newline after argument │ │ on resource.tf line 12, in resource "aws_secretsmanager_secret" "iam_user_access_key_secret": │ 12: force_overwrite_replica_secret = "{"accessKeyId":"${aws_iam_access_key.iam_user_access_key.create_date}","secretAccessKey":"${aws_iam_access_key.iam_user_access_key.secret}"}" │ │ An argument definition must end with a newline. ╵ ╷ │ Error: Invalid character │ │ on resource.tf line 12, in resource "aws_secretsmanager_secret" "iam_user_access_key_secret": │ 12: force_overwrite_replica_secret = "{"accessKeyId":"${aws_iam_access_key.iam_user_access_key.create_date}","secretAccessKey":"${aws_iam_access_key.iam_user_access_key.secret}"}" │ │ This character is not used within the language. ╵ ╷ │ Error: Invalid character │ │ on resource.tf line 12, in resource "aws_secretsmanager_secret" "iam_user_access_key_secret": │ 12: force_overwrite_replica_secret = "{"accessKeyId":"${aws_iam_access_key.iam_user_access_key.create_date}","secretAccessKey":"${aws_iam_access_key.iam_user_access_key.secret}"}" │ │ This character is not used within the language. ╵
Secrets Managerに設定するJSONがうまくコンバートできなかったみたいです。
diff --git a/resource.tf b/resource.tf index ef81a3e..380c0a0 100644 --- a/resource.tf +++ b/resource.tf @@ -9,6 +9,8 @@ resource "aws_iam_access_key" "iam_user_access_key" { resource "aws_secretsmanager_secret" "iam_user_access_key_secret" { name = "credentials/${aws_iam_user.iam_user.arn}" - force_overwrite_replica_secret = "{"accessKeyId":"${aws_iam_access_key.iam_user_access_key.create_date}","secretAccessKey":"${aws_iam_access_key.iam_user_access_key.secret}"}" + force_overwrite_replica_secret = jsonencode({ + accessKeyId = aws_iam_access_key.iam_user_access_key.create_date, + secretAccessKey = aws_iam_access_key.iam_user_access_key.secret + }) } -
このように修正して再度バリデートしてあげると
$ terraform validate Success! The configuration is valid.
成功です。
$ terraform plan Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_iam_access_key.iam_user_access_key will be created + resource "aws_iam_access_key" "iam_user_access_key" { + create_date = (known after apply) + encrypted_secret = (known after apply) + encrypted_ses_smtp_password_v4 = (known after apply) + id = (known after apply) + key_fingerprint = (known after apply) + secret = (sensitive value) + ses_smtp_password_v4 = (sensitive value) + status = "Active" + user = (known after apply) } # aws_iam_user.iam_user will be created + resource "aws_iam_user" "iam_user" { + arn = (known after apply) + force_destroy = false + id = (known after apply) + name = "test-user" + path = "/" + tags_all = (known after apply) + unique_id = (known after apply) } # aws_secretsmanager_secret.iam_user_access_key_secret will be created + resource "aws_secretsmanager_secret" "iam_user_access_key_secret" { + arn = (known after apply) + force_overwrite_replica_secret = (sensitive value) + id = (known after apply) + name = (known after apply) + name_prefix = (known after apply) + policy = (known after apply) + recovery_window_in_days = 30 + tags_all = (known after apply) } Plan: 3 to add, 0 to change, 0 to destroy. ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
terraform plan
も大丈夫そうでした。
まとめ
CFnテンプレートをわざわざ実環境にデプロイしなくてHCL化できるのは大変便利です。ただし、完璧にコンバードができるわけではなさそうなので、terraform validate
などと組み合わせて修正しつつ進める必要がありました。