Skip to content

Commit 8cfa35d

Browse files
committed
update to v1.5.0
1 parent 8dbc803 commit 8cfa35d

File tree

180 files changed

+21011
-7613
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

180 files changed

+21011
-7613
lines changed

.DS_Store

6 KB
Binary file not shown.

CHANGELOG.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,20 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [1.5.0] - 2022-05-31
8+
9+
### Added
10+
- New remediations - see Implementation Guide
11+
12+
### Changed
13+
- Improved cross-region remediation using resource region from Resources[0].Id
14+
- Added custom resource provider for SSM documents to allow in-place stack upgrades
15+
716
## [1.4.2] - 2022-01-14
817

918
### Changed
1019
- Fix to correct the generator id pattern for CIS 1.2.0 Ruleset.
1120

12-
1321
## [1.4.1] - 2022-01-05
1422

1523
### Changed
@@ -52,14 +60,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5260
- New PCI-DSS v3.2.1 Playbook support for 17 controls (see IG for details)
5361
- Library of remediation SSM Automation runbooks
5462
- NEWPLAYBOOK as a template for custom playbook creation
55-
63+
5664
### Changed
5765
- Updated to CDK v1.117.0
5866
- Reduced duplicate code
5967
- Updated CIS playbook to Orchestrator architecture
6068
- Single Orchestrator deployment to enable multi-standard remediation with a single click
6169
- Custom Actions now consolidated to one: "Remediate with SHARR"
62-
70+
6371
### Removed
6472
- AWS Service Catalog for Playbook deployment
6573

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ Detailed instructions for creating a new automated remediation in an existing Pl
7474

7575
### Prerequisites for Customization
7676

77-
- a Linux client with the AWS CLI v2 installed and python 3.7+, AWS CDK 1.114.0+
77+
- a Linux client with the following software
78+
- AWS CLI v2
79+
- Python 3.7+ with pip
80+
- AWS CDK 1.155.0+
81+
- Node.js with npm
7882
- source code downloaded from GitHub
7983
- two S3 buckets (minimum): 1 global and 1 for each region where you will deploy
8084
- An Amazon S3 Bucket for solution templates - accessed globally via https.
@@ -179,6 +183,10 @@ build-s3-dist.sh -b <bucketname> -v <version>
179183

180184
#### Run Unit Tests
181185

