Skip to content
This repository was archived by the owner on Dec 30, 2024. It is now read-only.

Commit a81b440

Browse files
committed
release v2.1.3
1 parent 7aecf2c commit a81b440

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed

source/lib/ingestion/index.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import json
2+
import logging
3+
import os
4+
import uuid
5+
6+
import boto3
7+
import cfnresponse
8+
9+
RESOURCE_PROPERTIES = "ResourceProperties"
10+
SOURCE_BUCKET_NAME = "SOURCE_BUCKET_NAME"
11+
LOGGING_BUCKET_NAME = "LOGGING_BUCKET_NAME"
12+
PHYSICAL_RESOURCE_ID = "PhysicalResourceId"
13+
POLICY_SID = "customingestionAccessLogsPolicy"
14+
STATEMENT = "Statement"
15+
16+
DEFAULT_LEVEL = "DEBUG"
17+
18+
s3 = boto3.client("s3")
19+
logger = logging.getLogger(__name__)
20+
logger.setLevel(os.environ.get("LOG_LEVEL", DEFAULT_LEVEL))
21+
22+
23+
def handler(event, context):
24+
logger.debug(f"The event is {event}")
25+
physical_resource_id = None
26+
27+
try:
28+
physical_resource_id = event.get(PHYSICAL_RESOURCE_ID, uuid.uuid4().hex[:8])
29+
30+
if event["RequestType"] == "Create" or event["RequestType"] == "Update":
31+
source_bucket_name = event[RESOURCE_PROPERTIES][SOURCE_BUCKET_NAME]
32+
logging_bucket_name = event[RESOURCE_PROPERTIES][LOGGING_BUCKET_NAME]
33+
account_id = context.invoked_function_arn.split(":")[4]
34+
aws_partition = context.invoked_function_arn.split(":")[1]
35+
36+
s3.put_public_access_block(
37+
Bucket=logging_bucket_name,
38+
PublicAccessBlockConfiguration={
39+
"BlockPublicAcls": True,
40+
"IgnorePublicAcls": True,
41+
"BlockPublicPolicy": False,
42+
"RestrictPublicBuckets": True,
43+
},
44+
ExpectedBucketOwner=account_id,
45+
)
46+
47+
policy_string = s3.get_bucket_policy(Bucket=logging_bucket_name)["Policy"]
48+
bucket_policy = json.loads(policy_string)
49+
50+
update_policy = True
51+
52+
for statement in bucket_policy[STATEMENT]:
53+
logger.debug(f"Statement is {json.dumps(statement)}")
54+
if "Sid" in statement and statement["Sid"] == POLICY_SID:
55+
if (
56+
f"arn:{aws_partition}:s3:::{source_bucket_name}"
57+
not in statement["Condition"]["ArnLike"]["aws:SourceArn"]
58+
):
59+
logger.info("Bucket policy exists but with a different bucket, hence removing it")
60+
bucket_policy[STATEMENT].remove(statement)
61+
break
62+
else:
63+
logger.info("Bucket policy exists, hence update not required")
64+
update_policy = false
65+
break
66+
67+
if update_policy:
68+
bucket_policy[STATEMENT].append(
69+
{
70+
"Action": "s3:PutObject",
71+
"Condition": {
72+
"ArnLike": {"aws:SourceArn": [f"arn:{aws_partition}:s3:::{source_bucket_name}"]},
73+
"StringEquals": {"aws:SourceAccount": account_id},
74+
},
75+
"Effect": "Allow",
76+
"Principal": {"Service": "logging.s3.amazonaws.com"},
77+
"Resource": f"arn:{aws_partition}:s3:::{logging_bucket_name}/customingestion*",
78+
"Sid": POLICY_SID,
79+
}
80+
)
81+
82+
s3.put_bucket_policy(Bucket=logging_bucket_name, Policy=json.dumps(bucket_policy))
83+
84+
s3.put_public_access_block(
85+
Bucket=logging_bucket_name,
86+
PublicAccessBlockConfiguration={
87+
"BlockPublicAcls": True,
88+
"IgnorePublicAcls": True,
89+
"BlockPublicPolicy": True,
90+
"RestrictPublicBuckets": True,
91+
},
92+
ExpectedBucketOwner=account_id,
93+
)
94+
logger.info("Policy Updated successfully. Sending success response to CloudFormation")
95+
96+
cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, physical_resource_id)
97+
except Exception as ex:
98+
logger.error(f"Failed to update policy, error is {str(ex)}")
99+
cfnresponse.send(
100+
event, context, cfnresponse.FAILED, {}, physicalResourceId=physical_resource_id, reason=str(ex)
101+
)

source/lib/utils/policy.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env node
2+
/**********************************************************************************************************************
3+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. *
4+
* *
5+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance *
6+
* with the License. A copy of the License is located at *
7+
* *
8+
* http://www.apache.org/licenses/LICENSE-2.0 *
9+
* *
10+
* or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES *
11+
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions *
12+
* and limitations under the License. *
13+
*********************************************************************************************************************/
14+
15+
import * as iam from '@aws-cdk/aws-iam';
16+
import * as s3 from '@aws-cdk/aws-s3';
17+
import * as cdk from '@aws-cdk/core';
18+
19+
/**
20+
* Function to add to logging bucket's resource policy
21+
*/
22+
export function updateBucketResourcePolicy(
23+
s3LoggingBucket: s3.Bucket,
24+
sourceBucket: s3.Bucket,
25+
sourcePrefix: string
26+
): any {
27+
s3LoggingBucket.addToResourcePolicy(
28+
new iam.PolicyStatement({
29+
sid: `${sourcePrefix}AccessLogsPolicy`,
30+
effect: iam.Effect.ALLOW,
31+
principals: [new iam.ServicePrincipal('logging.s3.amazonaws.com')],
32+
actions: ['s3:PutObject'],
33+
resources: [`${s3LoggingBucket.bucketArn}/${sourcePrefix}*`],
34+
conditions: {
35+
ArnLike: {
36+
'aws:SourceArn': [`${sourceBucket.bucketArn}`]
37+
},
38+
StringEquals: {
39+
'aws:SourceAccount': cdk.Aws.ACCOUNT_ID
40+
}
41+
}
42+
})
43+
);
44+
}

0 commit comments

Comments
 (0)