Organizations環境下で AWS Security Hubのコントロール無効化を自動化する

Organizations 環境で Security Hub 『基礎セキュリティのベストプラクティス』コントロールの無効化/有効化を自動化します。CFnスタックセットのOrganizations連携 および Lambda-backed カスタムリソースを組み合わせて実現します。
2021.11.01

はじめに

マルチアカウント環境な Security Hub を運用していく際に 大変になってくるのが 特定コントロールの無効化 です。

コントロールの無効化操作は全アカウントそれぞれに対して行う必要があります (つまり 管理者側で無効化してもメンバー側には反映されない)。

この無効化作業を自動化する仕組みを考えてみました。

※ なお Control Tower環境の場合は以下のブログに紹介する通り、 カスタマイズソリューションを活用することで自動化できます。

想定する Security Hub 環境

以下土台は整っている前提とします。

  • AWS Security Hub の Organizations 連携を活用している
  • 全てのアカウントで 『AWS 基礎セキュリティのベストプラクティス v1.0.0』 が自動有効されるようになっている

※この土台作りの詳細は以下ブログを参照ください。

どんな仕組みを作るのか?

『基礎セキュリティのベストプラクティス』特定コントロールを 自動無効化(有効化) する仕組みを作ります。 具体的には以下 2機能です。

  • 特定OU配下アカウントの 特定コントロールを一括で無効化(有効化)する
  • 新規アカウントが 特定 OUに所属したタイミングでも 自動で特定コントロールを無効化(有効化)する

どうやって作るのか?

以下ブログに紹介した『特定OUに所属したタイミングで Lambda を実行させる』 仕組みを活用します。(詳しい解説はこちら参照ください)

ざっくりと説明すると、 Lambda-backed カスタムリソースを展開する Organizations 連携のスタックセット を作成します。 これによりOU配下のアカウントに対してスタックが自動展開、 Lambdaが実行されます。 この Lambda によって Security Hub の更新(コントロール無効化/有効化)を行います。

img

CFnテンプレートを作ってみる

以下リソースを作成する CFnテンプレートを書きます。

リソース名 タイプ 備考
UpdateControls カスタムリソース UpdateControlsLambdaFunction を呼び出す
LambdaExecutionRole IAMロール UpdateControlsLambdaFunction の実行ロール
UpdateControlsLambdaFunction Lambda関数 指定したコントロールを無効化(有効化) する

以下にCFnテンプレートを置いています。利用される場合は活用ください。

インプットについて

インプットとして AFSBPDisableListAFSBPEnableList を使用します。 『基礎セキュリティのベストプラクティス』のコントロールIDを(カンマ区切りで) それぞれに書いていきます。

  • AFSBPDisableList
    • 無効化したいコントロールIDのリストです
    • 例: IAM.6,IAM.2,EC2.10,CloudTrail.5,S3.5
  • AFSBPEnableList
    • 有効化したいコントロールIDのリストです (無効化したけど再度有効化したいときに使います)
    • 例: CloudTrail.1,RDS.1,EC2.19

(参考) Lambda関数のコード

以下に Lambda関数のコード部分を抜粋します。 update_securityhub_controls 関数 がメインです。 ここで指定したコントロールIDを無効化(および有効化) します。

試してみる

特定OUにこの CFnテンプレートのスタックセットを作成します。 メンバーアカウントをこのOUに所属させて Security Hub のコントロールが更新されるかどうか確かめます。

スタックセット作成

適当に作成している MemberOU にスタックセットを仕込みます。

まずはスタックセットを作成します。 以下は IAM.5,APIGateway.3,CloudTrail.2,EC2.4,RDS.7,RDS.8 を無効化する例です。

TEMPLATE_PATH=(テンプレートのパス)
STACKSET_NAME="InitialSetup-SecurityHubAFSBPControls"
AFSBPDisableList="IAM.5,APIGateway.3,CloudTrail.2,EC2.4,RDS.7,RDS.8"
AFSBPEnableList=""

# スタックセット作成
aws cloudformation create-stack-set \
--stack-set-name "${STACKSET_NAME}" \
--template-body file://${TEMPLATE_PATH} \
--permission-model SERVICE_MANAGED \
--auto-deployment Enabled=true,RetainStacksOnAccountRemoval=false \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \
--parameters "[
  {
    \"ParameterKey\": \"AFSBPDisableList\",
    \"ParameterValue\": \"${AFSBPDisableList}\"
  },
  {
    \"ParameterKey\": \"AFSBPEnableList\",
    \"ParameterValue\": \"${AFSBPEnableList}\"
  }
]"

次にスタックインスタンスを作ります。

STACKSET_NAME="InitialSetup-SecurityHubAFSBPControls"
# OU IDの指定(複数ある場合はカンマ区切り)
OU_ID="ou-xxxx-example"

