Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

「AWS Security Hubの導入から運用を回すためにやってきたこと」というタイトルでSecurity-JAWS#27に登壇しました

こんにちは、SREチームの山口(@yamaguchi_tk)です。AWSに関わり始めて3年半くらいです。 今年1月にJOINして、気づけばセキュリティ系のタスクばっかりやってました。

こちらの記事はGunosy Advent Calendar 2022の4日目の記事です。 前回の記事は suchida さんの M1 Mac に挫けない!TensorFlow に躓かない開発環境をつくるでした。

はじめに

Security-JAWS#27*1でAWS Security Hubを運用に載せるまでの話をした内容のまとめです。

動画

www.youtube.com

資料

目次

テーマ

テーマはAWS Security Hubの導入と運用なのですが、実際はAWS Control Towerの導入と並行しているので話の流れが複雑になっています。 AWS Security Hubの導入と運用については、こちらの記事が非常に参考になります。

【資料公開】AWS Security Hub導入と運用の検討ポイント | DevelopersIO

導入開始時点ではこういった記事もなく、適用できそうな公開事例も見当たらず苦労しました。

AWS Security Hub導入の背景

AWS Security Hub導入の背景で一番大きかったのは、Log4j問題の時に人力で検知して対応するしか選択肢がなかったことです。

これをキッカケに、定期的・自動的にスキャンして検知して潰していくサイクルを構築する気運が出てきました。

AWS Security Hub導入の背景

導入

AWS Configが有効になっていれば導入するのは簡単です。 AWS Security Hubの紹介記事でも「とりあえず導入して、点数を確認しましょう」的な記事が多いのですが、実現したいことが上述の

定期的・自動的にスキャンして検知して潰していくサイクルを構築する

なので、導入の方法(というか設定や操作方法)はわかりますが、運用を構築していく前段階としてGunosyでのAWS設定のあるべき姿(ベースライン)を設定する参考にはなりませんでした。

AWS Security Hubを運用する上で、GunosyでのAWS設定のあるべき姿(ベースライン)は具体的には以下のことを指します。

  • どの標準を有効にするのか
  • どのコントロールを有効・無効にするか
  • 抑制(SUPPRESSED)にして良い基準は何か

導入の流れ

導入して終わりではないのと既存アカウントへの導入なので、保守的なフローで導入しました。

AWS Security Hub導入の流れ

導入は各アカウントへの展開の容易さや、今後のマルチアカウント環境での管理運用負荷も考慮してAWS Control Towerと併せて導入しました。

PoCで実施したこと

PoCではSandboxアカウントにAWS Security HubとAWS Control Towerを導入して、主にAWS Security Hub周りの検証を実施しました。

  • 指摘事項の調査
    • この項目が「導入してみて点数を見ましょう」というところ
  • 指摘の対応や抑制してみて、AWS Security Hubの変化を確認
  • 自動修復の挙動の調査
  • 委任アカウントからの見え方、メンバーアカウントからの見え方

PoCで判明した課題

PoCで判明した課題は以下の5つです。

  1. 点数があてにならない
  2. (自社の利用方法では)無駄な指摘、解決不能な指摘がある
  3. 基準・コントロールの有効化・無効化がメンバーアカウントへ伝搬しない
  4. リソース単位で抑制してもメンバーアカウントへ伝搬しない
  5. 自動修復の悩み

それぞれ細かく説明していきます。

点数があてにならない

AWS Security Hubの点数は失敗したコントロールの割合でしかない*2ので、点数がリスク評価を表しません

図ではHIGHが1件失敗していますが、MEDIUM、LOWの失敗に引きづられて点数が赤点になっています。

AWS Security Hubの点数

セキュリティの文脈で欲しい点数は、失敗の割合ではなくてリスク評価値です。 本当はリスク評価値として丸まった点数よりも、単純にCRITICAL、HIGH、MEDIUM、LOWの失敗件数をダッシュボードに表示してくれた方が運用しやすいです。

検知後の対応を検討する際に、ダッシュボードで各アカウントのリスク評価値か、Severity別の失敗件数が確認できれば、どのアカウントから対応するかのトリアージがしやすいです。

対応は単純に点数を気にしないことにしました。

(自社の利用方法では)無駄な指摘、解決不能な指摘がある

例えば以下

  • [IAM.6] (HIGH)ルートユーザーに対してハードウェア MFA を有効にする必要があります
  • [S3.9] (MEDIUM)S3 バケットサーバーアクセスログ記録を有効にする必要があります

