ForgeVision Engineer Blog

フォージビジョン エンジニア ブログ

CloudFormationの機能を活用しよう!~CloudFormation Hooksによるセキュリティとコンプライアンスのリスク軽減~

こんにちは。伊藤です。
今回はCloudFormationの機能のひとつであるCloudFormation Hooksについて紹介いたします。

概要

紹介いたしますと言ったものの、私もAWSアップデート記事を遡っていて初めて知った機能になります。
フックという名称からするとCloudFormationの操作に対して別のアクションを連携したりできるのでしょうか。

ということで、試しに使ってみました。

前提

後述しますが、現在の仕様ではフックの効果がアカウント内すべてのCloudFormationスタックに適用されます。
意図しない作業に適用されてしまうことで混乱を招く可能性も考えられますので、
複数人でアカウントを利用する場合は全体での認識を合わせてから導入するべきかと思います。

検証作業については社内メンバーへの作業影響を考慮し、個人アカウントにて実施しました。

CloudFormation Hooksとは?

CloudFormation Hooksとは、CloudFormationレジストリという機能を使って追加することができる拡張機能のうちのひとつとなります。

レジストリには以下3つの拡張機能が存在します。

  • リソースタイプ
    • サードパーティのリソースをCloudFormation内で使用するリソースタイプとして扱えるようにする
  • モジュール
    • CloudFormationテンプレートの共通部分をモジュールという形で切り出すことで繰り返し利用できるようにする
  • フック
    • スタックのプロビジョニングに際して、コンプライアンスに準拠しているかどうかの検査などを行うことができる


それぞれの拡張機能にはパブリック拡張タイププライベート拡張タイプが存在し、さらに以下のように分類されていきます。

  • パブリック拡張タイプ
    • AWSパブリック拡張
      • AWSによって公開されている拡張
      • デフォルトで有効化されているため設定は不要です
    • サードパーティ拡張
      • AWS以外のパブリッシャーによって公開されている拡張
  • プライベート拡張タイプ
    • アクティブ化されたプライベート拡張
      • パブリックなサードパーティ拡張をアクティブ化すると、プライベート拡張としてアカウントのローカルレジストリにコピーされます
    • 登録されているプライベート拡張
      • 主にユーザが自分で作成した拡張が当てはまります


今回は検証としてAWSSamples::S3BucketLoggingCompliance::Hookというフックを有効化します。

これは公開されたサードパーティ拡張に分類されますが、パブリッシャーがAWSSamplesとなっており、
AWSが公開しているフックであることには変わりないようです。

動作としては、
作成されるS3バケットに対して、事前に定義されたログ設定に準拠しているかどうかを検査する
といった内容になっております。

CloudFormation Hooksのアクティブ化

AWSマネジメントコンソールではCloudFormationのサービス画面に項目が存在します。

フックの確認01

フックの確認02


CloudFormation Hooksの料金は以下のようになります。

フックの料金設定01


アクティブ化のボタンを押下すると以下のように遷移します。

フックのアクティブ化01


実行ロールARNの入力以外はデフォルト値で進めましたが、実際の導入ではログ出力設定を追加しておく方がいいかと思います。

フックのロギング設定01

付与する実行ロールについて

拡張機能を呼び出すためにCloudFormationが引き受けるロールであり、信頼ポリシーが必要になります。
タイプによって必要となる信頼ポリシーが異なり、フックでは以下のようになります。

${AWS::AccountId}は実際のアカウントIDに読み替えてください。
IAMポリシーは付与しなくても問題ありませんでした。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "resources.cloudformation.amazonaws.com",
                    "hooks.cloudformation.amazonaws.com"
                ]
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "${AWS::AccountId}"
                },
                "StringLike": {
                    "aws:SourceArn": "arn:aws:cloudformation:ap-northeast-1:${AWS::AccountId}:type/hook/*"
                }
            }
        }
    ]
}


設定を進めると以下のような画面に遷移します。

フックの構成を設定01


設定エイリアスには設定の名前を入力します。
「test」と入力したところエラーになってしまいました。

構成の設定エラー01

命名規則は「1-256文字の英数字」と記載されておりますが、実際には「default」しか受け付けないようです。
設定後に名前を意識することは無かったので、defaultで問題ないかと思われます。


設定JSONにはフックの振る舞いを記載します。
設定値は以下の3つとなります。

  • TargetStacks
    • 「ALL / NONE」で指定します。全てのスタックを対象とするか否かの選択しかできません。
    • 前提項で記載した内容はここに起因します。
  • FailureMode
    • 「FAIL / WARN」で指定します。フックによる検査に成功しなかった場合の挙動を定義します。
    • FAILの場合、スタックの作成は失敗します。
    • WARNの場合、警告の表示を出してスタックの作成を継続します。
  • Properties
    • 画面左に記載されている設定スキーマの「properties」に沿って定義します。

