ablog

不器用で落着きのない技術者のメモ

S3バケットがPublic公開されたら Config -> CWE -> Lambda で自動的に Private に戻す

S3バケットACL でパブリック公開されたら、AWS Config のマネージドルール "s3-bucket-public-read-prohibited" で検知して CloudWatch Events 経由で Lambda を起動して Private に戻す検証をしてみたメモ。

設定

AWS Config のマネージドルールを追加する
  • AWSマネジメントコンソールにログインする。
  • [Config]-[ルール]を選択し、[ルールの追加]をクリックし、[s3-bucket-public-read-prohibited]を選択し、[保存]をクリックする。

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に自動修正されていることが分かる。


以下はイベントの詳細。

{
    "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 でバケットポリシーによるパブリック公開の戻しはしていない。