186+
Some Python unit tests execute AWS API calls. The calls that create, read, or modify resources are stubbed, but some
187+
calls to APIs that do not require any permissions execute against the real AWS APIs (e.g. STS GetCallerIdentity). The
188+
recommended way to run the unit tests is to configure your credentials for a no-access console role.
189+
182190
```bash
183191
cd ./deployment
184192
chmod +x ./run-unit-tests.sh

deployment/build-s3-dist.sh

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818

1919
# Important: CDK global version number
2020
# This controls the CDK and AWS Solutions Constructs version. Solutions
21-
# Constructs versions map 1:1 to CDK versions. When setting this value,
21+
# Constructs versions map 1:1 to CDK versions. When setting this value,
2222
# choose the latest AWS Solutions Constructs version.
23-
required_cdk_version=1.132.0
23+
required_cdk_version=1.155.0
2424

2525
# Get reference for all important folders
2626
template_dir="$PWD"
@@ -74,25 +74,25 @@ do
7474
b ) bucket=${OPTARG};;
7575
v ) version=${OPTARG};;
7676
t ) devtest=1;;
77-
c)
77+
c)
7878
clean
7979
exit 0
8080
;;
8181
*)
8282
echo "Usage: $0 -b <bucket> [-v <version>] [-t]"
83-
echo "Version must be provided via a parameter or ../version.txt. Others are optional."
83+
echo "Version must be provided via a parameter or ../version.txt. Others are optional."
8484
echo "-t indicates this is a pre-prod build and instructs the build to use a non-prod Solution ID, DEV-SOxxxx"
8585
echo "Production example: ./build-s3-dist.sh -b solutions -v v1.0.0"
86-
echo "Dev example: ./build-s3-dist.sh -b solutions -v v1.0.0 -t"
87-
exit 1
86+
echo "Dev example: ./build-s3-dist.sh -b solutions -v v1.0.0 -t"
87+
exit 1
8888
;;
8989
esac
9090
done
9191

9292
#------------------------------------------------------------------------------
9393
# DISABLE OVERRIDE WARNINGS
9494
#------------------------------------------------------------------------------
95-
# Use with care: disables the warning for overridden properties on
95+
# Use with care: disables the warning for overridden properties on
9696
# AWS Solutions Constructs
9797
export overrideWarningsEnabled=false
9898

@@ -127,7 +127,7 @@ echo "export DIST_VERSION=$version" >> ./setenv.sh
127127
#
128128
# It takes precedence over the command line (oddly backwards, but to prevent
129129
# errors)
130-
#
130+
#
131131
# Ex:
132132
# #!/bin/bash
133133
# SOLUTION_ID='SO0111'
@@ -162,7 +162,7 @@ fi
162162
if [[ -z "$SOLUTION_TRADEMARKEDNAME" ]]; then
163163
echo "SOLUTION_TRADEMARKEDNAME is missing from ../solution_env.sh"
164164
exit 1
165-
else
165+
else
166166
export SOLUTION_TRADEMARKEDNAME
167167
echo "export DIST_SOLUTION_NAME=$SOLUTION_TRADEMARKEDNAME" >> ./setenv.sh
168168
fi
@@ -196,7 +196,7 @@ export PATH=$(npm bin):$PATH
196196
# Check cdk version
197197
cdkver=`cdk --version | grep -Eo '^[0-9]{1,2}\.[0-9]+\.[0-9]+'`
198198
echo CDK version $cdkver
199-
if [[ $cdkver != $required_cdk_version ]]; then
199+
if [[ $cdkver != $required_cdk_version ]]; then
200200
echo Required CDK version is $required_cdk_version, found $cdkver
201201
exit 255
202202
fi
@@ -215,10 +215,19 @@ find . -name package-lock.json | while read file;do rm $file; done
215215

216216
mkdir -p $temp_work_dir/source/solution_deploy/lambdalayer/python
217217
cp ${template_dir}/${source_dir}/LambdaLayers/*.py $temp_work_dir/source/solution_deploy/lambdalayer/python
218-
pip install -r $template_dir/requirements.txt -t $temp_work_dir/source/solution_deploy/lambdalayer/python
218+
do_cmd pip install -r $template_dir/requirements.txt -t $temp_work_dir/source/solution_deploy/lambdalayer/python
219219
cd $temp_work_dir/source/solution_deploy/lambdalayer
220220
zip --recurse-paths ${build_dist_dir}/lambda/layer.zip python
221221

222+
echo "------------------------------------------------------------------------------"
223+
echo "[Pack] Member Stack Lambda Layer (used by custom resources)"
224+
echo "------------------------------------------------------------------------------"
225+
do_cmd mkdir -p $temp_work_dir/source/solution_deploy/memberlambdalayer/python
226+
do_cmd cp ${template_dir}/${source_dir}/LambdaLayers/cfnresponse.py $temp_work_dir/source/solution_deploy/memberlambdalayer/python
227+
do_cmd cp ${template_dir}/${source_dir}/LambdaLayers/logger.py $temp_work_dir/source/solution_deploy/memberlambdalayer/python
228+
do_cmd cd $temp_work_dir/source/solution_deploy/memberlambdalayer
229+
do_cmd zip --recurse-paths ${build_dist_dir}/lambda/memberLayer.zip python
230+
222231
echo "------------------------------------------------------------------------------"
223232
echo "[Pack] Custom Action Lambda"
224233
echo "------------------------------------------------------------------------------"
@@ -229,12 +238,18 @@ zip ${build_dist_dir}/lambda/createCustomAction.py.zip createCustomAction.py
229238
# These are not packaged with the Lambda
230239
do_cmd cp ../../LambdaLayers/*.py .
231240

241+
echo "------------------------------------------------------------------------------"
242+
echo "[Pack] Updatable Runbook Provider Lambda"
243+
echo "------------------------------------------------------------------------------"
244+
do_cmd cd $temp_work_dir/source/solution_deploy/source
245+
do_cmd zip ${build_dist_dir}/lambda/updatableRunbookProvider.py.zip updatableRunbookProvider.py
246+
232247
echo "------------------------------------------------------------------------------"
233248
echo "[Pack] Orchestrator Lambdas"
234249
echo "------------------------------------------------------------------------------"
235250
# cd $template_dir
236251
cd $temp_work_dir/source/Orchestrator
237-
ls | while read file; do
252+
ls | while read file; do
238253
if [ ! -d $file ]; then
239254
zip ${build_dist_dir}/lambda/${file}.zip ${file}
240255
fi
@@ -247,7 +262,7 @@ echo "--------------------------------------------------------------------------
247262
echo "[Create] Playbooks"
248263
echo "------------------------------------------------------------------------------"
249264
for playbook in `ls ${template_dir}/${source_dir}/playbooks`; do
250-
if [ $playbook == 'NEWPLAYBOOK' ] || [ $playbook == '.coverage' ]; then
265+
if [ $playbook == 'NEWPLAYBOOK' ] || [ $playbook == '.coverage' ] || [ $playbook == 'common' ]; then
251266
continue
252267
fi
253268
echo Create $playbook playbook

deployment/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
requests>=2.22.0
1+
requests>=2.25.0

deployment/run-unit-tests.sh

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,17 @@ echo "--------------------------------------------------------------------------
115115
run_pytest "${source_dir}/remediation_runbooks/scripts" "RemediationRunbooks"
116116

117117
echo "------------------------------------------------------------------------------"
118-
echo "[Test] Python Scripts for Playbook Scripts"
118+
echo "[Test] Python Scripts for Playbook common scripts"
119+
echo "------------------------------------------------------------------------------"
120+
run_pytest "${source_dir}/playbooks/common" "PlaybookCommon"
121+
122+
echo "------------------------------------------------------------------------------"
123+
echo "[Test] Python Scripts for Playbooks"
119124
echo "------------------------------------------------------------------------------"
120125
for playbook in `ls ${source_dir}/playbooks`; do
121-
# if [ $playbook == 'NEWPLAYBOOK' ]; then
122-
# continue
123-
# fi
124-
run_pytest "${source_dir}/playbooks/${playbook}/ssmdocs/scripts" "Playbook${playbook}"
126+
if [ -d ${source_dir}/playbooks/${playbook}/ssmdocs/scripts/tests ]; then
127+
run_pytest "${source_dir}/playbooks/${playbook}/ssmdocs/scripts" "Playbook${playbook}"
128+
fi
125129
done
126130

127131
# The pytest --cov with its parameters and .coveragerc generates a xml cov-report with `coverage/sources` list

deployment/testing_requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ pytest>=4.2.1
33
pytest-cov
44
pytest-env
55
bandit
6+
boto3==1.23.9
7+
requests==2.27.1

source/.DS_Store

6 KB
Binary file not shown.

source/LambdaLayers/.DS_Store

6 KB
Binary file not shown.

source/LambdaLayers/cfnresponse.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: MIT-0
3+
4+
from __future__ import print_function
5+
import urllib3
6+
import json
7+
8+
SUCCESS = "SUCCESS"
9+
FAILED = "FAILED"
10+
11+
http = urllib3.PoolManager()
12+
13+
def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None):
14+
responseUrl = event['ResponseURL']
15+
16+
print(responseUrl)
17+
18+
responseBody = {
19+
'Status' : responseStatus,
20+
'Reason' : reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name),
21+
'PhysicalResourceId' : physicalResourceId or context.log_stream_name,
22+
'StackId' : event['StackId'],
23+
'RequestId' : event['RequestId'],
24+
'LogicalResourceId' : event['LogicalResourceId'],
25+
'NoEcho' : noEcho,
26+
'Data' : responseData
27+
}
28+
29+
json_responseBody = json.dumps(responseBody)
30+
31+
print("Response body:")
32+
print(json_responseBody)
33+
34+
headers = {
35+
'content-type' : '',
36+
'content-length' : str(len(json_responseBody))
37+
}
38+
39+
try:
40+
response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
41+
print("Status code:", response.status)
42+
43+
except Exception as e:
44+
print("send(..) failed executing http.request(..):", e)

0 commit comments

Comments
 (0)