
AWS CloudFormationで手動で行った変更が検出可能になりました!!!
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
大栗です。
CloudFormationはAWSインフラのオーケストレーションを担っており、Infrastructure as Codeで構成のバージョン管理ができる素晴らしいサービスです。しかし大きな難点がありました。それはCloudFormation外の変更を認識しないことで、テンプレートの変更時に意図しない環境になることでした。今回のアップデートでCloudFormation外の変更(ドリフト)も検出可能になり、その様な問題発生を抑止できるようになりましたのでレポートします。
- New – CloudFormation Drift Detection
- AWS CloudFormation Now Supports Drift Detection
- Announcement: Introducing AWS CloudFormation Drift Detection! Detect changes made to your stack resources outside of CloudFormation
- Detecting Unmanaged Configuration Changes to Stacks and Resources
ドリフト検出とは?
概要
今回のアップデートであるドリフト検知はre:Invent 2017のセッションで発表されていた機能で、現在の状態とCloudFormationで定義されているあるべき状態の差分を検知することができる機能です。
初期の構築ではCloudFormationを利用するが、後のアップデートではUpdate Stackを実行せずに手動で変更したりCloudFormation以外の手段で変更してしまうことが多々あります。一旦別の手段へ変更してしまうと、テンプレートとの差が分からなくなりCloudFormationを利用した構成管理が行えなくなり、大きな問題になっていました。
実際のリソースとCloudFormationテンプレートの内容に乖離があることをドリフトと言い、それが可視化できる様になりました。
ドリフト検出は、一般の商用リージョン全てで利用可能です。
ドリフトを検出できるリソース
ドリフトを検出できるサービスは、2018年11月14日現在で以下となります。各サービスの対象となるリソースの詳細についてはドキュメントをご参照ください。
- API Gateway
- Auto Scaling
- CloudTrail
- CloudWatch Events
- CloudWatch Logs
- DynamoDB
- Amazon EC2
- Amazon ECS
- Elastic Load Balancing
- IAM
- AWS IoT
- Lambda
- Amazon RDS
- Route 53
- Amazon S3
- Amazon SNS
- Amazon SQS
ドリフト検出のステータス
ドリフトのステータスにはいくつかの種類があります。
- ドリフト検出オペレーションステータス: ドリフトの操作の現在のステータスを記述する。
- スタックドリフトステータス: そのリソースのドリフト状態に基づいて、スタック全体のドリフト状態を記述します。
- リソースドリフトステータス: 個々のリソースのドリフト状況を記述します。
ドリフト検出オペレーションステータス
| ドリフト検出オペレーションステータス | 説明 |
|---|---|
| DETECTION_COMPLETE | ドリフト検出をサポートするスタック内のすべてのリソースについて、スタックドリフト検出オペレーションが正常に完了した。 |
| DETECTION_FAILED | スタックドリフト検出オペレーションは、スタック内の少なくとも1つのリソースで失敗した。結果はCloudFormationがドリフト検出を正常に完了したリソースで利用できる。 |
| DETECTION_IN_PROGRESS | スタックドリフト検出オペレーションは現在進行中です。 |
スタックドリフトステータス
| スタックドリフトステータス | 説明 |
|---|---|
| DRIFTED | スタックは、予想されるテンプレート構成と異なるか、またはドリフトがある。1つ以上のリソースにドリフトがある場合、スタックはドリフトがあるみなされる |
| NOT_CHECKED | AWS CloudFormationは、スタックが予想されるテンプレート設定と異なるかチェックしていない |
| IN_SYNC | サポートされている各リソースの現在の構成は、期待されるテンプレート構成と一致します。ドリフト検出をサポートするリソースのないスタックもIN_SYNCのステータスを持つ |
リソースドリフトステータス
リソース自体
| リソースドリフトステータス | 説明 |
|---|---|
| DELETED | リソースが削除されたため、リソースは予想されるテンプレート構成とは異なる |
| MODIFIED | リソースは予想されるテンプレート構成とは異なる |
| NOT_CHECKED | CloudFormationはリソースが予想されるテンプレート構成と異なるかどうかをチェックしていない |
| IN_SYNC | リソースの現在の構成は予想されるテンプレート構成と一致する |
リソースのプロパティ
| プロパティの違いの種類 | 説明 |
|---|---|
| ADD | 配列またはリストのデータ型であるリソースプロパティに値が追加された |
| REMOVE | このプロパティは現在のリソース構成から削除された |
| NOT_EQUAL | 現在のプロパティの値はスタックテンプレートで定義されている期待値とは異なる |
注意
スタック上のドリフトを正常に検出するためには、以下の権限が必要です。
- スタックに含まれるリソースの読み込み権限
- cloudformation:DetectStackDrift
- cloudformation:DetectStackResourceDrift
特定のエッジケースの場合、正確なドリフトの結果を返せないことがあります。ドリフト結果を正しく解釈するためにエッジケースに注意してください。エッジケースはこちらのドキュメントをご参照ください。
やってみた
ここでは東京リージョンを前提として、マネージメントコンソールから実行します。マネージメントコンソールは新しいコンソールを使用するものとします。
以下の流れで動作を確認します。
- 事前のスタック作成
- 環境の手動変更
- ドリフトの検知
事前のスタック作成
CloudFormationの画面でCreate stackをクリックします。

