Skip to content

Commit 8b2733d

Browse files
authored
Merge pull request #24 from awslabs/1.3.1
1.3.1
2 parents 6927cf6 + 351e1af commit 8b2733d

4 files changed

Lines changed: 106 additions & 54 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,14 @@
114114
* Updated Cleanup section to reflect new cleanup capabilities.
115115
* Updated IAM Permissions examples within the README.
116116
* AWS CloudFormation template for deploying IAM Permissions to run cleanup code.
117-
* Header in files to reflect "Assisted Log Enabler for AWS", instead of "Assisted Log Enabler (ALE)".
117+
* Header in files to reflect "Assisted Log Enabler for AWS", instead of "Assisted Log Enabler (ALE)".
118+
119+
## [1.3.1] - 2021-07-22
120+
121+
### Added
122+
* Randomization to the end of the Amazon S3 bucket name in both single and multi account modes.
123+
* Instructions for deploying the AWS CloudFormation Stack individually, within the AWS Organizations root account for multi-account deployment.
124+
* Link for the AWS Security Analytics Bootstrap within the README.
125+
126+
### Changed
127+
* Feedback section within README to contain link to Issues section.

README.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,9 @@ python3 assisted_log_enabler.py --mode single_account --cloudtrail
205205
* Ensure that the AWS Account you're in is the account you want to store the logs. Additionally, ensure that the AWS account you're in has access to the AWS Organizations information within your AWS environment.
206206
* You may have to register your AWS account as a delegated administrator within AWS CloudFormation, in order to run this code in an AWS account of your choosing. Please see the following link for more details: [Register a delegated administrator](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-delegated-admin.html)
207207
2. Within the AWS Console, go to AWS CloudFormation.
208-
3. Within AWS CloudFormation, go to StackSets.
208+
3. To deploy the IAM Permissions within all child accounts: Within AWS CloudFormation, go to StackSets.
209209
4. Within the StackSets screen, select Create StackSet.
210-
5. In Step 1, under Specify Template, selecte Upload a template file, and use the AWS CloudFormation template provided in the permissions folder. [Link to the file](https://github.com/awslabs/assisted-log-enabler-for-aws/blob/main/permissions/ALE_child_account_role.yaml)
210+
5. In Step 1, under Specify Template, select Upload a template file, and use the AWS CloudFormation template provided in the permissions folder. [Link to the file](https://github.com/awslabs/assisted-log-enabler-for-aws/blob/main/permissions/ALE_child_account_role.yaml)
211211
6. In Step 2, under StackSet Name, add a descriptive name.
212212
7. In Step 2, under Parameters, add the parameters required:
213213
* AssistedLogEnablerPolicyName: You can leave this default, but you can also change it if desired.
@@ -218,23 +218,35 @@ python3 assisted_log_enabler.py --mode single_account --cloudtrail
218218
9. In Step 4, under Deployment targets, select the option that fits for your AWS Organization.
219219
* If you Deploy to Organization, it will deploy to all AWS accounts except the root AWS account. If you want to include that one, you can either deploy the template to the root AWS account directly, or use the other option (details below).
220220
* If you Deploy to organizational units (OUs), you can deploy directly to OUs that you define, including the root OU.
221-
10. In Step 4, under Specify Regions, select US East (N.Virginia)
221+
10. In Step 4, under Specify Regions, select US East (N.Virginia).
222222
* There's no need to select multiple regions here. This template only deploys AWS IAM resources, which are Global.
223223
11. In Step 4, under Deployment options, leave the default settings.
224224
12. In Step 5, review the settings you've set in the previous steps. If all is correct, check the box that states "I acknowledge that AWS CloudFormation might create IAM resources with custom names."
225225
* Once this is submitted, you'll need to wait until the StackSet is fully deployed. If there are errors, please examine the error and ensure that all the information from the above steps are correct.
226-
13. Once the StackSet is successfully deployed, click on the icon for AWS Cloudshell next to the search bar.
226+
13. To deploy the IAM Permissions within the AWS Account where Assisted Log Enabler for AWS is being ran: Within AWS CloudFormation, go to Stacks.
227+
14. Within the Stacks screen, go to the Create Stack dropdown, and select With new resources.
228+
15. In Step 1, select Upload a template file, select Choose File, and use the AWS CloudFormation template provided in the permissions folder. [Link to the file](https://github.com/awslabs/assisted-log-enabler-for-aws/blob/main/permissions/ALE_child_account_role.yaml)
229+
16. In Step 2, under Stack Name, add a descriptive name.
230+
17. In Step 2, under Parameters, add the parameters required:
231+
* AssistedLogEnablerPolicyName: You can leave this default, but you can also change it if desired.
232+
* OrgId: Provide the AWS Organization ID
233+
* SourceAccountNumber: Provide the source AWS account number that the Assisted Log Enabler for AWS will be running.
234+
18. In Step 3, add any tags that you desire, as well as any permissions options that you want to select.
235+
* The service-managed permissions work just fine for Assisted Log Enabler for AWS, but you can use self-service permissions if desired.
236+
19. In Step 5, review the settings you've set in the previous steps. If all is correct, check the box that states "I acknowledge that AWS CloudFormation might create IAM resources with custom names."
237+
* Once this is submitted, you'll need to wait until the StackSet is fully deployed. If there are errors, please examine the error and ensure that all the information from the above steps are correct.
238+
20. Once both the StackSet and Stack are successfully deployed, click on the icon for AWS Cloudshell next to the search bar.
227239
* Ensure that you're in a region where AWS CloudShell is currently available.
228-
14. Once the session begins, download the Assisted Log Enabler within the AWS CloudShell session.
240+
21. Once the session begins, download the Assisted Log Enabler within the AWS CloudShell session.
229241
```
230242
git clone https://github.com/awslabs/assisted-log-enabler-for-aws.git
231243
```
232-
15. Unzip the file, and change the directory to the unzipped folder:
244+
22. Unzip the file, and change the directory to the unzipped folder:
233245
```
234246
unzip assisted-log-enabler-for-aws-main.zip
235247
cd assisted-log-enabler-for-aws-main
236248
```
237-
16. Run the following command to run the Assisted Log Enabler in multi account mode, for the AWS service or services you want to check for:
249+
23. Run the following command to run the Assisted Log Enabler in multi account mode, for the AWS service or services you want to check for:
238250
```
239251
# For all services:
240252
python3 assisted_log_enabler.py --mode multi_account --all
@@ -281,6 +293,9 @@ NEW! A cleanup mode is available within the Assisted Log Enabler for AWS (curren
281293
python3 assisted_log_enabler.py --mode cleanup --single_r53querylogs
282294
```
283295

296+
## Additional Tools
297+
For analysing logs created by Assisted Log Enabler for AWS, consider taking a look at the AWS Security Analytics Bootstrap, a tool that provides an Amazon Athena analysis environment that's quick to deploy, ready to use, and easy to maintain. [Link](https://github.com/awslabs/aws-security-analytics-bootstrap)
298+
284299

285300
## Costs
286301
For answers to cost-related questions involved with this solution, refer to the following links:
@@ -292,7 +307,7 @@ For answers to cost-related questions involved with this solution, refer to the
292307

293308

294309
## Feedback
295-
Please use the Issues section to submit any feedback, such as features or recommendations, as well as any bugs that are encountered.
310+
Please use the [Issues](https://github.com/awslabs/assisted-log-enabler-for-aws/issues) section to submit any feedback, such as features or recommendations, as well as any bugs that are encountered.
296311

297312

298313
## Security

subfunctions/ALE_multi_account.py

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import datetime
1313
import argparse
1414
import csv
15+
import string
16+
import random
1517
from botocore.exceptions import ClientError
1618
from datetime import timezone
1719

@@ -32,6 +34,14 @@
3234
region_list = ['af-south-1', 'ap-east-1', 'ap-south-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-northeast-3', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-north-1', 'eu-south-1', 'me-south-1', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2']
3335

3436

37+
# 0. Define random string for S3 Bucket Name
38+
def random_string_generator():
39+
lower_letters = string.ascii_lowercase
40+
numbers = string.digits
41+
unique_end = (''.join(random.choice(lower_letters + numbers) for char in range(6)))
42+
return unique_end
43+
44+
3545
# 1. Obtain the AWS Accounts inside of AWS Organizations
3646
def org_account_grab():
3747
"""Function to list accounts inside of AWS Organizations"""
@@ -59,26 +69,26 @@ def get_account_number():
5969

6070

6171
# 3. Create a Bucket and Lifecycle Policy
62-
def create_bucket(organization_id, account_number):
72+
def create_bucket(organization_id, account_number, unique_end):
6373
"""Function to create the bucket for storing logs"""
6474
try:
6575
logging.info("Creating bucket in %s" % account_number)
6676
logging.info("CreateBucket API Call")
6777
if region == 'us-east-1':
6878
logging_bucket_dict = s3.create_bucket(
69-
Bucket="aws-log-collection-" + account_number + "-" + region
79+
Bucket="aws-log-collection-" + account_number + "-" + region + "-" + unique_end
7080
)
7181
else:
7282
logging_bucket_dict = s3.create_bucket(
73-
Bucket="aws-log-collection-" + account_number + "-" + region,
83+
Bucket="aws-log-collection-" + account_number + "-" + region + "-" + unique_end,
7484
CreateBucketConfiguration={
7585
'LocationConstraint': region
7686
}
7787
)
7888
logging.info("Bucket Created.")
7989
logging.info("Setting lifecycle policy.")
8090
lifecycle_policy = s3.put_bucket_lifecycle_configuration(
81-
Bucket="aws-log-collection-" + account_number + "-" + region,
91+
Bucket="aws-log-collection-" + account_number + "-" + region + "-" + unique_end,
8292
LifecycleConfiguration={
8393
'Rules': [
8494
{
@@ -100,22 +110,22 @@ def create_bucket(organization_id, account_number):
100110
)
101111
logging.info("Lifecycle Policy successfully set.")
102112
create_ct_path = s3.put_object(
103-
Bucket="aws-log-collection-" + account_number + "-" + region,
113+
Bucket="aws-log-collection-" + account_number + "-" + region + "-" + unique_end,
104114
Key='cloudtrail/AWSLogs/' + account_number + '/')
105115
create_ct_path_vpc = s3.put_object(
106-
Bucket="aws-log-collection-" + account_number + "-" + region,
116+
Bucket="aws-log-collection-" + account_number + "-" + region + "-" + unique_end,
107117
Key='vpcflowlogs/')
108118
create_ct_path_r53 = s3.put_object(
109-
Bucket="aws-log-collection-" + account_number + "-" + region,
119+
Bucket="aws-log-collection-" + account_number + "-" + region + "-" + unique_end,
110120
Key='r53querylogs/')
111121
bucket_policy = s3.put_bucket_policy(
112-
Bucket="aws-log-collection-" + account_number + "-" + region,
113-
Policy='{"Version": "2012-10-17", "Statement": [{"Sid": "AWSCloudTrailAclCheck20150319","Effect": "Allow","Principal": {"Service": "cloudtrail.amazonaws.com"},"Action": "s3:GetBucketAcl","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '"},{"Sid": "AWSCloudTrailWrite20150319","Effect": "Allow","Principal": {"Service": "cloudtrail.amazonaws.com"},"Action": "s3:PutObject","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '/cloudtrail/AWSLogs/' + account_number + '/*","Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}},{"Sid": "AWSLogDeliveryAclCheck","Effect": "Allow","Principal": {"Service": "delivery.logs.amazonaws.com"},"Action": "s3:GetBucketAcl","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '"},{"Sid": "AWSLogDeliveryWriteVPC","Effect": "Allow","Principal": {"Service": "delivery.logs.amazonaws.com"},"Action": "s3:PutObject","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '/vpcflowlogs/*","Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}},{"Sid": "AWSLogDeliveryWriteR53","Effect": "Allow","Principal": {"Service": "delivery.logs.amazonaws.com"},"Action": "s3:PutObject","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '/r53querylogs/*","Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}}]}'
122+
Bucket="aws-log-collection-" + account_number + "-" + region + "-" + unique_end,
123+
Policy='{"Version": "2012-10-17", "Statement": [{"Sid": "AWSCloudTrailAclCheck20150319","Effect": "Allow","Principal": {"Service": "cloudtrail.amazonaws.com"},"Action": "s3:GetBucketAcl","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '-' + unique_end + '"},{"Sid": "AWSCloudTrailWrite20150319","Effect": "Allow","Principal": {"Service": "cloudtrail.amazonaws.com"},"Action": "s3:PutObject","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '-' + unique_end + '/cloudtrail/AWSLogs/' + account_number + '/*","Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}},{"Sid": "AWSLogDeliveryAclCheck","Effect": "Allow","Principal": {"Service": "delivery.logs.amazonaws.com"},"Action": "s3:GetBucketAcl","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '-' + unique_end + '"},{"Sid": "AWSLogDeliveryWriteVPC","Effect": "Allow","Principal": {"Service": "delivery.logs.amazonaws.com"},"Action": "s3:PutObject","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '-' + unique_end + '/vpcflowlogs/*","Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}},{"Sid": "AWSLogDeliveryWriteR53","Effect": "Allow","Principal": {"Service": "delivery.logs.amazonaws.com"},"Action": "s3:PutObject","Resource": "arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '-' + unique_end + '/r53querylogs/*","Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}}]}'
114124
)
115125
logging.info("Setting the S3 bucket Public Access to Blocked")
116126
logging.info("PutPublicAccessBlock API Call")
117127
bucket_private = s3.put_public_access_block(
118-
Bucket="aws-log-collection-" + account_number + "-" + region,
128+
Bucket="aws-log-collection-" + account_number + "-" + region + "-" + unique_end,
119129
PublicAccessBlockConfiguration={
120130
'BlockPublicAcls': True,
121131
'IgnorePublicAcls': True,
@@ -129,7 +139,7 @@ def create_bucket(organization_id, account_number):
129139

130140

131141
# 4. Find VPCs and turn flow logs on if not on already.
132-
def flow_log_activator(account_number, OrgAccountIdList, region_list):
142+
def flow_log_activator(account_number, OrgAccountIdList, region_list, unique_end):
133143
"""Function to define the list of VPCs without logging turned on"""
134144
logging.info("Creating a list of VPCs without Flow Logs on.")
135145
for org_account in OrgAccountIdList:
@@ -176,7 +186,7 @@ def flow_log_activator(account_number, OrgAccountIdList, region_list):
176186
ResourceType='VPC',
177187
TrafficType='ALL',
178188
LogDestinationType='s3',
179-
LogDestination='arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '/vpcflowlogs',
189+
LogDestination='arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '-' + unique_end + '/vpcflowlogs',
180190
LogFormat='${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status} ${vpc-id} ${type} ${tcp-flags} ${subnet-id} ${sublocation-type} ${sublocation-id} ${region} ${pkt-srcaddr} ${pkt-dstaddr} ${instance-id} ${az-id} ${pkt-src-aws-service} ${pkt-dst-aws-service} ${flow-direction} ${traffic-path}'
181191
)
182192
logging.info("VPC Flow Logs are turned on for account " + org_account + ".")
@@ -245,7 +255,7 @@ def eks_logging(region_list, OrgAccountIdList):
245255

246256

247257
# 6. Turn on Route 53 Query Logging.
248-
def route_53_query_logs(region_list, account_number, OrgAccountIdList):
258+
def route_53_query_logs(region_list, account_number, OrgAccountIdList, unique_end):
249259
"""Function to turn on Route 53 Query Logs for VPCs"""
250260
for org_account in OrgAccountIdList:
251261
for aws_region in region_list:
@@ -294,7 +304,7 @@ def route_53_query_logs(region_list, account_number, OrgAccountIdList):
294304
logging.info("CreateResolverQueryLogConfig API Call")
295305
create_query_log = route53resolver_ma.create_resolver_query_log_config(
296306
Name='Assisted_Log_Enabler_Query_Logs_' + aws_region,
297-
DestinationArn='arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '/r53querylogs',
307+
DestinationArn='arn:aws:s3:::aws-log-collection-' + account_number + '-' + region + '-' + unique_end + '/r53querylogs',
298308
CreatorRequestId=timestamp_date_string,
299309
Tags=[
300310
{
@@ -325,30 +335,33 @@ def run_eks():
325335

326336
def run_vpc_flow_logs():
327337
"""Function that runs the defined VPC Flow Log logging code"""
338+
unique_end = random_string_generator()
328339
account_number = get_account_number()
329340
OrgAccountIdList, organization_id = org_account_grab()
330-
create_bucket(organization_id, account_number)
331-
flow_log_activator(account_number, OrgAccountIdList, region_list)
341+
create_bucket(organization_id, account_number, unique_end)
342+
flow_log_activator(account_number, OrgAccountIdList, region_list, unique_end)
332343
logging.info("This is the end of the script. Please feel free to validate that logs have been turned on.")
333344

334345

335346
def run_r53_query_logs():
336347
"""Function that runs the defined R53 Query Logging code"""
348+
unique_end = random_string_generator()
337349
account_number = get_account_number()
338350
OrgAccountIdList, organization_id = org_account_grab()
339-
create_bucket(organization_id, account_number)
340-
route_53_query_logs(region_list, account_number, OrgAccountIdList)
351+
create_bucket(organization_id, account_number, unique_end)
352+
route_53_query_logs(region_list, account_number, OrgAccountIdList, unique_end)
341353
logging.info("This is the end of the script. Please feel free to validate that logs have been turned on.")
342354

343355

344356
def lambda_handler(event, context):
345357
"""Function that runs all of the previously defined functions"""
358+
unique_end = random_string_generator()
346359
account_number = get_account_number()
347360
OrgAccountIdList, organization_id = org_account_grab()
348-
create_bucket(organization_id, account_number)
349-
flow_log_activator(account_number, OrgAccountIdList, region_list)
361+
create_bucket(organization_id, account_number, unique_end)
362+
flow_log_activator(account_number, OrgAccountIdList, region_list, unique_end)
350363
eks_logging(region_list, OrgAccountIdList)
351-
route_53_query_logs(region_list, account_number, OrgAccountIdList)
364+
route_53_query_logs(region_list, account_number, OrgAccountIdList, unique_end)
352365
logging.info("This is the end of the script. Please feel free to validate that logs have been turned on.")
353366

354367

0 commit comments

Comments
 (0)