diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ac7f0ec --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,21 @@ +# Change Log +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [5.3.2] - 2021-04 +### Added +- Added account ID to lambda resource policy +- Added flow logs to VPC +- Added access log for S3 bucket +- Added requests library for HTTP calls + +### Changed +- Updated AMIs for all the regions +- Updated build scripts +- Updated python runtime for lambda functions +- Updated deletion policies for VPC resources +- Updated the license +- Removed the vendored version for requests +- Removed older buildspec files diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1cebe21..927873a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ information to effectively respond to your bug report or contribution. We welcome you to use the GitHub issue tracker to report bugs or suggest features. -When filing an issue, please check [existing open](https://github.com/awslabs/iot-device-simulator/issues), or [recently closed](https://github.com/awslabs/iot-device-simulator/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already +When filing an issue, please check [existing open](https://github.com/awslabs/workspaces-cost-optimizer/issues), or [recently closed](https://github.com/awslabs/workspaces-cost-optimizer/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: * A reproducible test case or series of steps @@ -41,7 +41,7 @@ GitHub provides additional document on [forking a repository](https://help.githu ## Finding contributions to work on -Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/awslabs/iot-device-simulator/labels/help%20wanted) issues is a great place to start. +Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/awslabs/workspaces-cost-optimizer/labels/help%20wanted) issues is a great place to start. ## Code of Conduct @@ -56,6 +56,6 @@ If you discover a potential security issue in this project we ask that you notif ## Licensing -See the [LICENSE](https://github.com/awslabs/iot-device-simulator/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. +See the [LICENSE](https://github.com/awslabs/workspaces-cost-optimizer/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. diff --git a/LICENSE.txt b/LICENSE.txt index 0384f08..19dc35b 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,27 +1,175 @@ -Amazon Software License -This Amazon Software License (“License”) governs your use, reproduction, and distribution of the accompanying software as specified below. -1. Definitions -“Licensor” means any person or entity that distributes its Work. - -“Software” means the original work of authorship made available under this License. - -“Work” means the Software and any additions to or derivative works of the Software that are made available under this License. - -The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the meaning as provided under U.S. copyright law; provided, however, that for the purposes of this License, derivative works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work. - -Works, including the Software, are “made available” under this License by including in or with the Work either (a) a copyright notice referencing the applicability of this License to the Work, or (b) a copy of this License. -2. License Grants -2.1 Copyright Grant. Subject to the terms and conditions of this License, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free, copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense and distribute its Work and any resulting derivative works in any form. -2.2 Patent Grant. Subject to the terms and conditions of this License, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free patent license to make, have made, use, sell, offer for sale, import, and otherwise transfer its Work, in whole or in part. The foregoing license applies only to the patent claims licensable by Licensor that would be infringed by Licensor’s Work (or portion thereof) individually and excluding any combinations with any other materials or technology. -3. Limitations -3.1 Redistribution. You may reproduce or distribute the Work only if (a) you do so under this License, (b) you include a complete copy of this License with your distribution, and (c) you retain without modification any copyright, patent, trademark, or attribution notices that are present in the Work. -3.2 Derivative Works. You may specify that additional or different terms apply to the use, reproduction, and distribution of your derivative works of the Work (“Your Terms”) only if (a) Your Terms provide that the use limitation in Section 3.3 applies to your derivative works, and (b) you identify the specific derivative works that are subject to Your Terms. Notwithstanding Your Terms, this License (including the redistribution requirements in Section 3.1) will continue to apply to the Work itself. -3.3 Use Limitation. The Work and any derivative works thereof only may be used or intended for use with the web services, computing platforms or applications provided by Amazon.com, Inc. or its affiliates, including Amazon Web Services, Inc. -3.4 Patent Claims. If you bring or threaten to bring a patent claim against any Licensor (including any claim, cross-claim or counterclaim in a lawsuit) to enforce any patents that you allege are infringed by any Work, then your rights under this License from such Licensor (including the grants in Sections 2.1 and 2.2) will terminate immediately. -3.5 Trademarks. This License does not grant any rights to use any Licensor’s or its affiliates’ names, logos, or trademarks, except as necessary to reproduce the notices described in this License. -3.6 Termination. If you violate any term of this License, then your rights under this License (including the grants in Sections 2.1 and 2.2) will terminate immediately. -4. Disclaimer of Warranty. -THE WORK IS PROVIDED “AS IS” WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OR CONDITIONS OF M ERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT. YOU BEAR THE RISK OF UNDERTAKING ANY ACTIVITIES UNDER THIS LICENSE. SOME STATES’ CONSUMER LAWS DO NOT ALLOW EXCLUSION OF AN IMPLIED WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO YOU. -5. Limitation of Liability. -EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO LEGAL THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE SHALL ANY LICENSOR BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATED TO THIS LICENSE, THE USE OR INABILITY TO USE THE WORK (INCLUDING BUT NOT LIMITED TO LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS OR DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY OTHER COMM ERCIAL DAMAGES OR LOSSES), EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -Effective Date – April 18, 2008 © 2008 Amazon.com, Inc. or its affiliates. All rights reserved. \ No newline at end of file + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. \ No newline at end of file diff --git a/NOTICE.txt b/NOTICE.txt index 6ac3061..9edb4be 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1808,3 +1808,10 @@ Agreement. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +********************** +THIRD PARTY COMPONENTS +********************** +This software includes third party software subject to the following copyrights: + +requests under the Apache Software License diff --git a/README.md b/README.md index 4659424..627bd75 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,16 @@ Located in deployment/dist *** -Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. -Licensed under the Amazon Software License (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at - http://aws.amazon.com/asl/ + http://www.apache.org/licenses/LICENSE-2.0 -or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions and limitations under the License. +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/deployment/build-s3-dist.sh b/deployment/build-s3-dist.sh index 7c7c235..27d6daf 100755 --- a/deployment/build-s3-dist.sh +++ b/deployment/build-s3-dist.sh @@ -1,105 +1,105 @@ #!/bin/bash - # This assumes all of the OS-level configuration has been completed and git repo has already been cloned -#sudo apt-get update -#sudo apt-get install zip -y -#sudo pip install --upgrade pip -#pip install --upgrade setuptools -#pip install --upgrade virtualenv - +# # This script should be run from the repo's deployment directory # cd deployment -# ./build-s3-dist.sh source-bucket-base-name version -# source-bucket-base-name should be the base name for the S3 bucket location where the template will source the Lambda code from. -# The template will append '-[region_name]' to this bucket name. -# For example: ./build-s3-dist.sh solutions v1.0.0 -# The template will then expect the source code to be located in the solutions-[region_name] bucket - +# ./build-s3-dist.sh source-bucket-base-name trademarked-solution-name version-code +# +# Paramenters: +# - template-bucket: Name for the S3 bucket location where the templates are found +# - source-bucket-base-name: Name for the S3 bucket location where the Lambda source +# code is deployed. The template will append '-[region_name]' to this bucket name. +# - trademarked-solution-name: name of the solution for consistency +# - version-code: version of the package +# +# For example: ./build-s3-dist.sh template-bucket source-bucket-base-name my-solution v3.0 +# The template will then expect the source code to be located in the solutions-[region_name] bucket +# # Check to see if input has been provided: -if [ -z "$1" ] || [ -z "$2" ]; then - echo "Please provide the base source bucket name and version where the lambda code will eventually reside." - echo "For example: ./build-s3-dist.sh solutions v1.0.0" +if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then + echo "Please provide the base template-bucket, source-bucket-base-name, trademark-approved-solution-name and version" + echo "For example: ./build-s3-dist.sh solutions solutions-code trademarked-solution-name v3.0" exit 1 fi -# Build source -echo "Staring to build distribution" -echo "export deployment_dir=`pwd`" -export deployment_dir=`pwd` -echo "mkdir -p dist" -mkdir -p dist -echo "cp -f *.template dist" -cp -f *.template dist -echo "Updating code source bucket in templates with $1" -export replace="s/%%BUCKET_NAME%%/$1/g" -echo "sed -i -e $replace dist/transit-vpc-primary-account-existing-vpc.template" -sed -i -e $replace dist/transit-vpc-primary-account-existing-vpc.template -echo "sed -i -e $replace dist/transit-vpc-primary-account-marketplace.template" -sed -i -e $replace dist/transit-vpc-primary-account-marketplace.template -echo "sed -i -e $replace dist/transit-vpc-primary-account.template" -sed -i -e $replace dist/transit-vpc-primary-account.template -echo "sed -i -e $replace dist/transit-vpc-second-account.template" -sed -i -e $replace dist/transit-vpc-second-account.template - -export replace="s/%%VERSION%%/$2/g" -echo "sed -i -e $replace dist/transit-vpc-primary-account-existing-vpc.template" -sed -i -e $replace dist/transit-vpc-primary-account-existing-vpc.template -echo "sed -i -e $replace dist/transit-vpc-primary-account-marketplace.template" -sed -i -e $replace dist/transit-vpc-primary-account-marketplace.template -echo "sed -i -e $replace dist/transit-vpc-primary-account.template" -sed -i -e $replace dist/transit-vpc-primary-account.template -echo "sed -i -e $replace dist/transit-vpc-second-account.template" -sed -i -e $replace dist/transit-vpc-second-account.template - -cd $deployment_dir/../source/transit-vpc-poller -echo "Creating transit-vpc-poller ZIP file" -zip -q -r9 $deployment_dir/dist/transit-vpc-poller.zip * - -echo "Building transit-vpc-solution-helper ZIP file" -cd $deployment_dir/dist -pwd -echo "virtualenv env" -virtualenv env -echo "source env/bin/activate" -source env/bin/activate -echo "pip install $deployment_dir/../source/transit-vpc-solution-helper/. --target=$deployment_dir/dist/env/lib/python3.7/site-packages/ --upgrade --upgrade-strategy only-if-needed" -pip install $deployment_dir/../source/transit-vpc-solution-helper/. --target=$deployment_dir/dist/env/lib/python3.7/site-packages/ --upgrade --upgrade-strategy only-if-needed -# fail build if pip install fails -instl_status=$? -if [ ${instl_status} != '0' ]; then - echo "pip install solution helper status: ${instl_status}" - exit ${instl_status} -fi -cd $deployment_dir/dist/env/lib/python3.7/site-packages/ -zip -r9 $deployment_dir/dist/transit-vpc-solution-helper.zip . -cd $deployment_dir/dist -zip -q -d transit-vpc-solution-helper.zip pip* -zip -q -d transit-vpc-solution-helper.zip easy* -echo "Clean up build material in $VIRTUAL_ENV" -rm -rf $VIRTUAL_ENV - -echo "Building transit-vpc-push-cisco-config ZIP file" -cd $deployment_dir/dist +echo "template bucket = $1" +echo "source bucket = $2" +echo "solution = $3" +echo "version = $4" + +# Get reference for all important folders +template_dir="$PWD" +source_dir="$template_dir/../source" + +# There are now TWO dist directories +template_dist_dir="$template_dir/global-s3-assets" +build_dist_dir="$template_dir/regional-s3-assets" + +echo "------------------------------------------------------------------------------" +echo "[Init] Clean old dist folders" +echo "------------------------------------------------------------------------------" + +echo "rm -rf $template_dist_dir" +rm -rf $template_dist_dir +echo "mkdir -p $template_dist_dir" +mkdir -p $template_dist_dir + +echo "rm -rf $build_dist_dir" +rm -rf $build_dist_dir +echo "mkdir -p $build_dist_dir" +mkdir -p $build_dist_dir + +echo "find $source_dir -iname \"dist\" -type d -exec rm -r \"{}\" \; 2> /dev/null" +find "$source_dir" -iname "dist" -type d -exec rm -r "{}" \; 2> /dev/null +echo "find ../ -type f -name 'package-lock.json' -delete" +find "$source_dir" -type f -name 'package-lock.json' -delete +echo "find ../ -type f -name '.DS_Store' -delete" +find "$source_dir" -type f -name '.DS_Store' -delete +echo "find $source_dir -iname \"package\" -type d -exec rm -r \"{}\" \; 2> /dev/null" +find "$source_dir" -iname "package" -type d -exec rm -r "{}" \; 2> /dev/null + +echo "------------------------------------------------------------------------------" +echo "[Packing] Templates" +echo "------------------------------------------------------------------------------" + +SUB1="s/%TEMPLATE_OUTPUT_BUCKET%/$1/g" +SUB2="s/%DIST_OUTPUT_BUCKET%/$2/g" +SUB3="s/%SOLUTION_NAME%/$3/g" +SUB4="s/%VERSION%/$4/g" + +for FULLNAME in ./*.template +do + TEMPLATE=`basename $FULLNAME` + echo "Preparing $TEMPLATE" + sed -e $SUB1 -e $SUB2 -e $SUB3 -e $SUB4 $template_dir/$TEMPLATE > $template_dist_dir/$TEMPLATE +done + + +echo "------------------------------------------------------------------------------" +echo "[Packing] Transit VPC Poller" +echo "------------------------------------------------------------------------------" pwd -echo "virtualenv env" -virtualenv env -echo "source env/bin/activate" -source env/bin/activate -echo "pip install $deployment_dir/../source/transit-vpc-push-cisco-config/. --target=$deployment_dir/dist/env/lib/python3.7/site-packages/ --upgrade --upgrade-strategy only-if-needed" -pip install $deployment_dir/../source/transit-vpc-push-cisco-config/. --target=$deployment_dir/dist/env/lib/python3.7/site-packages/ --upgrade --upgrade-strategy only-if-needed -# TransitVPC-11 - 09/06/2018 - Allow build fail -# fail build if pip install fails -instl_status=$? -if [ ${instl_status} != '0' ]; then - echo "pip install cisco configurator status: ${instl_status}" - exit ${instl_status} -fi -cd $deployment_dir/dist/env/lib/python3.7/site-packages/ -zip -r9 $deployment_dir/dist/transit-vpc-push-cisco-config.zip . -cd $deployment_dir/dist -zip -q -d transit-vpc-push-cisco-config.zip pip* -zip -q -d transit-vpc-push-cisco-config.zip easy* -echo "Clean up build material in $VIRTUAL_ENV" -rm -rf $VIRTUAL_ENV - -echo "Completed building distribution" +cd "$source_dir"/transit-vpc-poller || exit 1 +zip -q -r9 "$build_dist_dir"/transit-vpc-poller.zip . + + +echo "------------------------------------------------------------------------------" +echo "[Packing] Transit VPC Push Cisco Config" +echo "------------------------------------------------------------------------------" +cd "$source_dir"/transit-vpc-push-cisco-config || exit 1 +pip3 install . --target ./package +cd "$source_dir"/transit-vpc-push-cisco-config/package || exit 1 +zip -q -r9 "$build_dist_dir"/transit-vpc-push-cisco-config.zip . +cd "$source_dir"/transit-vpc-push-cisco-config || exit 1 + + +echo "------------------------------------------------------------------------------" +echo "[Packing] Transit VPC Solution Helper" +echo "------------------------------------------------------------------------------" +cd "$source_dir"/transit-vpc-solution-helper || exit 1 + +pip3 install . --target ./package +cd "$source_dir"/transit-vpc-solution-helper/package || exit 1 +zip -q -r9 "$build_dist_dir"/transit-vpc-solution-helper.zip . +cd "$source_dir"/transit-vpc-solution-helper || exit 1 + diff --git a/deployment/transit-vpc-primary-account-existing-vpc.template b/deployment/transit-vpc-primary-account-existing-vpc.template index bbe7a46..da37feb 100644 --- a/deployment/transit-vpc-primary-account-existing-vpc.template +++ b/deployment/transit-vpc-primary-account-existing-vpc.template @@ -1,7 +1,7 @@ { "AWSTemplateFormatVersion" : "2010-09-09", - "Description" : "(SO0001) - Transit VPC: This template creates a dedicated transit VPC with Cisco CSRs for routing traffic. ***NOTE*** You must first subscribe to the appropriate Cisco CSR marketplace BYOL or License Included AMI from the AWS Marketplace before you launch this template. Version 5", + "Description" : "(SO0001) - Transit VPC: This template creates a dedicated transit VPC with Cisco CSRs for routing traffic. ***NOTE*** You must first subscribe to the appropriate Cisco CSR marketplace BYOL or License Included AMI from the AWS Marketplace before you launch this template. version %VERSION%", "Parameters" : { "KeyName" : { @@ -59,7 +59,7 @@ "Type" : "AWS::EC2::Subnet::Id" }, "CSRType" : { - "Description" : "Maximum network througput required for CSR instances.", + "Description" : "Maximum network throughput required for CSR instances.", "Type" : "String", "Default" : "2x500Mbps", "AllowedValues" : [ "2x500Mbps","2x1Gbps", "2x2Gbps", "2x4.5Gbps" ] @@ -128,32 +128,32 @@ "Mappings" : { "Function" : { "SolutionHelper" : { - "S3Bucket" : "%%BUCKET_NAME%%", - "S3Key" : "transit-vpc/%%VERSION%%/transit-vpc-solution-helper.zip", + "S3Bucket" : "%DIST_OUTPUT_BUCKET%", + "S3Key" : "%SOLUTION_NAME%/%VERSION%/transit-vpc-solution-helper.zip", "Name" : "transit-vpc-solution-helper", "Handler": "transit_vpc_solution_helper/transit-vpc-solution-helper.lambda_handler", "Description": "Transit VPC: This function is invoked for custom resources.", - "Runtime": "python3.7", + "Runtime": "python3.8", "Timeout": "60", "MemorySize": "128" }, "Configurator" : { - "S3Bucket" : "%%BUCKET_NAME%%", - "S3Key" : "transit-vpc/%%VERSION%%/transit-vpc-push-cisco-config.zip", + "S3Bucket" : "%DIST_OUTPUT_BUCKET%", + "S3Key" : "%SOLUTION_NAME%/%VERSION%/transit-vpc-push-cisco-config.zip", "Name" : "cisco-configurator", "Handler": "transit_vpc_push_cisco_config/lambda_function.lambda_handler", "Description": "Transit VPC: This function is invoked when a generic VPN configuration is placed in an S3 bucket - it converts the generic information into Cisco IOS specific commands and pushes the config to transit VPC routers.", - "Runtime": "python3.7", + "Runtime": "python3.8", "Timeout": "300", "MemorySize": "128" }, "Poller" : { - "S3Bucket" : "%%BUCKET_NAME%%", - "S3Key" : "transit-vpc/%%VERSION%%/transit-vpc-poller.zip", + "S3Bucket" : "%DIST_OUTPUT_BUCKET%", + "S3Key" : "%SOLUTION_NAME%/%VERSION%/transit-vpc-poller.zip", "Name" : "vgw-poller", "Handler": "transit-vpc-poller.lambda_handler", "Description": "Transit VPC: Poller function responsible for identifying specifically tagged VGWs and creating VPN connections to transit VPC.", - "Runtime": "python3.7", + "Runtime": "python3.8", "Timeout": "120", "MemorySize": "128" }, @@ -165,21 +165,21 @@ } }, "CiscoCsrAMI" : { - "ap-south-1" : { "BYOL": "ami-0126515024e181b2e", "LicenseIncluded": "ami-012e2d5a7048afe32" }, - "eu-west-3" : { "BYOL": "ami-030690944026827fc", "LicenseIncluded": "ami-028e6b1defb1f3071" }, - "eu-west-2" : { "BYOL": "ami-008715176303d298e", "LicenseIncluded": "ami-04897b16faacdf48f" }, - "eu-west-1" : { "BYOL": "ami-028ff7f30065ad8b3", "LicenseIncluded": "ami-02884305a2b03b67b" }, - "ap-northeast-2": { "BYOL": "ami-0ce275bb065baac48", "LicenseIncluded": "ami-0dd7ffc338c5cff83" }, - "ap-northeast-1": { "BYOL": "ami-09b350fd64ff59865", "LicenseIncluded": "ami-0f3f43158fe8c96fc" }, - "sa-east-1" : { "BYOL": "ami-073b915fb28bbfde0", "LicenseIncluded": "ami-04827a919fc29f946" }, - "ca-central-1" : { "BYOL": "ami-0705ab01e69f78310", "LicenseIncluded": "ami-0bdc99b952d2b636a" }, - "ap-southeast-1": { "BYOL": "ami-0544121f2f619b39c", "LicenseIncluded": "ami-0d00def253ffc9ffc" }, - "ap-southeast-2": { "BYOL": "ami-0162e0ac136ed0666", "LicenseIncluded": "ami-009555db80b895499" }, - "eu-central-1" : { "BYOL": "ami-04f69c92dcce31453", "LicenseIncluded": "ami-0026dc643b0d77fc5" }, - "us-east-2" : { "BYOL": "ami-07f8094154b663213", "LicenseIncluded": "ami-00e56dab70688b964" }, - "us-east-1" : { "BYOL": "ami-0d8a2f539abbd5763", "LicenseIncluded": "ami-060450ca7a4170427" }, - "us-west-1" : { "BYOL": "ami-0cf71f2688b924e36", "LicenseIncluded": "ami-002666afb57bfa7d0" }, - "us-west-2" : { "BYOL": "ami-01d5fc08abef26bc5", "LicenseIncluded": "ami-0f102b51dcabbf7ae" } + "ap-south-1" : { "BYOL": "ami-00543ec5f37dbe4b7", "LicenseIncluded": "ami-0a02c559bdf1bee46" }, + "eu-west-3" : { "BYOL": "ami-0424769ba0620ab86", "LicenseIncluded": "ami-09daac3761e22fa64" }, + "eu-west-2" : { "BYOL": "ami-013da819f1901fa98", "LicenseIncluded": "ami-073da297c9fa1e325" }, + "eu-west-1" : { "BYOL": "ami-03b19a1f6f34c9ee0", "LicenseIncluded": "ami-0355d7892fcafb3ce" }, + "ap-northeast-2": { "BYOL": "ami-0ea46cb656566cf94", "LicenseIncluded": "ami-05b8ee6bbdb3d7887" }, + "ap-northeast-1": { "BYOL": "ami-01dcfa7774d7970ec", "LicenseIncluded": "ami-08316d08348d0a9d7" }, + "sa-east-1" : { "BYOL": "ami-0c34ed90208723180", "LicenseIncluded": "ami-0564bd6e4b146df79" }, + "ca-central-1" : { "BYOL": "ami-0e925dc68e145a956", "LicenseIncluded": "ami-0a42834976c32974d" }, + "ap-southeast-1": { "BYOL": "ami-0457ce25738b0bd2f", "LicenseIncluded": "ami-0bfb37947dc1e6cc1" }, + "ap-southeast-2": { "BYOL": "ami-04ec026dd7d9fe013", "LicenseIncluded": "ami-0c753885c83794609" }, + "eu-central-1" : { "BYOL": "ami-0518e478f5f1f2834", "LicenseIncluded": "ami-05598662389aa95b4" }, + "us-east-2" : { "BYOL": "ami-0f661119da34de2f6", "LicenseIncluded": "ami-077f4573aa77bdf5e" }, + "us-east-1" : { "BYOL": "ami-02dc259ccbfac00e4", "LicenseIncluded": "ami-0bf895b97beacde98" }, + "us-west-1" : { "BYOL": "ami-093178e44ff7d37f7", "LicenseIncluded": "ami-05f8a03b2a8371be2" }, + "us-west-2" : { "BYOL": "ami-0c749a3d7520271aa", "LicenseIncluded": "ami-0f509756bc1a57b06" } }, "CsrInstance" : { "2x500Mbps" : { "Type" : "c4.large", "Bandwidth" : "500000" }, @@ -199,7 +199,30 @@ }, "Resources" : { "VPNConfigS3Bucket" : { - "Type" : "AWS::S3::Bucket" + "Type" : "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "AES256" + } + } + ] + }, + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + }, + "AccessControl": "LogDeliveryWrite", + "LoggingConfiguration": { + "DestinationBucketName": { + "Ref": "AccessLogBucket" + } + } + } }, "VPNConfigBucketPolicy" : { "Type" : "AWS::S3::BucketPolicy", @@ -233,6 +256,7 @@ "Type" : "AWS::KMS::Key", "Properties" : { "Description" : "TransitVPC CMK for S3 SSE-KMS", + "EnableKeyRotation": true, "KeyPolicy" : { "Version": "2012-10-17", "Id": "transit-vpc-1", @@ -444,6 +468,10 @@ { "id": "F4", "reason": "This solution utilizes a solution helper function to support the creation/update/deletion of CWE for S3 and custom Lambda functions prior to the ability existing in CloudFormation natively. In order to support these provisioning activities, lambda:* and event:* permissions are required." + }, + { + "id": "W12", + "reason": "Resource * is needed to describe VPCs, subnets and security groups" } ] } @@ -473,14 +501,21 @@ { "Effect": "Allow", "Action": [ - "lambda:*", - "events:*", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", - "ec2:DescribeVpcs" + "ec2:DescribeVpcs" ], "Resource": "*" }, + { + "Effect": "Allow", + "Action": [ + "lambda:InvokeFunction", + "lambda:RemovePermission", + "lambda:AddPermission" + ], + "Resource": { "Fn::GetAtt" : [ "CiscoConfigFunction", "Arn" ] } + }, { "Effect": "Allow", "Action": [ @@ -522,8 +557,31 @@ }, "Runtime": { "Fn::FindInMap" : [ "Function", "SolutionHelper", "Runtime"] }, "MemorySize": { "Fn::FindInMap" : [ "Function", "SolutionHelper", "MemorySize"] }, - "Timeout": { "Fn::FindInMap" : [ "Function", "SolutionHelper", "Timeout"] } - } + "Timeout": { "Fn::FindInMap" : [ "Function", "SolutionHelper", "Timeout"] }, + "Environment": { + "Variables": { + "USER_AGENT_STRING": "AwsSolution/SO0001/%VERSION%" + } + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with more restrictive permissions." + }, + { + "id": "W89", + "reason": "This lambda function does not need access to VPC resources" + }, + { + "id": "W92", + "reason": "This use case does not need to set the ReservedConcurrentExecutions" + } + ] + } + } }, "CreateRsaKey": { "Type": "Custom::LoadLambda", @@ -584,23 +642,39 @@ { "Effect": "Allow", "Action": [ - "ec2:CreateNetworkInterface", - "ec2:DescribeNetworkInterfaces", - "ec2:DetachNetworkInterface", - "ec2:DeleteNetworkInterface" + "ec2:CreateNetworkInterface", + "ec2:DetachNetworkInterface", + "ec2:DeleteNetworkInterface" + ], + "Resource": { "Fn::Join" : ["", ["arn:",{"Ref": "AWS::Partition"},":ec2:",{"Ref" : "AWS::Region"},":",{ "Ref" : "AWS::AccountId" }, ":*/*" ]]} + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeNetworkInterfaces" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ - "s3:PutObject", - "s3:GetObject" + "s3:PutObject", + "s3:GetObject" ], "Resource": { "Fn::Join": ["", ["arn:aws:s3:::", { "Ref" : "VPNConfigS3Bucket" }, "/", {"Ref": "S3Prefix"}, "*" ]] } } ] } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W12", + "reason": "Resource * is needed to describe and create network interfaces" + } + ] + } } }, "CiscoConfigFunction": { @@ -627,15 +701,31 @@ "Environment": { "Variables": { "CONFIG_FILE": "transit_vpc_config.txt", - "LOG_LEVEL":"INFO" + "LOG_LEVEL":"INFO", + "USER_AGENT_STRING": "AwsSolution/SO0001/%VERSION%" } } - } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with more tighter permissions." + }, + { + "id": "W92", + "reason": "This use case does not need to set the ReservedConcurrentExecutions" + } + ] + } + } }, "CiscoConfigS3Event": { "Type": "Custom::LoadLambda", "Properties": { "ServiceToken": { "Fn::GetAtt" : ["SolutionHelper", "Arn"] }, + "AccountId": { "Ref" : "AWS::AccountId" }, "FunctionName": { "Fn::Join": ["-", [ { "Ref" : "AWS::StackName" }, { "Fn::FindInMap" : [ "Function", "Configurator", "Name"]} ]] }, "LambdaArn": { "Fn::GetAtt" : ["CiscoConfigFunction", "Arn"] }, "S3Event" : { "Fn::Join": ["", [ @@ -723,28 +813,44 @@ { "Effect": "Allow", "Action": [ - "ec2:DescribeRegions", - "ec2:DescribeVpnGateways", - "ec2:DescribeVpnConnections", - "ec2:CreateTags", - "ec2:CreateCustomerGateway", - "ec2:DeleteCustomerGateway", - "ec2:CreateVpnConnection", - "ec2:DeleteVpnConnection" + "ec2:DescribeRegions", + "ec2:DescribeVpnGateways", + "ec2:DescribeVpnConnections" ], "Resource": "*" }, + { + "Effect": "Allow", + "Action": [ + "ec2:CreateTags", + "ec2:CreateCustomerGateway", + "ec2:DeleteCustomerGateway", + "ec2:CreateVpnConnection", + "ec2:DeleteVpnConnection" + ], + "Resource": { "Fn::Join" : ["", ["arn:",{"Ref": "AWS::Partition"},":ec2:*:",{ "Ref" : "AWS::AccountId" }, ":*/*" ]]} + }, { "Effect": "Allow", "Action": [ - "s3:PutObject", - "s3:PutObjectAcl", - "s3:GetObject" + "s3:PutObject", + "s3:PutObjectAcl", + "s3:GetObject" ], "Resource": { "Fn::Join": ["", ["arn:aws:s3:::", { "Ref" : "VPNConfigS3Bucket" }, "/", {"Ref": "S3Prefix"}, "*" ]] } } ] } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W12", + "reason": "Resource * is needed to describe and create vpn connections, regions, tags, customer gateways" + } + ] + } } }, "PollerFunction": { @@ -771,9 +877,28 @@ "BUCKET_NAME": { "Ref" : "VPNConfigS3Bucket" }, "BUCKET_PREFIX": { "Ref" : "S3Prefix" }, "CONFIG_FILE": "transit_vpc_config.txt", - "LOG_LEVEL":"INFO" + "LOG_LEVEL":"INFO", + "USER_AGENT_STRING": "AwsSolution/SO0001/%VERSION%" } } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with more tighter permissions." + }, + { + "id": "W89", + "reason": "This lambda function does not need access to VPC resources" + }, + { + "id": "W92", + "reason": "This use case does not need to set the ReservedConcurrentExecutions" + } + ] + } } }, "PollerEvent": { @@ -802,11 +927,37 @@ "Properties" : { "GroupDescription" : "CSR Security Group Rules", "VpcId" : { "Ref" : "TransitVPC" }, - "SecurityGroupIngress" : [ - { "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "SourceSecurityGroupId" : { "Ref" : "CiscoConfigSecurityGroup" }} - ], - "SecurityGroupEgress" : [ - { "IpProtocol" : "-1", "FromPort" : "0", "ToPort" : "65535", "CidrIp" : "0.0.0.0/0" } ] + "SecurityGroupIngress" : [{ + "Description": "Security rule for TCP traffic", + "IpProtocol" : "tcp", + "FromPort" : "22", + "ToPort" : "22", + "SourceSecurityGroupId" : { "Ref" : "CiscoConfigSecurityGroup" } + }], + "SecurityGroupEgress" : [{ + "Description": "Security rule for outbound traffic", + "IpProtocol" : "-1", + "FromPort" : "0", + "ToPort" : "65535", + "CidrIp" : "0.0.0.0/0" }] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W40", + "reason": "IpProtocol -1 used to allow all traffic. We recommend that you review the security groups and further restrict access as needed once the deployment is up and running" + }, + { + "id": "W5", + "reason": "Open CIDR used to connect to any VPC." + }, + { + "id": "W29", + "reason": "Port range used to allow all traffic." + } + ] + } } }, "CiscoConfigSecurityGroup" : { @@ -814,12 +965,28 @@ "Properties" : { "GroupDescription" : "Transit VPC Automation Security Group Rules", "VpcId" : { "Ref" : "TransitVPC" }, - "SecurityGroupEgress" : [{ "IpProtocol" : "tcp", "FromPort" : "443", "ToPort" : "443", "CidrIp" : "0.0.0.0/0" }] + "SecurityGroupEgress" : [{ + "Description": "Security rule for TCP traffic", + "IpProtocol" : "tcp", + "FromPort" : "443", + "ToPort" : "443", + "CidrIp" : "0.0.0.0/0" }] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Open CIDR used to allow api calls from lambda function." + } + ] + } } }, "SSHtoCSR": { "Type": "AWS::EC2::SecurityGroupEgress", "Properties":{ + "Description": "Security rule for outbound TCP traffic", "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", @@ -893,6 +1060,85 @@ ]] } } + }, + "AccessLogBucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "AccessControl": "LogDeliveryWrite", + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "AES256" + } + } + ] + }, + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W35", + "reason": "access logging disabled, its a logging bucket" + } + ] + } + } + }, + "AccessLogBucketPolicy": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "AccessLogBucket" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": "*", + "Resource": [ + { + "Fn::GetAtt": [ + "AccessLogBucket", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "AccessLogBucket", + "Arn" + ] + }, + "/*" + ] + ] + } + ], + "Sid": "HttpsOnly" + } + ], + "Version": "2012-10-17" + } + } } }, "Outputs" : { diff --git a/deployment/transit-vpc-primary-account.template b/deployment/transit-vpc-primary-account.template index eafc545..10c56ce 100644 --- a/deployment/transit-vpc-primary-account.template +++ b/deployment/transit-vpc-primary-account.template @@ -1,7 +1,7 @@ { "AWSTemplateFormatVersion" : "2010-09-09", - "Description" : "(SO0001) - Transit VPC: This template creates a dedicated transit VPC with Cisco CSRs for routing traffic. ***NOTE*** You must first subscribe to the appropriate Cisco CSR marketplace BYOL or License Included AMI from the AWS Marketplace before you launch this template. Version 5", + "Description" : "(SO0001) - Transit VPC: This template creates a dedicated transit VPC with Cisco CSRs for routing traffic. ***NOTE*** You must first subscribe to the appropriate Cisco CSR marketplace BYOL or License Included AMI from the AWS Marketplace before you launch this template. version %VERSION%", "Parameters" : { "KeyName" : { @@ -135,32 +135,32 @@ "Mappings" : { "Function" : { "SolutionHelper" : { - "S3Bucket" : "%%BUCKET_NAME%%", - "S3Key" : "transit-vpc/%%VERSION%%/transit-vpc-solution-helper.zip", + "S3Bucket" : "%DIST_OUTPUT_BUCKET%", + "S3Key" : "%SOLUTION_NAME%/%VERSION%/transit-vpc-solution-helper.zip", "Name" : "transit-vpc-solution-helper", "Handler": "transit_vpc_solution_helper/transit-vpc-solution-helper.lambda_handler", "Description": "Transit VPC: This function is invoked for custom resources.", - "Runtime": "python3.7", + "Runtime": "python3.8", "Timeout": "60", "MemorySize": "128" }, "Configurator" : { - "S3Bucket" : "%%BUCKET_NAME%%", - "S3Key" : "transit-vpc/%%VERSION%%/transit-vpc-push-cisco-config.zip", + "S3Bucket" : "%DIST_OUTPUT_BUCKET%", + "S3Key" : "%SOLUTION_NAME%/%VERSION%/transit-vpc-push-cisco-config.zip", "Name" : "cisco-configurator", "Handler": "transit_vpc_push_cisco_config/lambda_function.lambda_handler", "Description": "Transit VPC: This function is invoked when a generic VPN configuration is placed in an S3 bucket - it converts the generic information into Cisco IOS specific commands and pushes the config to transit VPC routers.", - "Runtime": "python3.7", + "Runtime": "python3.8", "Timeout": "300", "MemorySize": "128" }, "Poller" : { - "S3Bucket" : "%%BUCKET_NAME%%", - "S3Key" : "transit-vpc/%%VERSION%%/transit-vpc-poller.zip", + "S3Bucket" : "%DIST_OUTPUT_BUCKET%", + "S3Key" : "%SOLUTION_NAME%/%VERSION%/transit-vpc-poller.zip", "Name" : "vgw-poller", "Handler": "transit-vpc-poller.lambda_handler", "Description": "Transit VPC: Poller function responsible for identifying specifically tagged VGWs and creating VPN connections to transit VPC.", - "Runtime": "python3.7", + "Runtime": "python3.8", "Timeout": "120", "MemorySize": "128" }, @@ -172,21 +172,21 @@ } }, "CiscoCsrAMI" : { - "ap-south-1" : { "BYOL": "ami-0126515024e181b2e", "LicenseIncluded": "ami-012e2d5a7048afe32" }, - "eu-west-3" : { "BYOL": "ami-030690944026827fc", "LicenseIncluded": "ami-028e6b1defb1f3071" }, - "eu-west-2" : { "BYOL": "ami-008715176303d298e", "LicenseIncluded": "ami-04897b16faacdf48f" }, - "eu-west-1" : { "BYOL": "ami-028ff7f30065ad8b3", "LicenseIncluded": "ami-02884305a2b03b67b" }, - "ap-northeast-2": { "BYOL": "ami-0ce275bb065baac48", "LicenseIncluded": "ami-0dd7ffc338c5cff83" }, - "ap-northeast-1": { "BYOL": "ami-09b350fd64ff59865", "LicenseIncluded": "ami-0f3f43158fe8c96fc" }, - "sa-east-1" : { "BYOL": "ami-073b915fb28bbfde0", "LicenseIncluded": "ami-04827a919fc29f946" }, - "ca-central-1" : { "BYOL": "ami-0705ab01e69f78310", "LicenseIncluded": "ami-0bdc99b952d2b636a" }, - "ap-southeast-1": { "BYOL": "ami-0544121f2f619b39c", "LicenseIncluded": "ami-0d00def253ffc9ffc" }, - "ap-southeast-2": { "BYOL": "ami-0162e0ac136ed0666", "LicenseIncluded": "ami-009555db80b895499" }, - "eu-central-1" : { "BYOL": "ami-04f69c92dcce31453", "LicenseIncluded": "ami-0026dc643b0d77fc5" }, - "us-east-2" : { "BYOL": "ami-07f8094154b663213", "LicenseIncluded": "ami-00e56dab70688b964" }, - "us-east-1" : { "BYOL": "ami-0d8a2f539abbd5763", "LicenseIncluded": "ami-060450ca7a4170427" }, - "us-west-1" : { "BYOL": "ami-0cf71f2688b924e36", "LicenseIncluded": "ami-002666afb57bfa7d0" }, - "us-west-2" : { "BYOL": "ami-01d5fc08abef26bc5", "LicenseIncluded": "ami-0f102b51dcabbf7ae" } + "ap-south-1" : { "BYOL": "ami-00543ec5f37dbe4b7", "LicenseIncluded": "ami-0a02c559bdf1bee46" }, + "eu-west-3" : { "BYOL": "ami-0424769ba0620ab86", "LicenseIncluded": "ami-09daac3761e22fa64" }, + "eu-west-2" : { "BYOL": "ami-013da819f1901fa98", "LicenseIncluded": "ami-073da297c9fa1e325" }, + "eu-west-1" : { "BYOL": "ami-03b19a1f6f34c9ee0", "LicenseIncluded": "ami-0355d7892fcafb3ce" }, + "ap-northeast-2": { "BYOL": "ami-0ea46cb656566cf94", "LicenseIncluded": "ami-05b8ee6bbdb3d7887" }, + "ap-northeast-1": { "BYOL": "ami-01dcfa7774d7970ec", "LicenseIncluded": "ami-08316d08348d0a9d7" }, + "sa-east-1" : { "BYOL": "ami-0c34ed90208723180", "LicenseIncluded": "ami-0564bd6e4b146df79" }, + "ca-central-1" : { "BYOL": "ami-0e925dc68e145a956", "LicenseIncluded": "ami-0a42834976c32974d" }, + "ap-southeast-1": { "BYOL": "ami-0457ce25738b0bd2f", "LicenseIncluded": "ami-0bfb37947dc1e6cc1" }, + "ap-southeast-2": { "BYOL": "ami-04ec026dd7d9fe013", "LicenseIncluded": "ami-0c753885c83794609" }, + "eu-central-1" : { "BYOL": "ami-0518e478f5f1f2834", "LicenseIncluded": "ami-05598662389aa95b4" }, + "us-east-2" : { "BYOL": "ami-0f661119da34de2f6", "LicenseIncluded": "ami-077f4573aa77bdf5e" }, + "us-east-1" : { "BYOL": "ami-02dc259ccbfac00e4", "LicenseIncluded": "ami-0bf895b97beacde98" }, + "us-west-1" : { "BYOL": "ami-093178e44ff7d37f7", "LicenseIncluded": "ami-05f8a03b2a8371be2" }, + "us-west-2" : { "BYOL": "ami-0c749a3d7520271aa", "LicenseIncluded": "ami-0f509756bc1a57b06" } }, "CsrInstance" : { "2x500Mbps" : { "Type" : "c4.large", "Bandwidth" : "500000" }, @@ -202,11 +202,39 @@ }, "Send" : { "AnonymousUsage" : { "Data" : "Yes" } + }, + "LogRetention" : { + "Period" : { "Days" : 90 } } }, "Resources" : { "VPNConfigS3Bucket" : { - "Type" : "AWS::S3::Bucket" + "Type" : "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "AES256" + } + } + ] + }, + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + }, + "AccessControl": "LogDeliveryWrite", + "LoggingConfiguration": { + "DestinationBucketName": { + "Ref": "AccessLogBucket" + } + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" }, "VPNConfigBucketPolicy" : { "Type" : "AWS::S3::BucketPolicy", @@ -240,6 +268,7 @@ "Type" : "AWS::KMS::Key", "Properties" : { "Description" : "TransitVPC CMK for S3 SSE-KMS", + "EnableKeyRotation": true, "KeyPolicy" : { "Version": "2012-10-17", "Id": "transit-vpc-1", @@ -291,7 +320,9 @@ "Tags" : [ { "Key" : "Name", "Value" : "Transit VPC" } ] - } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" }, "VPCPubSub1" : { "Type" : "AWS::EC2::Subnet", @@ -303,7 +334,9 @@ { "Key" : "Network", "Value" : "Public" }, { "Key" : "Name", "Value" : "Transit VPC Subnet1" } ] - } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" }, "VPCPubSub2" : { "Type" : "AWS::EC2::Subnet", @@ -315,7 +348,9 @@ { "Key" : "Network", "Value" : "Public" }, { "Key" : "Name", "Value" : "Transit VPC Subnet2" } ] - } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" }, "IGW" : { "Type" : "AWS::EC2::InternetGateway", @@ -449,7 +484,9 @@ "ios-config-27=\"ip ssh server algorithm authentication publickey\"\n", "ios-config-28=\"ip ssh maxstartups 1\"\n" ]]}} - } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" }, "VpcCsr2" : { "Type" : "AWS::EC2::Instance", @@ -505,7 +542,9 @@ "ios-config-27=\"ip ssh server algorithm authentication publickey\"\n", "ios-config-28=\"ip ssh maxstartups 1\"\n" ]]}} - } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" }, "SolutionHelperRole": { "Type": "AWS::IAM::Role", @@ -531,6 +570,10 @@ { "id": "F4", "reason": "This solution utilizes a solution helper function to support the creation/update/deletion of CWE for S3 and custom Lambda functions prior to the ability existing in CloudFormation natively. In order to support these provisioning activities, lambda:* and event:* permissions are required." + }, + { + "id": "W12", + "reason": "Resource * is needed to describe VPCs, subnets and security groups" } ] } @@ -560,14 +603,21 @@ { "Effect": "Allow", "Action": [ - "lambda:*", - "events:*", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", - "ec2:DescribeVpcs" + "ec2:DescribeVpcs" ], "Resource": "*" }, + { + "Effect": "Allow", + "Action": [ + "lambda:InvokeFunction", + "lambda:RemovePermission", + "lambda:AddPermission" + ], + "Resource": { "Fn::GetAtt" : [ "CiscoConfigFunction", "Arn" ] } + }, { "Effect": "Allow", "Action": [ @@ -578,16 +628,16 @@ { "Effect": "Allow", "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:DeleteObject" + "s3:PutObject", + "s3:GetObject", + "s3:DeleteObject" ], "Resource": { "Fn::Join": ["", ["arn:aws:s3:::", { "Ref" : "VPNConfigS3Bucket" }, "/", {"Ref": "S3Prefix"}, "*" ]] } }, { "Effect": "Allow", "Action": [ - "s3:GetObject" + "s3:GetObject" ], "Resource": "arn:aws:s3:::solutions-reference/*" } @@ -609,8 +659,31 @@ }, "Runtime": { "Fn::FindInMap" : [ "Function", "SolutionHelper", "Runtime"] }, "MemorySize": { "Fn::FindInMap" : [ "Function", "SolutionHelper", "MemorySize"] }, - "Timeout": { "Fn::FindInMap" : [ "Function", "SolutionHelper", "Timeout"] } - } + "Timeout": { "Fn::FindInMap" : [ "Function", "SolutionHelper", "Timeout"] }, + "Environment": { + "Variables": { + "USER_AGENT_STRING": "AwsSolution/SO0001/%VERSION%" + } + } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with more tighter permissions." + }, + { + "id": "W89", + "reason": "This lambda function does not need access to VPC resources" + }, + { + "id": "W92", + "reason": "This use case does not need to set the ReservedConcurrentExecutions" + } + ] + } + } }, "CreateRsaKey": { "Type": "Custom::LoadLambda", @@ -668,26 +741,42 @@ ], "Resource": { "Fn::Join" : ["", ["arn:aws:logs:",{"Ref" : "AWS::Region"},":",{ "Ref" : "AWS::AccountId" }, ":log-group:/aws/lambda/*" ]]} }, - { + { "Effect": "Allow", "Action": [ - "ec2:CreateNetworkInterface", - "ec2:DescribeNetworkInterfaces", - "ec2:DetachNetworkInterface", - "ec2:DeleteNetworkInterface" + "ec2:CreateNetworkInterface", + "ec2:DetachNetworkInterface", + "ec2:DeleteNetworkInterface" + ], + "Resource": { "Fn::Join" : ["", ["arn:",{"Ref": "AWS::Partition"},":ec2:",{"Ref" : "AWS::Region"},":",{ "Ref" : "AWS::AccountId" }, ":*/*" ]]} + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeNetworkInterfaces" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ - "s3:PutObject", - "s3:GetObject" + "s3:PutObject", + "s3:GetObject" ], "Resource": { "Fn::Join": ["", ["arn:aws:s3:::", { "Ref" : "VPNConfigS3Bucket" }, "/", {"Ref": "S3Prefix"}, "*" ]] } } ] } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W12", + "reason": "Resource * is needed to describe and create network interfaces" + } + ] + } } }, "CiscoConfigFunction": { @@ -714,15 +803,31 @@ "Environment": { "Variables": { "CONFIG_FILE": "transit_vpc_config.txt", - "LOG_LEVEL":"INFO" + "LOG_LEVEL":"INFO", + "USER_AGENT_STRING": "AwsSolution/SO0001/%VERSION%" } } - } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with more tighter permissions." + }, + { + "id": "W92", + "reason": "This use case does not need to set the ReservedConcurrentExecutions" + } + ] + } + } }, "CiscoConfigS3Event": { "Type": "Custom::LoadLambda", "Properties": { "ServiceToken": { "Fn::GetAtt" : ["SolutionHelper", "Arn"] }, + "AccountId": { "Ref" : "AWS::AccountId" }, "FunctionName": { "Fn::Join": ["-", [ { "Ref" : "AWS::StackName" }, { "Fn::FindInMap" : [ "Function", "Configurator", "Name"]} ]] }, "LambdaArn": { "Fn::GetAtt" : ["CiscoConfigFunction", "Arn"] }, "S3Event" : { "Fn::Join": ["", [ @@ -810,28 +915,44 @@ { "Effect": "Allow", "Action": [ - "ec2:DescribeRegions", - "ec2:DescribeVpnGateways", - "ec2:DescribeVpnConnections", - "ec2:CreateTags", - "ec2:CreateCustomerGateway", - "ec2:DeleteCustomerGateway", - "ec2:CreateVpnConnection", - "ec2:DeleteVpnConnection" + "ec2:CreateTags", + "ec2:CreateCustomerGateway", + "ec2:DeleteCustomerGateway", + "ec2:CreateVpnConnection", + "ec2:DeleteVpnConnection" + ], + "Resource": { "Fn::Join" : ["", ["arn:",{"Ref": "AWS::Partition"},":ec2:*:",{ "Ref" : "AWS::AccountId" }, ":*/*" ]]} + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeRegions", + "ec2:DescribeVpnGateways", + "ec2:DescribeVpnConnections" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ - "s3:PutObject", - "s3:PutObjectAcl", - "s3:GetObject" + "s3:PutObject", + "s3:PutObjectAcl", + "s3:GetObject" ], "Resource": { "Fn::Join": ["", ["arn:aws:s3:::", { "Ref" : "VPNConfigS3Bucket" }, "/", {"Ref": "S3Prefix"}, "*" ]] } } ] } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W12", + "reason": "Resource * is needed to describe and create vpn connections, regions, tags, customer gateways" + } + ] + } } }, "PollerFunction": { @@ -858,9 +979,28 @@ "BUCKET_NAME": { "Ref" : "VPNConfigS3Bucket" }, "BUCKET_PREFIX": { "Ref" : "S3Prefix" }, "CONFIG_FILE": "transit_vpc_config.txt", - "LOG_LEVEL":"INFO" + "LOG_LEVEL":"INFO", + "USER_AGENT_STRING": "AwsSolution/SO0001/%VERSION%" } } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with more tighter permissions." + }, + { + "id": "W89", + "reason": "This lambda function does not need access to VPC resources" + }, + { + "id": "W92", + "reason": "This use case does not need to set the ReservedConcurrentExecutions" + } + ] + } } }, "PollerEvent": { @@ -889,11 +1029,42 @@ "Properties" : { "GroupDescription" : "CSR Security Group Rules", "VpcId" : { "Ref" : "TransitVPC" }, - "SecurityGroupIngress" : [ - { "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "SourceSecurityGroupId" : { "Ref" : "CiscoConfigSecurityGroup" }} - ], - "SecurityGroupEgress" : [ - { "IpProtocol" : "-1", "FromPort" : "0", "ToPort" : "65535", "CidrIp" : "0.0.0.0/0" } ] + "SecurityGroupIngress" : [{ + "Description": "Security rule for for inbound TCP traffic", + "IpProtocol" : "tcp", + "FromPort" : "22", + "ToPort" : "22", + "SourceSecurityGroupId" : { + "Ref" : "CiscoConfigSecurityGroup" + } + }], + "SecurityGroupEgress" : [{ + "Description": "Security Rule for outbound traffic", + "IpProtocol" : "-1", + "FromPort" : "0", + "ToPort" : "65535", + "CidrIp" : "0.0.0.0/0" + }] + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W40", + "reason": "IpProtocol -1 used to allow all traffic. We recommend that you review the security groups and further restrict access as needed once the deployment is up and running" + }, + { + "id": "W5", + "reason": "Open CIDR used to connect to any VPC." + }, + { + "id": "W29", + "reason": "Port range used to allow for transit vpc traffic." + } + ] + } } }, "CiscoConfigSecurityGroup" : { @@ -901,12 +1072,30 @@ "Properties" : { "GroupDescription" : "Transit VPC Automation Security Group Rules", "VpcId" : { "Ref" : "TransitVPC" }, - "SecurityGroupEgress" : [{ "IpProtocol" : "tcp", "FromPort" : "443", "ToPort" : "443", "CidrIp" : "0.0.0.0/0" }] + "SecurityGroupEgress" : [{ + "Description": "Security rule for outbound TCP traffic", + "IpProtocol" : "tcp", + "FromPort" : "443", + "ToPort" : "443", + "CidrIp" : "0.0.0.0/0" }] + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W5", + "reason": "Open CIDR used to allow api calls from lambda function." + } + ] + } } }, "SSHtoCSR": { "Type": "AWS::EC2::SecurityGroupEgress", - "Properties":{ + "Properties": { + "Description": "Egress Security rule", "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", @@ -979,8 +1168,184 @@ ]] } } + }, + "FlowLog": { + "Type": "AWS::EC2::FlowLog", + "Properties": { + "ResourceId": { + "Ref": "TransitVPC" + }, + "ResourceType": "VPC", + "TrafficType": "ALL", + "DeliverLogsPermissionArn": { + "Fn::GetAtt": [ + "RoleFlowLogs", + "Arn" + ] + }, + "LogGroupName": { + "Ref": "AWS::StackName" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "RoleFlowLogs": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "vpc-flow-logs.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "FlowLogPolicy": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + "logs:CreateLogGroup", + "logs:DescribeLogGroups" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "LogGroupFlowLogs", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "FlowLogPolicy", + "Roles": [ + { + "Ref": "RoleFlowLogs" + } + ] + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "LogGroupFlowLogs": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": { + "Ref": "AWS::StackName" + }, + "RetentionInDays": { "Fn::FindInMap" : [ "LogRetention", "Period", "Days"]} + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W84", + "reason": "CloudWatch logs are encrypted by the service" + } + ] + } + } + }, + "AccessLogBucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "AccessControl": "LogDeliveryWrite", + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "AES256" + } + } + ] + }, + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W35", + "reason": "access logging disabled, its a logging bucket" + } + ] + } + } + }, + "AccessLogBucketPolicy": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "AccessLogBucket" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": "*", + "Resource": [ + { + "Fn::GetAtt": [ + "AccessLogBucket", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "AccessLogBucket", + "Arn" + ] + }, + "/*" + ] + ] + } + ], + "Sid": "HttpsOnly" + } + ], + "Version": "2012-10-17" + } + } } + }, + "Outputs" : { "CSR1" : { "Description" : "IP Address for CSR1", diff --git a/deployment/transit-vpc-second-account.template b/deployment/transit-vpc-second-account.template index d8c4844..8c9b81f 100644 --- a/deployment/transit-vpc-second-account.template +++ b/deployment/transit-vpc-second-account.template @@ -12,13 +12,17 @@ "Type" : "String", "Default" : "vpnconfigs/", "AllowedPattern": "^[a-zA-Z0-9_\\-/.]*/$" + }, + "KMSKeyARN" : { + "Description" : "Key ARN for the KMS Key created by the primary stack. Example - arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", + "Type" : "String" } }, "Mappings" : { "Function" : { "Poller" : { - "S3Bucket" : "%%BUCKET_NAME%%", - "S3Key" : "transit-vpc/%%VERSION%%/transit-vpc-poller.zip", + "S3Bucket" : "%DIST_OUTPUT_BUCKET%", + "S3Key" : "%SOLUTION_NAME%/%VERSION%/transit-vpc-poller.zip", "Name" : "vgw-poller", "Handler": "transit-vpc-poller.lambda_handler", "Description": "Transit VPC: Poller function responsible for identifying specifically tagged VGWs and creating VPN connections to transit VPC.", @@ -43,7 +47,7 @@ } ] }, "Path": "/", - "Policies": [ { + "Policies": [{ "PolicyName": "My_Lambda_Function_Permissions", "PolicyDocument": { "Version" : "2012-10-17", @@ -60,38 +64,53 @@ { "Effect": "Allow", "Action": [ - "ec2:DescribeRegions", - "ec2:DescribeVpnGateways", - "ec2:DescribeVpnConnections", - "ec2:CreateTags", - "ec2:CreateCustomerGateway", - "ec2:DeleteCustomerGateway", - "ec2:CreateVpnConnection", - "ec2:DeleteVpnConnection" + "ec2:CreateTags", + "ec2:CreateCustomerGateway", + "ec2:DeleteCustomerGateway", + "ec2:CreateVpnConnection", + "ec2:DeleteVpnConnection" + ], + "Resource": { "Fn::Join" : ["", ["arn:",{"Ref": "AWS::Partition"},":ec2:*:",{ "Ref" : "AWS::AccountId" }, ":*/*" ]]} + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeRegions", + "ec2:DescribeVpnGateways", + "ec2:DescribeVpnConnections" ], "Resource": "*" - }, - { - "Effect": "Allow", - "Action": [ - "kms:Decrypt", - "kms:GenerateDataKey*", - "kms:Encrypt" - ], - "Resource": "*" - }, + }, { "Effect": "Allow", "Action": [ - "s3:PutObject", - "s3:PutObjectAcl", - "s3:GetObject" + "s3:PutObject", + "s3:PutObjectAcl", + "s3:GetObject" ], "Resource": { "Fn::Join": ["", ["arn:aws:s3:::", { "Ref" : "BucketName" }, "/", {"Ref": "BucketPrefix"}, "*" ]] } - } - ] - } - } ] + }, + { + "Effect": "Allow", + "Action": [ + "kms:Decrypt", + "kms:GenerateDataKey*", + "kms:Encrypt" + ], + "Resource": { "Ref": "KMSKeyARN" } + } + ]} + }] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W11", + "reason": "Resource * is needed to describe and create vpn connections, regions, tags, customer gateways" + } + ] + } } }, "PollerFunction": { @@ -116,9 +135,25 @@ "BUCKET_NAME": { "Ref" : "BucketName" }, "BUCKET_PREFIX": { "Ref" : "BucketPrefix" }, "CONFIG_FILE": "transit_vpc_config.txt", - "LOG_LEVEL":"INFO" + "LOG_LEVEL":"INFO", + "USER_AGENT_STRING": "AwsSolution/SO0001/%VERSION%" + } } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W89", + "reason": "This lambda function does not need access to VPC resources" + }, + { + "id": "W92", + "reason": "This use case does not need to set the ReservedConcurrentExecutions" + } + ] + } } }, "PollerEvent": { diff --git a/deployment/transit-vpc-spoke-vpc-withec2-tsunamiudp.template b/deployment/transit-vpc-spoke-vpc-withec2-tsunamiudp.template index d04e9c2..2a85184 100644 --- a/deployment/transit-vpc-spoke-vpc-withec2-tsunamiudp.template +++ b/deployment/transit-vpc-spoke-vpc-withec2-tsunamiudp.template @@ -30,6 +30,10 @@ "Type" : "String", "Default" : "10.255.0.0/16" }, + "SSHCidr" : { + "Description" : "IP address or range for SSH access to EC2 instance (needs to be a CIDR block such as 123.123.123.123/32).", + "Type" : "String" + }, "KeyName": { "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances", "Type": "AWS::EC2::KeyPair::KeyName", @@ -49,7 +53,7 @@ "ParameterGroups" : [ { "Label" : { "default":"EC2 Configuration" }, - "Parameters" : [ "KeyName", "InstanceType", "DBInstanceType" ] + "Parameters" : [ "KeyName", "InstanceType", "SSHCidr" ] }, { "Label" : { "default" : "Network Configuration" }, @@ -61,7 +65,8 @@ "HubTagValue" : { "default" : "Transit VPC Tag Value" }, "PreferredPathTag" : { "default" : "Preferred VPN Endpoint Tag Name" }, "PreferredPathValue" : { "default" : "Preferred Path" }, - "VpcCidr" : { "default" : "Spoke VPC CIDR Block" } + "VpcCidr" : { "default" : "Spoke VPC CIDR Block" }, + "SSHCidr" : { "default" : "Enable SSH From" } } } }, @@ -133,8 +138,10 @@ "ap-southeast-2" : {"PV64" : "ami-ced887ad", "HVM64" : "ami-48d38c2b", "HVMG2" : "ami-0c1a446f"}, "sa-east-1" : {"PV64" : "ami-7d15ad11", "HVM64" : "ami-6817af04", "HVMG2" : "NOT_SUPPORTED"}, "cn-north-1" : {"PV64" : "ami-18ac6575", "HVM64" : "ami-43a36a2e", "HVMG2" : "NOT_SUPPORTED"} + }, + "LogRetention" : { + "Period" : { "Days" : 90 } } - }, "Resources" : { @@ -279,18 +286,21 @@ "VpcId" : { "Ref" : "SpokeVPC"}, "SecurityGroupIngress" : [ { + "Description": "Security rule for SSH", "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", - "CidrIp" : "0.0.0.0/0" + "CidrIp" : { "Ref" : "SSHCidr" } }, { + "Description": "Security rule for TCP protocol", "IpProtocol" : "tcp", "FromPort" : "46224", "ToPort" : "46224", "CidrIp" : "10.0.0.0/8" }, { + "Description": "Security rule for UDP protocol", "IpProtocol" : "udp", "FromPort" : "46224", "ToPort" : "46224", @@ -299,10 +309,29 @@ ], "SecurityGroupEgress": [ { + "Description": "Security rule for outbound traffic", "IpProtocol": "-1", "CidrIp": "0.0.0.0/0" } ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W40", + "reason": "IpProtocol -1 used to allow all traffic. We recommend that you review the security groups and further restrict access as needed once the deployment is up and running." + }, + { + "id": "W5", + "reason": "Open CIDR used to connect to any VPC." + }, + { + "id": "W9", + "reason": "CIDR Ip range used for VPC. We recommend that you review the security groups and further restrict access as needed once the deployment is up and running." + } + ] + } } }, "EC2Eip" : { @@ -311,6 +340,101 @@ "Domain" : "vpc", "InstanceId" : { "Ref" : "EC2Instance" } } + }, + "FlowLog": { + "Type": "AWS::EC2::FlowLog", + "Properties": { + "ResourceId": { + "Ref": "SpokeVPC" + }, + "ResourceType": "VPC", + "TrafficType": "ALL", + "DeliverLogsPermissionArn": { + "Fn::GetAtt": [ + "RoleFlowLogs", + "Arn" + ] + }, + "LogGroupName": { + "Ref": "AWS::StackName" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "RoleFlowLogs": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "vpc-flow-logs.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "FlowLogPolicy": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + "logs:CreateLogGroup", + "logs:DescribeLogGroups" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "LogGroupFlowLogs", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "FlowLogPolicy", + "Roles": [ + { + "Ref": "RoleFlowLogs" + } + ] + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "LogGroupFlowLogs": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": { + "Ref": "AWS::StackName" + }, + "RetentionInDays": { "Fn::FindInMap" : [ "LogRetention", "Period", "Days"]} + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W84", + "reason": "CloudWatch logs are encrypted by the service" + } + ] + } + } } }, diff --git a/deployment/transit-vpc-spoke-vpc-withec2.template b/deployment/transit-vpc-spoke-vpc-withec2.template index 7405d50..3062405 100644 --- a/deployment/transit-vpc-spoke-vpc-withec2.template +++ b/deployment/transit-vpc-spoke-vpc-withec2.template @@ -92,6 +92,9 @@ "ap-southeast-2" : {"AMI" : "ami-55d4e436"}, "ap-south-1" : {"AMI" : "ami-cacbbea5"}, "sa-east-1" : {"AMI" : "ami-b777e4db"} + }, + "LogRetention" : { + "Period" : { "Days" : 90 } } }, @@ -205,12 +208,14 @@ "GroupDescription" : "Enable SSH access via port 22", "VpcId" : { "Ref" : "SpokeVPC"}, "SecurityGroupIngress" : [ { + "Description": "Security rule for inbound TCP traffic", "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHCidr" } }, { + "Description": "Security rule for ICMP protocol", "IpProtocol" : "icmp", "FromPort" : "-1", "ToPort" : "-1", @@ -218,10 +223,25 @@ } ], "SecurityGroupEgress": [ { + "Description": "Security rule for outbound traffic", "IpProtocol": "-1", "CidrIp": "0.0.0.0/0" } ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W40", + "reason": "IpProtocol -1 used to allow all traffic. We recommend that you review the security groups and further restrict access as needed once the deployment is up and running" + }, + { + "id": "W5", + "reason": "Open CIDR used to connect to any VPC." + } + ] + } } }, "EC2Eip" : { @@ -230,8 +250,102 @@ "Domain" : "vpc", "InstanceId" : { "Ref" : "EC2Instance" } } + }, + "FlowLog": { + "Type": "AWS::EC2::FlowLog", + "Properties": { + "ResourceId": { + "Ref": "SpokeVPC" + }, + "ResourceType": "VPC", + "TrafficType": "ALL", + "DeliverLogsPermissionArn": { + "Fn::GetAtt": [ + "RoleFlowLogs", + "Arn" + ] + }, + "LogGroupName": { + "Ref": "AWS::StackName" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "RoleFlowLogs": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "vpc-flow-logs.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "FlowLogPolicy": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + "logs:CreateLogGroup", + "logs:DescribeLogGroups" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "LogGroupFlowLogs", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "FlowLogPolicy", + "Roles": [ + { + "Ref": "RoleFlowLogs" + } + ] + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "LogGroupFlowLogs": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": { + "Ref": "AWS::StackName" + }, + "RetentionInDays": { "Fn::FindInMap" : [ "LogRetention", "Period", "Days"]} + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W84", + "reason": "CloudWatch logs are encrypted by the service" + } + ] + } + } } - }, "Outputs" : { "VPCID" : { diff --git a/deployment/transit-vpc-spoke-vpc.template b/deployment/transit-vpc-spoke-vpc.template index 0b0de13..0cb2135 100644 --- a/deployment/transit-vpc-spoke-vpc.template +++ b/deployment/transit-vpc-spoke-vpc.template @@ -48,7 +48,11 @@ } } }, - + "Mappings" : { + "LogRetention" : { + "Period" : { "Days" : 90 } + } + }, "Resources" : { "SpokeVPC" : { "Type" : "AWS::EC2::VPC", @@ -68,7 +72,9 @@ { "Key" : { "Ref" : "PreferredPathTag" }, "Value" : { "Ref" : "PreferredPathValue" }}, { "Key" : { "Ref" : "SpokeTag" }, "Value" : { "Ref" : "SpokeTagValue" }} ] - } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" }, "AttachVGWToVPC" : { "Type" : "AWS::EC2::VPCGatewayAttachment", @@ -94,7 +100,103 @@ "RouteTableIds" : [ { "Ref" : "VPCRouteTable" } ], "VpnGatewayId" : { "Ref" : "VGW" } } + }, + "FlowLog": { + "Type": "AWS::EC2::FlowLog", + "Properties": { + "ResourceId": { + "Ref": "SpokeVPC" + }, + "ResourceType": "VPC", + "TrafficType": "ALL", + "DeliverLogsPermissionArn": { + "Fn::GetAtt": [ + "RoleFlowLogs", + "Arn" + ] + }, + "LogGroupName": { + "Ref": "AWS::StackName" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "RoleFlowLogs": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "vpc-flow-logs.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "FlowLogPolicy": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + "logs:CreateLogGroup", + "logs:DescribeLogGroups" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "LogGroupFlowLogs", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "FlowLogPolicy", + "Roles": [ + { + "Ref": "RoleFlowLogs" + } + ] + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "LogGroupFlowLogs": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": { + "Ref": "AWS::StackName" + }, + "RetentionInDays": { "Fn::FindInMap" : [ "LogRetention", "Period", "Days"]} + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W84", + "reason": "CloudWatch logs are encrypted by the service" + } + ] + } + } } + }, "Outputs" : { "VPCID" : { diff --git a/source/transit-vpc-poller/transit-vpc-poller.py b/source/transit-vpc-poller/transit-vpc-poller.py index ba020dd..05d27ed 100644 --- a/source/transit-vpc-poller/transit-vpc-poller.py +++ b/source/transit-vpc-poller/transit-vpc-poller.py @@ -1,10 +1,10 @@ ###################################################################################################################### -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. # +# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # # -# Licensed under the Amazon Software License (the "License"). You may not use this file except in compliance # +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # # with the License. A copy of the License is located at # # # -# http://aws.amazon.com/asl/ # +# http://www.apache.org/licenses/LICENSE-2.0 # # # # or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES # # OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # @@ -29,7 +29,7 @@ bucket_name=str(os.environ.get('BUCKET_NAME')) bucket_prefix=str(os.environ.get('BUCKET_PREFIX')) config_file=str(os.environ.get('CONFIG_FILE')) - +USER_AGENT_STRING = os.environ['USER_AGENT_STRING'] #VGW tags come in the format of [{"Key": "Tag1", "Value":"Tag1value"},{"Key":"Tag2","Value":"Tag2value"}] #This function converts the array of Key/Value dicts to a single tag dictionary def getTags(vgwTags): @@ -110,7 +110,7 @@ def lambda_handler(event, context): #Figure out the account number by parsing this function's ARN account_id = re.findall(':(\d+):', context.invoked_function_arn)[0] #Retrieve Transit VPC configuration from transit_vpn_config.txt - s3=boto3.client('s3', config=Config(signature_version='s3v4', user_agent='transit-vpc-s3')) + s3=boto3.client('s3', config=Config(signature_version='s3v4', user_agent_extra=USER_AGENT_STRING)) log.info('Getting config file %s/%s%s',bucket_name, bucket_prefix, config_file) config_string = s3.get_object(Bucket=bucket_name,Key=bucket_prefix+config_file)['Body'].read().decode('utf-8') config=ast.literal_eval(config_string) @@ -119,7 +119,7 @@ def lambda_handler(event, context): # use this variable to determine if a VGW has been processed so we will only process one VGW per run (one per minute) processed_vgw = False #Get list of regions so poller can look for VGWs in all regions - ec2=boto3.client('ec2',region_name='us-east-1',config=Config(user_agent='transit-vpc-ec2-describe-regions')) + ec2=boto3.client('ec2',region_name='us-east-1',config=Config(user_agent_extra=USER_AGENT_STRING)) regions=ec2.describe_regions() for region in regions['Regions']: @@ -127,7 +127,7 @@ def lambda_handler(event, context): region_id=region['RegionName'] log.debug('Checking region: %s',region_id) #Create EC2 connection to this region to get list of VGWs - ec2=boto3.client('ec2',region_name=region_id,config=Config(user_agent='transit-vpc-ec2-{}'.format(region_id))) + ec2=boto3.client('ec2',region_name=region_id,config=Config(user_agent_extra=USER_AGENT_STRING)) #Get list of VGWs that are available and tagged for Transit VPC #vgws=ec2.describe_vpn_gateways(Filters=[ # {'Name':'state','Values':['available', 'attached', 'detached']}, diff --git a/source/transit-vpc-push-cisco-config/lambda_function.py b/source/transit-vpc-push-cisco-config/lambda_function.py index 0e2e8f4..8c7e756 100644 --- a/source/transit-vpc-push-cisco-config/lambda_function.py +++ b/source/transit-vpc-push-cisco-config/lambda_function.py @@ -1,10 +1,10 @@ ###################################################################################################################### -# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. # +# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # # -# Licensed under the Amazon Software License (the "License"). You may not use this file except in compliance # +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # # with the License. A copy of the License is located at # # # -# http://aws.amazon.com/asl/ # +# http://www.apache.org/licenses/LICENSE-2.0 # # # # or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES # # OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # @@ -27,6 +27,8 @@ log.setLevel(log_level) config_file=str(os.environ.get('CONFIG_FILE')) +USER_AGENT_STRING = os.environ['USER_AGENT_STRING'] + #These S3 endpoint URLs are provided to support VPC endpoints for S3 in regions such as Frankfort that require explicit region endpoint definition endpoint_url = { "us-east-1" : "https://s3.amazonaws.com", @@ -137,7 +139,7 @@ def getBucketPrefix(bucket_name, bucket_key): #Logic to download the transit VPC configuration file from S3 def getTransitConfig(bucket_name, bucket_prefix, s3_url, config_file): s3=boto3.client('s3', endpoint_url=s3_url, - config=Config(s3={'addressing_style': 'virtual'}, signature_version='s3v4')) + config=Config(s3={'addressing_style': 'virtual'}, signature_version='s3v4', user_agent_extra=USER_AGENT_STRING)) log.info("Downloading config file: %s/%s/%s%s", s3_url, bucket_name, bucket_prefix,config_file) config_string = s3.get_object(Bucket=bucket_name,Key=bucket_prefix+config_file)['Body'].read().decode('utf-8') return ast.literal_eval(config_string) @@ -145,7 +147,7 @@ def getTransitConfig(bucket_name, bucket_prefix, s3_url, config_file): #Logic to upload a new/updated transit VPC configuration file to S3 (not currently used) def putTransitConfig(bucket_name, bucket_prefix, s3_url, config_file, config): s3=boto3.client('s3', endpoint_url=s3_url, - config=Config(s3={'addressing_style': 'virtual'}, signature_version='s3v4')) + config=Config(s3={'addressing_style': 'virtual'}, signature_version='s3v4', user_agent_extra=USER_AGENT_STRING)) log.info("Uploading new config file: %s/%s/%s%s", s3_url,bucket_name, bucket_prefix,config_file) s3.put_object(Bucket=bucket_name,Key=bucket_prefix+config_file,Body=str(config)) @@ -154,7 +156,7 @@ def downloadPrivateKey(bucket_name, bucket_prefix, s3_url, prikey): if os.path.exists('/tmp/'+prikey): os.remove('/tmp/'+prikey) s3=boto3.client('s3', endpoint_url=s3_url, - config=Config(s3={'addressing_style': 'virtual'}, signature_version='s3v4')) + config=Config(s3={'addressing_style': 'virtual'}, signature_version='s3v4', user_agent_extra=USER_AGENT_STRING)) log.info("Downloading private key: %s/%s/%s%s",s3_url, bucket_name, bucket_prefix, prikey) s3.download_file(bucket_name,bucket_prefix+prikey, '/tmp/'+prikey) @@ -164,7 +166,7 @@ def create_cisco_config(bucket_name, bucket_key, s3_url, bgp_asn, ssh): #Download the VPN configuration XML document s3=boto3.client('s3',endpoint_url=s3_url, - config=Config(s3={'addressing_style': 'virtual'}, signature_version='s3v4')) + config=Config(s3={'addressing_style': 'virtual'}, signature_version='s3v4', user_agent_extra=USER_AGENT_STRING)) config=s3.get_object(Bucket=bucket_name,Key=bucket_key) xmldoc=minidom.parseString(config['Body'].read()) diff --git a/source/transit-vpc-push-cisco-config/setup.py b/source/transit-vpc-push-cisco-config/setup.py index d859c26..913386d 100644 --- a/source/transit-vpc-push-cisco-config/setup.py +++ b/source/transit-vpc-push-cisco-config/setup.py @@ -1,5 +1,18 @@ +###################################################################################################################### +# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # +# with the License. A copy of the License is located at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES # +# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # +# and limitations under the License. # +###################################################################################################################### # coding: utf-8 + from setuptools import setup, find_packages # TransitVPC-11 - 09/06/2018 - Pip version # pip version handling diff --git a/source/transit-vpc-solution-helper/pycfn_custom_resource/lambda_backed.py b/source/transit-vpc-solution-helper/pycfn_custom_resource/lambda_backed.py index e1d3252..2ee1616 100644 --- a/source/transit-vpc-solution-helper/pycfn_custom_resource/lambda_backed.py +++ b/source/transit-vpc-solution-helper/pycfn_custom_resource/lambda_backed.py @@ -1,11 +1,17 @@ -# Changes from original pycfn_custom_resource: -# -# Changed/updated a couple of imports. -# -# Removed unused exception variable - +###################################################################################################################### +# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # +# with the License. A copy of the License is located at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES # +# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # +# and limitations under the License. # +###################################################################################################################### from . import util -from botocore.vendored import requests +import requests import json import uuid import sys diff --git a/source/transit-vpc-solution-helper/pycfn_custom_resource/util.py b/source/transit-vpc-solution-helper/pycfn_custom_resource/util.py index 2cd3a8d..4b3ca1d 100644 --- a/source/transit-vpc-solution-helper/pycfn_custom_resource/util.py +++ b/source/transit-vpc-solution-helper/pycfn_custom_resource/util.py @@ -1,26 +1,21 @@ #============================================================================== # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved. # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#============================================================================== - -# Changes from original pycfn_custom_resource: -# -# Changed/updated imports. -# -# Updated exception syntax for Python 3. - -from botocore.vendored.requests.exceptions import ConnectionError, HTTPError, Timeout, SSLError +###################################################################################################################### +# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # +# with the License. A copy of the License is located at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES # +# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # +# and limitations under the License. # +###################################################################################################################### + + +from requests.exceptions import ConnectionError, HTTPError, Timeout, SSLError import logging import random import time diff --git a/source/transit-vpc-solution-helper/setup.py b/source/transit-vpc-solution-helper/setup.py index e89ae55..739e4ce 100644 --- a/source/transit-vpc-solution-helper/setup.py +++ b/source/transit-vpc-solution-helper/setup.py @@ -1,3 +1,15 @@ +###################################################################################################################### +# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # +# with the License. A copy of the License is located at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES # +# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # +# and limitations under the License. # +###################################################################################################################### # coding: utf-8 from setuptools import setup, find_packages @@ -18,9 +30,11 @@ packages=['transit_vpc_solution_helper', 'pycfn_custom_resource'], package_dir={'transit_vpc_solution_helper': '.', 'pycfn_custom_resource' : './pycfn_custom_resource'}, install_requires=[ - 'paramiko>=1.16.0' + 'paramiko>=1.16.0', + 'requests==2.2.0', + 'cffi==1.14.3' ], classifiers=[ - 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', ], ) diff --git a/source/transit-vpc-solution-helper/transit-vpc-solution-helper.py b/source/transit-vpc-solution-helper/transit-vpc-solution-helper.py index 725c8af..d144c39 100644 --- a/source/transit-vpc-solution-helper/transit-vpc-solution-helper.py +++ b/source/transit-vpc-solution-helper/transit-vpc-solution-helper.py @@ -1,10 +1,10 @@ ###################################################################################################################### -# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. # +# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # # -# Licensed under the Amazon Software License (the "License"). You may not use this file except in compliance # +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance # # with the License. A copy of the License is located at # # # -# http://aws.amazon.com/asl/ # +# http://www.apache.org/licenses/LICENSE-2.0 # # # # or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES # # OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions # @@ -31,11 +31,12 @@ log = logging.getLogger() log.setLevel(logging.INFO) +USER_AGENT_STRING = os.environ['USER_AGENT_STRING'] # Function to create an S3 bucket event to invoke the new Lambda Function -def createS3Event(FunctName, S3Event): +def createS3Event(FunctName, S3Event, AccountId): try: - funct = boto3.client('lambda') + funct = boto3.client('lambda', config=Config(user_agent_extra=USER_AGENT_STRING)) try: response = funct.remove_permission(FunctionName=FunctName, StatementId='S3Events_' + FunctName) except Exception as e: @@ -46,9 +47,11 @@ def createS3Event(FunctName, S3Event): StatementId='S3Events_' + FunctName, Action='lambda:InvokeFunction', Principal='s3.amazonaws.com', - SourceArn="arn:aws:s3:::" + S3Event['Bucket'] + SourceArn="arn:aws:s3:::" + S3Event['Bucket'], + SourceAccount=AccountId + ) - s3 = boto3.client('s3', config=Config(signature_version='s3v4')) + s3 = boto3.client('s3', config=Config(signature_version='s3v4', user_agent_extra=USER_AGENT_STRING)) response = s3.put_bucket_notification_configuration( Bucket=S3Event['Bucket'], NotificationConfiguration=S3Event['EventPattern'] @@ -64,7 +67,7 @@ def StoreInS3(S3Info): log.debug("Storing all this data in S3: %s.", S3Info) for S3Object in S3Info: # log.error("Storing requested data in S3: %s.", S3Object) - s3 = boto3.client('s3', config=Config(signature_version='s3v4')) + s3 = boto3.client('s3', config=Config(signature_version='s3v4', user_agent_extra=USER_AGENT_STRING)) response = s3.put_object( Bucket=S3Object['Bucket'], Key=S3Object['Key'], @@ -83,7 +86,7 @@ def StoreInS3KMS(S3Info): log.debug("Storing all this data in S3: %s.", S3Info) for S3Object in S3Info: # log.debug("Storing requested data in S3: %s.", S3Object) - s3 = boto3.client('s3', config=Config(signature_version='s3v4')) + s3 = boto3.client('s3', config=Config(signature_version='s3v4', user_agent_extra=USER_AGENT_STRING)) response = s3.put_object( Bucket=S3Object['Bucket'], Key=S3Object['Key'], @@ -185,6 +188,7 @@ def create(self): CreateRandomPassword = self._resourceproperties.get('CreateRandomPassword') CreateUniqueID = self._resourceproperties.get('CreateUniqueID') SendData = self._resourceproperties.get('SendAnonymousData') + AccountId = self._resourceproperties.get('AccountId') response = None if S3Event is not None: @@ -192,7 +196,7 @@ def create(self): S3Event = ast.literal_eval(S3Event) if FunctArn is not None: S3Event['EventPattern']['LambdaFunctionConfigurations'][0]['LambdaFunctionArn'] = FunctArn - createS3Event(FunctName, S3Event) + createS3Event(FunctName, S3Event, AccountId) if S3StoreKMS is not None: log.debug("Create S3StoreKMS: %s", S3StoreKMS) @@ -251,13 +255,14 @@ def update(self): FunctArn = self._resourceproperties.get('LambdaArn') S3Event = self._resourceproperties.get('S3Event') SendData = self._resourceproperties.get('SendAnonymousData') + AccountId = self._resourceproperties.get('AccountId') response = None if S3Event is not None: S3Event = ast.literal_eval(S3Event) S3Event['EventPattern']['LambdaFunctionConfigurations'][0]['LambdaFunctionArn'] = FunctArn - createS3Event(FunctName, S3Event) + createS3Event(FunctName, S3Event, AccountId) if SendData is not None: log.debug("Sending Data: %s", SendData) @@ -296,7 +301,7 @@ def delete(self): if CreateSshKey is not None: CreateSshKey = ast.literal_eval(CreateSshKey) - s3 = boto3.client('s3', config=Config(signature_version='s3v4')) + s3 = boto3.client('s3', config=Config(signature_version='s3v4', user_agent_extra=USER_AGENT_STRING)) s3.delete_object({'Bucket': CreateSshKey['Bucket'], 'Key': CreateSshKey['PrivateKey']}) s3.delete_object({'Bucket': CreateSshKey['Bucket'], 'Key': CreateSshKey['PublicKey']}) @@ -311,6 +316,7 @@ def delete(self): def lambda_handler(event, context): #print "Lambda Event \n", event #print "Lambda Context \n", context + resource = myCustomResource(event) resource.process_event() return {'message': 'done'}