Use a sample templateを選択して、Multi_AZ_SimpleのLAMP Stackを選択します。テンプレートのURLはhttps://s3-ap-northeast-1.amazonaws.com/cloudformation-templates-ap-northeast-1/LAMP_Multi_AZ.templateです。

Configure stack optionsでは、以下の設定を行いました。
| 項目 | 値 | 備考 |
|---|---|---|
| Stack name | DRIFT-TEST | |
| DBAllocatedStorage | 5 | |
| DBInstanceClass | db.t2.small | |
| DBName | myDatabase | |
| DBPassword | mypassword | |
| DBUser | awsuser | |
| InstanceType | t2.small | |
| KeyName | <任意> | |
| MultiAZDatabase | true | |
| SSHLocation | 0.0.0.0/0 | |
| Subnets | <任意> | ここではap-northeast-1a, ap-northeast-1c, ap-northeast-1dの2サブネットを設定 |
| VpcId | <任意> | ここではデフォルト VPCを設定 |
| WebServerCapacity | 2 |

内容を確認してスタックを実行します。

スタックが作成完了すると以下のリソースが作成されます。
| Logical ID | Type | ドリフト検知対象 |
|---|---|---|
| ALBListener | AWS::ElasticLoadBalancingV2::Listener | Yes |
| ALBTargetGroup | AWS::ElasticLoadBalancingV2::TargetGroup | No |
| ApplicationLoadBalancer | AWS::ElasticLoadBalancingV2::LoadBalancer | Yes |
| DBEC2SecurityGroup | AWS::EC2::SecurityGroup | Yes |
| LaunchConfig | AWS::AutoScaling::LaunchConfiguration | Yes |
| MySQLDatabase | AWS::RDS::DBInstance | Yes |
| WebServerGroup | AWS::AutoScaling::AutoScalingGroup | Yes |
| WebServerSecurityGroup | AWS::EC2::SecurityGroup | Yes |
環境の手動変更
ここで、以下のリソースを変更してみます。
- ApplicationLoadBalancer
- MySQLDatabase
- WebServerSecurityGroup
ApplicationLoadBalancerの変更
ApplicationLoadBalancerの属性を変更します。
| 項目 | 変更前 | 変更後 |
|---|---|---|
| 削除保護 | 無効 | 有効 |
| アイドルタイムアウト | 60 秒 | 120 秒 |
| HTTP/2 | 有効 | 無効 |
| アクセスログ | 無効 | <変更無し> |
変更前

変更後

MySQLDatabaseの変更
MySQLDatabaseの詳細を以下のように変更します。
| 項目 | 変更前 | 変更後 |
|---|---|---|
| IAM DB 認証 が有効です | いいえ | はい |
| マルチ AZ | はい | いいえ |
| メンテナンスウィンドウ | wed:18:58-wed:19:28 UTC (GMT) | wed:20:00-wed:21:00 UTC (GMT) |

変更前

変更後

WebServerSecurityGroupの変更
WebServerSecurityGroupのインバウンドのルールについて以下の内容を追加します。
| タイプ | プロトコル | ポート範囲 | ソース | 説明 |
|---|---|---|---|---|
| HTTPS (443) | TCP (6) | 443 | 0.0.0.0/0 |
変更前

変更後

ドリフトの検知
CloudFormationテンプレートと差がある環境を構築できたのでドリフトの検知を行います。
マネージメントコンソールで対象のテンプレートを選択して、ActionsからDetect driftをクリックします。

ドリフトの検出が開始されました。

スタックのドリフト結果を確認します。対象のスタックを選択してActionsからView drift resultsをクリックします。

ドリフトの結果を確認すると変更を行ったApplicationLoadBalancerが検出されておらす、以下のリソースが検知されています。
- MySQLDatabase
- WebServerSecurityGroup

テンプレート上ではApplicationLoadBalancerはサブネットしか定義されていなかったため差を検出できなかったと思われます。エッジケースとしてデフォルト値の設定はまだ検出できないためです。今後のアップデートに期待しましょう。
"ApplicationLoadBalancer" : {
"Type" : "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties" : {
"Subnets" : { "Ref" : "Subnets"}
}
},
MySQLDatabaseの詳細を確認するために、対象をリソースを選択してView drift detailsをクリックします。

詳細を確認してみてもリソースレベルのドリフトの内容が分かりませんでした。設定した項目が、まだ検出をサポートしていないのかもしれません。

次にWebServerSecurityGroupの詳細を確認してみます。
WebServerSecurityGroupでは追加したHTTPSのルールが確認できました。

現時点ではリソースによって取得できるドリフトの詳細に差があるようです。
さいごに
CloudFormationユーザー待望の機能がお目見えしました。これが欲しかったんだ!という機能です。今まで一旦手動で変更を行った時にはCloudFormationの利用を諦めざるを得なかったですが、差が分かることで対応が楽になります。
現時点では取れる情報が限定的ですが、CloudFormation運用を行いやすくなるアップデートですので有効活用していきましょう。






