Security Hubのアラーム多いな
Security HubでPCI DSSやCIS AWS Foundations Benchmarkのセキュリティ標準を有効化した場合に、S3バケットに対してSSL通信のみの設定をするよう求められる。
どんな構成が必要なのか
具体的にはバケットのStatementに以下の記載をすることでアラームが解消される。
このStatementはS3にオブジェクトを操作する際に、SSL通信(つまりはHTTPS)でないと拒否Denyする設定となります。
{
"Sid": "AllowSSLRequestsOnly",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<bucket_name>",
"arn:aws:s3:::<bucket_name>"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
もう一杯S3作っちゃったよ
Security Hubを有効化した際に全てのS3が走査され、このセキュリティ基準に準拠しないものがすべて通知されます。
数十あるバケットに対して手作業でこのポリシーを追記する(バケット名も転記する)ことは、面倒だと思いますのでpythonスクリプトを作成しました。
pythonスクリプト
このスクリプトでは boto3とjsonを利用しているため、pip install boto3
とpip install json
をしてください。
動作としては、
- 全てのバケットを走査します。
- バケットポリシーが有効化されている(何かしらバケットポリシーが記載されている)バケットに対して、
"aws:SecureTransport": "false"
の記載があるかを確認します。
バケットポリシーになにも記載がないバケットはスキップするようにしていますが、お好みでバケットポリシーを新規作成する形に変更していただければと思います。 - 記載がなければPolicyを追記し、反映します。
ログ表示
-
Statement exists
= SSL通信Onlyの記載が既にあるため、スキップ -
No Bucket Policy
= バケットポリシーが有効化されていないため、スキップ -
Bucket Policy changed
= バケットポリシーにSSL通信Onlyを設定した
import boto3
import json
def check_sslonly(bucket_name, json):
for statement in json['Statement']:
try:
statement['Condition']['Bool']['aws:SecureTransport']
print(bucket_name + ' : Statement exists')
return True
except KeyError:
continue
print(bucket_name + ' : Statement not exists')
return False
secure_transport_obj = {
"Sid": "AllowSSLRequestsOnly",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
def add_secure_transport_obj(bucket_name, bucket_policy_obj):
secure_transport_obj['Resource'] = [
"arn:aws:s3:::" + bucket_name,
"arn:aws:s3:::" + bucket_name + '/*'
]
bucket_policy_obj['Statement'].append(secure_transport_obj)
return
s3 = boto3.client('s3')
buckets = s3.list_buckets()
bucket_policy = None
for bucket in buckets['Buckets']:
try:
bucket_policy = s3.get_bucket_policy(Bucket=bucket['Name'])
except s3.exceptions.from_code('NoSuchBucketPolicy'):
print(bucket['Name'] + ' : No Bucket Policy')
continue
bucket_policy_obj = json.loads(bucket_policy['Policy'])
if(check_sslonly(bucket['Name'], bucket_policy_obj) == False):
add_secure_transport_obj(bucket['Name'], bucket_policy_obj)
s3.put_bucket_policy(
Bucket=bucket['Name'],
Policy=json.dumps(bucket_policy_obj)
)
print(bucket['Name'] + ' : Bucket Policy changed')