こんにちは、技術4課の多田です。
突然ですが、皆さんはTerraformは利用されていますか?
AWSのサービスも幅広く対応しているHashiCorp社のオーケストレーションツールですが、今回はTerraformが対応していない、AWS Config(以下、Config)の有効化方法をレポートしたいと思います。
サービスのサポート範囲のおさらい
本題に入る前にConfigの概要について振り返ります。
Configとは、AWSのリソースの構成履歴、構成変更の通知を行うためのフルマネージドサービスです。
対象のリソースについてこちらのブログで紹介しましたが、サポートする対象が拡大しておりましたので、再掲します。
対象 | |
EC2 | EC2インスタンス EC2 Network Interface EC2 セキュリティグループ EC2 Elastic IP EC2 Dedicated Hosts |
EBS | 汎用(SSD)ボリューム プロビジョンドIOPS(SSD)ボリューム マグネティックボリューム |
VPC | カスタマーゲートウェイ インターネットゲートウェイ ネットワークACL ルートテーブル サブネット VPN ゲートウェイ VPN接続 |
CloudTrail | |
IAM | IAM ユーザー IAM Group IAM ロール IAM 管理ポリシー |
ACM | |
EC2 Systems Manager | Managed instance inventory |
ELB | ALB |
Redshift | Redshiftクラスター クラスターパラメータグループ クラスターセキュリティグループ クラスタースナップショット クラスターサブネットグループ イベントサブスクリプション |
RDS | RDSインスタンス RDSセキュリティグループ RDSスナップショット RDSサブネットグループ イベントサブスクリプション |
S3 | S3バケット |
詳しくは、こちらのドキュメントも合わせて参照ください(英語のドキュメントになります)。
Terraformのパラメーターの肝について
本題のTerraformの設定パラメーターについてです。
サポートされていないConfigを有効化する方法として、(1)AWS CLIと、(2)TerraformでサポートされているCloudFormationで確認を行いました。
(1) AWS CLIで行う場合
具体的にはTerraformのパラメーターとして次のようなコマンドを実行しました。
provisioner "local-exec" { command = "sleep 15s && aws configservice subscribe --s3-bucket ${aws_s3_bucket.<S3バケット名>.id} --sns-topic ${aws_sns_topic.<SNSトピック名>.arn} --iam-role ${aws_iam_role.<IAMロール名>.arn} && aws configservice put-configuration-recorder --configuration-recorder name=default,roleARN=${aws_iam_role.<IAMロール名>.arn} --recording-group allSupported=true,includeGlobalResourceTypes=true" }
「local-exec」は、Terraformのコード実行後の後処理として組み込みたいものを定義する部分になります。詳しくはこちらのドキュメントを合わせてご覧ください(英語のドキュメントになります)
そのコードの中では、まず15秒の制止時間を設けています。制止時間がないとエラーが出力されてしまったための対処です。
また、「subscribe」コマンドでConfigによる変更履歴をログとして溜めるS3バケット、通知を送るSNSトピック、Configで使うIAMロールの指定をしています。CLIコマンドのリソース指定もTerraformの文法が使えるのは便利だと思いました。
その他、IAM、S3などのグローバルなAWSサービスの変更履歴を記録する場合「put-configuration-recorder」にincludeGlobalResourceTypesオプションを有効化すれば対応可能です。
Terraformの実行と有効化確認
それでは、実際にTerraformで実行してみてみましょう。
「local-exec」をS3バケット作成の最後の処理として組み込んでいるためS3バケット作成中に制止時間が発生しています。
$ terraform apply aws_sns_topic.xxxxxx: Creating... ~中略~ aws_s3_bucket.xxxxxxx: Still creating... (10s elapsed) aws_s3_bucket.xxxxxxx: Still creating... (20s elapsed) aws_s3_bucket.xxxxxxx (local-exec): Using existing S3 bucket: xxxxxxx aws_s3_bucket.xxxxxxx (local-exec): Using existing SNS topic: arn:aws:sns:ap-northeast-1:xxxxxxx:xxxxxxx aws_s3_bucket.xxxxxxx (local-exec): Subscribe succeeded:aws_s3_bucket.xxxxxxx (local-exec): Configuration Recorders: [ aws_s3_bucket.xxxxxxx (local-exec): { aws_s3_bucket.xxxxxxx (local-exec): "recordingGroup": { aws_s3_bucket.xxxxxxx (local-exec): "allSupported": true, aws_s3_bucket.xxxxxxx (local-exec): "resourceTypes": [], aws_s3_bucket.xxxxxxx (local-exec): "includeGlobalResourceTypes": false aws_s3_bucket.xxxxxxx (local-exec): }, aws_s3_bucket.xxxxxxx (local-exec): "roleARN": "arn:aws:iam::xxxxxxx:role/xxxxxxx", aws_s3_bucket.xxxxxxx (local-exec): "name": "default" aws_s3_bucket.xxxxxxx (local-exec): } aws_s3_bucket.xxxxxxx (local-exec): ]
aws_s3_bucket.xxxxxxx (local-exec): Delivery Channels: [ aws_s3_bucket.xxxxxxx (local-exec): { aws_s3_bucket.xxxxxxx (local-exec): "snsTopicARN": "arn:aws:sns:ap-northeast-1:xxxxxxx:xxxxxxx", aws_s3_bucket.xxxxxxx (local-exec): "name": "default", aws_s3_bucket.xxxxxxx (local-exec): "s3BucketName": "xxxxxxx" aws_s3_bucket.xxxxxxx (local-exec): } aws_s3_bucket.xxxxxxx (local-exec): ] aws_s3_bucket.xxxxxxx: Creation complete
Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
「Apply Complete!」と表示されたので、Terraformの実行は成功しました。
「terraform apply」実行後、有効化ができているかを確認します。
変更履歴の記録の「Configuration Recorders」と変更履歴のログ格納や通知する処理の「Delivery Channels」のステータスがいずれも「SUCCESS」となっていますので、有効化できていることを確認しました。
$ aws configservice get-status Configuration Recorders: name: default recorder: ON last status: SUCCESS Delivery Channels: name: default last stream delivery status: SUCCESS
注意点
上記まででConfig有効化に必要な作業について書いてきました。
本項では、紹介した方法を使う上での注意点についても記載します。
注意点としては、当然ながらCofigのリソースはAWS CLIで作成しているため、Terraformによるリソース削除の対象とはなりません。
つまり、「terraform destory」コマンドを実行してもConfigの無効化することができません。
そのため、以下ではConfigの無効化を行う場合のAWS CLIコマンドを記載します。
まず、下記コマンドでConfigがAWSリソースの変更履歴の記録を削除します。
aws configservice delete-configuration-recorder --configuration-recorder-name <標準ですと「default」になります>
次に、下記コマンドでAWSリソースの変更履歴のログをS3に溜めたり、SNSに通知する処理を削除します。
「delete-delivery-channel」は、予め上記の変更履歴の記録を停止している状態でないと実行ができませんので、注意が必要です。
aws configservice delete-delivery-channel --delivery-channel-name <標準ですと「default」になります>
(2)TerraformでCloudFormationを実行
もう1つの方法として、CloudFromationでConfigを有効化する方法も確認してみました。
以下が実際のConfig有効化に必要なIAMロールとポリシーの作成、ConfigのDeliveryChannelとConfigurationRecorderを設定しています。
また、template内でIAMロールを作成しているので、capabilitiesでCAPABILITY_IAMを指定します。
resource "aws_cloudformation_stack" "Config" { name = "config-stack" capabilities = ["CAPABILITY_IAM"] template_body = <<STACK { "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "ConfigRoleTest": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version" : "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "config.amazonaws.com" ] }, "Action": [ "sts:AssumeRole" ] } ] }, "ManagedPolicyArns": ["arn:aws:iam::aws:policy/service-role/AWSConfigRole"], "Path": "/", "Policies": [ { "PolicyName": "ConfigRolePolicy", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject" ], "Resource": [ "arn:aws:s3:::xxxxxxx/AWSLogs/xxxxxxxx/*" ], "Condition": { "StringLike": { "s3:x-amz-acl": "bucket-owner-full-control" } } }, { "Effect": "Allow", "Action": [ "s3:GetBucketAcl" ], "Resource": "arn:aws:s3:::xxxxxxx" }, { "Effect":"Allow", "Action":"sns:Publish", "Resource":"arn:aws:sns:ap-northeast-1:xxxxxxxx:xxxxxxx" } ] } }] } }, "ConfigDeliveryChannel": { "Type" : "AWS::Config::DeliveryChannel", "Properties" : { "Name" : "default", "S3BucketName" : "awsconfig-testbucket", "SnsTopicARN" : "arn:aws:sns:ap-northeast-1:xxxxxxxx:xxxxxxx" } }, "ConfigRecorder": { "Type" : "AWS::Config::ConfigurationRecorder", "Properties" : { "Name" : "default", "RecordingGroup" : { "AllSupported" : true, "IncludeGlobalResourceTypes" : true }, "RoleARN": {"Fn::GetAtt": ["ConfigRoleTest", "Arn"]} } } } } STACK }
実際に「terraform apply」を実行すると以下のような実行結果になります。
$ terraform apply ~中略~ aws_cloudformation_stack.ConfigActivate: Creating... capabilities.#: "" => "1" capabilities.1328347040: "" => "CAPABILITY_IAM" name: "" => "config-stack" outputs.%: "" => "<computed>" parameters.%: "" => "<computed>" policy_body: "" => "<computed>" template_body: "" => "{\"AWSTemplateFormatVersion\":\"2010-09-09\",\"Resources\":{\"ConfigDeliver ~中略~ aws_sns_topic.ConfigTopic:aws_cloudformation_stack.ConfigActivate: Still creating... (10s elapsed) aws_cloudformation_stack.ConfigActivate: Still creating... (20s elapsed) aws_cloudformation_stack.ConfigActivate: Still creating... (30s elapsed) aws_cloudformation_stack.ConfigActivate: Still creating... (40s elapsed) aws_cloudformation_stack.ConfigActivate: Still creating... (50s elapsed) aws_cloudformation_stack.ConfigActivate: Still creating... (1m0s elapsed) aws_cloudformation_stack.ConfigActivate: Still creating... (1m10s elapsed) aws_cloudformation_stack.ConfigActivate: Creation completeApply complete! Resources: 3 added, 0 changed, 0 destroyed.
Configが有効化されているかを確認してみます。Configuration RecordersとDelivery Channelsのstatusが「SUCCESS」となっているので、有効化されています。
$ aws configservice get-status Configuration Recorders:name: default recorder: ON last status: SUCCESS
Delivery Channels:
name: default last stream delivery status: SUCCESS
まとめ
TerraformでConfigを有効化する方法についてレポートになりました。
AWS CLIとCloudFormationで有効化する方法について紹介しましたが、非サポートのサービスでもTerraformのコードに組み込んでAWSリソースを作成することができることがわかりました。
この記事が何かの参考になれば幸いです。それでは!