TerraformでAWS Configを有効化する

記事タイトルとURLをコピーする

こんにちは、技術4課の多田です。

突然ですが、皆さんはTerraformは利用されていますか?

AWSのサービスも幅広く対応しているHashiCorp社のオーケストレーションツールですが、今回はTerraformが対応していない、AWS Config(以下、Config)の有効化方法をレポートしたいと思います。

サービスのサポート範囲のおさらい

本題に入る前にConfigの概要について振り返ります。

Configとは、AWSのリソースの構成履歴、構成変更の通知を行うためのフルマネージドサービスです。

対象のリソースについてこちらのブログで紹介しましたが、サポートする対象が拡大しておりましたので、再掲します。

 対象
EC2EC2インスタンス
EC2 Network Interface
EC2 セキュリティグループ
EC2 Elastic IP
EC2 Dedicated Hosts

EBS汎用(SSD)ボリューム
プロビジョンドIOPS(SSD)ボリューム
マグネティックボリューム
VPCカスタマーゲートウェイ
インターネットゲートウェイ
ネットワークACL
ルートテーブル
サブネット
VPN ゲートウェイ
VPN接続
CloudTrail 
IAMIAM ユーザー
IAM Group
IAM ロール
IAM 管理ポリシー
ACM 
EC2 Systems ManagerManaged instance inventory
ELBALB
RedshiftRedshiftクラスター
クラスターパラメータグループ
クラスターセキュリティグループ
クラスタースナップショット
クラスターサブネットグループ
イベントサブスクリプション
RDSRDSインスタンス
RDSセキュリティグループ
RDSスナップショット
RDSサブネットグループ
イベントサブスクリプション
S3S3バケット

詳しくは、こちらのドキュメントも合わせて参照ください(英語のドキュメントになります)。

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 complete

Apply 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リソースを作成することができることがわかりました。

この記事が何かの参考になれば幸いです。それでは!