# スタックインスタンス作成
# (※注意) 以下の例は --regions に全てのリージョンを指定しています。
#          稼働している Security Hub のリージョンを絞っている場合は、それに合わせてください
aws cloudformation create-stack-instances \
--stack-set-name "${STACKSET_NAME}" \
--deployment-targets OrganizationalUnitIds=${OU_ID} \
--regions eu-north-1 ap-south-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 ap-northeast-1 sa-east-1 ca-central-1 ap-southeast-1 ap-southeast-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2 \
--operation-preferences RegionConcurrencyType=PARALLEL

以下のようなスタックセットができました( MemberOU にはまだアカウントを所属させていないのでスタックインスタンスは無い)。

img

img

アカウントを移動させてみる

メンバーアカウントを MemberOU へ移動させます。

移動後にスタックセットを確認します。自動で CREATE オペレーションが開始されていました。 アカウントの各リージョンにスタックインスタンスが作成されています。

img

▼ すべて CURRENT になったら OKです

img

このメンバーアカウントの Security Hubを確認します。 (ほぼノータッチの) ムンバイリージョンに訪れてみました。

img

IAM.5,APIGateway.3,CloudTrail.2,EC2.4,RDS.7,RDS.8 が無効化されていること確認できました。

▼ CloudWatch Logs にて実行ログを確認できます

img

無効化したものを有効化する

  • 追加で RDS.19,RDS.20,RDS.21,RDS.22 を無効化する
  • やっぱり RDS.7,RDS.8 は有効化する

上記更新を先程のスタックセットに反映させてみます。

TEMPLATE_PATH=(テンプレートのパス)
STACKSET_NAME="InitialSetup-SecurityHubAFSBPControls"

# 追加で RDS.19,RDS.20,RDS.21,RDS.22 を無効化する
AFSBPDisableList="IAM.5,APIGateway.3,CloudTrail.2,EC2.4,RDS.19,RDS.20,RDS.21,RDS.22"

# やっぱり RDS.7,RDS.8 は有効化する
AFSBPEnableList="RDS.7,RDS.8"

# スタックセット更新
aws cloudformation update-stack-set \
--stack-set-name "${STACKSET_NAME}" \
--use-previous-template \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \
--operation-preferences RegionConcurrencyType=PARALLEL \
--parameters "[
  {
    \"ParameterKey\": \"AFSBPDisableList\",
    \"ParameterValue\": \"${AFSBPDisableList}\"
  },
  {
    \"ParameterKey\": \"AFSBPEnableList\",
    \"ParameterValue\": \"${AFSBPEnableList}\"
  }
]"

UPDATE オペレーションの完了後に再度 メンバーアカウントの Security Hubを確認します。

RDS.19,RDS.20,RDS.21,RDS.22 が追加で無効化されていること確認できました。

img

RDS.7,RDS.8 が再び有効化されていることも確認できました。

img

▼ (参考) CloudWatch Logs のログ抜粋

[INFO]	2021-10-(略)	7582(略)7ad2a	disabling controls...
[INFO]	2021-10-(略)	7582(略)7ad2a	  IAM.5 is already disabled, or not exist
[INFO]	2021-10-(略)	7582(略)7ad2a	  APIGateway.3 is already disabled, or not exist
[INFO]	2021-10-(略)	7582(略)7ad2a	  CloudTrail.2 is already disabled, or not exist
[INFO]	2021-10-(略)	7582(略)7ad2a	  EC2.4 is already disabled, or not exist
[INFO]	2021-10-(略)	7582(略)7ad2a	  disabling RDS.19
[INFO]	2021-10-(略)	7582(略)7ad2a	    disable successfully
[INFO]	2021-10-(略)	7582(略)7ad2a	  disabling RDS.20
[INFO]	2021-10-(略)	7582(略)7ad2a	    disable successfully
[INFO]	2021-10-(略)	7582(略)7ad2a	  disabling RDS.21
[INFO]	2021-10-(略)	7582(略)7ad2a	    disable successfully
[INFO]	2021-10-(略)	7582(略)7ad2a	  disabling RDS.22
[INFO]	2021-10-(略)	7582(略)7ad2a	    disable successfully
[INFO]	2021-10-(略)	7582(略)7ad2a	enabling controls...
[INFO]	2021-10-(略)	7582(略)7ad2a	  enabling RDS.7
[INFO]	2021-10-(略)	7582(略)7ad2a	    enable successfully
[INFO]	2021-10-(略)	7582(略)7ad2a	  enabling RDS.8
[INFO]	2021-10-(略)	7582(略)7ad2a	    enable successfully

おわりに

CFnスタックセットのOrganizations 連携、および Lambda-backed カスタムリソースを 組み合わせた Security Hub における活用例でした。

今回は『基礎セキュリティのベストプラクティス』のみの対応ですが、 コード/テンプレートを少し修正するだけで CISなど他のセキュリティ基準にも対応できると思います。

Organizations環境で Security Hub のコントロール無効化/有効化周りの作業 に辛さを感じている人の参考になれば幸いです。

参考