【AWS Control Tower】「CfCTによる意図せぬ変更」のリスクに注意しよう

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

サムネイル

はじめに

こんにちは。CC2課の古屋です。

私の住む山梨では、梅雨入りすると盆地特有の一層蒸し暑い季節がやってきますよ。

さて、皆様はAWS Control Towerのマルチアカウント環境をコードで一元管理できるソリューション、CfCT(Customizations for AWS Control Tower)をご存じでしょうか。

「初めて聞いた」「構築方法を知りたい」という方は、ぜひ事前に弊社の過去ブログをご覧ください。
AWS Control Towerのカスタマイズソリューション(CfCT) - サーバーワークスエンジニアブログ

CfCTは複数アカウントのガバナンスを自動化できる非常に便利な仕組みですが、その挙動を正しく理解していないと、「意図しない設定の上書き」や「不要なルールの残留」による障害を引き起こす可能性もあります。

本記事では、CfCTを運用する上で押さえておくべき挙動の注意点と、実環境との乖離が招くリスクについてお伝えします。

対象読者

  • AWS中級者の方
  • AWS Control Towerを用いたマルチアカウント環境を管理している方
  • CfCTによる設定(SCPやStackSets)のコード管理を検討・運用している方

CfCTの概要

注意点に入る前に、CfCTの基本的な特徴を整理しておきます。

CfCTとは

manifest.yaml という定義ファイルに、適用したいSCP(サービスコントロールポリシー)やAWS CloudFormation テンプレート、および対象のOU(組織単位)を記述し、Amazon S3 バケットにアップロード(またはGitリポジトリにプッシュ)することで、複数アカウントへ設定を自動展開する仕組みです。

メリット

ガバナンス設定をコード化(IaC)し、変更管理や一元デプロイが可能になります。

「CfCTによる意図せぬ変更」が起きる要因

ここが本記事の核心です。

CfCTを動かす際、基本的にはコードの差分が反映されますが、「実環境(マネジメントコンソール等)で手動変更を行った場合」には、想定外の挙動が発生するケースがあります。

ここに注意が必要です。

①:コード上で差分がなくても、実環境の手動変更は「上書き」される

ポリシーの定義(JSONファイル)自体には変更を加えずにパイプラインを実行した場合でも、実環境のポリシーの内容は上書きされます。

例えばSCPの定義に着目すると、「コード上で前回実行時との差分がなければCfCTはSCPを編集するような動作はしないでしょ。」と思われる方もいるかもしれません。

しかし実際には、コードの差分の有無にかかわらずSCPは上書きされます。

つまり、実環境を手動で変更しているにもかかわらずmanifest.yamlを変更せずに実行してしまうと、手動で変更する前の状態に戻ってしまうよということです。

実際に挙動を確認してみましょう。

①の実演

前提

まず、実演を行う環境の初期状態を確認します。

適用されているSCP

IAMユーザーの作成操作を明示的に禁止するSCP「deny-create-IAMuser-policy」が実環境に存在します。

IAMユーザー作成禁止SCPが存在する

このSCPのターゲットとしてDevT OUが指定されていることも実環境から確認できます。

DevT OUにアタッチされている

CfCT側のコード(manifest.yaml)

CfCTの manifest.yaml でも、このSCPがDevT OUに対して定義されています。実環境とコードの状態は一致していますね。

manifest.yamlでもDevT OUが定義されている

ポリシーのJSON定義についても、実環境と乖離はありません。

ポリシーのJSON定義も一致している

この時点では、実環境とCfCTのコードは完全に一致しており、正常な状態です。

想定外の挙動につながるケース

Step 1:緊急対応 ― マネジメントコンソールから手動でSCPを修正

現状のポリシーではIAMユーザーの作成は禁止されているものの、アクセスキーの発行ができてしまうことにAさんが気が付きました。
これはセキュリティ上の問題であるため、応急処置としてマネジメントコンソールから直接SCPを修正し、アクセスキーの操作も禁止する記述を追加しました。

SCPをマネジメントコンソールから編集

この時点で、実環境のSCPとCfCT側のコードに「乖離」が発生しています。
実環境:アクセスキー発行も禁止
CfCTコード:IAMユーザー作成のみ禁止(アクセスキー発行の禁止なし)

Step 2:コードの修正を忘れたまま、別の変更でCfCTを実行

数日後、同僚のBさんが全く関係のない別のSCPを追加するため、manifest.yamlを修正しS3バケットにアップロードしました。CfCTのパイプラインが実行されます。

差分は新規に追加するポリシーのみ

