AWS Security Hub 『基礎セキュリティのベストプラクティス』で失敗している検出結果をCSV出力したい【Python, Boto3】
Security Hub 『基礎セキュリティのベストプラクティス』にて どのコントロールでどれだけのリソースが失敗しているのか を把握したいです。
もちろんマネジメントコンソールにて確認できますが、 細かいフィルタリングや分析を行うには、CSVなどの シート形式でまとまっていたほうが便利ですよね。
そこで今回は Python(Boto3)スクリプトを書いて、 失敗している検出結果をCSV出力してみます。
(補足) 一応 マネジメントコンソールからCSVを取得する機能はあります。ですが現時点では「全コントロールの検出結果を取得する」となると、各コントロールのページにてCSVダウンロードを押下しないといけなくて、大変です。
書いたスクリプト
以下に作成した Pythonスクリプトを記載します。 追加で pip install が必要なパッケージは boto3 のみです。
import boto3 import csv import logging from operator import itemgetter from datetime import datetime logging.basicConfig(level=logging.INFO) sh_client = boto3.client('securityhub') def generate_sh_failed_findings_csv(file_path): header = ['ControlID', 'ControlTitle', 'Severity', 'AccountName', 'AccountID', 'ResourceType', 'ResourceID', 'ResourceNameTag', 'ComplianceStatus', 'RecordStatus', 'WorkflowStatus'] findings = [] # securityhub.GetFindings 実行 paginator = sh_client.get_paginator('get_findings') response_iterator = paginator.paginate( Filters={ 'ProductFields': [ { 'Key': 'StandardsArn', 'Value': 'arn:aws:securityhub:::standards/aws-foundational-security-best-practices/v/1.0.0', 'Comparison': "EQUALS" } ], 'ComplianceStatus': [ { 'Value': 'FAILED', 'Comparison': 'EQUALS' } ], 'RecordState': [ { 'Value': 'ACTIVE', 'Comparison': 'EQUALS' } ] } ) # CSV作成のための配列作成 page_count = 0 for page in response_iterator: page_count = page_count + 1 logging.info(f'fetching page#{page_count}...') for finding in page.get('Findings'): resource_name = '' if finding.get('Resources')[0].get('Tags'): resource_name = finding.get('Resources')[0].get('Tags').get('Name') findings.append([ finding.get('Compliance').get('SecurityControlId'), finding.get('Title'), finding.get('Severity').get('Label'), finding.get('AwsAccountName'), finding.get('AwsAccountId'), finding.get('Resources')[0].get('Type'), finding.get('Resources')[0].get('Id'), resource_name, finding.get('Compliance').get('Status'), finding.get('RecordState'), finding.get('Workflow').get('Status') ]) # CSV出力 rows = [header] + sorted(findings, key=itemgetter(0,3)) with open(file_path, 'w', newline='') as csvfile: writer = csv.writer(csvfile, quoting=csv.QUOTE_ALL) writer.writerows(rows) def main(): datetime_now = datetime.now().strftime('%Y-%m-%d_%H-%M-%S') file_path = f'securityhub_{datetime_now}.csv' logging.info(f'[start] timestamp: {datetime_now}') generate_sh_failed_findings_csv(file_path) logging.info(f'[end] output: {file_path}') main()
実行例
実行するにあたって、以下AWSアクションの権限が必要です。
SecurityHub:GetFindings
上記権限を持った認証情報を事前にセットして、 スクリプトを実行します。 以下実行サンプルです。
$ python3 ./securityhub-inventory-failed-resources.py # INFO:botocore.credentials:Found credentials in environment variables. # INFO:root:[start] timestamp: 2024-04-04_16-33-20 # INFO:root:fetching page#1... # INFO:root:fetching page#2... # INFO:root:fetching page#3... # INFO:root:fetching page#4... # INFO:root:[end] output: securityhub_2024-04-04_16-33-20.csv
securityhub_%Y-%m-%d_%H-%M-%S.csv
といったCSVファイルが出力されます。 (以下 Excelで体裁調整して、 EC2.15
のみにフィルタを絞って表示させたものです)
各列の属性は以下のとおりです。
# | 列名 | 内容 |
---|---|---|
1 | ControlID | コントロールID |
2 | ControlTitle | コントロールのタイトル |
3 | Severity | 重要度(CRITICAL, HIGH, MEDIUM など) |
4 | AccountName | アカウント名(注意1) |
5 | AccountID | アカウントID |
6 | ResourceType | リソースタイプ |
7 | ResourceID | リソースID(ARN) |
8 | ResourceNameTag | Nameタグの値 |
9 | ComplianceStatus | コンプライアンスステータス(FAILEDのみ) |
10 | RecordStatus | レコードステータス(ACTIVEのみ) |
11 | WorkflowStatus | ワークフローステータス(NEW, NOTIFIED, SUPPRESSED など) |
(注意1) アカウント名は Organizations統合を利用していないと取得できない可能性があります。
Security Hub の管理アカウント上でスクリプトを実行することで、 複数アカウント横断で「失敗している検出結果」を取得できます。
おわりに
Security Hub のセキュリティチェック状況を棚卸ししてみました。 このCSVを使って コントロールのチューニングや、QuickSight 可視化などができると良さそうです。
以上、参考になれば幸いです。
補足
実行環境
- OS: macOS Sonoma 14.3.1
- Python: 3.12.2
- boto3: 1.34.77