Security Hub 『基礎セキュリティのベストプラクティス』にて どのコントロールでどれだけのリソースが失敗しているのか を把握したいです。
もちろんマネジメントコンソールにて確認できますが、 細かいフィルタリングや分析を行うには、CSVなどの シート形式でまとまっていたほうが便利ですよね。
そこで今回は Python(Boto3)スクリプトを書いて、 失敗している検出結果をCSV出力してみます。
(補足) 一応 マネジメントコンソールからCSVを取得する機能はあります。ですが現時点では「全コントロールの検出結果を取得する」となると、各コントロールのページにてCSVダウンロードを押下しないといけなくて、大変です。
書いたスクリプト
以下に作成した Pythonスクリプトを記載します。 追加で pip install が必要なパッケージは boto3 のみです。
securityhub-inventory-failed-resources.py
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