クラスメソッドさんのBlogにこの辺りの参考情報(「[目指せ上級者] 最強にセキュアなAWSアカウントの作り方」というタイトルでDevelopersIO 2022に登壇しました #devio2022 | DevelopersIO)がありますが、ルールで判断できることはさほど多くはなく、コントロール個別に利用環境に応じて検討することが必要になります。

Gunosyでも全てのコントロールをスプレッドシートに一覧で整理して、個別に以下の項目を決定していきました。

  • 有効・無効を判断する
  • リソースが指摘されたときの対応方針を明確にする

コントロール有効化・無効化スプレッドシート

基準・コントロールの有効化・無効化がメンバーアカウントへ伝搬しない

AWS Security Hubは委任することで委任アカウント側に情報を集約することができるのですが、委任アカウント側でコントロールを有効化・無効化してもそれがメンバーアカウントに伝搬しません。全社的なベースラインとして、全てのアカウント共通のルールで運用することを目的として委任アカウント側で一括操作したかったのですが、標準機能では実現できませんでした。

AWS samplesにちょうど良いソリューション*3があったので、それを利用して解決しました。

AWSサポートやセキュリティスペシャリストSAさんに聞いても有効なソリューションが出てこない時もあるので、諦めずに探すことが大事です。

この時点では日本語の記事が本当にどこにもなかったので、クラスメソッドさんにお願いしてBlog化*4して頂きました。

リソース単位で抑制してもメンバーアカウントへ伝搬しない

これも委任アカウント側で操作してもメンバーアカウントへステータスが伝搬してくれない系です。 委任アカウント側のAWS Security Hubでリソースを抑止(SUPPRESSED)してもメンバーアカウントへ伝搬しないので、次のAWS Security Hubのチェックで再度指摘が上がってきます。

委任アカウント側のAWS Security Hubは標準機能では表示をまとめるダッシュボード機能でしかなく、これはこれでありがたいのですが、ミスコンフィグを潰していく運用フローを考えるとツラいです。

リソース単位での抑止(SUPPRESSED)をメンバーアカウント側で操作することで解決しました。

自動修復の悩み

GunosyではIaCでコンフィグや、リソース生成を行っているので、相性が悪かったです。

どういうことかというと

IaCで管理していないリソースに対する自動修復は助かる面もありますが、修復タイミングが選べないので何か想定外の事態が発生した時に、自動修復での修正が原因であった場合に、それを発見するのが遅れてしまう恐れがあります。

IaCで管理しているリソースだと、単純にIaCをデプロイすると元に戻ってしまいます。

そのため自動修復設定を入れずに、(リソース作成時に自動で発生する項目も含めて)IaCで管理・修正する方向で運用しています。

そもそも論として自動で作成されたりデフォルトで作成されるリソースや設定は、AWS Security Hubで指摘されない状態(デフォルトでセキュアな状態)が望ましいと思っています。

運用

運用では以下の4つの項目を決定しました。

  1. どのSeverityまで対応するか
  2. 誰が対応するか
  3. 抑制(SUPPRESSED)にする基準をどうするか
  4. 対応のステータスの追跡をどうやるか
  5. 新しい指摘はどうやって確認するか

また選定する為の評価軸を設定しました。

  1. 開発チームにあまり負担をかけたくない
  2. 今のSREの体制で運用が回るか
  3. セキュリティは担保したい

決定事項をそれぞれ細かく説明していきます。

どのSeverityまで対応するか

CRITICAL、HIGHを対応することに決定しました。

MEDIUM以下は放置です。 設計でセキュリティが確保できていればという前提つきですが、自社の利用範囲では即座に問題になるコントロールはありませんでした。 多層防御の観点からは対応が望ましいことは理解しているのですが、対応工数との絡みで一旦放置の決定をしました。

誰が対応するか

CRITICALはSREが最速で対応する。 これはリスク低減という観点から、開発チームがタスクに積んで日々の開発タスクの合間に対応する、では間に合わない可能性を考慮しました。

HIGHは開発チームがスプリントに積んで対応する。 CRITICALよりも切迫度が低いという判断と、SREが指摘事項をトリアージ、対応方法をサジェストすることで負担感を軽減することで開発チームで受け入れ可能と判断しました。

抑制(SUPPRESSED)にする基準をどうするか

抑制(SUPPRESSED)にすると指摘は無くなりますが、なんでもかんでも抑制(SUPPRESSED)にしてしまうと、当初の目的の検知して潰していくということができません。

リスクが許容できることが大前提として以下の場合に抑制(SUPPRESSED)することに決定しました。

  • 設計、システム構成、運用上回避できない場合
  • 対応する際にリソースの再作成が必要な場合
  • 対応すると別の問題が発生する場合

抑制(SUPPRESSED)で問題ないのかどうかは、定期的に実施しているSLOふりかえりの場で開発チームからリソースの利用状況を確認し、SREがサジェストしています。

対応のステータスの追跡をどうやるか

対応する場合はJIRAチケットを起票する運用にしています。起票するJIRAボードは開発チーム別になっているので、スプシでまとめて追跡できるようにしています。

新しい指摘はどうやって確認するか

通知運用も検討しましたが、ふりかえり資料作成時にAWS Security Hubを確認する必要があるため、SREが定期的に指摘を確認する運用にしています。

運用フロー

運用フローは非常にシンプルになりました。

定例のふりかえりの準備

  1. SREがAWS Security Hubの指摘を確認する
  2. 指摘事項をトリアージ、対応事項をサジェストしてスプレッドシートにまとめる
  3. CRITICAL指摘があればSREがJIRAチケットを起票して対応する

定例のふりかえり

  1. SREが開発チームへ対応を依頼する
  2. 開発チームとSREが協議して対応有無を決定し、その場でJIRAチケットを起票する
  3. すでに起票されているJIRAチケットのステータスを確認する

本番アカウントへの導入

本番アカウントへの導入は、AWS Control Towerが導入されていて、AWS Security Hubの委任がされていれば非常に簡単です。

  1. メンバーアカウントをAWS Control Tower配下に追加する
  2. 委任アカウントのマネコンからメンバーアカウントのAWS Security Hubを有効化する

Terraformで委任されたAWS Security Hubへのアカウント追加をすると毎回差分が発生するので、ここはマネコンでやっています。

本番展開後に発生した問題

事前に調査、PoCは実施したのですが、本番展開後にも問題が発生しました。

AWS Security Hubのダッシュボードが使いにくい

PoCの段階である程度予測はしていたのですが、予想以上にAWS Security Hubのダッシュボードが使いにくく問題となりました。

委任アカウント側のAWS Security Hubのダッシュボードで検索条件が保存できないので、マルチアカウントでアカウントを絞り込んでトリアージする場合に何度も同じ操作が必要になりました。

これは、メンバーアカウントのAWS Security Hubの画面でトリアージすることで対応しました。 リソース単位の抑止もメンバーアカウント側で実行する必要があるので、トリアージと同時に実施することで省力化をしています。

いろいろな情報をAWS Security HubにIntegrationして集約することができるのですが、集約すればするほどダッシュボードが使いにくくなるので、現時点ではIntegrationした情報の活用ができていません。

料金爆発

リージョンは絞っているのですが、AWS Configの料金が爆発しました。

AWS Config料金

クラウドらしく、immutableにリソースを使い捨てしていたアカウントで発生しました。CI/CD、バッチ回すたびにチャリンチャリンと料金が発生している状態でした。 これは事前調査段階でAWS Control Tower導入で料金爆発した事例と解決事例*5があったので、それを参考に対応しました。

親アカウントのStackSetにAWSControlTowerBP-BASELINE-CONFIGが存在しているのでパラメーターを変更して更新する必要があります。

  • AllSupported: false
  • IncludeGlobalResourceTypes: false
  • ResourceTypes: (記録対象リソースをCSV形式で指定)

記録対象リソースはホワイトリスト形式で全量指定する必要がある為、以下のワンライナーをCloudShellで実行して作成しました。

$ aws configservice list-discovered-resources help \
| sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})*)?m//g" \
| grep "o AWS::" | sed -e "s/ *+\x08o //g" \
| grep -v -E "ECS::TaskDefinition|EC2::NetworkInterface" \
| sort | tr '\n' ',' | sed -e  's/,$//'

