IT統制のためのAWS CloudFormationスタック管理
はじめに
急激な市場の変化に柔軟かつ迅速な対応が必要となる昨今、ITシステムの基盤においてもスピーディに構築・変更・運用することが求められています。Infrastructure as Code(IaC)をはじめとする技術でインフラ構築を自動化し、よりスピーディに再現性高く提供することが重要になっており、アマゾン ウェブ サービス(AWS)を利用している場合においても、AWS CloudFormationの利用は標準的な選択肢となってきます。
このAWS CloudFormationを利用してAWSリソースを作成する際、テンプレートから生成されるリソース(リソース群)を「スタック」と言いますが、「IaC」「自動化」等をキーワードにインフラシステム開発を推し進めた結果、スタックが肥大化し、管理が煩雑化していることも珍しくありません。また、クラウドが認知されることで、新たなセキュリティ要件や運用要件等が発生するケースもあるかと思います。
このような問題/課題に対処するため、スタックのシンプル化が必要となる場面が出てきますが、上記の背景などから、該当のシステムは「運用中」である可能性が高くなってきます。そこで本記事では、上記のような際に発生するスタックの分解/再構築について、注意点を踏まえて解説したいと思います。
スタックの分解/再構築が必要となる場面について
スタックを分解/再構築が必要となる場面は、下記のようなものがあるかと思います。
①AWS CloudFormationのクオータ制限
②IT統制等のセキュリティ要件によるもの
一つ目について、スタックは基本的には論理的な単位で小規模に分割して管理することが推奨されています。しかし、VPC、サブネット、セキュリティグループ等を一括してスタックに記載して、インフラ基盤を一度のスタック作成で完結させることもできるため、ある程度まとまった単位でスタックを構成している場合があります。
このような場合、システム構築当初は良かったものの、規模が大きくになるにつれて、スタックも肥大化して制限に引っ掛かるといった事象に当たることがあります。別の新たなスタックを用意する選択肢もありますが、スタックのシンプル化を検討するタイミングになってきます。
二つ目についてまず一例として、「禁止行為の検知時ロールの権限を自動ではく奪する」といった仕組みについて考えたいと思います。(図1)
▼図1 EventBridge-Lambdaの連携によるUpdateStack自動化
スタックは、AWSに取り込む際に、「パラメータ」を設定でき、そのパラメータによって、処理を分岐させることができます。
例えば、AWS Identity and Access Management(IAM)ロールとポリシーを生成するスタックに対し、「normal」「emergency」というパラメータを用意しておき、normalの場合は通常の操作ができるが、emergencyの場合、一切のアクションを拒否(deny)する、というロール/ポリシーを生成するスタックを作成しておきます。
この前提で、図1を説明すると、以下のようになります。
①ユーザにて定義した禁止操作をAmazon EventBridgeにて検知(イベントソースは図1では、AWS CloudTrailやAWS Config)
②検知アクションにてAWS Lambdaを起動
③AWS Lambdaにてスタックのパラメータを「emergency」へ変更するコマンドを発行し、UpdateStackを実行
このように、スタックに通常時と緊急時のパターンを記述することで、IT統制を自動化できますが、スタックの中身が複雑だと、どれに何をすればいいのか把握が困難になり、思ったように機能しないといった事態が想定されます。また、運用面からもメンテナンスが難しくなります。そのため、スタックの分解/再構築によるシンプル化が必要となってきます。
スタックのシンプル化について
単純にスタックをスクラップ&ビルドで対応できるのであれば簡単ですが、運用中のシステムだと難しい状況もあるかと思います。今回は、複数のIAMロールとポリシーを含むスタックの分解/再構築によるシンプル化についてご紹介していきます。
IAMは、ほぼ必ず利用されるサービスであり、共通ポリシーの管理をAWS CloudFormationで行っているユーザが多いかと考えております。また、作業ミスはユーザ影響やコンプライアンス違反等にも直結してくるため、最もミスできない箇所であるのと同時に、複雑で注意点等が多い部分となります。
以下、想定ケースです。
- 複数のIAMロールとIAMポリシーが記述されているスタックがある
- 精査の結果、EC2アタッチロール(以降EC2ロール)とその他1つのロールのみ必要
- ロールは常に利用されているためデタッチや削除はできない
- 必要なロールをそれぞれ個別にスタック化
- 必要なロールには「Outputs」や「インラインポリシー」が(スタックに)記述されている
▼図2 スタックの分解/再構築 ゴールイメージ
要約すると、スタック内に必要なリソースが複数あり、それらを個別にスタック管理したいという要件となります。
必要なリソースが1つであれば、必要なリソースのみ残してスタック更新すればよいのですが、上記の場合は、後述するようにスタックを削除して再構築するStepを経る必要があります。
※今回は、混乱回避のため基本的にEC2ロールの動きにフィーチャーします。
Step.1 必要なリソース(「○」のリソース)に対し「DeletionPolicy: Retain」を付与
Retainとは「保持する」という意味で、この設定値を持つリソースは、スタックが削除されてもリソースそのものはAWS内に残ります。逆に、「×」のリソースはスタックが削除されると、リソースが抹消され一切見えなくなります。
そこでまずは「Retain」をスタック内に記述し、スタックを更新する必要があります。今回Retainを付与する対象は、赤線で示している4箇所となります。(図3)
※スタック更新方法については割愛します。
▼図3 スタックへの「Retain」付与イメージ
※Outputsとインラインポリシーの詳細記述は省略します。
注意点として、「InstanceProfile」についても「Retain」が必要となります。EC2にIAMロールを付与する場合、AWSの内部的な動きとしては、IAMロールのコンテナである「インスタンスプロファイル」を使用して、IAMロールをアタッチ、という動きになります。そのため、「インスタンスプロファイル」が削除されるとEC2がIAMロールを借り受けできなくなります。(つまり、IAMロールに定義された操作が一切できなくなります。)必要なロール = IAMロールのみ「Retain」という理解で進めると、即ユーザ影響となりますのでご注意ください。
※補足:記事末尾に「補足説明」を記載しておりますので、よろしければご一読ください。
Step.2 スタックの削除
分解したいスタックを削除します。この削除によって、Retainが付与されたリソースのみ、AWS内に残ります。
▼図4 スタック削除のイメージ
Step.3 既存リソースのスタックへのインポート
AWSに残ったリソースを再びスタック化します。既存リソースをスタック化するためには、スタック化したいリソースをAWS CloudFormation(スタック))管理できる形式に記述したファイルを用意し、インポートを行います。(図5)
図3とほぼ変わらないように思うかもしれませんが、以下の違いや特徴があります。
①Outputsに関する記述が無い
②インラインポリシーに関する記述が無い
③DelitionPolicyがDeleteである(Retainでなくとも良い)
▼図5 インポートするリソースを記述したスタックテンプレート
注意点として、①②のOutputsとインラインポリシーに関しては、インポート時に記述はできません。これはAWSの仕様となります。Outputsはリソースではなく、スタックのオプション機能ですので、「リソースをインポートする」という操作からはズレている、と理解がしやすいかと思います。
また、インラインポリシーは厳密には、「AWS::IAM::Policy」というリソースタイプのインポートはサポートされておりません。
※インポートができないだけで、Policyのスタック管理はもちろん可能です。
なお、AWSもしくはカスタマー管理のマネージドポリシーであれば、インポートするロールの記述内に「アタッチするポリシーのARN」を記載することで、適切なポリシーが付与されたロールがインポートされます。(この場合は、「ロール」のインポートなので問題無し)
③のDelitionPolicyは、これまでの手順を見ると「Retain」と思うかもしれませんが、この項目は「スタックを削除する際」のオプションですので、インポート=今まさにスタックを作成するタイミングにおいては、実はなんでも構いません。ただし、必ずDelitionPolicyは設定する必要があります。
スタック管理するリソース内容に応じて適切なオプションを設定してください。
※参考:インポートおよびドリフト検出オペレーションをサポートするリソース
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html
※参考:スタックへの既存リソースのインポート
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import-existing-stack.html
“インポートする各リソースは、テンプレートに DeletionPolicy 属性がある必要があります。”
インポートが完了したタイミングでのイメージは以下図6となります。スタック管理したいリソースの「一部のみ」スタック管理している状況となります。
▼図6 スタックインポート完了時のスタックの管理状況とリソース実態との差分
※EC2ロールについてのみ記載しております。
Step.4 リソース実態に合わせたスタックの更新
差分である「Outputs」と「インラインポリシー」を含めたスタック(リソースの実態と整合性の取れたスタック)を用意し、スタック更新します。その他ロールについても同様に必要なインポート、更新処理を施せば、図2のゴールイメージのスタック管理となります。
※EC2ロールに関しては、実質図3のTestOtherRole(40行目以降)に関する記述を削除したものが、今回更新に使うファイルとなります。
最後に
通常は、インラインポリシーではなく管理ポリシーを使用することがAWSより推奨されていますが、実際のところインラインポリシーを使用されている場面も多いかと思いますので、今回取り上げてみました。AWS CloudFormationの運用管理を適正化するフェーズに差し掛かっている皆様の参考となれば幸いです。
著:TIS株式会社
IT基盤技術事業本部 IT基盤技術事業部
IT基盤エンジニアリング第3部
鈴木 裕文
補足説明
EC2コンソール上も「IAMロール」と表現されるのでややこしいのですが、実際はインスタンスプロファイルがアタッチされています。これを確認するために、EC2にロールをアタッチした状態で、インスタンスプロファイルのみを削除します。
すると、削除前(図7)は「TestEC2Role」へのリンクが表示されていましたが、削除後(図8)はリンクが消えて、「当時アタッチしていたインスタンスプロファイルARN」が表示されています。
▼図7 インスタンスプロファイル削除前 EC2ロールアタッチ様子
▼図8 インスタンスプロファイル削除後 EC2ロールアタッチ様子
このことから、インスタンスプロファイルを通じてIAMロールがアタッチされていたことが伺えます。なお、(当時の)ARNが表記されているだけで、当該EC2ロールの操作権限は持っておりません。
※厳密には、セッションの関係でしばらくは操作権限が保持されますが、直に操作できなくなります
また、EC2インスタンス起動ウィザード内の「高度な詳細」でも、アタッチするのはロールではなくインスタンスプロファイルであることが確認できます。
▼図9 EC2インスタンス起動ウィザード「高度な詳細」内の設定内容
IAMコンソールから手動で(GUIで)ロールを作成する場合は、自動的にロールと同名のインスタンスプロファイルが作成されますので、インスタンスプロファイルは意識しない場合も多いかと思います。しかし今回は、既に「スタック管理されているEC2ロール」です。
つまり、インスタンスプロファイルはスタックに記述されている可能性が高いので、インスタンスプロファイルについてのスタック管理も意識して記述しました。