S3バケットが ACL でパブリック公開されたら、AWS Config のマネージドルール "s3-bucket-public-read-prohibited" で検知して CloudWatch Events 経由で Lambda を起動して Private に戻す検証をしてみたメモ。
設定
AWS Config のマネージドルールを追加する
Lambda 関数に付与するロールを作成する
- [IAM]-[ロール]を選択する。
- [ロールの作成]をクリックし、[AWSサービス]-[Lambda] を選択して、[次のステップ]をクリックする。
- [AmazonS3FullAccess]、[CloudWatchLogsFullAccess] をチェックして、[次のステップ]をクリックする。
- ロール名: S3FullAccess と入力して、[ロールの作成]をクリックする。
Lambda 関数を作成する
- 名前: S3BucketPublic2PrivateFunction
- ランタイム: Python 2.7
- ロール: S3FullAccess
import json import boto3 s3 = boto3.client('s3') def lambda_handler(event, context): print('s3 public') print( event ) print( context ) bucket=event['detail']['oldEvaluationResult']['evaluationResultIdentifier']['evaluationResultQualifier']['resourceId'] s3.put_bucket_acl(Bucket=bucket, ACL="private") return 'Hello from S3 private Lambda'
CloudWatch Events
- [CloudWatch]-[イベント]-[ルール]を選択し、[ルールの作成]をクリックしてルールを作成する。
- サービス名: Config
- イベントタイプ: Config Rules Compliance Change
- "Specific rule name(s)" を選択し、"s3-bucket-public-read-prohibited" と入力する。
- Lambda関数の機能で "S3BucketPublic2PrivateFunction" を指定する。
- 上記の通り設定すると、イベントパターンは以下の通りとなる。
{ "source": [ "aws.config" ], "detail-type": [ "Config Rules Compliance Change" ], "detail": { "configRuleName": [ "s3-bucket-public-read-prohibited" ] } }
検証
- [CloudWatch]-[ログ]を選択し、"/aws/lambda/S3BucketPublic2PrivateFunction" をクリックする
2018-09-02 14:49:20 START RequestId: 5f730527-aebf-11e8-bc27-2387da2ec865 Version: $LATEST s3 public {'account': '...', 'region': 'ap-northeast-1', 'detail': {'oldEvaluationResult': {'configRuleInvokedTime': '2018-09-02T13: 38: 49.243Z', 'evaluationResultIdentifier': {'orderingTimestamp': '2018-09-02T13: 38: 48.407Z', 'evaluationResultQualifier': {'resourceType': 'AWS: :S3: :Bucket', 'resourceId': 'az-test3', 'configRuleName': 's3-bucket-public-read-prohibited' } }, 'resultRecordedTime': '2018-09-02T13: 38: 50.095Z', 'complianceType': 'COMPLIANT' }, 'configRuleName': 's3-bucket-public-read-prohibited', 'configRuleARN': 'arn:aws:config:ap-northeast-1: ...:config-rule/config-rule-8czpzy', 'resourceId': 'az-test3', 'resourceType': 'AWS: :S3: :Bucket', 'awsRegion': 'ap-northeast-1', 'recordVersion': '1.0', 'notificationCreationTime': '2018-09-02T14: 49: 16.641Z', 'messageType': 'ComplianceChangeNotification', 'newEvaluationResult': {'configRuleInvokedTime': '2018-09-02T14: 49: 14.685Z', 'evaluationResultIdentifier': {'orderingTimestamp': '2018-09-02T14: 49: 13.974Z', 'evaluationResultQualifier': {'resourceType': 'AWS: :S3: :Bucket', 'resourceId': 'az-test3', 'configRuleName': 's3-bucket-public-read-prohibited' } }, 'resultRecordedTime': '2018-09-02T14: 49: 15.645Z', 'annotation': 'The S3 bucket ACL allows public read access.', 'complianceType': 'NON_COMPLIANT' }, 'awsAccountId': '...' }, 'detail-type': 'Config Rules Compliance Change', 'source': 'aws.config', 'version': '0', 'time': '2018-09-02T14: 49: 16Z', 'id': '1885395f-643e-7b33-2023-d5183e922a05', 'resources': [] } <__main__.LambdaContext object at 0x7f332f96c610> az-test3 END RequestId: 5f730527-aebf-11e8-bc27-2387da2ec865 REPORT RequestId: 5f730527-aebf-11e8-bc27-2387da2ec865 Duration: 1190.15 ms Billed Duration: 1200 ms Memory Size: 128 MB Max Memory Used: 45 MB
- CloudTrail を確認すると、バケットをパブリック公開した後、Lambdaに自動修正されていることが分かる。
- S3バケットをパブリック公開したイベント
{ "eventVersion": "1.05", "userIdentity": { "type": "IAMUser", "principalId": "...", "arn": "arn:aws:iam::...:user/...", "accountId": "...", "accessKeyId": "...", "userName": "...", "sessionContext": { "attributes": { "mfaAuthenticated": "true", "creationDate": "2018-09-02T02:47:58Z" } }, "invokedBy": "signin.amazonaws.com" }, "eventTime": "2018-09-02T14:47:03Z", "eventSource": "s3.amazonaws.com", "eventName": "PutBucketAcl", "awsRegion": "ap-northeast-1", "sourceIPAddress": "...", "userAgent": "signin.amazonaws.com", "requestParameters": { "bucketName": "az-test3", "AccessControlPolicy": { "AccessControlList": { "Grant": [ { "Grantee": { "xsi:type": "CanonicalUser", "DisplayName": "...", "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance", "ID": "..." }, "Permission": "FULL_CONTROL" }, { "Grantee": { "xsi:type": "Group", "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance", "URI": "http://acs.amazonaws.com/groups/global/AllUsers" }, "Permission": "FULL_CONTROL" } ] }, "xmlns": "http://s3.amazonaws.com/doc/2006-03-01/", "Owner": { "DisplayName": "...", "ID": "..." } }, "acl": [ "" ] }, "responseElements": null, "additionalEventData": { "vpcEndpointId": "vpce-..." }, "requestID": "840FD40783BDA22A", "eventID": "c5c9c51a-bd2e-4332-8d76-238a9f093e39", "eventType": "AwsApiCall", "recipientAccountId": "...", "vpcEndpointId": "vpce-..." }
- Lambda が公開されたS3バケットを元に戻したイベント
{ "eventVersion": "1.05", "userIdentity": { "type": "AssumedRole", "principalId": "...:S3BucketPublic2PrivateFunction", "arn": "arn:aws:sts::...:assumed-role/S3FullAccess/S3BucketPublic2PrivateFunction", "accountId": "...", "accessKeyId": "...", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2018-09-02T14:17:11Z" }, "sessionIssuer": { "type": "Role", "principalId": "...", "arn": "arn:aws:iam::...:role/S3FullAccess", "accountId": "...", "userName": "S3FullAccess" } } }, "eventTime": "2018-09-02T14:49:21Z", "eventSource": "s3.amazonaws.com", "eventName": "PutBucketAcl", "awsRegion": "ap-northeast-1", "sourceIPAddress": "...", "userAgent": "[Boto3/1.7.74 Python/2.7.12 Linux/4.14.62-65.117.amzn1.x86_64 exec-env/AWS_Lambda_python2.7 Botocore/1.10.74]", "requestParameters": { "x-amz-acl": [ "private" ], "bucketName": "az-test3", "acl": [ "" ] }, "responseElements": null, "requestID": "E1B2289AA1381E26", "eventID": "6fbdd0c6-b03c-497e-8391-dc70e79d6772", "eventType": "AwsApiCall", "recipientAccountId": "..." }
補足
- Lambda でバケットポリシーによるパブリック公開の戻しはしていない。