キャプチャからもわかる通り、Bさんの変更内容は新しいポリシーの追加のみであり、既存のdeny-create-IAMuser-policyには一切手を加えていません。

Step 3:ポリシー上書き ― 手動変更が消失

しかし、CfCTはmanifest.yamlに記載されているすべてのSCPを実環境へ完全上書き(置換)します。

その結果: - CfCTのコード上にある「IAMユーザー作成の禁止」のみが適用された状態に戻る - 手動で追加した「アクセスキー発行の禁止」は跡形もなく消失する

SCPの記述が戻ってしまった

結果

アクセスキーの発行を禁止していたSCPの記述がCfCTによって上書き・消失したことで、DevT OU配下のアカウントではアクセスキーが発行し放題の状態に戻ってしまいました。

今回のケースでは、手動で追加したセキュリティ対策が、別のエンジニアの無関係な変更をきっかけに意図せず消えてしまいました。

この状態ではAさんもBさんもアクセスキーが発行できるようになってしまったことには気がつかないまま放置されてしまうリスクがあります。

①のまとめ

今回のケースから得られる教訓は明確です。実環境を手動で変更するのではなく、manifest.yamlやポリシーのJSONを修正してCfCT経由でデプロイすべきということです。

では、「SCPが不要になった場合もCfCTのコードから削除してデプロイすればいいんだな」と考えますよね。しかし、これも想定外の挙動につながる可能性があります。

②:manifest.yamlから削除しても、実環境からは削除されない

①のケースの教訓を踏まえ、「それならCfCTのコードを修正してデプロイすれば安心だ」と思いたいところですが、削除についてはそれだけでは不十分です。

例えば、不要になったSCPの定義を manifest.yaml から削除してデプロイしたとします。このとき、CfCTは「実環境のSCPを削除(デタッチ)する」のではなく、「単にCfCTの管理対象から外す(無視する)」という挙動をします。

結果として、不要になったはずの制限が実環境に残り続けてしまいます。
実際に確認してみましょう。

②の実演

前提

①の実演と同じく、deny-create-IAMuser-policyがDevT OUにアタッチされている状態です。

想定外の挙動につながるケース

manifest.yamlからdeny-create-IAMuser-policyの定義を削除し、S3バケットにアップロードしてパイプラインを実行します。

アップロードするファイルは以下の通りです。

ポリシーフォルダから「deny-create-IAMuser-policy」を削除しました。

deny-create-IAMuser-policyを削除

manifest.yamlでも「deny-create-IAMuser-policyをDevT OUにアタッチする」という定義の部分をコメントアウトします。

manifest.yamlから定義をコメントアウト

この状態でS3にアップロードしてみます。

結果

CfCTの実行が完了しましたが、AWS Organizations上のSCPは削除されず、DevT OUにもアタッチされたままです。

SCPは削除されずに残っている

manifest.yamlから消しただけでは、実環境からSCPは消えない ことがお分かりいただけたと思います。

①のケースとは打って変わり、今回のケースでは実環境へ意図しない制限が残り続けてしまうことで開発のスピードを遅らせてしまうかもしれません。

②のまとめ

今回のケースでは、CfCTコードから削除しても実際のリソースは削除できないことが確認できました。

実際にCfCTで運用する中で不要になったSCPを確実に除去するには、以下の順序で作業する必要があります。

  1. 先に実環境で手動デタッチ・削除を行う(マネジメントコンソールまたはCLI)
  2. その後、manifest.yamlからコードを削除する

この順序を守ることで、「コードにも実環境にも存在しない」一貫した状態を維持できます。

全体のまとめ

CfCTはマルチアカウント運用において変更管理や一元管理ができる便利な機能ですが、以下のルールを守ることが重要となります。

1.一時的な変更も必ずコードで行う

「一時的だから」とマネジメントコンソールで手動変更せず、必ずCfCT経由で適用・ロールバックを行いましょう。
コードと実環境の乖離を未然に防ぐことにつながります。

2.リソースの削除は手動で先に行う

manifest.yamlから削除する際は、先に実環境でリソースの削除・デタッチを手動で行ってから、コードを削除しましょう。
コードの削除だけではリソースは消えません。

コードと実環境を常に一致させておくことこそが、CfCTでの運用における理想です。


とはいえ、現場ではスピードが優先される、マネジメントコンソールで応急処置をする、といった状況もあるかと思います。
そういった場合は 忘れないうちにコードも実環境に合わせて修正すること を心掛けましょう。
それだけで「CfCTによる意図せぬ変更」を防ぐことができるはずです。