執筆時点(2022/12/04)だとAWS Configの項目が増えているため、2項目のみ除外する設定だとStackSetがエラーになります。 項目数ではなく文字数で4250あたりが上限になっているようです。

指摘通りに対応したら障害発生

以下のコントロールで指摘されていたセキュリティグループを削除したらEKSクラスターのインプレースアップデートができなくなりました。

  • [EC2.22] (MEDIUM)未使用の EC2 セキュリティグループを削除する必要があります
  • EC2.18セキュリティグループは、許可されたポートに対してのみ無制限の受信トラフィックを許可する必要があります

似たような事例 Cannot upgrade EKS | AWS re:Post

Issueもありました [EKS] [request]: Change security group of EKS master without replacing the cluster · Issue #738 · aws/containers-roadmap · GitHub

結果的にEKSクラスターの再作成が必要になりました。

何度も言いますが、AWS内部サービスで自動的に作成されるリソースへの指摘は無いようにしてほしいところです。

まとめ

導入そのものよりもその後の運用でミスコンフィグが無い状態を継続することが大事です。

実環境でミスコンフィグを潰せたら、新たなミスコンフィグを持ち込ませないようにしましょう。Shift-left大事です。

AWS Security Hubを使うとAWS環境のミスコンフィグを効率よく監査できます。指摘が細かすぎるところがあるので、うまくトリアージしましょう。 トリアージの基準は、環境だったり、準拠すべきセキュリティ標準によって異なります。コントロール毎に有効・無効の判断、リソース毎に対応・抑制の判断が必要ですが、コンテキストありきですので、それぞれ個別の判断が求められます。ここはガイドラインがあっても省略できないので頑張って対応する必要があります。

アクセス権限、不正アクセスはAWS Security Hub単体ではチェックできないので、他のサービスと組み合わせて対応しましょう。 IAM Access Analyzer、GuardDuty等々あります。

今後

実環境でのミスコンフィグの検知と対応のフローの構築が終わったので、今後はShift-leftの文脈でのDevSecOpsの構築と、社内への情報セキュリティ文化の構築をやっていく予定です。

参考URL

AWS Control Towerで設定されたAWS Configの料金が高騰したのでどうにかした話 - Qiita boto3から無理やりSecurity Hubのセキュリティスコアを算出してみた | DevelopersIO

次回は marice0819 さんの digdag が止まった話 です。お楽しみに!