今回の設定値は以下のように定義しました。
ログ出力バケットとしてloggingbucket-cfn-hooks-logging-compliance-testが設定されていない場合、スタックの作成に失敗する
という動作をします。

{
    "CloudFormationConfiguration": {
        "HookConfiguration": {
            "TargetStacks": "ALL",
            "FailureMode": "FAIL",
            "Properties": {
                "LoggingBucket": "loggingbucket-cfn-hooks-logging-compliance-test"
            }
        }
    }
}


構成の設定を行うとアクティブ化が完了します。
設定内容はマネジメントコンソールで確認、修正することが可能です。

アクティブ化後の内容確認01

スタックの作成

フックの定義に準拠するものとしないものでテンプレートを作成し、スタックを作成してみます。

## スタックの作成に成功するテンプレート
AWSTemplateFormatVersion: "2010-09-09"
Description: Sample template for the AWSSamples::S3BucketLoggingCompliance::Hook

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    DependsOn: LoggingBucket
    Properties:
      BucketName: "mybucket-cfn-hooks-logging-compliance-test"
      LoggingConfiguration:
        DestinationBucketName: "loggingbucket-cfn-hooks-logging-compliance-test"
        LogFilePrefix: "/logs-samples/"

  LoggingBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: "loggingbucket-cfn-hooks-logging-compliance-test"
      LoggingConfiguration:
        DestinationBucketName: "loggingbucket-cfn-hooks-logging-compliance-test"
        LogFilePrefix: "/logs-samples/"


スタックの作成に成功しました。

成功したスタック01


「フックの呼び出し」という項目に記載されているイベントをクリックすると以下のようなステータスが確認できます。

成功したスタック詳細01

成功したスタック詳細02


この項目は普段では見慣れませんが、本作業のどこかのタイミングで自動的に有効になっていたようです。
歯車マークの設定から変更することができます。

スタックの表示設定01


次に、もうひとつのテンプレートを使用してスタックを作成します。

## スタックの作成に失敗するテンプレート
AWSTemplateFormatVersion: "2010-09-09"
Description: Sample template for the AWSSamples::S3BucketLoggingCompliance::Hook

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    DependsOn: LoggingBucket
    Properties:
      BucketName: "mybucket-cfn-hooks-logging-compliance-test"
      LoggingConfiguration:
        DestinationBucketName: "not-loggingbucket-cfn-hooks-logging-compliance-test"
        LogFilePrefix: "/logs-samples/"

  LoggingBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: "loggingbucket-cfn-hooks-logging-compliance-test"
      LoggingConfiguration:
        DestinationBucketName: "not-loggingbucket-cfn-hooks-logging-compliance-test"
        LogFilePrefix: "/logs-samples/"


スタックの作成に失敗しました。

失敗したスタック01


フックの呼び出しイベントは以下のようになっております。
簡単ですが理由も記載されています。

失敗したスタック詳細01


FailureModeをWARNに設定した場合、以下のようなステータスで処理が続行されます。

失敗したスタック詳細02

CloudFormation Hooksを新規作成するには

フックはCFN-CLIで開発することができます。

Developing hooks - CloudFormation Command Line Interface

What is the CloudFormation Command Line Interface (CFN-CLI)? - CloudFormation Command Line Interface


ワークショップも公開されており、S3とSQSの暗号化について検査するフックの作成となっております。
catalog.us-east-1.prod.workshops.aws


ただし、コンソール上で行ったフック設定の裏で動いている処理に関して、開発用のドキュメントが見当たらず、
サンプルにないリソースを対象としてゼロからフックを作成するのはかなり大変なように感じました。


導入に際して、現状ではサンプルにあるものを使っていくことが効率的かと思います。

まとめ

用意されているサンプルをアクティブ化し、CloudFormation Hooksを使ってみました。

正直なところでは、もう少し柔軟性のあるアクションを関連付けられるのかなと考えていたのですが、
サンプルフックに関してはセキュリティ面の強化という位置づけが強いような印象を受けました。

リソースタイプの指定はあるものの全てのスタックに影響するということで、使いどころが難しい場合もあるかもしれませんが、
ここだけは必ず遵守しなければならない、という要件部分に関して
逸脱することのないように予防策を導入する意味合いでは有効に利用できるかと思います。

参考

  • パブリック拡張機能についてのAWSドキュメント

docs.aws.amazon.com

  • サンプルフックの仕様確認

github.com