diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..3f91e9bc --- /dev/null +++ b/.flake8 @@ -0,0 +1,24 @@ +[flake8] +max-line-length = 150 +max-parameters-amount = 7 +min_python_version = 3.9.0 +copyright-regexp = Copyright Amazon.com, Inc\..* +exclude = + .git, + __pycache__, + .vscode + +# enables all flake8 checks +select = A,B,B9,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,0,1,2,3,4,5,6,7,8,9 + +# disable below checks: +ignore = + FS003 # f-string missing prefix (false positives with raw strings) + T003: # add link on issue into TODO + +# disable flake8 checks for Lambda function source code that will be used inline. (max 4096 characters) +per-file-ignores = + inline_lambda.py:D100,D103,C801 + ; D100 # missing docstring in public module + ; D103 # missing docstring in public function + ; C801 # copyright notice not present diff --git a/.gitignore b/.gitignore index af5998bd..f6707e88 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - # Created by https://www.toptal.com/developers/gitignore/api/osx,node,linux,python,pycharm,windows,visualstudiocode,intellij # Edit at https://www.toptal.com/developers/gitignore?templates=osx,node,linux,python,pycharm,windows,visualstudiocode,intellij @@ -240,7 +239,6 @@ dist # Icon must end with two \r Icon - # Thumbnails ._* @@ -502,4 +500,10 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk -# End of https://www.toptal.com/developers/gitignore/api/osx,node,linux,python,pycharm,windows,visualstudiocode,intellij \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/osx,node,linux,python,pycharm,windows,visualstudiocode,intellij + +# Other +*.zip +**/local/* +**/sra_staging_manual_upload/* +**/dist-*/* diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 00000000..74a17ee6 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,4 @@ +{ + "MD013": false, + "MD024": false +} diff --git a/CHANGELOG.md b/CHANGELOG.md index cd24ca04..f2d95f33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,50 @@ -# Change Log +# Change Log + +## Table of Contents + +- [Introduction](#introduction) +- [2021-11-19](#2021-11-19) +- [2021-09-02](#2021-09-02) +- [2021-09-01](#2021-09-01) + +--- + +## Introduction + All notable changes to this project will be documented in this file. --- +## 2021-11-19 + +### Added + +- Added `.flake8`, `poetry.lock`, `pyproject.toml`, and `.markdownlint.json` to define coding standards that we will require and use when building future solutions. Contributors should use the standards defined within these files before submitting + pull requests. Existing solutions will get refactored to these standards in future updates. +- Added S3 `BucketKeyEnabled` to the solutions that create S3 objects (e.g. CloudTrail, GuardDuty, and Macie) + +### Changed + +- Removed the AWS Config Aggregator account solution since AWS Control Tower deploys an account aggregator within the Audit account. +- Modified the directory structure to support multiple internal packages (e.g. 1 for each solution). The folder structure also allows for tests (integration, unit, etc.). See + [Real Python Application with Internal Packages](https://realpython.com/python-application-layouts/#application-with-internal-packages) +- Renamed folders and files with snake_case to align with [PEP8 Package and Module Names](https://www.python.org/dev/peps/pep-0008/#package-and-module-names) +- Modified links within `README.md` files to align with the updated folders and file names +- Updated the `README.md` files to provide consistency and improved formatting. +- Renamed parameter and template files to `sra-...` +- Updated default values for parameters for resource names with sra- prefix to help with protecting resources deployed + ## 2021-09-02 -### Added +### Added - Nothing Added -### Changed +### Changed -- Removed all code and references to AWS Landing Zone as it is currently in Long-term Support and will not receive any - additional features. +- Removed all code and references to AWS Landing Zone as it is currently in Long-term Support and will not receive any additional features. -### Fixed +### Fixed - Nothing Fixed @@ -22,18 +52,18 @@ All notable changes to this project will be documented in this file. ## 2021-09-01 -### Added +### Added - AWS IAM Access Analyzer solution - Organization AWS Config Aggregator Solution - Common Register Delegated Administrator Solution -### Changed +### Changed - Nothing Changed -### Fixed +### Fixed - Nothing Fixed ---- \ No newline at end of file +--- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 914e0741..d89e6f61 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,29 +1,37 @@ -# Contributing Guidelines +# Contributing Guidelines -Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional -documentation, we greatly value feedback and contributions from our community. +## Table of Contents -Please read through this document before submitting any issues or pull requests to ensure we have all the necessary -information to effectively respond to your bug report or contribution. +- [Introduction](#introduction) +- [Reporting Bugs/Feature Requests](#reporting-bugsfeature-requests) +- [Contributing via Pull Requests](#contributing-via-pull-requests) +- [Finding contributions to work on](#finding-contributions-to-work-on) +- [Code of Conduct](#code-of-conduct) +- [Security issue notifications](#security-issue-notifications) +- [Licensing](#licensing) +## Introduction + +Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional documentation, we greatly value feedback and contributions from our community. + +Please read through this document before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution. ## Reporting Bugs/Feature Requests We welcome you to use the GitHub issue tracker to report bugs or suggest features. -When filing an issue, please check existing open, or recently closed, 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 -* The version of our code being used -* Any modifications you've made relevant to the bug -* Anything unusual about your environment or deployment +When filing an issue, please check existing open, or recently closed, 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 +- The version of our code being used +- Any modifications you've made relevant to the bug +- Anything unusual about your environment or deployment ## Contributing via Pull Requests + Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: -1. You are working against the latest source on the *master* branch. +1. You are working against the latest source on the _master_ branch. 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. @@ -36,23 +44,21 @@ To send us a pull request, please: 5. Send us a pull request, answering any default questions in the pull request interface. 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. -GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and -[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). - +GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). ## 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' 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' issues +is a great place to start. ## Code of Conduct -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). -For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact -opensource-codeofconduct@amazon.com with any additional questions or comments. +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact opensource-codeofconduct@amazon.com +with any additional questions or comments. ## Security issue notifications -If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. +If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. ## Licensing diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 319dda94..c86d95ce 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,4 +1,5 @@ Andy Wickersham Kisshore Gunasekaran Neal Rothleder -Todd Gruet \ No newline at end of file +Todd Gruet +Julio Delgado Jr. \ No newline at end of file diff --git a/GENERAL-CONTRIBUTING-GUIDANCE.md b/GENERAL-CONTRIBUTING-GUIDANCE.md index 5ce072e7..1a07493d 100644 --- a/GENERAL-CONTRIBUTING-GUIDANCE.md +++ b/GENERAL-CONTRIBUTING-GUIDANCE.md @@ -1,6 +1,14 @@ -## General Guidance for Contributing +# General Guidance for Contributing -### CloudFormation +## Table of Contents + +- [CloudFormation](#cloudformation) +- [Encryption](#encryption) +- [IAM](#iam) +- [Lambda](#lambda) +- [Testing](#testing) + +## CloudFormation - [ ] GG-CLOUDFORMATION1 = Parameterize all resource values - [ ] GG-CLOUDFORMATION2 = Include parameter groups and labels @@ -8,24 +16,21 @@ - [ ] GG-CLOUDFORMATION4 = Sort everything in alphabetical order (e.g. Labels, Parameters, Policy Actions, etc.) - [ ] GG-CLOUDFORMATION5 = No inline Lambda code - [ ] GG-CLOUDFORMATION6 = Use custom resource properties over Lambda resource environment variables -- [ ] GG-CLOUDFORMATION7 = Scan templates using CFN NAG and provide metadata with specific reason for any findings that - cannot be remediated +- [ ] GG-CLOUDFORMATION7 = Scan templates using CFN NAG and provide metadata with specific reason for any findings that cannot be remediated -### Encryption +## Encryption - [ ] GG-ENCRYPTION1 = Enable encryption by default. Customer Managed KMS Key preferred. - [ ] GG-ENCRYPTION2 = Least privilege used in key policies - -### IAM -- [ ] GG-IAM1 = All IAM roles and users must be least privileged with full action names (no wildcards) listed in - policies -- [ ] GG-IAM2 = IAM policy files and/or statements are grouped by service with read and write actions in separate - statements +## IAM + +- [ ] GG-IAM1 = All IAM roles and users must be least privileged with full action names (no wildcards) listed in policies +- [ ] GG-IAM2 = IAM policy files and/or statements are grouped by service with read and write actions in separate statements - [ ] GG-IAM3 = Avoid using AWS managed policies - [ ] GG-IAM4 = Restrict actions to a resource or resource prefix when possible - -### Lambda + +## Lambda - [ ] GG-LAMBDA1 = Add disclaimer stating input validation covered in CloudFormation - [ ] GG-LAMBDA2 = Handle all exceptions @@ -34,14 +39,10 @@ - [ ] GG-LAMBDA5 = Unique IAM role used for each function - [ ] GG-LAMBDA6 = Only include libraries that are not included by the Lambda runtime (e.g. boto3 containing new API) - [ ] GG-LAMBDA7 = Include a packaging script or instructions instead of including packaged Lambda code (e.g. zip file) -- [ ] GG-LAMBDA8 = Run a SAST scan on the code and fix all findings, if possible but at a minimum fix critical and high - findings (e.g. bandit for python) - -### Testing - -- [ ] GG-SOLUTION_TESTING1 = Test deploying the solution in a multi-account environment using Customizations for - AWS Control Tower -- [ ] GG-SOLUTION_TESTING2 = Test removing the solution in a multi-account environment following the provided - instructions -- [ ] GG-SOLUTION_TESTING3 = Have at least 1 peer review of the solution before submitting a merge/pull request +- [ ] GG-LAMBDA8 = Run a SAST scan on the code and fix all findings, if possible but at a minimum fix critical and high findings (e.g. bandit for python) + +## Testing +- [ ] GG-SOLUTION_TESTING1 = Test deploying the solution in a multi-account environment using Customizations for AWS Control Tower +- [ ] GG-SOLUTION_TESTING2 = Test removing the solution in a multi-account environment following the provided instructions +- [ ] GG-SOLUTION_TESTING3 = Have at least 1 peer review of the solution before submitting a merge/pull request diff --git a/LICENSE-SUMMARY b/LICENSE-SUMMARY index 39b5a31c..744f0480 100644 --- a/LICENSE-SUMMARY +++ b/LICENSE-SUMMARY @@ -3,3 +3,5 @@ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. The documentation is made available under the Creative Commons Attribution-ShareAlike 4.0 International License. See the LICENSE file. The sample code within this documentation is made available under the MIT-0 license. See the LICENSE-SAMPLECODE file. + +Please note when building the project that some of the configured developer dependencies are subject to copyleft licenses. Please review these as needed for your use. \ No newline at end of file diff --git a/README.md b/README.md index 5b21fb0b..64c80992 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,115 @@ +# AWS Security Reference Architecture Examples + Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 -## AWS Security Reference Architecture Examples +## Table of Contents + +- [Introduction](#introduction) +- [Example Solutions](#example-solutions) +- [Utils](#utils) +- [Repository and Solution Naming Convention](#repository-and-solution-naming-convention) +- [Frequently Asked Questions](#frequently-asked-questions) +- [Contributors](#contributors) +- [License Summary](#license-summary) + +## Introduction -This repository contains AWS CloudFormation templates to help developers and engineers deploy AWS security-related -services in a multi-account environment following patterns that align with the -[AWS Security Reference Architecture](https://docs.aws.amazon.com/prescriptive-guidance/latest/security-reference-architecture/). -The Amazon Web Services (AWS) Security Reference Architecture (AWS SRA) is a holistic set of guidelines for deploying +This repository contains AWS CloudFormation templates to help developers and engineers deploy AWS security-related services in a multi-account environment following patterns that align with the +[AWS Security Reference Architecture](https://docs.aws.amazon.com/prescriptive-guidance/latest/security-reference-architecture/). The Amazon Web Services (AWS) Security Reference Architecture (AWS SRA) is a holistic set of guidelines for deploying the full complement of AWS security services in a multi-account environment. -The AWS service configurations and resources (e.g. IAM roles and policies) deployed by these templates are deliberately -very restrictive. They are intended to illustrate an implementation path rather than provide a complete solution. -You will need to modify and tailor these templates to suit your individual environment and security needs. +The AWS service configurations and resources (e.g. IAM roles and policies) deployed by these templates are deliberately very restrictive. They are intended to illustrate an implementation path rather than provide a complete solution. You will need to +modify and tailor these templates to suit your individual environment and security needs. -The examples within this repository have been deployed and tested using the corresponding deployment -platform (e.g. AWS Control Tower and AWS CloudFormation StackSets). +The examples within this repository have been deployed and tested using the corresponding deployment platform (e.g. AWS Control Tower and AWS CloudFormation StackSets). ## Example Solutions -* CloudTrail - * [Organization CloudTrail](solutions/cloudtrail/cloudtrail-org) -* Config - * [Account Aggregator](solutions/config/aggregator-acct) - * [Organization Aggregator](solutions/config/aggregator-org) - * [Organization Conformance Pack](solutions/config/conformance-pack-org) -* Firewall Manager - * [Organization Firewall Manager](solutions/firewall-manager/firewall-manager-org) -* GuardDuty - * [Organization GuardDuty](solutions/guardduty/guardduty-org) -* IAM - * [Access Analyzer](solutions/iam/access-analyzer) - * [Account Password Policy](solutions/iam/password-policy-acct) -* Macie - * [Organization Macie](solutions/macie/macie-org) -* SecurityHub - * [Account SecurityHub Enabler](solutions/securityhub/securityhub-enabler-acct) - -## Extras - * [Prerequisites for AWS Control Tower solutions](extras/aws-control-tower/prerequisites) - * packaging-scripts - * package-lambda.sh (Creates the Lambda zip file and uploads to an S3 bucket) + +- CloudTrail + - [Organization CloudTrail](aws_sra_examples/solutions/cloudtrail/cloudtrail_org) +- Config + - [Organization Aggregator](aws_sra_examples/solutions/config/config_aggregator_org) + - [Organization Conformance Pack](aws_sra_examples/solutions/config/config_conformance_pack_org) +- Firewall Manager + - [Organization Firewall Manager](aws_sra_examples/solutions/firewall_manager/firewall_manager_org) +- GuardDuty + - [Organization GuardDuty](aws_sra_examples/solutions/guardduty/guardduty_org) +- IAM + - [Access Analyzer](aws_sra_examples/solutions/iam/iam_access_analyzer) + - [Account Password Policy](aws_sra_examples/solutions/iam/iam_password_policy_acct) +- Macie + - [Organization Macie](aws_sra_examples/solutions/macie/macie_org) +- SecurityHub + - [Account SecurityHub Enabler](aws_sra_examples/solutions/securityhub/securityhub_enabler_acct) + +## Utils + +- [Prerequisites for AWS Control Tower solutions](aws_sra_examples/utils/aws_control_tower/prerequisites) +- packaging_scripts + - package-lambda.sh (Creates the Lambda zip file and uploads to an S3 bucket) ## Repository and Solution Naming Convention -The repository is organized by AWS service solutions, which include deployment platforms (e.g., AWS Control Tower - and AWS CloudFormation StackSet). +The repository is organized by AWS service solutions, which include deployment platforms (e.g., AWS Control Tower and AWS CloudFormation StackSet). **Example:** -``` + +```shell . -|-- solutions - |-- guardduty - |-- guardduty-org - |-- aws-control-tower/ - |-- parameters/ - |-- manifest.yaml - |-- code/src/ - |-- app.py - |-- requirements.txt - |-- templates/ - |-- guardduty-org-configuration.yaml - |-- ... - |-- ... +├── solutions +│ ├── guardduty +│ │ └── guardduty_org +│ │ ├── README.md +│ │ ├── customizations_for_aws_control_tower +│ │ │ ├── manifest-v2.yaml +│ │ │ ├── manifest.yaml +│ │ │ └── parameters +│ │ ├── documentation +│ │ ├── lambda +│ │ │ └── src +│ │ │ ├── app.py +│ │ │ └── requirements.txt +│ │ └── templates +│ │ ├── guardduty-org-configuration-role.yaml +│ │ ├── guardduty-org-configuration.yaml +│ │ ├── guardduty-org-delete-detector-role.yaml +│ │ ├── guardduty-org-delivery-kms-key.yaml +│ │ └── guardduty-org-delivery-s3-bucket.yaml +│ ├── ... ``` -The example solutions within this repository can be managed/deployed to accounts using AWS Organizations or directly -within individual accounts. The suffix on the solution name identifies how the solution is managed/deployed. +The example solutions within this repository can be managed/deployed to accounts using AWS Organizations or directly within individual accounts. The suffix on the solution name identifies how the solution is managed/deployed. -| Solution Suffix | Description | -| --------------- | ----------- | -| acct | The solution is managed/deployed within each account | -| org | The solution is managed/deployed to accounts via AWS Organizations | +| Solution Suffix | Description | +| --------------- | ------------------------------------------------------------------- | +| acct | The solution is managed/deployed within each account | +| org | The solution is managed/deployed to accounts via AWS Organizations | | ou | The solution is managed/deployed to accounts via Organization Units | - ## Frequently Asked Questions -Q. How were these particular solutions chosen? -A. All the examples in this repository are derived from common patterns that many customers ask us to help them deploy - within their environments. We will be adding to the examples over time. +Q. How were these particular solutions chosen? A. All the examples in this repository are derived from common patterns that many customers ask us to help them deploy within their environments. We will be adding to the examples over time. + +Q. How were these solutions created? A. We’ve collected, cataloged, and curated our multi-account security solution knowledge based on working with a variety of AWS customers. -Q. How were these solutions created? -A. We’ve collected, cataloged, and curated our multi-account security solution knowledge based on working with a - variety of AWS customers. +Q. Who is the audience for these AWS Security Reference Architecture examples? A. Security professionals that are looking for illustrative examples of deploying security patterns in AWS. These code samples provide a starting point from which you can +build and tailor infrastructure for your needs. -Q. Who is the audience for these AWS Security Reference Architecture examples? -A. Security professionals that are looking for illustrative examples of deploying security patterns in AWS. These - code samples provide a starting point from which you can build and tailor infrastructure for your needs. +Q. Why didn't the solutions use inline Lambda functions within the CloudFormation templates? A. Reasons: -Q. Why didn't the solutions use inline Lambda functions within the CloudFormation templates? -A. Reasons: - * You should control the dependencies in your function's deployment package as stated in the - [best practices for working with AWS Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html). - * The [AWS Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html) - might not be the latest version, which contains a feature that is needed for the solution. +- You should control the dependencies in your function's deployment package as stated in the [best practices for working with AWS Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html). +- The [AWS Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html) might not be the latest version, which contains a feature that is needed for the solution. -Q. I have ideas to improve this repository. What should I do? -A. Please create an issue or submit a pull request. +Q. I have ideas to improve this repository. What should I do? A. Please create an issue or submit a pull request. ## Contributors + [Contributors](CONTRIBUTORS) ## License Summary -The documentation is made available under the Creative Commons Attribution-ShareAlike 4.0 International License. -See the LICENSE file. + +The documentation is made available under the Creative Commons Attribution-ShareAlike 4.0 International License. See the LICENSE file. The sample code within this documentation is made available under the MIT-0 license. See the LICENSE-SAMPLECODE file. + +Please note when building the project that some of the configured developer dependencies are subject to copyleft licenses. Please review these as needed for your use. diff --git a/aws_sra_examples/solutions/README.md b/aws_sra_examples/solutions/README.md new file mode 100644 index 00000000..60374cf9 --- /dev/null +++ b/aws_sra_examples/solutions/README.md @@ -0,0 +1,46 @@ +# Solutions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Solutions Folder layout](#solutions-folder-layout) +- [Resources](#resources) + +## Introduction + +The structure of the Security Reference Architecture solution folders are in the below format and include the files needed to deploy the solutions using different deployment platforms including the Customizations for AWS Control Tower and +CloudFormation StackSets. + +## Solutions Folder layout + +- aws_service_name + - aws_service_solution + - customizations_for_aws_control_tower + - parameters [required for manifest version 2020-01-01] + - solution-template-name.json [Update the values to align with your deployment] + - manifest.yaml [Update the OU, account names, and parameters to align with your deployment] + - documentation + - solution-architecture.png + - solution-architecture.pptx + - lambda + - lambda_function_1_source + - lambda_function_name.py + - requirements.txt + - lambda_function_n_source + - lambda_function_name.py + - requirements.txt + - policies + - service-control-policy.json + - iam-policy.json + - templates [CloudFormation template files for deploying resources] + - sra-solution-name-template.yaml + - scripts + - verification_script.py + - helper_script.py + +## Resources + +- [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/README.md b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/README.md new file mode 100644 index 00000000..c10d44aa --- /dev/null +++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/README.md @@ -0,0 +1,198 @@ +# Organization CloudTrail + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [Appendix](#appendix) +- [References](#references) + +## Introduction + +The Organization CloudTrail solution will create an Organization CloudTrail within the Organization Management Account that is encrypted with a Customer Managed KMS Key managed in the Audit Account and logs delivered to the Log Archive Account. An +Organization CloudTrail logs all events for all AWS accounts in the AWS Organization. + +When you create an organization trail, a trail with the name that you give it will be created in every AWS account that belongs to your organization. Users with CloudTrail permissions in member accounts will be able to see this trail when they log +into the AWS CloudTrail console from their AWS accounts, or when they run AWS CLI commands such as describe-trail. However, users in member accounts will not have sufficient permissions to delete the organization trail, turn logging on or off, change +what types of events are logged, or otherwise alter the organization trail in any way. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/sra-cloudtrail-org.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 AWS Lambda Function + +- The Lambda Function contains logic for configuring the AWS Organization CloudTrail within the `management account`. + +#### 1.3 Lambda Execution IAM Role + +- The AWS Lambda Function Role allows the AWS Lambda service to assume the role and perform actions defined in the attached IAM policies. + +#### 1.4 Lambda CloudWatch Log Group + +- All the `AWS Lambda Function` logs are sent to a CloudWatch Log Group `` to help with debugging and traceability of the actions performed. +- By default the `AWS Lambda Function` will create the CloudWatch Log Group with a `Retention` (14 days) and are encrypted with a CloudWatch Logs service managed encryption key. + +#### 1.5 Organization CloudTrail + +- AWS CloudTrail for all AWS Organization accounts +- Member accounts are automatically added and cannot modify +- Data events can be disabled via the parameters +- CloudWatch logs can be disabled via the parameters + +#### 1.6 Organization CloudTrail CloudWatch Log Group Role + +- IAM role used to send CloudTrail logs to the CloudWatch log group + +#### 1.7 Organization CloudTrail CloudWatch Log Group + +- Contains the CloudTrail logs with a `Retention` (400 days) + +--- + +### 2.0 Audit Account + +#### 2.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 2.2 Organization CloudTrail KMS Key + +- Customer managed KMS key for the AWS Organizations CloudTrail logs and S3 server-side encryption + +--- + +### 3.0 Security Log Archive Account + +#### 3.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 3.2 Organization CloudTrail S3 Bucket + +- S3 bucket where the Organization CloudTrail logs are sent for all accounts in the AWS Organization + +--- + +## Implementation Instructions + +### Prerequisites + +- AWS Control Tower is deployed. +- `aws-security-reference-architecture-examples` repository is stored on your local machine or location where you will be deploying from. + +### Staging + +1. In the `management account (home region)`, launch the AWS CloudFormation **Stack** using the [prereq-controltower-execution-role.yaml](../../../utils/aws_control_tower/prerequisites/prereq-controltower-execution-role.yaml) template file as the + source, to implement the `AWSControlTowerExecution` role pre-requisite. + - **Note:** Only do this step, if the `AWSControlTowerExecution` IAM role doesn't already exist in the Control Tower `management account`. +2. In the `management account (home region)`, launch the AWS CloudFormation **StackSet** targeting only the `management account` in all of the enabled regions (include home region) + [prereq-lambda-s3-bucket.yaml](../../../utils/aws_control_tower/prerequisites/prereq-lambda-s3-bucket.yaml) template file as the source, to implement an S3 bucket that will store the Lambda Zip files. (Example Bucket Name: + `lambda-zips--`) + - For additional guidance see [CloudFormation StackSet Instructions](#cloudformation-stackset-instructions) + - Take note of the S3 Bucket Name from the CloudFormation Outputs, as you will need it for both the packaging step, and the **Solution Deployment Order** section. + - **Note:** Only do this step if you don't already have an S3 bucket to store the Lambda zip files for CloudFormation custom resources in the Control Tower `management account`. + - Lambda functions can only access Zip files from an S3 bucket in the same AWS region as the where Lambda function resides. + - Although for this solution, S3 bucket is only needed in the `home region`, it is recommended to deploy the S3 bucket as a **stackset**, so that you can support future Lambda functions in other regions. +3. Package the Lambda code into a zip file and upload it to the S3 bucket (from above step), using the [Packaging script](../../../utils/packaging_scripts/package-lambda.sh). + - `SRA_REPO` environment variable should point to the folder where `aws-security-reference-architecture-examples` repository is stored. + - `BUCKET` environment variable should point to the S3 Bucket where the Lambda zip files are stored. + - See CloudFormation Output from Step 2 + - Or follow this syntax: `lambda-zips--` + +```bash +# Example (assumes repository was downloaded to your home directory) +export SRA_REPO="$HOME"/aws-security-reference-architecture-examples +export BUCKET=sra-staging-123456789012-us-east-1 +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name cloudtrail-org.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/lambda/src +``` + +```bash +# Export AWS CLI profile for the 'management account' +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= +export AWS_SESSION_TOKEN= + +# Use template below and set the 'SRA_REPO' and 'BUCKET' with your values. +export SRA_REPO= +export BUCKET= +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name cloudtrail-org.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/lambda/src +``` + +### Solution Deployment + +#### Customizations for AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account (home region)` using the [sra-cloudtrail-kms.yaml](templates/sra-cloudtrail-org-kms.yaml) template file as the source. +2. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Log Archive account (home region)` using the [sra-cloudtrail-org-bucket.yaml](templates/sra-cloudtrail-org-bucket.yaml) template file as the + source. +3. In the `management account (home region)`, launch an AWS CloudFormation **Stack** using the [sra-cloudtrail-org.yaml](templates/sra-cloudtrail-org.yaml) template file as the source. +4. After the initial deployment, uncomment the bucket policy statements within the [sra-cloudtrail-org-bucket.yaml](templates/sra-cloudtrail-org-bucket.yaml) and update the AWS CloudFormation **Stack Set** created in step 2 + +> If replacing an existing Organization Trail with this solution: +> +> - Update any metric filters and any other resources that reference the CloudWatch Log Group +> - If a CloudWatch Log Group Subscription is used for forwarding the logs, remove the Subscription from the old group and add it to the new group + +#### Verify Solution Deployment + +1. Log into the `Management account` and navigate to the CloudTrail page +2. Select Trails and select the "sra-cloudtrail-org" trail +3. Verify the correct configurations have been applied + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **Stack** created in step 3 of the solution deployment. +2. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 2 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +3. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 1 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +4. In the `management account (home region)`, delete the AWS CloudWatch **Log Group** (e.g. /aws/lambda/) for the Lambda function deployed in step 3 of the solution deployment. + +--- + +## Appendix + +### CloudFormation StackSet Instructions + +If you need to launch an AWS CloudFormation **StackSet** in the `management account`, see below steps (for additional details, see +[Create a stack set with self-managed permissions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started-create.html#stacksets-getting-started-create-self-managed)) + +1. AWS CloudFormation -> StackSets -> Create StackSet +2. Choose a Template (upload template) +3. Specify StackSet Details (enter parameter values) +4. Configure StackSet Options -> Self-service permissions + - IAM Admin Role Name: `AWSControlTowerStackSetRole` + - IAM Execution Role Name: `AWSControlTowerExecution` +5. Set Deployment Options -> Deploy New Stacks + - Deploy Stacks in Accounts -> enter the AWS Control Tower Management Account ID + - Specify Regions: choose regions you want to deploy stacks too (include home region) +6. If in future, you need to update the Stack Set (e.g., add/remove a region), see [Getting Started with AWS CloudFormation StackSets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started.html) + +--- + +## References + +- [Creating a CloudTrail for the Organization](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/creating-trail-organization.html) +- [Allowing Cross-Account Access to a KMS Key](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-modifying-external-accounts.html) diff --git a/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..e17f9642 --- /dev/null +++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/manifest-v2.yaml b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/manifest-v2.yaml similarity index 68% rename from solutions/cloudtrail/cloudtrail-org/aws-control-tower/manifest-v2.yaml rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/manifest-v2.yaml index 35af8896..f4545b9b 100644 --- a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/manifest-v2.yaml +++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/manifest-v2.yaml @@ -5,11 +5,11 @@ version: 2021-03-15 # Control Tower Custom Resources (Service Control Policies or CloudFormation) resources: -# ----------------------------------------------------------------------------- -# Organization CloudTrail -# ----------------------------------------------------------------------------- - - name: CloudTrailOrgKMSKey - resource_file: templates/cloudtrail-org-kms.yaml + # ----------------------------------------------------------------------------- + # Organization CloudTrail + # ----------------------------------------------------------------------------- + - name: sra-cloudtrail-org-kms + resource_file: templates/sra-cloudtrail-org-kms.yaml parameters: - parameter_key: pOrganizationCloudTrailKeyAlias parameter_value: CloudTrailOrgKMSKey @@ -18,9 +18,9 @@ resources: - parameter_key: pLoggingAccountId parameter_value: $[alfred_ssm_/org/member/logging/account_id] - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: @@ -29,17 +29,17 @@ resources: - name: /org/cloudtrail/kms_key_arn value: $[output_oOrganizationCloudTrailKeyArn] - - name: CloudTrailOrgBucket - resource_file: templates/cloudtrail-org-bucket.yaml + - name: sra-cloudtrail-org-bucket + resource_file: templates/sra-cloudtrail-org-bucket.yaml parameters: - parameter_key: pBucketNamePrefix - parameter_value: cfct-cloudtrail-org + parameter_value: sra-cloudtrail-org - parameter_key: pOrganizationCloudTrailKMSKey parameter_value: $[alfred_ssm_/org/cloudtrail/kms_key_arn] - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: @@ -48,29 +48,29 @@ resources: - name: /org/cloudtrail/s3_bucket value: $[output_oOrganizationCloudTrailS3] - - name: CloudTrailOrgConfig - resource_file: templates/cloudtrail-org.yaml + - name: sra-cloudtrail-org + resource_file: templates/sra-cloudtrail-org.yaml parameters: - parameter_key: pCloudTrailName - parameter_value: cfct-cloudtrail-org + parameter_value: sra-cloudtrail-org - parameter_key: pCloudTrailS3BucketName parameter_value: $[alfred_ssm_/org/cloudtrail/s3_bucket] - parameter_key: pCloudTrailS3KeyPrefix parameter_value: CloudTrail - parameter_key: pCreateCloudWatchLogGroup - parameter_value: "true" + parameter_value: 'true' - parameter_key: pDefaultLogGroupRetention - parameter_value: "400" + parameter_value: '400' - parameter_key: pEnableDataEventsOnly - parameter_value: "false" + parameter_value: 'false' - parameter_key: pEnableLambdaDataEvents - parameter_value: "true" + parameter_value: 'true' - parameter_key: pEnableS3DataEvents - parameter_value: "true" + parameter_value: 'true' - parameter_key: pLambdaExecutionRoleName - parameter_value: cfct-cloudtrail-org-config-lambda + parameter_value: sra-cloudtrail-org-config-lambda - parameter_key: pLambdaFunctionName - parameter_value: cfct-cloudtrail-org-config + parameter_value: sra-cloudtrail-org-config - parameter_key: pLambdaS3BucketName parameter_value: $[alfred_ssm_/org/primary/lambda_zips_bucket/us-east-1] - parameter_key: pLambdaZipFileName @@ -80,12 +80,12 @@ resources: - parameter_key: pOrganizationCloudTrailKMSKey parameter_value: $[alfred_ssm_/org/cloudtrail/kms_key_arn] - parameter_key: pResourceNamePrefix - parameter_value: cfct + parameter_value: sra - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: - - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME \ No newline at end of file + - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME diff --git a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/manifest.yaml b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/manifest.yaml similarity index 51% rename from solutions/cloudtrail/cloudtrail-org/aws-control-tower/manifest.yaml rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/manifest.yaml index 5d6656ad..142804bc 100644 --- a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/manifest.yaml +++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/manifest.yaml @@ -8,9 +8,12 @@ organization_policies: [] # Control Tower Custom CloudFormation Resources cloudformation_resources: - - name: CloudTrailOrgKMSKey - template_file: templates/cloudtrail-org-kms.yaml - parameter_file: parameters/cloudtrail-org-kms.json + # ----------------------------------------------------------------------------- + # Organization CloudTrail + # ----------------------------------------------------------------------------- + - name: sra-cloudtrail-org-kms + template_file: templates/sra-cloudtrail-org-kms.yaml + parameter_file: parameters/sra-cloudtrail-org-kms.json deploy_method: stack_set ssm_parameters: - name: /org/cloudtrail/kms_key_arn @@ -18,9 +21,9 @@ cloudformation_resources: deploy_to_account: - Audit - - name: CloudTrailOrgS3Bucket - template_file: templates/cloudtrail-org-bucket.yaml - parameter_file: parameters/cloudtrail-org-bucket.json + - name: sra-cloudtrail-org-bucket + template_file: templates/sra-cloudtrail-org-bucket.yaml + parameter_file: parameters/sra-cloudtrail-org-bucket.json deploy_method: stack_set ssm_parameters: - name: /org/cloudtrail/s3_bucket @@ -28,9 +31,9 @@ cloudformation_resources: deploy_to_account: - Log archive - - name: CloudTrailOrgConfig - template_file: templates/cloudtrail-org.yaml - parameter_file: parameters/cloudtrail-org.json + - name: sra-cloudtrail-org + template_file: templates/sra-cloudtrail-org.yaml + parameter_file: parameters/sra-cloudtrail-org.json deploy_method: stack_set deploy_to_account: - - Control Tower Primary Account \ No newline at end of file + - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME diff --git a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/parameters/cloudtrail-org-bucket.json b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/parameters/sra-cloudtrail-org-bucket.json similarity index 70% rename from solutions/cloudtrail/cloudtrail-org/aws-control-tower/parameters/cloudtrail-org-bucket.json rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/parameters/sra-cloudtrail-org-bucket.json index 40bd7c18..a41dbbf1 100644 --- a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/parameters/cloudtrail-org-bucket.json +++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/parameters/sra-cloudtrail-org-bucket.json @@ -1,7 +1,7 @@ [ { "ParameterKey": "pBucketNamePrefix", - "ParameterValue": "cfct-cloudtrail-org" + "ParameterValue": "sra-cloudtrail-org" }, { "ParameterKey": "pOrganizationCloudTrailKMSKey", @@ -9,10 +9,10 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/parameters/cloudtrail-org-kms.json b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/parameters/sra-cloudtrail-org-kms.json similarity index 86% rename from solutions/cloudtrail/cloudtrail-org/aws-control-tower/parameters/cloudtrail-org-kms.json rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/parameters/sra-cloudtrail-org-kms.json index e26c0913..6c8071f9 100644 --- a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/parameters/cloudtrail-org-kms.json +++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/parameters/sra-cloudtrail-org-kms.json @@ -13,10 +13,10 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/parameters/cloudtrail-org.json b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/parameters/sra-cloudtrail-org.json similarity index 84% rename from solutions/cloudtrail/cloudtrail-org/aws-control-tower/parameters/cloudtrail-org.json rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/parameters/sra-cloudtrail-org.json index 58f7c194..0c508253 100644 --- a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/parameters/cloudtrail-org.json +++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/customizations_for_aws_control_tower/parameters/sra-cloudtrail-org.json @@ -1,7 +1,7 @@ [ { "ParameterKey": "pCloudTrailName", - "ParameterValue": "cfct-cloudtrail-org" + "ParameterValue": "sra-cloudtrail-org" }, { "ParameterKey": "pCloudTrailS3BucketName", @@ -33,11 +33,11 @@ }, { "ParameterKey": "pLambdaExecutionRoleName", - "ParameterValue": "cfct-cloudtrail-org-config-lambda" + "ParameterValue": "sra-cloudtrail-org-config-lambda" }, { "ParameterKey": "pLambdaFunctionName", - "ParameterValue": "cfct-cloudtrail-org-config" + "ParameterValue": "sra-cloudtrail-org-config" }, { "ParameterKey": "pLambdaS3BucketName", @@ -57,14 +57,14 @@ }, { "ParameterKey": "pResourceNamePrefix", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/documentation/sra-cloudtrail-org.png b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/documentation/sra-cloudtrail-org.png new file mode 100644 index 00000000..073cb06d Binary files /dev/null and b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/documentation/sra-cloudtrail-org.png differ diff --git a/solutions/cloudtrail/cloudtrail-org/documentation/Organization-CloudTrail-Diagram.pptx b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/documentation/sra-cloudtrail-org.pptx similarity index 84% rename from solutions/cloudtrail/cloudtrail-org/documentation/Organization-CloudTrail-Diagram.pptx rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/documentation/sra-cloudtrail-org.pptx index b4ea4474..7cb3e375 100644 Binary files a/solutions/cloudtrail/cloudtrail-org/documentation/Organization-CloudTrail-Diagram.pptx and b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/documentation/sra-cloudtrail-org.pptx differ diff --git a/solutions/cloudtrail/cloudtrail-org/code/src/app.py b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/lambda/src/app.py similarity index 100% rename from solutions/cloudtrail/cloudtrail-org/code/src/app.py rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/lambda/src/app.py diff --git a/solutions/cloudtrail/cloudtrail-org/code/src/requirements.txt b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/lambda/src/requirements.txt similarity index 100% rename from solutions/cloudtrail/cloudtrail-org/code/src/requirements.txt rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/lambda/src/requirements.txt diff --git a/solutions/cloudtrail/cloudtrail-org/templates/cloudtrail-org-bucket.yaml b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org-bucket.yaml similarity index 84% rename from solutions/cloudtrail/cloudtrail-org/templates/cloudtrail-org-bucket.yaml rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org-bucket.yaml index 16e4dc85..2ee13447 100644 --- a/solutions/cloudtrail/cloudtrail-org/templates/cloudtrail-org-bucket.yaml +++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org-bucket.yaml @@ -8,8 +8,7 @@ Description: Creates the Organization CloudTrail logging S3 bucket Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Organization CloudTrail S3 Attributes Parameters: - pBucketNamePrefix @@ -29,35 +28,32 @@ Metadata: Parameters: pBucketNamePrefix: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: S3 bucket prefix. The account and region will get added to the end. e.g. bucket-prefix-123456789012-us-east-1 Default: org-trail-logs Type: String pOrganizationCloudTrailKMSKey: - AllowedPattern: - '^arn:(aws[a-zA-Z-]*)?:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$' - ConstraintDescription: - 'Key ARN example: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab' + AllowedPattern: '^arn:(aws[a-zA-Z-]*)?:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$' + ConstraintDescription: 'Key ARN example: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab' Description: KMS Key ARN to use for encrypting S3 Buckets Type: String pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -80,6 +76,7 @@ Resources: - ServerSideEncryptionByDefault: KMSMasterKeyID: !Ref pOrganizationCloudTrailKMSKey SSEAlgorithm: aws:kms + BucketKeyEnabled: True PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True @@ -99,10 +96,9 @@ Resources: PolicyDocument: Version: 2012-10-17 Statement: - - Sid: DenyPutObject Effect: Deny - Principal: "*" + Principal: '*' Action: s3:PutObject Resource: - !Sub arn:${AWS::Partition}:s3:::${rOrgTrailBucket} @@ -113,14 +109,14 @@ Resources: - Sid: SecureTransport Effect: Deny - Principal: "*" - Action: "s3:*" + Principal: '*' + Action: 's3:*' Resource: - !Sub arn:${AWS::Partition}:s3:::${rOrgTrailBucket} - !Sub arn:${AWS::Partition}:s3:::${rOrgTrailBucket}/* Condition: Bool: - "aws:SecureTransport": "false" + 'aws:SecureTransport': 'false' - Sid: AWSBucketPermissionsCheck Effect: Allow @@ -141,7 +137,7 @@ Resources: Resource: !Sub arn:${AWS::Partition}:s3:::${rOrgTrailBucket}/* Condition: StringEquals: - "s3:x-amz-acl": "bucket-owner-full-control" + 's3:x-amz-acl': 'bucket-owner-full-control' # ---------------------------------------------------------------------------- # These statements prevent creating the Org Trail @@ -165,8 +161,7 @@ Resources: # StringNotEquals: # "s3:x-amz-server-side-encryption-aws-kms-key-id": !Sub ${pOrganizationCloudTrailKMSKey} - Outputs: oOrganizationCloudTrailS3: Description: Organization CloudTrail S3 Bucket - Value: !Ref rOrgTrailBucket \ No newline at end of file + Value: !Ref rOrgTrailBucket diff --git a/solutions/cloudtrail/cloudtrail-org/templates/cloudtrail-org-kms.yaml b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org-kms.yaml similarity index 100% rename from solutions/cloudtrail/cloudtrail-org/templates/cloudtrail-org-kms.yaml rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org-kms.yaml diff --git a/solutions/cloudtrail/cloudtrail-org/templates/cloudtrail-org.yaml b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org.yaml similarity index 66% rename from solutions/cloudtrail/cloudtrail-org/templates/cloudtrail-org.yaml rename to aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org.yaml index d51983d1..0620a9fa 100644 --- a/solutions/cloudtrail/cloudtrail-org/templates/cloudtrail-org.yaml +++ b/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/templates/sra-cloudtrail-org.yaml @@ -8,8 +8,7 @@ Description: Creates and configures an Organization CloudTrail Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Organization CloudTrail Attributes Parameters: - pCloudTrailName @@ -19,8 +18,7 @@ Metadata: - pEnableLambdaDataEvents - pEnableS3DataEvents - pOrganizationCloudTrailKMSKey - - - Label: + - Label: default: Lambda Function Attributes Parameters: - pLambdaExecutionRoleName @@ -28,15 +26,13 @@ Metadata: - pLambdaS3BucketName - pLambdaZipFileName - pLogLevel - - - Label: + - Label: default: CloudWatch Log Group Attributes Parameters: - pCreateCloudWatchLogGroup - pDefaultLogGroupRetention - pResourceNamePrefix - - - Label: + - Label: default: Resource Tags Parameters: - pTagKey1 @@ -82,20 +78,17 @@ Parameters: pCloudTrailName: AllowedPattern: "^[A-Za-z0-9][a-zA-Z0-9-\\-_.]{2,127}$" ConstraintDescription: - Contain only ASCII letters (a-z, A-Z), numbers (0-9), periods (.), underscores (_), or dashes (-) - Start with a letter or number, and end with a letter or number - Be between 3 and 128 characters - Have no adjacent periods, underscores or dashes. Names like my-_namespace and my--namespace are invalid. - Not be in IP address format (for example, 192.168.5.4) + Contain only ASCII letters (a-z, A-Z), numbers (0-9), periods (.), underscores (_), or dashes (-) Start with a letter or number, and end with a + letter or number Be between 3 and 128 characters Have no adjacent periods, underscores or dashes. Names like my-_namespace and my--namespace are + invalid. Not be in IP address format (for example, 192.168.5.4) Default: organization-trail Description: CloudTrail name Type: String pCloudTrailS3BucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: CloudTrail S3 Bucket Name Type: String @@ -147,10 +140,9 @@ Parameters: Type: String pLambdaS3BucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: The Amazon S3 bucket name where the lambda zip file is stored. Example Bucket Name = lambda-zips-us-east-1 Type: String @@ -177,25 +169,23 @@ Parameters: pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String - Conditions: cCreateCloudWatchLogGroup: !Equals [!Ref pCreateCloudWatchLogGroup, true] cCreateS3KeyPrefix: !Not [!Equals [!Ref pCloudTrailS3KeyPrefix, '']] - Resources: rCloudTrailLogGroupRole: Type: AWS::IAM::Role @@ -210,15 +200,15 @@ Resources: Properties: RoleName: !Sub ${pResourceNamePrefix}-cloudtrail-cloudwatch-logs AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - - Effect: Allow - Principal: - Service: - - cloudtrail.amazonaws.com - Action: - - sts:AssumeRole - Path: "/" + - Effect: Allow + Principal: + Service: + - cloudtrail.amazonaws.com + Action: + - sts:AssumeRole + Path: '/' Policies: - PolicyName: !Sub ${pResourceNamePrefix}-cloudtrail-cloudwatch-logs PolicyDocument: @@ -244,7 +234,7 @@ Resources: Condition: cCreateCloudWatchLogGroup Properties: RetentionInDays: !Ref pDefaultLogGroupRetention - LogGroupName: !Sub "CloudTrail/${pCloudTrailName}" + LogGroupName: !Sub 'CloudTrail/${pCloudTrailName}' rLambdaLogGroup: Type: AWS::Logs::LogGroup @@ -254,9 +244,10 @@ Resources: - id: W84 reason: No KMS Key Provided DeletionPolicy: Retain + UpdateReplacePolicy: Retain Properties: RetentionInDays: !Ref pDefaultLogGroupRetention - LogGroupName: !Sub "/aws/lambda/${pLambdaFunctionName}" + LogGroupName: !Sub '/aws/lambda/${pLambdaFunctionName}' rLambdaRole: Type: AWS::IAM::Role @@ -270,92 +261,92 @@ Resources: Properties: RoleName: !Ref pLambdaExecutionRoleName AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - - Effect: Allow - Principal: - Service: - - lambda.amazonaws.com - Action: - - sts:AssumeRole - Path: "/" + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + Path: '/' Policies: - - PolicyName: cloudtrail-org-policy-logs - PolicyDocument: - Version: 2012-10-17 - Statement: - - Sid: CreateLogGroup - Effect: Allow - Action: logs:CreateLogGroup - Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup} - - - Sid: CreateLogStreamAndEvents - Effect: Allow - Action: - - logs:CreateLogStream - - logs:PutLogEvents - Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup}:log-stream:* - - - PolicyName: cloudtrail-org-policy-cloudtrail - PolicyDocument: - Version: 2012-10-17 - Statement: - - Sid: AllowCloudTrail - Effect: Allow - Action: - - cloudtrail:AddTags - - cloudtrail:RemoveTags - - cloudtrail:CreateTrail - - cloudtrail:DeleteTrail - - cloudtrail:GetEventSelectors - - cloudtrail:PutEventSelectors - - cloudtrail:StartLogging - - cloudtrail:StopLogging - - cloudtrail:UpdateTrail - Resource: !Sub arn:${AWS::Partition}:cloudtrail:${AWS::Region}:${AWS::AccountId}:trail/* - - - PolicyName: cloudtrail-org-policy-organization - PolicyDocument: - Version: 2012-10-17 - Statement: - - Sid: AllowOrganizationsAccess - Effect: Allow - Action: - - organizations:DescribeOrganization - - organizations:DisableAWSServiceAccess - - organizations:EnableAWSServiceAccess - - organizations:ListAWSServiceAccessForOrganization - - organizations:ListAccounts - Resource: "*" - - - PolicyName: cloudtrail-org-policy-iam - PolicyDocument: - Version: 2012-10-17 - Statement: - - Sid: AllowReadIamActions - Effect: Allow - Action: iam:GetRole - Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/* - - - !If - - cCreateCloudWatchLogGroup - - Sid: AllowPassRoleForCWLogGroupRole + - PolicyName: cloudtrail-org-policy-logs + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: CreateLogGroup + Effect: Allow + Action: logs:CreateLogGroup + Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup} + + - Sid: CreateLogStreamAndEvents + Effect: Allow + Action: + - logs:CreateLogStream + - logs:PutLogEvents + Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup}:log-stream:* + + - PolicyName: cloudtrail-org-policy-cloudtrail + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowCloudTrail + Effect: Allow + Action: + - cloudtrail:AddTags + - cloudtrail:RemoveTags + - cloudtrail:CreateTrail + - cloudtrail:DeleteTrail + - cloudtrail:GetEventSelectors + - cloudtrail:PutEventSelectors + - cloudtrail:StartLogging + - cloudtrail:StopLogging + - cloudtrail:UpdateTrail + Resource: !Sub arn:${AWS::Partition}:cloudtrail:${AWS::Region}:${AWS::AccountId}:trail/* + + - PolicyName: cloudtrail-org-policy-organization + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowOrganizationsAccess Effect: Allow - Action: iam:PassRole - Resource: !GetAtt rCloudTrailLogGroupRole.Arn - Condition: - StringEqualsIfExists: - iam:PassedToService: - - cloudtrail.amazonaws.com - - !Ref AWS::NoValue - - - Sid: AllowCreateDeleteServiceLinkedRole - Effect: Allow - Action: - - iam:CreateServiceLinkedRole - - iam:DeleteServiceLinkedRole - Resource: - - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/cloudtrail.amazonaws.com/AWSServiceRoleForCloudTrail* + Action: + - organizations:DescribeOrganization + - organizations:DisableAWSServiceAccess + - organizations:EnableAWSServiceAccess + - organizations:ListAWSServiceAccessForOrganization + - organizations:ListAccounts + Resource: '*' + + - PolicyName: cloudtrail-org-policy-iam + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowReadIamActions + Effect: Allow + Action: iam:GetRole + Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/* + + - !If + - cCreateCloudWatchLogGroup + - Sid: AllowPassRoleForCWLogGroupRole + Effect: Allow + Action: iam:PassRole + Resource: !GetAtt rCloudTrailLogGroupRole.Arn + Condition: + StringEqualsIfExists: + iam:PassedToService: + - cloudtrail.amazonaws.com + - !Ref AWS::NoValue + + - Sid: AllowCreateDeleteServiceLinkedRole + Effect: Allow + Action: + - iam:CreateServiceLinkedRole + - iam:DeleteServiceLinkedRole + Resource: + - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/cloudtrail.amazonaws.com/AWSServiceRoleForCloudTrail* Tags: - Key: !Ref pTagKey1 Value: !Ref pTagValue1 @@ -372,7 +363,7 @@ Resources: Properties: Description: Update the S3 account level public access block settings FunctionName: !Ref pLambdaFunctionName - Handler: "app.lambda_handler" + Handler: 'app.lambda_handler' MemorySize: 128 ReservedConcurrentExecutions: 1 Role: !GetAtt rLambdaRole.Arn @@ -390,7 +381,7 @@ Resources: rLambdaCustomResource: Type: Custom::LambdaCustomResource - Version: "1.0" + Version: '1.0' Properties: ServiceToken: !GetAtt rLambdaFunction.Arn AWS_PARTITION: !Sub ${AWS::Partition} @@ -404,4 +395,4 @@ Resources: S3_BUCKET_NAME: !Ref pCloudTrailS3BucketName S3_KEY_PREFIX: !If [cCreateS3KeyPrefix, !Ref pCloudTrailS3KeyPrefix, ''] TAG_KEY1: !Ref pTagKey1 - TAG_VALUE1: !Ref pTagValue1 \ No newline at end of file + TAG_VALUE1: !Ref pTagValue1 diff --git a/aws_sra_examples/solutions/common/common_register_delegated_administrator/README.md b/aws_sra_examples/solutions/common/common_register_delegated_administrator/README.md new file mode 100644 index 00000000..9556e87b --- /dev/null +++ b/aws_sra_examples/solutions/common/common_register_delegated_administrator/README.md @@ -0,0 +1,173 @@ +# Register Delegated Administrator Account + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [Appendix](#appendix) +- [References](#references) + +--- + +## Introduction + +The register delegated administrator account solution is a common solution to register a delegated administrator account (e.g. Security Tooling Account) within the AWS Organizations management account using the AWS Organizations APIs. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/sra-common-register-delegated-administrator.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 AWS Lambda Function + +- The Lambda function delegates the administrator account for the provided service principals + +#### 1.3 Lambda CloudWatch Log Group + +- Contains Lambda function execution logs + +#### 1.4 Lambda Execution IAM Role + +- IAM role used by the Lambda function to enable AWS service access for the provided service and register an AWS account as the delegated administrator. + +#### 1.5 AWS Organizations + +- AWS Organizations APIs are used to delegate the administrator account + +--- + +### 2.0 Delegated Administrator Account (Audit) + +#### 2.1 Services Supported + +- The services that support a delegated administrator account can be configured and managed within this account. +- Service Principal Mapping + +| Service | Service Principal | +| ---------------------------- | -------------------------------------- | +| AWS IAM Access Analyzer | access-analyzer.amazonaws.com | +| AWS Audit Manager | auditmanager.amazonaws.com | +| AWS CloudFormation StackSets | stacksets.cloudformation.amazonaws.com | +| AWS Config | config.amazonaws.com | +| AWS Config Conformance Packs | config-multiaccountsetup.amazonaws.com | +| Amazon Macie | macie.amazonaws.com | +| AWS Security Hub | securityhub.amazonaws.com | +| Amazon S3 Storage Lens | storage-lens.s3.amazonaws.com | + +--- + +## Implementation Instructions + +### Prerequisites + +- AWS Control Tower is deployed. +- `aws-security-reference-architecture-examples` repository is stored on your local machine or location where you will be deploying from. + +### Staging + +1. In the `management account (home region)`, launch the AWS CloudFormation **Stack** using the [prereq-controltower-execution-role.yaml](../../../utils/aws_control_tower/prerequisites/prereq-controltower-execution-role.yaml) source, to implement the + `AWSControlTowerExecution` role pre-requisite. + - **Note:** Only do this step, if the `AWSControlTowerExecution` IAM role doesn't already exist in the Control Tower `management account`. +2. In the `management account (home region)`, launch the AWS CloudFormation **StackSet** targeting only the `management account` in all of the enabled regions (include home region) + [prereq-lambda-s3-bucket.yaml](../../../utils/aws_control_tower/prerequisites/prereq-lambda-s3-bucket.yaml) template file as the source, to implement an S3 bucket that will store the Lambda Zip files. (Example Bucket Name: + `lambda-zips--`) + - For additional guidance see [CloudFormation StackSet Instructions](#cloudformation-stackset-instructions) + - Take note of the S3 Bucket Name from the CloudFormation Outputs, as you will need it for both the packaging step, and the **Solution Deployment Order** section. + - **Note:** Only do this step if you don't already have an S3 bucket to store the Lambda zip files for CloudFormation custom resources in the Control Tower `management account`. + - Lambda functions can only access Zip files from an S3 bucket in the same AWS region as the where Lambda function resides. + - Although for this solution, S3 bucket is only needed in the `home region`, it is recommended to deploy the S3 bucket as a **stackset**, so that you can support future Lambda functions in other regions. +3. Package the Lambda code into a zip file and upload it to the S3 bucket (from above step), using the [Packaging script](../../../utils/packaging_scripts/package-lambda.sh). + - `SRA_REPO` environment variable should point to the folder where `aws-security-reference-architecture-examples` repository is stored. + - `BUCKET` environment variable should point to the S3 Bucket where the Lambda zip files are stored. + - See CloudFormation Output from Step 2 + - Or follow this syntax: `lambda-zips--` + +```bash +# Example (assumes repository was downloaded to your home directory) +export SRA_REPO="$HOME"/aws-security-reference-architecture-examples +export BUCKET=sra-staging-123456789012-us-east-1 +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name common-register-delegated-administrator.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/common/common_register_delegated_administrator/lambda/src +``` + +```bash +# Export AWS CLI profile for the 'management account' +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= +export AWS_SESSION_TOKEN= + +# Use template below and set the 'SRA_REPO' and 'BUCKET' with your values. +export SRA_REPO= +export BUCKET= +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name common-register-delegated-administrator.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/commmon/common_register_delegated_administrator/lambda/src +``` + +### Solution Deployment + +#### Customizations for AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack** using the [sra-common-register-delegated-administrator.yaml](templates/sra-common-register-delegated-administrator.yaml) template file as the source. + +#### Verify Solution Deployment + +- Verify the configuration using the following AWS CLI shell script + + ```shell + # Export management account AWS credentials before running the below command + for accountId in $(aws organizations list-delegated-administrators --query 'DelegatedAdministrators[*].Id' \ + --output text); do echo -e "$accountId\n Service Principals: " \ + $(aws organizations list-delegated-services-for-account --account-id $accountId \ + --query 'DelegatedServices[*].ServicePrincipal'); done + ``` + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **Stack** created in step 1 of the solution deployment. +2. In the `management account (home region)`, delete the AWS CloudWatch **Log Group** (e.g. /aws/lambda/) for the Lambda function deployed in step 3 of the solution deployment. + +--- + +## Appendix + +### CloudFormation StackSet Instructions + +If you need to launch an AWS CloudFormation **StackSet** in the `management account`, see below steps (for additional details, see +[Create a stack set with self-managed permissions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started-create.html#stacksets-getting-started-create-self-managed)) + +1. AWS CloudFormation -> StackSets -> Create StackSet +2. Choose a Template (upload template) +3. Specify StackSet Details (enter parameter values) +4. Configure StackSet Options -> Self-service permissions + - IAM Admin Role Name: `AWSControlTowerStackSetRole` + - IAM Execution Role Name: `AWSControlTowerExecution` +5. Set Deployment Options -> Deploy New Stacks + - Deploy Stacks in Accounts -> enter the AWS Control Tower Management Account ID + - Specify Regions: choose regions you want to deploy stacks too (include home region) +6. If in future, you need to update the Stack Set (e.g., add/remove a region), see [Getting Started with AWS CloudFormation StackSets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started.html) + +--- + +## References + +- [AWS services that you can use with AWS Organizations](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_integrate_services_list.html) diff --git a/aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..e17f9642 --- /dev/null +++ b/aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/solutions/common/register-delegated-administrator/aws-control-tower/manifest-v2.yaml b/aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/manifest-v2.yaml similarity index 58% rename from solutions/common/register-delegated-administrator/aws-control-tower/manifest-v2.yaml rename to aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/manifest-v2.yaml index 2643a695..3a39e78c 100644 --- a/solutions/common/register-delegated-administrator/aws-control-tower/manifest-v2.yaml +++ b/aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/manifest-v2.yaml @@ -5,18 +5,18 @@ version: 2021-03-15 # Control Tower Custom Resources (Service Control Policies or CloudFormation) resources: -# ----------------------------------------------------------------------------- -# Common Register Delegated Administrator Solution -# ----------------------------------------------------------------------------- - - name: CommonRegisterDelegatedAdmin - resource_file: templates/common-register-delegated-administrator.yaml + # ----------------------------------------------------------------------------- + # Common Register Delegated Administrator Solution + # ----------------------------------------------------------------------------- + - name: sra-common-register-delegated-administrator + resource_file: templates/sra-common-register-delegated-administrator.yaml parameters: - parameter_key: pDelegatedAdminAccountId parameter_value: $[alfred_ssm_/org/member/Audit/account_id] - parameter_key: pLambdaExecutionRoleName - parameter_value: cfct-aggregator-register-delegated-admin-lambda + parameter_value: sra-common-register-delegated-administrator-lambda - parameter_key: pLambdaFunctionName - parameter_value: cfct-aggregator-register-delegated-admin + parameter_value: sra-common-register-delegated-administrator - parameter_key: pLambdaS3BucketName parameter_value: $[alfred_ssm_/org/primary/lambda_zips_bucket/us-east-1] - parameter_key: pLambdaZipFileName @@ -24,12 +24,12 @@ resources: - parameter_key: pLogLevel parameter_value: debug - parameter_key: pServicePrincipalList - parameter_value: "CHANGE_ME_SERVICE_PRINCIPAL_LIST" + parameter_value: CHANGE_ME_SERVICE_PRINCIPAL_LIST - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: - - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME \ No newline at end of file + - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME diff --git a/solutions/common/register-delegated-administrator/aws-control-tower/manifest.yaml b/aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/manifest.yaml similarity index 74% rename from solutions/common/register-delegated-administrator/aws-control-tower/manifest.yaml rename to aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/manifest.yaml index 51f915d9..0968477e 100644 --- a/solutions/common/register-delegated-administrator/aws-control-tower/manifest.yaml +++ b/aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/manifest.yaml @@ -11,9 +11,9 @@ cloudformation_resources: # ----------------------------------------------------------------------------- # Common Register Delegated Administrator # ----------------------------------------------------------------------------- - - name: CommonRegisterDelegatedAdmin - template_file: templates/common-register-delegated-administrator.yaml - parameter_file: parameters/common-register-delegated-administrator.json + - name: sra-common-register-delegated-administrator + template_file: templates/sra-common-register-delegated-administrator.yaml + parameter_file: parameters/sra-common-register-delegated-administrator.json deploy_method: stack_set deploy_to_account: - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME diff --git a/solutions/config/conformance-pack-org/aws-control-tower/parameters/conformance-pack-org-register-delegated-admin.json b/aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/parameters/sra-common-register-delegated-administrator.json similarity index 59% rename from solutions/config/conformance-pack-org/aws-control-tower/parameters/conformance-pack-org-register-delegated-admin.json rename to aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/parameters/sra-common-register-delegated-administrator.json index bae4db58..816ce59e 100644 --- a/solutions/config/conformance-pack-org/aws-control-tower/parameters/conformance-pack-org-register-delegated-admin.json +++ b/aws_sra_examples/solutions/common/common_register_delegated_administrator/customizations_for_aws_control_tower/parameters/sra-common-register-delegated-administrator.json @@ -1,19 +1,15 @@ [ - { - "ParameterKey": "pDefaultLogGroupRetention", - "ParameterValue": "30" - }, { "ParameterKey": "pDelegatedAdminAccountId", "ParameterValue": "$[alfred_ssm_/org/member/Audit/account_id]" }, { "ParameterKey": "pLambdaExecutionRoleName", - "ParameterValue": "cfct-config-register-delegated-admin-lambda" + "ParameterValue": "sra-common-register-delegated-admin-lambda" }, { "ParameterKey": "pLambdaFunctionName", - "ParameterValue": "cfct-config-register-delegated-admin" + "ParameterValue": "sra-common-register-delegated-admin" }, { "ParameterKey": "pLambdaS3BucketName", @@ -21,18 +17,22 @@ }, { "ParameterKey": "pLambdaZipFileName", - "ParameterValue": "organization-register-delegated-admin.zip" + "ParameterValue": "common-register-delegated-administrator.zip" }, { "ParameterKey": "pLogLevel", - "ParameterValue": "info" + "ParameterValue": "debug" + }, + { + "ParameterKey": "pServicePrincipalList", + "ParameterValue": "CHANGE_ME_SERVICE_PRINCIPAL_LIST" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/aws_sra_examples/solutions/common/common_register_delegated_administrator/documentation/sra-common-register-delegated-administrator.png b/aws_sra_examples/solutions/common/common_register_delegated_administrator/documentation/sra-common-register-delegated-administrator.png new file mode 100644 index 00000000..f6526890 Binary files /dev/null and b/aws_sra_examples/solutions/common/common_register_delegated_administrator/documentation/sra-common-register-delegated-administrator.png differ diff --git a/solutions/common/register-delegated-administrator/documentation/Register-Delegated-Admin-Architecture.pptx b/aws_sra_examples/solutions/common/common_register_delegated_administrator/documentation/sra-common-register-delegated-administrator.pptx similarity index 94% rename from solutions/common/register-delegated-administrator/documentation/Register-Delegated-Admin-Architecture.pptx rename to aws_sra_examples/solutions/common/common_register_delegated_administrator/documentation/sra-common-register-delegated-administrator.pptx index 86eb6614..c82c67c9 100644 Binary files a/solutions/common/register-delegated-administrator/documentation/Register-Delegated-Admin-Architecture.pptx and b/aws_sra_examples/solutions/common/common_register_delegated_administrator/documentation/sra-common-register-delegated-administrator.pptx differ diff --git a/solutions/common/register-delegated-administrator/code/src/app.py b/aws_sra_examples/solutions/common/common_register_delegated_administrator/lambda/src/app.py similarity index 100% rename from solutions/common/register-delegated-administrator/code/src/app.py rename to aws_sra_examples/solutions/common/common_register_delegated_administrator/lambda/src/app.py diff --git a/solutions/common/register-delegated-administrator/code/src/requirements.txt b/aws_sra_examples/solutions/common/common_register_delegated_administrator/lambda/src/requirements.txt similarity index 100% rename from solutions/common/register-delegated-administrator/code/src/requirements.txt rename to aws_sra_examples/solutions/common/common_register_delegated_administrator/lambda/src/requirements.txt diff --git a/solutions/common/register-delegated-administrator/templates/common-register-delegated-administrator.yaml b/aws_sra_examples/solutions/common/common_register_delegated_administrator/templates/sra-common-register-delegated-administrator.yaml similarity index 87% rename from solutions/common/register-delegated-administrator/templates/common-register-delegated-administrator.yaml rename to aws_sra_examples/solutions/common/common_register_delegated_administrator/templates/sra-common-register-delegated-administrator.yaml index e398fd36..4e30000e 100644 --- a/solutions/common/register-delegated-administrator/templates/common-register-delegated-administrator.yaml +++ b/aws_sra_examples/solutions/common/common_register_delegated_administrator/templates/sra-common-register-delegated-administrator.yaml @@ -8,8 +8,7 @@ Description: Register delegated administrator account Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Lambda Function Attributes Parameters: - pDelegatedAdminAccountId @@ -18,8 +17,7 @@ Metadata: - pLambdaZipFileName - pLogLevel - pServicePrincipalList - - - Label: + - Label: default: Lambda Role Attributes Parameters: - pLambdaExecutionRoleName @@ -67,10 +65,9 @@ Parameters: Type: String pLambdaS3BucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: The Amazon S3 bucket name where the lambda zip file is stored Type: String @@ -86,35 +83,34 @@ Parameters: Type: String pServicePrincipalList: -# AllowedValues: -# - access-analyzer.amazonaws.com -# - auditmanager.amazonaws.com -# - config-multiaccountsetup.amazonaws.com -# - config.amazonaws.com -# - macie.amazonaws.com -# - securityhub.amazonaws.com -# - stacksets.cloudformation.amazonaws.com -# - storage-lens.s3.amazonaws.com + # AllowedValues: + # - access-analyzer.amazonaws.com + # - auditmanager.amazonaws.com + # - config-multiaccountsetup.amazonaws.com + # - config.amazonaws.com + # - macie.amazonaws.com + # - securityhub.amazonaws.com + # - stacksets.cloudformation.amazonaws.com + # - storage-lens.s3.amazonaws.com Description: Comma delimited list of AWS service principals to delegate an administrator account Type: CommaDelimitedList pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String - Resources: rLambdaRole: Type: AWS::IAM::Role @@ -127,14 +123,14 @@ Resources: reason: The role name is defined to identify resources Properties: AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole - Path: "/" + Path: '/' Policies: - PolicyName: register-delegated-admin-policy-logs PolicyDocument: @@ -165,7 +161,7 @@ Resources: - organizations:ListDelegatedAdministrators - organizations:RegisterDelegatedAdministrator Effect: Allow - Resource: "*" + Resource: '*' Sid: OrganizationsAccess RoleName: !Ref pLambdaExecutionRoleName Tags: @@ -202,7 +198,7 @@ Resources: rLambdaCustomResource: Type: Custom::LambdaCustomResource - Version: "1.0" + Version: '1.0' Properties: ServiceToken: !GetAtt rLambdaFunction.Arn AWS_SERVICE_PRINCIPAL_LIST: !Ref pServicePrincipalList diff --git a/aws_sra_examples/solutions/config/config_aggregator_org/README.md b/aws_sra_examples/solutions/config/config_aggregator_org/README.md new file mode 100644 index 00000000..ca845121 --- /dev/null +++ b/aws_sra_examples/solutions/config/config_aggregator_org/README.md @@ -0,0 +1,98 @@ +# AWS Config Aggregator + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [References](#references) + +--- + +## Introduction + +The AWS Config Aggregator Organization solution configures an AWS Config aggregator by delegating administration to a member account (e.g. Audit or Security Tooling) within the Organization Management account and then configuring AWS Config +Aggregator within the delegated administrator account for all the existing and future AWS Organization accounts. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/config-aggregator-org.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 AWS Organizations + +- AWS Organizations is used to delegate an administrator account for AWS Config and to identify AWS accounts for aggregation. + +--- + +### 2.0 Delegated Administrator Account (e.g. Security Tooling, Audit) + +#### 2.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 2.2 AWS Config Aggregator IAM Role + +- IAM role used by AWS Config to access AWS Organizations APIs + +#### 2.3 AWS Config Aggregator + +- AWS Config Aggregator is configured for the AWS Organization and all AWS Regions. + +--- + +### 3.0 All Existing and Future Organization Member Accounts + +#### 3.1 AWS Config Aggregator + +- AWS Config Aggregator within each member account has Authorizations for the Delegated Administrator Account to collect AWS Config compliance and configuration data. + +--- + +## Implementation Instructions + +### Prerequisites + +- AWS Control Tower is deployed. +- `aws-security-reference-architecture-examples` repository is stored on your local machine or location where you will be deploying from. +- Register a `delegated administrator` using the [Common Register Delegated Administrator](../../common/common_register_delegated_administrator) solution + - pServicePrincipalList = "config.amazonaws.com" + +### Solution Deployment + +#### Customizations for AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account (home region)` using the [sra-config-aggregator-org-configuration.yaml](templates/sra-config-aggregator-org-configuration.yaml) + template file as the source. + +#### Verify Solution Deployment + +- Log into the Audit account and navigate to the AWS Config page + 1. Verify the correct AWS Config Aggregator configurations have been applied + 2. Verify all existing accounts have been enabled (This can take a few minutes to complete) + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 1 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +2. Clean up the `delegated administrator` registered in the **Prerequisites** + +--- + +## References + +- [Multi-Account Multi-Region Data Aggregation](https://docs.aws.amazon.com/config/latest/developerguide/aggregate-data.html) diff --git a/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..e17f9642 --- /dev/null +++ b/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/manifest-v2.yaml b/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/manifest-v2.yaml new file mode 100644 index 00000000..c3184a09 --- /dev/null +++ b/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/manifest-v2.yaml @@ -0,0 +1,25 @@ +--- +#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets +region: us-east-1 +version: 2021-03-15 + +# Control Tower Custom Resources (Service Control Policies or CloudFormation) +resources: + # ----------------------------------------------------------------------------- + # AWS Config Aggregator Solution + # ----------------------------------------------------------------------------- + - name: sra-config-aggregator-org-configuration + resource_file: templates/sra-config-aggregator-org-configuration.yaml + parameters: + - parameter_key: pAggregatorName + parameter_value: sra-org-config-aggregator + - parameter_key: pAggregatorRoleName + parameter_value: sra-org-config-aggregator + - parameter_key: pTagKey1 + parameter_value: sra + - parameter_key: pTagValue1 + parameter_value: managed-by-sra + deploy_method: stack_set + deployment_targets: + accounts: + - Audit diff --git a/solutions/config/aggregator-org/aws-control-tower/manifest.yaml b/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/manifest.yaml similarity index 74% rename from solutions/config/aggregator-org/aws-control-tower/manifest.yaml rename to aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/manifest.yaml index 7ec939f6..d874ecfe 100644 --- a/solutions/config/aggregator-org/aws-control-tower/manifest.yaml +++ b/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/manifest.yaml @@ -11,9 +11,9 @@ cloudformation_resources: # ----------------------------------------------------------------------------- # AWS Config Aggregator Organization Solution # ----------------------------------------------------------------------------- - - name: AggregatorConfiguration - template_file: templates/aggregator-org-configuration.yaml - parameter_file: parameters/aggregator-org-configuration.json + - name: sra-config-aggregator-org-configuration + template_file: templates/sra-config-aggregator-org-configuration.yaml + parameter_file: parameters/sra-config-aggregator-org-configuration.json deploy_method: stack_set deploy_to_account: - Audit diff --git a/solutions/config/aggregator-org/aws-control-tower/parameters/aggregator-org-configuration.json b/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/parameters/sra-config-aggregator-org-configuration.json similarity index 54% rename from solutions/config/aggregator-org/aws-control-tower/parameters/aggregator-org-configuration.json rename to aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/parameters/sra-config-aggregator-org-configuration.json index a0ed56c2..0a60e6e7 100644 --- a/solutions/config/aggregator-org/aws-control-tower/parameters/aggregator-org-configuration.json +++ b/aws_sra_examples/solutions/config/config_aggregator_org/customizations_for_aws_control_tower/parameters/sra-config-aggregator-org-configuration.json @@ -1,18 +1,18 @@ [ { "ParameterKey": "pAggregatorName", - "ParameterValue": "cfct-org-config-aggregator" + "ParameterValue": "sra-org-config-aggregator" }, { "ParameterKey": "pAggregatorRoleName", - "ParameterValue": "cfct-org-config-aggregator" + "ParameterValue": "sra-org-config-aggregator" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] diff --git a/aws_sra_examples/solutions/config/config_aggregator_org/documentation/config-aggregator-org.png b/aws_sra_examples/solutions/config/config_aggregator_org/documentation/config-aggregator-org.png new file mode 100644 index 00000000..1fa5e8e4 Binary files /dev/null and b/aws_sra_examples/solutions/config/config_aggregator_org/documentation/config-aggregator-org.png differ diff --git a/solutions/config/aggregator-org/documentation/Aggregator-Org-Architecture.pptx b/aws_sra_examples/solutions/config/config_aggregator_org/documentation/config-aggregator-org.pptx similarity index 85% rename from solutions/config/aggregator-org/documentation/Aggregator-Org-Architecture.pptx rename to aws_sra_examples/solutions/config/config_aggregator_org/documentation/config-aggregator-org.pptx index 5627ee24..11552af0 100644 Binary files a/solutions/config/aggregator-org/documentation/Aggregator-Org-Architecture.pptx and b/aws_sra_examples/solutions/config/config_aggregator_org/documentation/config-aggregator-org.pptx differ diff --git a/solutions/config/aggregator-org/templates/aggregator-org-configuration.yaml b/aws_sra_examples/solutions/config/config_aggregator_org/templates/sra-config-aggregator-org-configuration.yaml similarity index 100% rename from solutions/config/aggregator-org/templates/aggregator-org-configuration.yaml rename to aws_sra_examples/solutions/config/config_aggregator_org/templates/sra-config-aggregator-org-configuration.yaml diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/README.md b/aws_sra_examples/solutions/config/config_conformance_pack_org/README.md new file mode 100644 index 00000000..b41efe3b --- /dev/null +++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/README.md @@ -0,0 +1,135 @@ +# Conformance Pack Organization Rules + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [References](#references) + +--- + +## Introduction + +The Conformance Pack Organization Rules solution deploys Organization AWS Config rules by delegating administration to a member account within the Organization Management account and then creating an Organization Conformance Pack within the delegated +administrator account for all the existing and future AWS Organization accounts. + +An [AWS Config Conformance Pack](https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html) is a collection of AWS Config rules and remediation actions that can be easily deployed as a single entity in an account and a Region or +across an organization in AWS Organizations. + +Conformance packs are created by authoring a YAML template that contains the list of AWS Config managed or custom rules and remediation actions. You can deploy the template by using the AWS Config console or the AWS CLI. To quickly get started and to +evaluate your AWS environment, use one of the sample conformance pack templates. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/config-conformance-pack-org.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 AWS Organizations + +- AWS Organizations is used to delegate an administrator account for AWS Config and to identify AWS accounts for aggregation. + +--- + +### 2.0 Security Log Archive Account + +#### 2.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 2.2 Conformance Pack Delivery Bucket + +- Organization Conformance Packs require a delivery S3 bucket with "awsconfigconforms" as the bucket name prefix. We create this bucket within the Security Log Archive account to stay consistent with where our consolidated logs are stored. + +#### 2.3 Organization Conformance Pack + +- The Organization conformance pack template is deployed to each provided region within the `delegated administrator account` and all accounts within the AWS Organization (except excluded accounts) + +--- + +### 3.0 Audit Account + +#### 3.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 3.2 Conformance Pack Templates S3 Bucket + +- S3 bucket containing the conformance pack templates containing the collection of AWS Config rules + +#### 3.3 Organization Conformance Pack + +- See [2.3 Organization Conformance Pack](#23-organization-conformance-pack) + +--- + +### 4.0 All Existing and Future Organization Member Accounts + +#### 4.1 AWS Config Service-Linked Roles + +- AWS Config creates 2 service-linked roles within each AWS account which are used to setup and send data to the delivery S3 bucket + - AWSServiceRoleForConfigMultiAccountSetup - is used for the AWS Config multi-account setup + - AWSServiceRoleForConfigConforms - is used to send data to the delivery S3 bucket + +#### 4.2 Organization Conformance Pack + +- See [2.3 Organization Conformance Pack](#23-organization-conformance-pack) + +--- + +## Implementation Instructions + +### Prerequisites + +- AWS Control Tower is deployed. +- `aws-security-reference-architecture-examples` repository is stored on your local machine or location where you will be deploying from. +- Register a `delegated administrator` using the [Common Register Delegated Administrator](../../common/common_register_delegated_administrator) solution + - pServicePrincipalList = "config-multiaccountsetup.amazonaws.com" +- Create the AWS Config Conformance Pack Templates S3 Bucket in the `Audit account (home region)` using the [sra-config-conformance-pack-templates-bucket.yaml](templates/sra-config-conformance-pack-templates-bucket.yaml) to create a CloudFormation + **Stack** +- Upload [Operational-Best-Practices-for-Encryption-and-Keys.yaml](./documentation/setup/conformance_pack_templates/Operational-Best-Practices-for-Encryption-and-Keys.yaml) to the AWS Config Conformance Pack Templates S3 Bucket +- Verify that all accounts in the organization have an AWS Configuration Recorder + - Run the [list_config_recorder_status.py](../../../utils/aws_control_tower/helper_scripts/list_config_recorder_status.py) within the Organization Management account to get the list of accounts without an AWS Configuration Recorder. + - Include the Account IDs without an AWS Configuration Recorder in the pExcludedAccounts parameter when deploying the [sra-config-conformance-pack-org-deployment.yaml](templates/sra-config-conformance-pack-org-deployment.yaml) template + - [Optional] Add the /org/config/conformance_pack_templates_bucket SSM Parameter in the `management account` + +### Solution Deployment + +#### Customizations for AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account` in all target regions using the + [sra-config-conformance-pack-org-deployment.yaml](templates/sra-config-conformance-pack-org-deployment.yaml) template file as the source. + +#### Verify Solution Deployment + +1. Log into the Audit account and navigate to the AWS Config page +2. Verify the correct configurations have been applied to each region + 1. Conformance packs -> OrgConformsPack-Operational-Best-Practices-for-Encryption-and-Keys-\* created in each region + 2. Settings -> Delivery location set to the `awsconfigconforms--` + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 1 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +2. Clean up the `delegated administrator` registered in the **Prerequisites** + +--- + +## References + +- [Enabling AWS Config Rules Across all Accounts in Your Organization](https://docs.aws.amazon.com/config/latest/developerguide/config-rule-multi-account-deployment.html) +- [Conformance Packs](https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html) diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..3d621646 --- /dev/null +++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/manifest-v2.yaml b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/manifest-v2.yaml new file mode 100644 index 00000000..0af2293d --- /dev/null +++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/manifest-v2.yaml @@ -0,0 +1,51 @@ +--- +#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets +region: us-east-1 +version: 2021-03-15 + +# Control Tower Custom Resources (Service Control Policies or CloudFormation) +resources: + # ----------------------------------------------------------------------------- + # Organization Config Conformance Pack + # ----------------------------------------------------------------------------- + - name: sra-config-conformance-pack-org-delivery-bucket + resource_file: templates/sra-config-conformance-pack-org-delivery-bucket.yaml + parameters: + - parameter_key: pOrganizationId + parameter_value: $[alfred_ssm_/org/primary/organization_id] + - parameter_key: pTagKey1 + parameter_value: sra + - parameter_key: pTagValue1 + parameter_value: managed-by-sra + deploy_method: stack_set + deployment_targets: + accounts: + - Log archive + export_outputs: + - name: /org/config/conformance_pack_delivery_bucket + value: $[output_oConformancePackDeliveryBucket] + + - name: sra-config-conformance-pack-org-deployment + resource_file: templates/sra-config-conformance-pack-org-deployment.yaml + parameters: + - parameter_key: pConformancePackName + parameter_value: Operational-Best-Practices-for-Encryption-and-Keys + - parameter_key: pDeliveryBucketName + parameter_value: $[alfred_ssm_/org/config/conformance_pack_delivery_bucket] + - parameter_key: pDeliveryS3KeyPrefix + parameter_value: Config + - parameter_key: pExcludedAccounts + parameter_value: REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME_AND_OTHER_ACCOUNTS_WITHOUT_CONFIG_ENABLED + - parameter_key: pTemplateBucketName + parameter_value: $[alfred_ssm_/org/config/conformance_pack_templates_bucket] + - parameter_key: pTemplatePrefix + parameter_value: Operational-Best-Practices-for-Encryption-and-Keys.yaml + deploy_method: stack_set + deployment_targets: + accounts: + - Audit + regions: + # All Governed AWS Control Tower Regions + - us-east-1 + - us-east-2 + - us-west-2 diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/manifest.yaml b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/manifest.yaml new file mode 100644 index 00000000..0e6c4c28 --- /dev/null +++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/manifest.yaml @@ -0,0 +1,34 @@ +--- +#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets +region: us-east-1 +version: 2020-01-01 + +# Control Tower Custom Service Control Policies +organization_policies: [] + +# Control Tower Custom CloudFormation Resources +cloudformation_resources: + # ----------------------------------------------------------------------------- + # Organization Config Conformance Pack + # ----------------------------------------------------------------------------- + - name: sra-config-conformance-pack-org-delivery-bucket + template_file: templates/sra-config-conformance-pack-org-delivery-bucket.yaml + parameter_file: parameters/sra-config-conformance-pack-org-delivery-bucket.json + deploy_method: stack_set + ssm_parameters: + - name: /org/config/conformance_pack_delivery_bucket + value: $[output_oConformancePackDeliveryBucket] + deploy_to_account: + - Log archive + + - name: sra-config-conformance-pack-org-deployment + template_file: templates/sra-config-conformance-pack-org-deployment.yaml + parameter_file: parameters/sra-config-conformance-pack-org-deployment.json + deploy_method: stack_set + deploy_to_account: + - Audit + regions: + # All Governed AWS Control Tower Regions + - us-east-1 + - us-east-2 + - us-west-2 diff --git a/solutions/config/conformance-pack-org/aws-control-tower/parameters/conformance-pack-org-delivery-bucket.json b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/parameters/sra-config-conformance-pack-org-delivery-bucket.json similarity index 74% rename from solutions/config/conformance-pack-org/aws-control-tower/parameters/conformance-pack-org-delivery-bucket.json rename to aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/parameters/sra-config-conformance-pack-org-delivery-bucket.json index 142b75ca..e3ae0a65 100644 --- a/solutions/config/conformance-pack-org/aws-control-tower/parameters/conformance-pack-org-delivery-bucket.json +++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/parameters/sra-config-conformance-pack-org-delivery-bucket.json @@ -5,10 +5,10 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/config/conformance-pack-org/aws-control-tower/parameters/conformance-pack-org-deployment.json b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/parameters/sra-config-conformance-pack-org-deployment.json similarity index 87% rename from solutions/config/conformance-pack-org/aws-control-tower/parameters/conformance-pack-org-deployment.json rename to aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/parameters/sra-config-conformance-pack-org-deployment.json index f4279a54..7572b224 100644 --- a/solutions/config/conformance-pack-org/aws-control-tower/parameters/conformance-pack-org-deployment.json +++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/customizations_for_aws_control_tower/parameters/sra-config-conformance-pack-org-deployment.json @@ -13,7 +13,7 @@ }, { "ParameterKey": "pExcludedAccounts", - "ParameterValue": "$[alfred_ssm_/org/member/Control-Tower-Management/account_id]" + "ParameterValue": "REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME_AND_OTHER_ACCOUNTS_WITHOUT_CONFIG_ENABLED" }, { "ParameterKey": "pTemplateBucketName", diff --git a/aws_sra_examples/solutions/config/config_conformance_pack_org/documentation/config-conformance-pack-org.png b/aws_sra_examples/solutions/config/config_conformance_pack_org/documentation/config-conformance-pack-org.png new file mode 100644 index 00000000..418198d6 Binary files /dev/null and b/aws_sra_examples/solutions/config/config_conformance_pack_org/documentation/config-conformance-pack-org.png differ diff --git a/solutions/config/conformance-pack-org/documentation/diagram/AWS-Config-Organization-Rules-Architecture.pptx b/aws_sra_examples/solutions/config/config_conformance_pack_org/documentation/config-conformance-pack-org.pptx similarity index 63% rename from solutions/config/conformance-pack-org/documentation/diagram/AWS-Config-Organization-Rules-Architecture.pptx rename to aws_sra_examples/solutions/config/config_conformance_pack_org/documentation/config-conformance-pack-org.pptx index fd0b66c2..d244198f 100644 Binary files a/solutions/config/conformance-pack-org/documentation/diagram/AWS-Config-Organization-Rules-Architecture.pptx and b/aws_sra_examples/solutions/config/config_conformance_pack_org/documentation/config-conformance-pack-org.pptx differ diff --git a/solutions/config/conformance-pack-org/documentation/setup/conformance-pack-templates/Operational-Best-Practices-for-Encryption-and-Keys.yaml b/aws_sra_examples/solutions/config/config_conformance_pack_org/documentation/setup/conformance_pack_templates/Operational-Best-Practices-for-Encryption-and-Keys.yaml similarity index 100% rename from solutions/config/conformance-pack-org/documentation/setup/conformance-pack-templates/Operational-Best-Practices-for-Encryption-and-Keys.yaml rename to aws_sra_examples/solutions/config/config_conformance_pack_org/documentation/setup/conformance_pack_templates/Operational-Best-Practices-for-Encryption-and-Keys.yaml diff --git a/solutions/config/conformance-pack-org/templates/conformance-pack-org-delivery-bucket.yaml b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-delivery-bucket.yaml similarity index 86% rename from solutions/config/conformance-pack-org/templates/conformance-pack-org-delivery-bucket.yaml rename to aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-delivery-bucket.yaml index d05a741a..576f76a9 100644 --- a/solutions/config/conformance-pack-org/templates/conformance-pack-org-delivery-bucket.yaml +++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-delivery-bucket.yaml @@ -8,8 +8,7 @@ Description: Creates S3 buckets to store the conformance pack results Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Bucket Attributes Parameters: - pOrganizationId @@ -19,9 +18,9 @@ Metadata: ParameterLabels: pOrganizationId: default: AWS Organizations ID - pTagKey1: + pTagKey1: default: Tag Key - pTagValue1: + pTagValue1: default: Tag Value Parameters: @@ -37,20 +36,19 @@ Parameters: pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String - Resources: rConformancePackBucket: Type: AWS::S3::Bucket @@ -60,6 +58,7 @@ Resources: - id: W35 reason: S3 access logging not enabled DeletionPolicy: Retain + UpdateReplacePolicy: Retain Properties: BucketEncryption: ServerSideEncryptionConfiguration: @@ -97,7 +96,7 @@ Resources: StringEquals: aws:PrincipalOrgID: !Ref pOrganizationId Effect: Allow - Principal: "*" + Principal: '*' Resource: !Sub arn:${AWS::Partition}:s3:::${rConformancePackBucket} Sid: AWSConfigConformsBucketPermissionsCheck @@ -106,7 +105,7 @@ Resources: StringEquals: aws:PrincipalOrgID: !Ref pOrganizationId Effect: Allow - Principal: "*" + Principal: '*' Resource: !Sub arn:${AWS::Partition}:s3:::${rConformancePackBucket}/* Sid: AWSConfigConformsBucketDelivery @@ -115,34 +114,33 @@ Resources: StringEquals: aws:PrincipalOrgID: !Ref pOrganizationId Effect: Allow - Principal: "*" + Principal: '*' Resource: !Sub arn:${AWS::Partition}:s3:::${rConformancePackBucket}/* Sid: AWSConfigConformsBucketReadAccess - - Action: "s3:*" + - Action: 's3:*' Condition: StringNotEquals: aws:PrincipalOrgID: !Ref pOrganizationId Effect: Deny - Principal: "*" - Resource: + Principal: '*' + Resource: - !Sub arn:${AWS::Partition}:s3:::${rConformancePackBucket} - !Sub arn:${AWS::Partition}:s3:::${rConformancePackBucket}/* Sid: DenyExternalPrincipals - - Action: "s3:*" + - Action: 's3:*' Condition: Bool: - "aws:SecureTransport": "false" + 'aws:SecureTransport': 'false' Effect: Deny - Principal: "*" + Principal: '*' Resource: - !Sub arn:${AWS::Partition}:s3:::${rConformancePackBucket} - !Sub arn:${AWS::Partition}:s3:::${rConformancePackBucket}/* Sid: SecureTransport - Outputs: oConformancePackDeliveryBucket: Description: Conformance Pack Delivery Bucket - Value: !Ref rConformancePackBucket \ No newline at end of file + Value: !Ref rConformancePackBucket diff --git a/solutions/config/conformance-pack-org/templates/conformance-pack-org-deployment.yaml b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-deployment.yaml similarity index 100% rename from solutions/config/conformance-pack-org/templates/conformance-pack-org-deployment.yaml rename to aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-org-deployment.yaml diff --git a/solutions/config/conformance-pack-org/documentation/setup/create-conformance-pack-templates-bucket.yaml b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-templates-bucket.yaml similarity index 78% rename from solutions/config/conformance-pack-org/documentation/setup/create-conformance-pack-templates-bucket.yaml rename to aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-templates-bucket.yaml index 3b2c17a7..8a917a55 100644 --- a/solutions/config/conformance-pack-org/documentation/setup/create-conformance-pack-templates-bucket.yaml +++ b/aws_sra_examples/solutions/config/config_conformance_pack_org/templates/sra-config-conformance-pack-templates-bucket.yaml @@ -8,8 +8,7 @@ Description: Creates S3 bucket to store conformance pack templates Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Bucket Attributes Parameters: - pBucketName @@ -22,17 +21,16 @@ Metadata: default: Bucket Name pOrganizationId: default: AWS Organizations ID - pTagKey1: + pTagKey1: default: Tag Key - pTagValue1: + pTagValue1: default: Tag Value Parameters: pBucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: S3 bucket name. Recommended name = conformance-pack-templates-[Account ID]-[Region] Type: String @@ -48,20 +46,19 @@ Parameters: pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String - Resources: rS3Bucket: Type: AWS::S3::Bucket @@ -69,7 +66,7 @@ Resources: cfn_nag: rules_to_suppress: - id: W35 - reason: "S3 access logging covered by CloudTrail S3 data events" + reason: 'S3 access logging covered by CloudTrail S3 data events' Properties: BucketEncryption: ServerSideEncryptionConfiguration: @@ -97,37 +94,37 @@ Resources: PolicyDocument: Version: 2012-10-17 Statement: - - Action: "s3:*" + - Action: 's3:*' Condition: StringNotEquals: aws:PrincipalOrgID: !Ref pOrganizationId Effect: Deny - Principal: "*" - Resource: + Principal: '*' + Resource: - !Sub arn:${AWS::Partition}:s3:::${rS3Bucket} - !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* Sid: DenyExternalPrincipals - - Action: "s3:*" + - Action: 's3:*' Condition: Bool: - "aws:SecureTransport": "false" + 'aws:SecureTransport': 'false' Effect: Deny - Principal: "*" + Principal: '*' Resource: !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* Sid: SecureTransport rS3BucketSSMParameter: - Type: AWS::SSM::Parameter + Type: AWS::SSM::Parameter Properties: Description: Organization conformance pack templates bucket Name: /org/config/conformance_pack_templates_bucket Type: String Value: !Ref rS3Bucket -# Tags: -# cfct: !Ref pTagValue1 # Change Tag Key Manually + Tags: + sra-solution: sra-config-conformance-pack-org Outputs: oConformancePackTemplatesBucket: Description: Conformance Pack Templates Bucket - Value: !Ref rS3Bucket \ No newline at end of file + Value: !Ref rS3Bucket diff --git a/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/README.md b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/README.md new file mode 100755 index 00000000..282bb9e6 --- /dev/null +++ b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/README.md @@ -0,0 +1,259 @@ +# Firewall Manager + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [Appendix](#appendix) +- [References](#references) + +## Introduction + +The Organization Firewall Manager solution will delegate an administrator account (e.g. Audit Account), deploy a maximum allowed security group, configure a security group policy, and configure multiple WAF policies. + +AWS Firewall Manager simplifies your AWS WAF, AWS Shield Advanced, and Amazon VPC security groups administration and maintenance tasks across multiple accounts and resources. With Firewall Manager, you set up your AWS WAF firewall rules, Shield +Advanced protections, and Amazon VPC security groups just once. Firewall Manager is particularly useful when you want to protect your entire organization rather than a few number of specific accounts and resources, or if you frequently add new +resources that you want to protect. To use Firewall Manager, your account must be a member of an organization in the AWS Organizations service, and you must **enable AWS Config** for each member account in your AWS Organization. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/firewall-manager-org.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 AWS Lambda Function + +The Lambda function contains logic to associate a delegated administrator account for Firewall Manager + +#### 1.3 Lambda Execution IAM Role + +- IAM role used by the Lambda function to configure the Firewall Delegated Administrator Account + +#### 1.4 Lambda CloudWatch Log Group + +- All the `AWS Lambda Function` logs are sent to a CloudWatch Log Group `` to help with debugging and traceability of the actions performed. +- By default the `AWS Lambda Function` will create the CloudWatch Log Group with a `Retention` (14 days) and are encrypted with a CloudWatch Logs service managed encryption key. + +#### 1.5 Firewall Manager + +- Firewall Manager APIs are used to delegate an administrator account. + +--- + +### 2.0 Audit Account + +#### 2.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 2.2 VPC and Security Group + +- A security group is used by the Firewall Manager security group policy to define the maximum allowed rules. +- A VPC is required for creating the security group. + +- **Using AWS Firewall Manager to audit VPC Security Groups:** + + - AWS Firewall Manager enables the ability to audit (and remediate - if desired) security groups across the AWS Organization Unit. This solution utilizes + [Content Audit Security Group Policies](https://docs.aws.amazon.com/waf/latest/developerguide/security-group-policies.html#security-group-policies-audit) to verify that Security Groups created across the AWS Organization Unit adhere to the rules. + - A [Usage Audit Security Group Policy](https://docs.aws.amazon.com/waf/latest/developerguide/security-group-policies.html#security-group-policies-usage) is used to identify and remediate unused security groups to keep proper hygiene in the target + accounts. + +- **Security Group Policies:** + - Firewall Manager Security Group Content Audit Policy + - This Security Group Policy utilizes a provided security group to audit against 2 rules: + - The only protocol that can ever allow inbound traffic is TCP/443 (HTTPS) + - All other protocols are allowed internally to the CIDR blocks for the VPC Networks + - Firewall Manager Unused Security Group Policy + - This Security Group policy specifically targets unused Security groups. + - If remediation is enabled, Firewall Manager will automatically clean up security groups that are not actively being used to maintain good hygiene in the AWS environment. + +#### 2.3 Firewall Manager + +- This solution utilizes AWS Firewall Manager to deploy a baseline set of [AWS Managed WAF Rules](https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html) to monitor and remediate the configured resources within the + AWS Organization. +- [Firewall Manager WAF Policies](https://docs.aws.amazon.com/waf/latest/developerguide/waf-policies.html) allow Firewall Manager to centrally mandate the application of AWS WAF Rule sets and Web ACLs to endpoints (ELBs, CloudFront Distributions, and + API Gateway) in the environment. +- The solution enforces the policies based on resource tags, which can be enforced using an IAM or SCP policy. + +- **WAF Policies:** + - FMS Regional WAF Default Policy + - Resource Types + - ELBv2 + - API Gateway + - AWS Managed Rule sets + - AWS Core Ruleset + - AWS SQL Database Ruleset + - AWS IP Reputation List + - Resource Tag + - Key: fms-default-policy + - Value: true + - FMS CloudFront Default Policy + - Resource Types + - Cloudfront Distribution + - AWS Managed Rule sets + - AWS Core Ruleset + - AWS SQL Database Ruleset + - AWS IP Reputation List + - Resource Tag + - Key: fms-default-policy + - Value: true + - FMS Regional WAF Windows Policy + - Resource Types + - ELBv2 + - API Gateway + - AWS Managed Rule sets + - AWS Windows Operating System Ruleset + - Resource Tag + - Key: workload-os + - Value: windows + - FMS Regional WAF Linux Policy + - Resource Types + - ELBv2 + - API Gateway + - AWS Managed Rule sets + - AWS Linux Operating System Ruleset + - Resource Tag + - Key: workload-os + - Value: linux + - FMS Regional WAF Posix Policy + - Resource Types + - ELBv2 + - API Gateway + - AWS Managed Rule sets + - AWS Posix Operating System Ruleset + - Resource Tag + - Key: workload-os + - Value: posix + +#### 2.4 Firewall Manager Disassociate IAM Role + +- The Firewall Manager Disassociate IAM role is deployed to the `delegated administrator account` to disassociate the account from Firewall Manager when the solution is deleted. +- Firewall Manager requires the disassociation to happen within the `delegated administrator account`. The `management account` Lambda function assumes this role to disassociate the account when the custom resource is deleted via CloudFormation. + +--- + +## Implementation Instructions + +### Prerequisites + +- AWS Control Tower is deployed. +- `aws-security-reference-architecture-examples` repository is stored on your local machine or location where you will be deploying from. + +### Staging + +1. In the `management account (home region)`, launch the AWS CloudFormation **Stack** using the [prereq-controltower-execution-role.yaml](../../../utils/aws_control_tower/prerequisites/prereq-controltower-execution-role.yaml) template file as the + source, to implement the `AWSControlTowerExecution` role pre-requisite. + - **Note:** Only do this step, if the `AWSControlTowerExecution` IAM role doesn't already exist in the Control Tower `management account`. +2. In the `management account (home region)`, launch the AWS CloudFormation **StackSet** targeting only the `management account` in all of the enabled regions (include home region) + [prereq-lambda-s3-bucket.yaml](../../../utils/aws_control_tower/prerequisites/prereq-lambda-s3-bucket.yaml) template file as the source, to implement an S3 bucket that will store the Lambda Zip files. (Example Bucket Name: + `lambda-zips--`) + - For additional guidance see [CloudFormation StackSet Instructions](#cloudformation-stackset-instructions) + - Take note of the S3 Bucket Name from the CloudFormation Outputs, as you will need it for both the packaging step, and the **Solution Deployment Order** section. + - **Note:** Only do this step if you don't already have an S3 bucket to store the Lambda zip files for CloudFormation custom resources in the Control Tower `management account`. + - Lambda functions can only access Zip files from an S3 bucket in the same AWS region as the where Lambda function resides. + - Although for this solution, S3 bucket is only needed in the `home region`, it is recommended to deploy the S3 bucket as a **stackset**, so that you can support future Lambda functions in other regions. +3. Package the Lambda code into a zip file and upload it to the S3 bucket (from above step), using the [Packaging script](../../../utils/packaging_scripts/package-lambda.sh). + - `SRA_REPO` environment variable should point to the folder where `aws-security-reference-architecture-examples` repository is stored. + - `BUCKET` environment variable should point to the S3 Bucket where the Lambda zip files are stored. + - See CloudFormation Output from Step 2 + - Or follow this syntax: `lambda-zips--` + +```bash +# Example (assumes repository was downloaded to your home directory) +export SRA_REPO="$HOME"/aws-security-reference-architecture-examples +export BUCKET=sra-staging-123456789012-us-east-1 +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name firewall-manager-org-delegate-admin.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/lambda/src +``` + +```bash +# Export AWS CLI profile for the 'management account' +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= +export AWS_SESSION_TOKEN= + +# Use template below and set the 'SRA_REPO' and 'BUCKET' with your values. +export SRA_REPO= +export BUCKET= +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name firewall-manager-org-delegate-admin.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/lambda/src +``` + +### Solution Deployment + +#### Customizations for AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack** using the [sra-firewall-manager-org-delegate-admin.yaml](templates/sra-firewall-manager-org-delegate-admin.yaml) template file as the source. +2. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account (home region)` using the + [sra-firewall-manager-org-disassociate-iam-role.yaml](templates/sra-firewall-manager-org-disassociate-iam-role.yaml) template file as the source. +3. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account (home region)` using the [sra-firewall-manager-org-sg-policy.yaml](templates/sra-firewall-manager-org-sg-policy.yaml) template + file as the source. +4. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account (home region)` using the [sra-firewall-manager-org-waf-policy.yaml](templates/sra-firewall-manager-org-waf-policy.yaml) template + file as the source. + +#### Verify Solution Deployment + +1. Log into the Audit account and navigate to the AWS Firewall Manager page +2. Verify the correct configurations have been applied + 1. Security policies + - security-group-maximum-allowed + - security-group-common-policy + - fms-regional-waf-default-policy + - fms-regional-waf-windows-policy + - fms-regional-waf-linux-policy + - fms-regional-waf-posix-policy + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 4 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +2. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 3 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +3. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 2 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +4. In the `management account (home region)`, delete the AWS CloudFormation **Stack** created in step 1 of the solution deployment. +5. In the `management account (home region)`, delete the AWS CloudWatch **Log Group** (e.g. /aws/lambda/) for the Lambda function deployed in step 3 of the solution deployment. + +--- + +## Appendix + +### CloudFormation StackSet Instructions + +If you need to launch an AWS CloudFormation **StackSet** in the `management account`, see below steps (for additional details, see +[Create a stack set with self-managed permissions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started-create.html#stacksets-getting-started-create-self-managed)) + +1. AWS CloudFormation -> StackSets -> Create StackSet +2. Choose a Template (upload template) +3. Specify StackSet Details (enter parameter values) +4. Configure StackSet Options -> Self-service permissions + - IAM Admin Role Name: `AWSControlTowerStackSetRole` + - IAM Execution Role Name: `AWSControlTowerExecution` +5. Set Deployment Options -> Deploy New Stacks + - Deploy Stacks in Accounts -> enter the AWS Control Tower Management Account ID + - Specify Regions: choose regions you want to deploy stacks too (include home region) +6. If in future, you need to update the Stack Set (e.g., add/remove a region), see [Getting Started with AWS CloudFormation StackSets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started.html) + +--- + +## References + +- [Firewall Manager Developer Guide](https://docs.aws.amazon.com/waf/latest/developerguide/fms-chapter.html) +- [Firewall Manager WAF Policies](https://docs.aws.amazon.com/waf/latest/developerguide/waf-policies.html) +- [Firewall Manager Security Group Policy Usage](https://docs.aws.amazon.com/waf/latest/developerguide/security-group-policies.html#security-group-policies-usage) diff --git a/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..e17f9642 --- /dev/null +++ b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/manifest-v2.yaml b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/manifest-v2.yaml similarity index 60% rename from solutions/firewall-manager/firewall-manager-org/aws-control-tower/manifest-v2.yaml rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/manifest-v2.yaml index c3d2a066..1f7e8615 100644 --- a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/manifest-v2.yaml +++ b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/manifest-v2.yaml @@ -5,20 +5,20 @@ version: 2021-03-15 # Control Tower Custom Resources (Service Control Policies or CloudFormation) resources: -# ----------------------------------------------------------------------------- -# Organization Firewall Manager -# ----------------------------------------------------------------------------- - - name: FirewallManagerOrgDelegateAdmin - resource_file: templates/firewall-manager-org-delegate-admin.yaml + # ----------------------------------------------------------------------------- + # Organization Firewall Manager + # ----------------------------------------------------------------------------- + - name: sra-firewall-manager-org-delegate-admin + resource_file: templates/sra-firewall-manager-org-delegate-admin.yaml parameters: - parameter_key: pDefaultLogGroupRetention - parameter_value: "14" + parameter_value: '14' - parameter_key: pDelegatedAdminAccountId parameter_value: $[alfred_ssm_/org/member/Audit/account_id] - parameter_key: pLambdaExecutionRoleName - parameter_value: cfct-firewall-manager-org-lambda + parameter_value: sra-firewall-manager-org-lambda - parameter_key: pLambdaFunctionName - parameter_value: cfct-firewall-manager-org-delegate-admin + parameter_value: sra-firewall-manager-org-delegate-admin - parameter_key: pLambdaS3BucketName parameter_value: $[alfred_ssm_/org/primary/lambda_zips_bucket/us-east-1] - parameter_key: pLambdaZipFileName @@ -26,61 +26,61 @@ resources: - parameter_key: pLogLevel parameter_value: info - parameter_key: pRoleToAssume - parameter_value: cfct-fms-disassociate + parameter_value: sra-fms-disassociate - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME export_outputs: - name: /org/firewall_manager/lambda_role - value: $[output_oLamdbaRole] + value: $[output_oLambdaRole] - - name: FirewallManagerOrgDisassociateRole - resource_file: templates/firewall-manager-org-disassociate-iam-role.yaml + - name: sra-firewall-manager-org-disassociate-iam-role + resource_file: templates/sra-firewall-manager-org-disassociate-iam-role.yaml parameters: - parameter_key: pFMSDisassociateRoleName - parameter_value: cfct-fms-disassociate + parameter_value: sra-fms-disassociate - parameter_key: pOrgManagementAccountId parameter_value: $[alfred_ssm_/org/primary/account_id] - parameter_key: pOrgManagementLambdaRoleName parameter_value: $[alfred_ssm_/org/firewall_manager/lambda_role] - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: - Audit - - name: FirewallManagerOrgSGPolicy - resource_file: templates/firewall-manager-org-sg-policy.yaml + - name: sra-firewall-manager-org-sg-policy + resource_file: templates/sra-firewall-manager-org-sg-policy.yaml parameters: - parameter_key: pCreateVpcForSG - parameter_value: "true" + parameter_value: 'true' - parameter_key: pEnableRemediation - parameter_value: "false" + parameter_value: 'false' - parameter_key: pInternalNetCIDR - parameter_value: "192.168.1.0/24" + parameter_value: '192.168.1.0/24' - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra - parameter_key: pVPCCidrBlock - parameter_value: "10.0.0.0/28" + parameter_value: '10.0.0.0/28' - parameter_key: pVpcId - parameter_value: "" + parameter_value: '' deploy_method: stack_set deployment_targets: accounts: - Audit - - name: FirewallManagerOrgWAFPolicy - resource_file: templates/firewall-manager-org-waf-policy.yaml + - name: sra-firewall-manager-org-waf-policy + resource_file: templates/sra-firewall-manager-org-waf-policy.yaml parameters: [] deploy_method: stack_set deployment_targets: diff --git a/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/manifest.yaml b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/manifest.yaml new file mode 100644 index 00000000..83f2dbf5 --- /dev/null +++ b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/manifest.yaml @@ -0,0 +1,42 @@ +--- +#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets +region: us-east-1 +version: 2020-01-01 + +# Control Tower Custom Service Control Policies +organization_policies: [] + +# Control Tower Custom CloudFormation Resources +cloudformation_resources: + # ----------------------------------------------------------------------------- + # Organization Firewall Manager + # ----------------------------------------------------------------------------- + - name: sra-firewall-manager-org-delegate-admin + template_file: templates/sra-firewall-manager-org-delegate-admin.yaml + parameter_file: parameters/sra-firewall-manager-org-delegate-admin.json + deploy_method: stack_set + ssm_parameters: + - name: /org/firewall_manager/lambda_role + value: $[output_oLambdaRole] + deploy_to_account: + - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME + + - name: sra-firewall-manager-org-disassociate-iam-role + template_file: templates/sra-firewall-manager-org-disassociate-iam-role.yaml + parameter_file: parameters/sra-firewall-manager-org-disassociate-iam-role.json + deploy_method: stack_set + deploy_to_account: + - Audit + + - name: sra-firewall-manager-org-sg-policy + template_file: templates/sra-firewall-manager-org-sg-policy.yaml + parameter_file: parameters/sra-firewall-manager-org-sg-policy.json + deploy_method: stack_set + deploy_to_account: + - Audit + + - name: sra-firewall-manager-org-waf-policy + template_file: templates/sra-firewall-manager-org-waf-policy.yaml + deploy_method: stack_set + deploy_to_account: + - Audit diff --git a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/parameters/firewall-manager-org-delegate-admin.json b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-delegate-admin.json similarity index 76% rename from solutions/firewall-manager/firewall-manager-org/aws-control-tower/parameters/firewall-manager-org-delegate-admin.json rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-delegate-admin.json index e1a92bd4..94d54af6 100644 --- a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/parameters/firewall-manager-org-delegate-admin.json +++ b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-delegate-admin.json @@ -9,11 +9,11 @@ }, { "ParameterKey": "pLambdaExecutionRoleName", - "ParameterValue": "cfct-firewall-manager-org-lambda" + "ParameterValue": "sra-firewall-manager-org-lambda" }, { "ParameterKey": "pLambdaFunctionName", - "ParameterValue": "cfct-firewall-manager-org-delegate-admin" + "ParameterValue": "sra-firewall-manager-org-delegate-admin" }, { "ParameterKey": "pLambdaS3BucketName", @@ -29,14 +29,14 @@ }, { "ParameterKey": "pRoleToAssume", - "ParameterValue": "cfct-fms-disassociate" + "ParameterValue": "sra-fms-disassociate" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/parameters/firewall-manager-org-disassociate-iam-role.json b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-disassociate-iam-role.json similarity index 77% rename from solutions/firewall-manager/firewall-manager-org/aws-control-tower/parameters/firewall-manager-org-disassociate-iam-role.json rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-disassociate-iam-role.json index cca7ef11..683ba35b 100644 --- a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/parameters/firewall-manager-org-disassociate-iam-role.json +++ b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-disassociate-iam-role.json @@ -1,7 +1,7 @@ [ { "ParameterKey": "pFMSDisassociateRoleName", - "ParameterValue": "cfct-fms-disassociate" + "ParameterValue": "sra-fms-disassociate" }, { "ParameterKey": "pOrgManagementAccountId", @@ -13,10 +13,10 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/parameters/firewall-manager-org-sg-policy.json b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-sg-policy.json similarity index 87% rename from solutions/firewall-manager/firewall-manager-org/aws-control-tower/parameters/firewall-manager-org-sg-policy.json rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-sg-policy.json index 3f8cc767..c00b6e99 100644 --- a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/parameters/firewall-manager-org-sg-policy.json +++ b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-sg-policy.json @@ -13,11 +13,11 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" }, { "ParameterKey": "pVPCCidrBlock", diff --git a/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-waf-policy.json b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-waf-policy.json new file mode 100644 index 00000000..c44dc44f --- /dev/null +++ b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/customizations_for_aws_control_tower/parameters/sra-firewall-manager-org-waf-policy.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/documentation/firewall-manager-org.png b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/documentation/firewall-manager-org.png new file mode 100644 index 00000000..caf45d14 Binary files /dev/null and b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/documentation/firewall-manager-org.png differ diff --git a/solutions/firewall-manager/firewall-manager-org/documentation/Organization-Firewall-Manager-Architecture.pptx b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/documentation/firewall-manager-org.pptx similarity index 84% rename from solutions/firewall-manager/firewall-manager-org/documentation/Organization-Firewall-Manager-Architecture.pptx rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/documentation/firewall-manager-org.pptx index c6db3087..838e6c00 100644 Binary files a/solutions/firewall-manager/firewall-manager-org/documentation/Organization-Firewall-Manager-Architecture.pptx and b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/documentation/firewall-manager-org.pptx differ diff --git a/solutions/firewall-manager/firewall-manager-org/code/src/app.py b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/lambda/src/app.py similarity index 100% rename from solutions/firewall-manager/firewall-manager-org/code/src/app.py rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/lambda/src/app.py diff --git a/solutions/firewall-manager/firewall-manager-org/code/src/requirements.txt b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/lambda/src/requirements.txt similarity index 100% rename from solutions/firewall-manager/firewall-manager-org/code/src/requirements.txt rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/lambda/src/requirements.txt diff --git a/solutions/firewall-manager/firewall-manager-org/templates/firewall-manager-org-delegate-admin.yaml b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/templates/sra-firewall-manager-org-delegate-admin.yaml similarity index 90% rename from solutions/firewall-manager/firewall-manager-org/templates/firewall-manager-org-delegate-admin.yaml rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/templates/sra-firewall-manager-org-delegate-admin.yaml index 5d27edcb..ba64dada 100644 --- a/solutions/firewall-manager/firewall-manager-org/templates/firewall-manager-org-delegate-admin.yaml +++ b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/templates/sra-firewall-manager-org-delegate-admin.yaml @@ -4,8 +4,7 @@ ######################################################################## AWSTemplateFormatVersion: 2010-09-09 Description: > - Cloudformation Stack to enable AWS Firewall Manager and delegate a member account as the - administrator + Cloudformation Stack to enable AWS Firewall Manager and delegate a member account as the administrator Metadata: AWS::CloudFormation::Interface: @@ -14,8 +13,7 @@ Metadata: default: Firewall Manager Attributes Parameters: - pDelegatedAdminAccountId - - - Label: + - Label: default: Lambda Function Attributes Parameters: - pLambdaFunctionName @@ -29,13 +27,11 @@ Metadata: - pLambdaExecutionRoleName - pRoleToAssume - - - Label: + - Label: default: CloudWatch Log Group Attributes Parameters: - pDefaultLogGroupRetention - - - Label: + - Label: default: Resource Tags Parameters: - pTagKey1 @@ -65,7 +61,7 @@ Metadata: Parameters: pDefaultLogGroupRetention: - AllowedValues: [ 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653 ] + AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653] Default: 14 Description: Specifies the number of days you want to retain log events in the CloudWatch Logs Type: String @@ -90,10 +86,9 @@ Parameters: Type: String pLambdaS3BucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: The Amazon S3 bucket name where the lambda zip file is stored. Example Bucket Name = lambda-zips-us-east-1 Type: String @@ -116,16 +111,16 @@ Parameters: pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -140,7 +135,7 @@ Resources: - id: W84 reason: KMS key not provided Properties: - LogGroupName: !Sub "/aws/lambda/${pLambdaFunctionName}" + LogGroupName: !Sub '/aws/lambda/${pLambdaFunctionName}' RetentionInDays: !Ref pDefaultLogGroupRetention rLambdaRole: @@ -175,7 +170,7 @@ Resources: StringLike: iam:AWSServiceName: fms.amazonaws.com Effect: Allow - Resource: "*" + Resource: '*' Sid: AllowCreateDeleteServiceLinkedRole - Action: @@ -194,7 +189,7 @@ Resources: - fms:DisassociateAdminAccount - fms:GetAdminAccount Effect: Allow - Resource: "*" + Resource: '*' Sid: AllowFMS - PolicyName: firewall-manager-org-policy-logs @@ -219,12 +214,12 @@ Resources: Statement: - Action: ec2:DescribeRegions Effect: Allow - Resource: "*" + Resource: '*' Sid: EC2ListRegions - Action: health:DescribeEventAggregates Effect: Allow - Resource: "*" + Resource: '*' Sid: HealthDescribeEventAggregates - Action: @@ -234,14 +229,14 @@ Resources: - organizations:EnableAWSServiceAccess - organizations:RegisterDelegatedAdministrator Effect: Allow - Resource: "*" + Resource: '*' Sid: AllowOrganizations - Action: sts:AssumeRole Effect: Allow Resource: !Sub arn:${AWS::Partition}:iam::${pDelegatedAdminAccountId}:role/${pRoleToAssume} Sid: AssumeRole - + Tags: - Key: !Ref pTagKey1 Value: !Ref pTagValue1 @@ -281,6 +276,6 @@ Resources: ServiceToken: !GetAtt rLambdaFunction.Arn Outputs: - oLamdbaRole: + oLambdaRole: Description: Lambda execution role name - Value: !Ref rLambdaRole \ No newline at end of file + Value: !Ref rLambdaRole diff --git a/solutions/firewall-manager/firewall-manager-org/templates/firewall-manager-org-disassociate-iam-role.yaml b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/templates/sra-firewall-manager-org-disassociate-iam-role.yaml similarity index 100% rename from solutions/firewall-manager/firewall-manager-org/templates/firewall-manager-org-disassociate-iam-role.yaml rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/templates/sra-firewall-manager-org-disassociate-iam-role.yaml diff --git a/solutions/firewall-manager/firewall-manager-org/templates/firewall-manager-org-sg-policy.yaml b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/templates/sra-firewall-manager-org-sg-policy.yaml similarity index 100% rename from solutions/firewall-manager/firewall-manager-org/templates/firewall-manager-org-sg-policy.yaml rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/templates/sra-firewall-manager-org-sg-policy.yaml diff --git a/solutions/firewall-manager/firewall-manager-org/templates/firewall-manager-org-waf-policy.yaml b/aws_sra_examples/solutions/firewall_manager/firewall_manager_org/templates/sra-firewall-manager-org-waf-policy.yaml similarity index 100% rename from solutions/firewall-manager/firewall-manager-org/templates/firewall-manager-org-waf-policy.yaml rename to aws_sra_examples/solutions/firewall_manager/firewall_manager_org/templates/sra-firewall-manager-org-waf-policy.yaml diff --git a/aws_sra_examples/solutions/guardduty/guardduty_org/README.md b/aws_sra_examples/solutions/guardduty/guardduty_org/README.md new file mode 100644 index 00000000..91f26c29 --- /dev/null +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/README.md @@ -0,0 +1,218 @@ +# GuardDuty Organization + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Table of Contents](#table-of-contents) +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [Appendix](#appendix) +- [References](#references) + +--- + +## Introduction + +The GuardDuty Organization solution will enable Amazon GuardDuty by delegating administration to a member account within the Organization management account and configuring GuardDuty within the delegated administrator account for all the existing and +future AWS Organization accounts. GuardDuty is also configured to send the findings to a central S3 bucket encrypted with a KMS key. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/guardduty-org.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 AWS Lambda Function + +- The Lambda function includes logic to enable and configure GuardDuty + +#### 1.3 Lambda CloudWatch Log Group + +- All the `AWS Lambda Function` logs are sent to a CloudWatch Log Group `` to help with debugging and traceability of the actions performed. +- By default the `AWS Lambda Function` will create the CloudWatch Log Group and logs are encrypted with a CloudWatch Logs service managed encryption key. + +#### 1.4 Lambda Execution IAM Role + +- IAM role used by the Lambda function to enable the GuardDuty Delegated Administrator Account within each region provided + +#### 1.5 GuardDuty + +- GuardDuty is enabled for each existing active account and region during the initial setup +- GuardDuty will automatically enable new member accounts/regions when added to the AWS Organization + +--- + +### 2.0 Security Log Archive Account + +#### 2.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 2.2 GuardDuty Delivery S3 Bucket + +- S3 bucket where GuardDuty findings are exported for each account/region within the AWS Organization + +#### 2.3 GuardDuty + +- See [1.5 GuardDuty](#15-guardduty) + +--- + +### 3.0 Audit Account + +#### 3.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 3.2 GuardDuty Delivery KMS Key + +- GuardDuty is configured to encrypt the exported findings with a customer managed KMS key + +#### 3.3 Configuration IAM Role + +- IAM role assumed by the Lambda function within the management account to configure GuardDuty within each region provided + +#### 3.4 GuardDuty + +- See [1.5 GuardDuty](#15-guardduty) + +--- + +### 4.0 All Existing and Future Organization Member Accounts + +#### 4.1 GuardDuty + +- See [1.5 GuardDuty](#15-guardduty) + +#### 4.2 Delete Detector Role + +- An IAM role is created within all the accounts to clean up the GuardDuty detectors in a CloudFormation delete event + +--- + +## Implementation Instructions + +### Prerequisites + +- AWS Control Tower is deployed. +- `aws-security-reference-architecture-examples` repository is stored on your local machine or location where you will be deploying from. +- GuardDuty is not enabled in any of the accounts within the AWS Organization + +### Staging + +1. In the `management account (home region)`, launch the AWS CloudFormation **Stack** using the [prereq-controltower-execution-role.yaml](../../../utils/aws_control_tower/prerequisites/prereq-controltower-execution-role.yaml) template file as the + source, to implement the `AWSControlTowerExecution` role pre-requisite. + - **Note:** Only do this step, if the `AWSControlTowerExecution` IAM role doesn't already exist in the Control Tower `management account`. +2. In the `management account (home region)`, launch the AWS CloudFormation **StackSet** targeting only the `management account` in all of the enabled regions (include home region) + [prereq-lambda-s3-bucket.yaml](../../../utils/aws_control_tower/prerequisites/prereq-lambda-s3-bucket.yaml) template file as the source, to implement an S3 bucket that will store the Lambda Zip files. (Example Bucket Name: + `lambda-zips--`) + - For additional guidance see [CloudFormation StackSet Instructions](#cloudformation-stackset-instructions) + - Take note of the S3 Bucket Name from the CloudFormation Outputs, as you will need it for both the packaging step, and the **Solution Deployment Order** section. + - **Note:** Only do this step if you don't already have an S3 bucket to store the Lambda zip files for CloudFormation custom resources in the Control Tower `management account`. + - Lambda functions can only access Zip files from an S3 bucket in the same AWS region as the where Lambda function resides. + - Although for this solution, S3 bucket is only needed in the `home region`, it is recommended to deploy the S3 bucket as a **stackset**, so that you can support future Lambda functions in other regions. +3. Package the Lambda code into a zip file and upload it to the S3 bucket (from above step), using the [Packaging script](../../../utils/packaging_scripts/package-lambda.sh). + - `SRA_REPO` environment variable should point to the folder where `aws-security-reference-architecture-examples` repository is stored. + - `BUCKET` environment variable should point to the S3 Bucket where the Lambda zip files are stored. + - See CloudFormation Output from Step 2 + - Or follow this syntax: `lambda-zips--` + +```bash +# Example (assumes repository was downloaded to your home directory) +export SRA_REPO="$HOME"/aws-security-reference-architecture-examples +export BUCKET=sra-staging-123456789012-us-east-1 +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name guardduty-org.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/guardduty/guardduty_org/lambda/src +``` + +```bash +# Export AWS CLI profile for the 'management account' +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= +export AWS_SESSION_TOKEN= + +# Use template below and set the 'SRA_REPO' and 'BUCKET' with your values. +export SRA_REPO= +export BUCKET= +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name guardduty-org.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/guardduty/guardduty_org/lambda/src +``` + +### Solution Deployment + +#### Customizations for AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account (home region)` using the [sra-guardduty-org-configuration-role.yaml](templates/sra-guardduty-org-configuration-role.yaml) + template file as the source. +2. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account (home region)` using the [sra-guardduty-org-delivery-kms-key.yaml](templates/sra-guardduty-org-delivery-kms-key.yaml) template + file as the source. +3. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Log archive account (home region)` using the [sra-guardduty-org-delivery-s3-bucket.yaml](templates/sra-guardduty-org-delivery-s3-bucket.yaml) + template file as the source. +4. In the `management account (home region)`, launch an AWS CloudFormation **Stack** using the [sra-guardduty-org-configuration.yaml](templates/sra-guardduty-org-configuration.yaml) template file as the source. +5. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to `All active accounts (home region)` using the [sra-guardduty-org-delete-detector-role.yaml](templates/sra-guardduty-org-delete-detector-role.yaml) + +#### Verify Solution Deployment + +1. Log into the Management account and navigate to the GuardDuty page + 1. Validate that the delegated admin account is set for each region +2. Log into the Audit account and navigate to the GuardDuty page + 1. Verify the correct GuardDuty configurations have been applied to each region + 2. Verify all existing accounts have been enabled + 3. Verify the findings export is configured for the S3 bucket + 4. Generate sample findings to verify S3 delivery +3. Log into the Log archive account and navigate to the S3 page + 1. Verify the sample findings have been delivered + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **Stack** created in step 4 of the solution deployment. +2. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 5 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +3. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 3 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. + 1. In the `Log Archive account (home region)`, empty and delete the S3 bucket created in step 3 +4. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 2 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +5. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 1 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +6. In the `management account (home region)`, delete the AWS CloudWatch **Log Group** (e.g. /aws/lambda/) for the Lambda function deployed in step 4 of the solution deployment. + +--- + +## Appendix + +### CloudFormation StackSet Instructions + +If you need to launch an AWS CloudFormation **StackSet** in the `management account`, see below steps (for additional details, see +[Create a stack set with self-managed permissions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started-create.html#stacksets-getting-started-create-self-managed)) + +1. AWS CloudFormation -> StackSets -> Create StackSet +2. Choose a Template (upload template) +3. Specify StackSet Details (enter parameter values) +4. Configure StackSet Options -> Self-service permissions + - IAM Admin Role Name: `AWSControlTowerStackSetRole` + - IAM Execution Role Name: `AWSControlTowerExecution` +5. Set Deployment Options -> Deploy New Stacks + - Deploy Stacks in Accounts -> enter the AWS Control Tower Management Account ID + - Specify Regions: choose regions you want to deploy stacks too (include home region) +6. If in future, you need to update the Stack Set (e.g., add/remove a region), see [Getting Started with AWS CloudFormation StackSets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started.html) + +--- + +## References + +- [Managing GuardDuty Accounts with AWS Organizations](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_organizations.html) diff --git a/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..e17f9642 --- /dev/null +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/solutions/guardduty/guardduty-org/aws-control-tower/manifest-v2.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/manifest-v2.yaml similarity index 59% rename from solutions/guardduty/guardduty-org/aws-control-tower/manifest-v2.yaml rename to aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/manifest-v2.yaml index 8fe4b84d..0473b708 100644 --- a/solutions/guardduty/guardduty-org/aws-control-tower/manifest-v2.yaml +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/manifest-v2.yaml @@ -5,40 +5,40 @@ version: 2021-03-15 # Control Tower Custom Resources (Service Control Policies or CloudFormation) resources: -# ----------------------------------------------------------------------------- -# Organization GuardDuty -# ----------------------------------------------------------------------------- - - name: GuardDutyOrgConfigurationRole - resource_file: templates/guardduty-org-configuration-role.yaml + # ----------------------------------------------------------------------------- + # Organization GuardDuty + # ----------------------------------------------------------------------------- + - name: sra-guardduty-org-configuration-role + resource_file: templates/sra-guardduty-org-configuration-role.yaml parameters: - parameter_key: pConfigurationRoleName - parameter_value: cfct-guardduty-configuration - - parameter_key: pOrgPrimaryAccountId + parameter_value: sra-guardduty-configuration + - parameter_key: pOrgManagementAccountId parameter_value: $[alfred_ssm_/org/primary/account_id] - - parameter_key: pOrgPrimaryLambdaRoleName - parameter_value: cfct-guardduty-org-lambda + - parameter_key: pLambdaRoleName + parameter_value: sra-guardduty-org-lambda - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: - Audit - - name: GuardDutyOrgDeliveryKMSKey - resource_file: templates/guardduty-org-delivery-kms-key.yaml + - name: sra-guardduty-org-delivery-kms-key + resource_file: templates/sra-guardduty-org-delivery-kms-key.yaml parameters: - parameter_key: pGuardDutyDeliveryKeyAlias parameter_value: GuardDutyDeliveryKMSKey - parameter_key: pLoggingAccountId - parameter_value: $[alfred_ssm_/org/member/Log-archive/account_id] - - parameter_key: pOrgPrimaryAccountId + parameter_value: $[alfred_ssm_/org/member/logging/account_id] + - parameter_key: pOrgManagementAccountId parameter_value: $[alfred_ssm_/org/primary/account_id] - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: @@ -47,17 +47,17 @@ resources: - name: /org/guardduty/kms_key_arn value: $[output_oGuardDutyDeliveryKeyArn] - - name: GuardDutyOrgDeliveryS3Bucket - resource_file: templates/guardduty-org-delivery-s3-bucket.yaml + - name: sra-guardduty-org-delivery-s3-bucket + resource_file: templates/sra-guardduty-org-delivery-s3-bucket.yaml parameters: - parameter_key: pGuardDutyDeliveryBucketPrefix - parameter_value: cfct-guardduty-delivery + parameter_value: sra-guardduty-delivery - parameter_key: pGuardDutyDeliveryKMSKeyArn parameter_value: $[alfred_ssm_/org/guardduty/kms_key_arn] - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: @@ -66,33 +66,33 @@ resources: - name: /org/guardduty/s3_bucket value: $[output_oGuardDutyDeliveryS3Bucket] - - name: GuardDutyOrgConfiguration - resource_file: templates/guardduty-org-configuration.yaml + - name: sra-guardduty-org-configuration + resource_file: templates/sra-guardduty-org-configuration.yaml parameters: - parameter_key: pAutoEnableS3Logs - parameter_value: "false" + parameter_value: 'false' - parameter_key: pConfigurationRoleName - parameter_value: cfct-guardduty-configuration + parameter_value: sra-guardduty-configuration - parameter_key: pDefaultLogGroupRetention - parameter_value: "14" + parameter_value: '14' - parameter_key: pDelegatedAdminAccountId parameter_value: $[alfred_ssm_/org/member/Audit/account_id] - parameter_key: pDeleteDetectorRoleName - parameter_value: cfct-guardduty-delete-detector + parameter_value: sra-guardduty-delete-detector - parameter_key: pEnabledRegions - parameter_value: "" + parameter_value: '' - parameter_key: pFindingPublishingFrequency parameter_value: FIFTEEN_MINUTES - parameter_key: pKMSKeyArn parameter_value: $[alfred_ssm_/org/guardduty/kms_key_arn] - parameter_key: pLambdaExecutionRoleName - parameter_value: cfct-guardduty-org-lambda + parameter_value: sra-guardduty-org-lambda - parameter_key: pLambdaFunctionName - parameter_value: cfct-guardduty-org-configuration + parameter_value: sra-guardduty-org - parameter_key: pLambdaS3BucketName parameter_value: $[alfred_ssm_/org/primary/lambda_zips_bucket/us-east-1] - parameter_key: pLambdaZipFileName - parameter_value: guardduty-org-configuration.zip + parameter_value: guardduty-org.zip - parameter_key: pLogLevel parameter_value: debug - parameter_key: pOrganizationId @@ -100,30 +100,31 @@ resources: - parameter_key: pPublishingDestinationBucketName parameter_value: $[alfred_ssm_/org/guardduty/s3_bucket] - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME - - name: GuardDutyDeleteDetectorRole - resource_file: templates/guardduty-org-delete-detector-role.yaml + - name: sra-guardduty-org-delete-detector-role + resource_file: templates/sra-guardduty-org-delete-detector-role.yaml parameters: - parameter_key: pDeleteDetectorRoleName - parameter_value: cfct-guardduty-delete-detector - - parameter_key: pOrgPrimaryAccountId + parameter_value: sra-guardduty-delete-detector + - parameter_key: pOrgManagementAccountId parameter_value: $[alfred_ssm_/org/primary/account_id] - - parameter_key: pOrgPrimaryLambdaRoleName - parameter_value: cfct-guardduty-org-lambda + - parameter_key: pLambdaRoleName + parameter_value: sra-guardduty-org-lambda - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: organizational_units: + # All OUs with active accounts - Core - - primary - - workloads \ No newline at end of file + - management + - workloads diff --git a/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/manifest.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/manifest.yaml new file mode 100644 index 00000000..501a7b59 --- /dev/null +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/manifest.yaml @@ -0,0 +1,56 @@ +--- +#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets +region: us-east-1 +version: 2020-01-01 + +# Control Tower Custom Service Control Policies +organization_policies: [] + +# Control Tower Custom CloudFormation Resources +cloudformation_resources: + # ----------------------------------------------------------------------------- + # Organization GuardDuty + # ----------------------------------------------------------------------------- + - name: sra-guardduty-org-configuration-role + template_file: templates/sra-guardduty-org-configuration-role.yaml + parameter_file: parameters/sra-guardduty-org-configuration-role.json + deploy_method: stack_set + deploy_to_account: + - Audit + + - name: sra-guardduty-org-delivery-kms-key + template_file: templates/sra-guardduty-org-delivery-kms-key.yaml + parameter_file: parameters/sra-guardduty-org-delivery-kms-key.json + deploy_method: stack_set + ssm_parameters: + - name: /org/guardduty/kms_key_arn + value: $[output_oGuardDutyDeliveryKeyArn] + deploy_to_account: + - Audit + + - name: sra-guardduty-org-delivery-s3-bucket + template_file: templates/sra-guardduty-org-delivery-s3-bucket.yaml + parameter_file: parameters/sra-guardduty-org-delivery-s3-bucket.json + deploy_method: stack_set + ssm_parameters: + - name: /org/guardduty/s3_bucket + value: $[output_oGuardDutyDeliveryS3Bucket] + deploy_to_account: + - Log archive + + - name: sra-guardduty-org-configuration + template_file: templates/sra-guardduty-org-configuration.yaml + parameter_file: parameters/sra-guardduty-org-configuration.json + deploy_method: stack_set + deploy_to_account: + - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME + + - name: sra-guardduty-org-delete-detector-role + template_file: templates/sra-guardduty-org-delete-detector-role.yaml + parameter_file: parameters/sra-guardduty-org-delete-detector-role.json + deploy_method: stack_set + deploy_to_ou: + # Add all OUs with active accounts + - Core + - management + - workloads diff --git a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-configuration-role.json b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-configuration-role.json similarity index 51% rename from solutions/macie/macie-org/aws-control-tower/parameters/macie-org-configuration-role.json rename to aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-configuration-role.json index 6424a70d..5126681c 100644 --- a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-configuration-role.json +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-configuration-role.json @@ -1,22 +1,22 @@ [ { "ParameterKey": "pConfigurationRoleName", - "ParameterValue": "cfct-macie-configuration" + "ParameterValue": "sra-guardduty-configuration" }, { "ParameterKey": "pOrgManagementAccountId", - "ParameterValue": "$[alfred_ssm_/org/member/Control-Tower-Management/account_id]" + "ParameterValue": "$[alfred_ssm_/org/primary/account_id]" }, { "ParameterKey": "pLambdaRoleName", - "ParameterValue": "cfct-macie-org-lambda" + "ParameterValue": "sra-guardduty-org-lambda" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-configuration.json b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-configuration.json similarity index 80% rename from solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-configuration.json rename to aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-configuration.json index d5df8023..7144f125 100644 --- a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-configuration.json +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-configuration.json @@ -5,7 +5,7 @@ }, { "ParameterKey": "pConfigurationRoleName", - "ParameterValue": "cfct-guardduty-configuration" + "ParameterValue": "sra-guardduty-configuration" }, { "ParameterKey": "pDefaultLogGroupRetention", @@ -17,7 +17,7 @@ }, { "ParameterKey": "pDeleteDetectorRoleName", - "ParameterValue": "cfct-guardduty-delete-detector" + "ParameterValue": "sra-guardduty-delete-detector" }, { "ParameterKey": "pFindingPublishingFrequency", @@ -33,11 +33,11 @@ }, { "ParameterKey": "pLambdaExecutionRoleName", - "ParameterValue": "cfct-guardduty-org-lambda" + "ParameterValue": "sra-guardduty-org-lambda" }, { "ParameterKey": "pLambdaFunctionName", - "ParameterValue": "cfct-guardduty-org-configuration" + "ParameterValue": "sra-guardduty-org-configuration" }, { "ParameterKey": "pLambdaS3BucketName", @@ -45,7 +45,7 @@ }, { "ParameterKey": "pLambdaZipFileName", - "ParameterValue": "guardduty-org-configuration.zip" + "ParameterValue": "guardduty-org.zip" }, { "ParameterKey": "pLogLevel", @@ -61,10 +61,10 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-delete-detector-role.json b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-delete-detector-role.json new file mode 100644 index 00000000..13bda110 --- /dev/null +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-delete-detector-role.json @@ -0,0 +1,22 @@ +[ + { + "ParameterKey": "pDeleteDetectorRoleName", + "ParameterValue": "sra-guardduty-delete-detector" + }, + { + "ParameterKey": "pOrgManagementAccountId", + "ParameterValue": "$[alfred_ssm_/org/primary/account_id]" + }, + { + "ParameterKey": "pLambdaRoleName", + "ParameterValue": "sra-guardduty-org-lambda" + }, + { + "ParameterKey": "pTagKey1", + "ParameterValue": "sra" + }, + { + "ParameterKey": "pTagValue1", + "ParameterValue": "managed-by-sra" + } +] \ No newline at end of file diff --git a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-delivery-kms-key.json b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-delivery-kms-key.json similarity index 77% rename from solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-delivery-kms-key.json rename to aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-delivery-kms-key.json index 0fa5ac59..6858408a 100644 --- a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-delivery-kms-key.json +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-delivery-kms-key.json @@ -8,15 +8,15 @@ "ParameterValue": "$[alfred_ssm_/org/member/Log-archive/account_id]" }, { - "ParameterKey": "pOrgPrimaryAccountId", + "ParameterKey": "pOrgManagementAccountId", "ParameterValue": "$[alfred_ssm_/org/primary/account_id]" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-delivery-s3-bucket.json b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-delivery-s3-bucket.json similarity index 70% rename from solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-delivery-s3-bucket.json rename to aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-delivery-s3-bucket.json index f39d2bb7..35beff03 100644 --- a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-delivery-s3-bucket.json +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-delivery-s3-bucket.json @@ -1,7 +1,7 @@ [ { "ParameterKey": "pGuardDutyDeliveryBucketPrefix", - "ParameterValue": "cfct-guardduty-delivery" + "ParameterValue": "sra-guardduty-delivery" }, { "ParameterKey": "pGuardDutyDeliveryKMSKeyArn", @@ -9,10 +9,10 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/aws_sra_examples/solutions/guardduty/guardduty_org/documentation/guardduty-org.png b/aws_sra_examples/solutions/guardduty/guardduty_org/documentation/guardduty-org.png new file mode 100644 index 00000000..8c021468 Binary files /dev/null and b/aws_sra_examples/solutions/guardduty/guardduty_org/documentation/guardduty-org.png differ diff --git a/solutions/guardduty/guardduty-org/documentation/diagram/Organization-GuardDuty-Architecture.pptx b/aws_sra_examples/solutions/guardduty/guardduty_org/documentation/guardduty-org.pptx similarity index 87% rename from solutions/guardduty/guardduty-org/documentation/diagram/Organization-GuardDuty-Architecture.pptx rename to aws_sra_examples/solutions/guardduty/guardduty_org/documentation/guardduty-org.pptx index a888adfd..8b27e4f6 100644 Binary files a/solutions/guardduty/guardduty-org/documentation/diagram/Organization-GuardDuty-Architecture.pptx and b/aws_sra_examples/solutions/guardduty/guardduty_org/documentation/guardduty-org.pptx differ diff --git a/solutions/guardduty/guardduty-org/code/src/app.py b/aws_sra_examples/solutions/guardduty/guardduty_org/lambda/src/app.py similarity index 100% rename from solutions/guardduty/guardduty-org/code/src/app.py rename to aws_sra_examples/solutions/guardduty/guardduty_org/lambda/src/app.py diff --git a/solutions/config/conformance-pack-org/code/src/requirements.txt b/aws_sra_examples/solutions/guardduty/guardduty_org/lambda/src/requirements.txt similarity index 100% rename from solutions/config/conformance-pack-org/code/src/requirements.txt rename to aws_sra_examples/solutions/guardduty/guardduty_org/lambda/src/requirements.txt diff --git a/solutions/guardduty/guardduty-org/templates/guardduty-org-configuration-role.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration-role.yaml similarity index 74% rename from solutions/guardduty/guardduty-org/templates/guardduty-org-configuration-role.yaml rename to aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration-role.yaml index 26a41c52..2a84ca28 100644 --- a/solutions/guardduty/guardduty-org/templates/guardduty-org-configuration-role.yaml +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration-role.yaml @@ -8,23 +8,22 @@ Description: Create an IAM role for configuration in the delegated administrator Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Role Attributes Parameters: - pConfigurationRoleName - - pOrgPrimaryAccountId - - pOrgPrimaryLambdaRoleName + - pOrgManagementAccountId + - pLambdaRoleName - pTagKey1 - pTagValue1 ParameterLabels: pConfigurationRoleName: default: Configuration IAM Role Name - pOrgPrimaryAccountId: - default: Organization Primary Account ID - pOrgPrimaryLambdaRoleName: - default: Organization Primary Lambda Role Name + pOrgManagementAccountId: + default: Organization Management Account ID + pLambdaRoleName: + default: Lambda Role Name pTagKey1: default: Lambda Role Tag Key pTagValue1: @@ -37,31 +36,31 @@ Parameters: Description: Configuration IAM Role Name Type: String - pOrgPrimaryAccountId: + pOrgManagementAccountId: AllowedPattern: '^\d{12}$' ConstraintDescription: Must be 12 digits - Description: Organization Primary Account ID + Description: Organization Management Account ID Type: String - pOrgPrimaryLambdaRoleName: + pLambdaRoleName: AllowedPattern: '^[\w+=,.@-]{1,64}$' ConstraintDescription: Max 64 alphanumeric characters. Also special characters supported [+, =, ., @, -] - Description: Organization Primary Account Lambda Role Name + Description: Lambda Role Name Type: String pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -78,37 +77,39 @@ Resources: Properties: RoleName: !Ref pConfigurationRoleName AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - - Action: sts:AssumeRole + - Effect: Allow + Action: sts:AssumeRole Condition: StringEquals: - aws:PrincipalArn: !Sub arn:${AWS::Partition}:iam::${pOrgPrimaryAccountId}:role/${pOrgPrimaryLambdaRoleName} - Effect: Allow + aws:PrincipalArn: !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:role/${pLambdaRoleName} Principal: AWS: - - !Sub arn:${AWS::Partition}:iam::${pOrgPrimaryAccountId}:root - Path: "/" + - !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:root + Path: '/' Policies: - PolicyName: guardduty-org-policy-organizations PolicyDocument: Version: 2012-10-17 Statement: - - Action: organizations:ListAccounts + - Sid: OrganizationsListAccounts Effect: Allow - Resource: "*" - Sid: OrganizationsListAccounts + Action: organizations:ListAccounts + Resource: '*' - PolicyName: guardduty-org-policy-guardduty PolicyDocument: Version: 2012-10-17 Statement: - - Action: guardduty:ListDetectors + - Sid: GuardDutyNoResource Effect: Allow - Resource: "*" - Sid: GuardDutyNoResource + Action: guardduty:ListDetectors + Resource: '*' - - Action: + - Sid: GuardDutyWithResource + Effect: Allow + Action: - guardduty:CreateMembers - guardduty:CreatePublishingDestination - guardduty:DeleteDetector @@ -120,37 +121,36 @@ Resources: - guardduty:UpdateMemberDetectors - guardduty:UpdateOrganizationConfiguration - guardduty:UpdatePublishingDestination - Effect: Allow Resource: - !Sub arn:${AWS::Partition}:guardduty:*:${AWS::AccountId}:/detector/* - !Sub arn:${AWS::Partition}:guardduty:*:${AWS::AccountId}:detector/* - Sid: GuardDutyWithResource - PolicyName: guardduty-org-policy-iam PolicyDocument: Version: 2012-10-17 Statement: - - Action: iam:GetRole + - Sid: AllowReadIamActions Effect: Allow + Action: iam:GetRole Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/* - Sid: AllowReadIamActions - - Action: + - Sid: AllowCreateDeleteServiceLinkedRole + Effect: Allow + Action: - iam:CreateServiceLinkedRole - iam:DeleteServiceLinkedRole Condition: StringLike: iam:AWSServiceName: guardduty.amazonaws.com - Effect: Allow Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty - Sid: AllowCreateDeleteServiceLinkedRole - - Action: + - Sid: AllowPolicyActions + Effect: Allow + Action: - iam:DeleteRolePolicy - iam:PutRolePolicy - Effect: Allow Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty - Sid: AllowPolicyActions + Tags: - Key: !Ref pTagKey1 Value: !Ref pTagValue1 diff --git a/solutions/guardduty/guardduty-org/templates/guardduty-org-configuration.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration.yaml similarity index 78% rename from solutions/guardduty/guardduty-org/templates/guardduty-org-configuration.yaml rename to aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration.yaml index 26e12c97..cf024493 100644 --- a/solutions/guardduty/guardduty-org/templates/guardduty-org-configuration.yaml +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-configuration.yaml @@ -8,8 +8,7 @@ Description: Organization GuardDuty delegated admin template for configuring Gua Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Lambda Function Attributes Parameters: - pLambdaExecutionRoleName @@ -18,8 +17,7 @@ Metadata: - pLambdaZipFileName - pLogLevel - pOrganizationId - - - Label: + - Label: default: GuardDuty Attributes Parameters: - pAutoEnableS3Logs @@ -30,13 +28,11 @@ Metadata: - pFindingPublishingFrequency - pKMSKeyArn - pPublishingDestinationBucketName - - - Label: + - Label: default: CloudWatch Log Group Attributes Parameters: - pDefaultLogGroupRetention - - - Label: + - Label: default: Resource Tags Parameters: - pTagKey1 @@ -132,10 +128,9 @@ Parameters: Type: String pLambdaS3BucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: The Amazon S3 bucket name where the lambda zip file is stored. Example Bucket Name = lambda-zips-us-east-1 Type: String @@ -165,26 +160,25 @@ Parameters: Type: String pPublishingDestinationBucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: GuardDuty S3 bucket name Type: String pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -197,7 +191,7 @@ Resources: - id: W84 reason: KMS key not provided Properties: - LogGroupName: !Sub "/aws/lambda/${pLambdaFunctionName}" + LogGroupName: !Sub '/aws/lambda/${pLambdaFunctionName}' RetentionInDays: !Ref pDefaultLogGroupRetention rLambdaRole: @@ -212,7 +206,7 @@ Resources: Properties: RoleName: !Ref pLambdaExecutionRoleName AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - Action: sts:AssumeRole Effect: Allow @@ -220,38 +214,37 @@ Resources: Service: - lambda.amazonaws.com - Path: "/" + Path: '/' Policies: - PolicyName: guardduty-org-policy-logs PolicyDocument: Version: 2012-10-17 Statement: - - Action: logs:CreateLogGroup + - Sid: CreateLogGroup Effect: Allow - Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup} - Sid: CreateLogGroup - - - Action: + Action: + - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - Effect: Allow Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup}:log-stream:* - Sid: CreateLogStreamAndEvents - PolicyName: guardduty-org-policy-organizations PolicyDocument: Version: 2012-10-17 Statement: - - Action: + - Sid: OrganizationsReadAccess + Effect: Allow + Action: - organizations:DescribeOrganization - organizations:ListAWSServiceAccessForOrganization - organizations:ListAccounts - organizations:ListDelegatedAdministrators - Effect: Allow - Resource: "*" - Sid: OrganizationsReadAccess + Resource: '*' + + - Sid: RegisterDeregisterDelegatedAdministrator - - Action: + Effect: Allow + Action: - organizations:DeregisterDelegatedAdministrator - organizations:DisableAWSServiceAccess - organizations:EnableAWSServiceAccess @@ -259,67 +252,66 @@ Resources: Condition: StringLikeIfExists: organizations:ServicePrincipal: guardduty.amazonaws.com - Effect: Allow - Resource: "*" - Sid: RegisterDeregisterDelegatedAdministrator + Resource: '*' - PolicyName: guardduty-org-policy-guardduty PolicyDocument: Version: 2012-10-17 Statement: - - Action: + - Sid: GuardDutyNoResource + Effect: Allow + Action: - guardduty:DisableOrganizationAdminAccount - guardduty:EnableOrganizationAdminAccount - guardduty:ListDetectors - guardduty:ListOrganizationAdminAccounts - Effect: Allow - Resource: "*" - Sid: GuardDutyNoResource + Resource: '*' - - Action: + - Sid: GuardDutyWithResource + Effect: Allow + Action: - guardduty:DeleteDetector - guardduty:ListMembers - Effect: Allow Resource: - !Sub arn:${AWS::Partition}:guardduty:*:${AWS::AccountId}:detector/* - !Sub arn:${AWS::Partition}:guardduty:*:${AWS::AccountId}:/detector/* - Sid: GuardDutyWithResource - PolicyName: guardduty-org-policy-iam PolicyDocument: Version: 2012-10-17 Statement: - - Action: iam:GetRole - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/* - Sid: AllowReadIamActions - - - Action: - - iam:CreateServiceLinkedRole - - iam:DeleteServiceLinkedRole - Effect: Allow - Condition: - StringLike: - iam:AWSServiceName: guardduty.amazonaws.com - Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty - Sid: AllowCreateDeleteServiceLinkedRole - - - Action: - - iam:DeleteRolePolicy - - iam:PutRolePolicy - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty - Sid: AllowPolicyActions - - - Action: sts:AssumeRole - Condition: - StringEquals: - aws:PrincipalOrgId: !Ref pOrganizationId - Effect: Allow - Resource: - - !Sub arn:${AWS::Partition}:iam::*:role/${pDeleteDetectorRoleName} - - !Sub arn:${AWS::Partition}:iam::*:role/${pConfigurationRoleName} - Sid: AssumeRole + - Sid: AllowReadIamActions + Effect: Allow + Action: iam:GetRole + Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/* + + - Sid: AllowCreateDeleteServiceLinkedRole + Effect: Allow + Action: + - iam:CreateServiceLinkedRole + - iam:DeleteServiceLinkedRole + Condition: + StringLike: + iam:AWSServiceName: guardduty.amazonaws.com + Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty + + - Sid: AllowPolicyActions + Effect: Allow + Action: + - iam:DeleteRolePolicy + - iam:PutRolePolicy + Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty + + - Sid: AssumeRole + + Effect: Allow + Action: sts:AssumeRole + Condition: + StringEquals: + aws:PrincipalOrgId: !Ref pOrganizationId + Resource: + - !Sub arn:${AWS::Partition}:iam::*:role/${pDeleteDetectorRoleName} + - !Sub arn:${AWS::Partition}:iam::*:role/${pConfigurationRoleName} Tags: - Key: !Ref pTagKey1 @@ -355,7 +347,7 @@ Resources: rLambdaCustomResource: Type: Custom::LambdaCustomResource - Version: "1.0" + Version: '1.0' Properties: ServiceToken: !GetAtt rLambdaFunction.Arn AUTO_ENABLE_S3_LOGS: !Ref pAutoEnableS3Logs @@ -366,4 +358,4 @@ Resources: ENABLED_REGIONS: !Ref pEnabledRegions FINDING_PUBLISHING_FREQUENCY: !Ref pFindingPublishingFrequency KMS_KEY_ARN: !Ref pKMSKeyArn - PUBLISHING_DESTINATION_BUCKET_ARN: !Sub arn:${AWS::Partition}:s3:::${pPublishingDestinationBucketName} \ No newline at end of file + PUBLISHING_DESTINATION_BUCKET_ARN: !Sub arn:${AWS::Partition}:s3:::${pPublishingDestinationBucketName} diff --git a/solutions/guardduty/guardduty-org/templates/guardduty-org-delete-detector-role.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delete-detector-role.yaml similarity index 68% rename from solutions/guardduty/guardduty-org/templates/guardduty-org-delete-detector-role.yaml rename to aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delete-detector-role.yaml index 4861f271..be465c30 100644 --- a/solutions/guardduty/guardduty-org/templates/guardduty-org-delete-detector-role.yaml +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delete-detector-role.yaml @@ -8,23 +8,22 @@ Description: Create an IAM role for deleting the GuardDuty detector Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Role Attributes Parameters: - pDeleteDetectorRoleName - - pOrgPrimaryAccountId - - pOrgPrimaryLambdaRoleName + - pOrgManagementAccountId + - pLambdaRoleName - pTagKey1 - pTagValue1 ParameterLabels: pDeleteDetectorRoleName: default: Delete Detector IAM Role Name - pOrgPrimaryAccountId: - default: Organization Primary Account ID - pOrgPrimaryLambdaRoleName: - default: Organization Primary Lambda Role Name + pOrgManagementAccountId: + default: Organization Management Account ID + pLambdaRoleName: + default: Lambda Role Name pTagKey1: default: Lambda Role Tag Key pTagValue1: @@ -37,31 +36,31 @@ Parameters: Description: Delete Detector IAM Role Name Type: String - pOrgPrimaryAccountId: + pOrgManagementAccountId: AllowedPattern: '^\d{12}$' ConstraintDescription: Must be 12 digits - Description: Organization Primary Account ID + Description: Organization Management Account ID Type: String - pOrgPrimaryLambdaRoleName: + pLambdaRoleName: AllowedPattern: '^[\w+=,.@-]{1,64}$' ConstraintDescription: Max 64 alphanumeric characters. Also special characters supported [+, =, ., @, -] - Description: Organization Primary Account Lambda Role Name + Description: Lambda Role Name Type: String pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -82,23 +81,23 @@ Resources: Condition: StringEquals: aws:PrincipalArn: - - !Sub arn:${AWS::Partition}:iam::${pOrgPrimaryAccountId}:role/${pOrgPrimaryLambdaRoleName} - - !Sub arn:${AWS::Partition}:iam::${pOrgPrimaryAccountId}:role/Admin - Effect: "Allow" + - !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:role/${pLambdaRoleName} + - !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:role/Admin + Effect: 'Allow' Principal: AWS: - - !Sub arn:${AWS::Partition}:iam::${pOrgPrimaryAccountId}:root - Version: "2012-10-17" + - !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:root + Version: '2012-10-17' - Path: "/" + Path: '/' Policies: - - PolicyName: "guardduty-org-policy-guardduty-delete" + - PolicyName: 'guardduty-org-policy-guardduty-delete' PolicyDocument: Version: 2012-10-17 Statement: - Action: guardduty:ListDetectors Effect: Allow - Resource: "*" + Resource: '*' Sid: GuardDutyNoResource - Action: guardduty:DeleteDetector @@ -108,4 +107,4 @@ Resources: RoleName: !Ref pDeleteDetectorRoleName Tags: - Key: !Ref pTagKey1 - Value: !Ref pTagValue1 \ No newline at end of file + Value: !Ref pTagValue1 diff --git a/solutions/guardduty/guardduty-org/templates/guardduty-org-delivery-kms-key.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-kms-key.yaml similarity index 72% rename from solutions/guardduty/guardduty-org/templates/guardduty-org-delivery-kms-key.yaml rename to aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-kms-key.yaml index a338857f..0c77e756 100644 --- a/solutions/guardduty/guardduty-org/templates/guardduty-org-delivery-kms-key.yaml +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-kms-key.yaml @@ -8,12 +8,11 @@ Description: Creates the GuardDuty Delivery KMS Key Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: KMS Key Attributes Parameters: - pGuardDutyDeliveryKeyAlias - - pOrgPrimaryAccountId + - pOrgManagementAccountId - pLoggingAccountId - pTagKey1 - pTagValue1 @@ -21,8 +20,8 @@ Metadata: ParameterLabels: pGuardDutyDeliveryKeyAlias: default: GuardDuty Delivery KMS Key Alias - pOrgPrimaryAccountId: - default: Organization Primary Account ID + pOrgManagementAccountId: + default: Organization Management Account ID pLoggingAccountId: default: Security Log Archive Account ID pTagKey1: @@ -36,9 +35,9 @@ Parameters: Description: GuardDuty Delivery KMS Key Alias Default: GuardDutyDeliveryKMSKey - pOrgPrimaryAccountId: + pOrgManagementAccountId: Type: String - Description: Organization primary account ID + Description: Organization management account ID pLoggingAccountId: Type: String @@ -59,51 +58,52 @@ Resources: Description: GuardDuty Delivery Key EnableKeyRotation: True KeyPolicy: - Version: "2012-10-17" + Version: '2012-10-17' Id: !Sub ${pGuardDutyDeliveryKeyAlias} Statement: - - Action: "kms:*" + - Sid: Enable IAM User Permissions Effect: Allow + Action: 'kms:*' + Resource: '*' Principal: AWS: !Sub arn:aws:iam::${AWS::AccountId}:root - Resource: "*" - Sid: Enable IAM User Permissions - Action: kms:GenerateDataKey Effect: Allow Principal: Service: guardduty.amazonaws.com - Resource: "*" + Resource: '*' Sid: Allow GuardDuty to encrypt logs - - Action: kms:CreateAlias + - Sid: Allow alias creation during setup + Effect: Allow + Action: kms:CreateAlias Condition: StringEquals: - "kms:CallerAccount": !Sub ${AWS::AccountId} - "kms:ViaService": cloudformation.us-east-1.amazonaws.com - Effect: Allow + 'kms:CallerAccount': !Sub ${AWS::AccountId} + 'kms:ViaService': cloudformation.us-east-1.amazonaws.com + Resource: '*' Principal: AWS: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:root - Resource: "*" - Sid: Allow alias creation during setup - - Action: kms:Decrypt + - Sid: Allow Log Archive and Management account access Effect: Allow + Action: kms:Decrypt + Resource: '*' Principal: AWS: - !Sub arn:${AWS::Partition}:iam::${pLoggingAccountId}:root - - !Sub arn:${AWS::Partition}:iam::${pOrgPrimaryAccountId}:root - Resource: "*" - Sid: Allow Log Archive and Primary account access + - !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:root - - Action: + - Sid: Allow account access + Effect: Allow + Action: - kms:DescribeKey - kms:Decrypt - Effect: Allow + Resource: '*' Principal: AWS: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:root - Resource: "*" - Sid: Allow account access + Tags: - Key: !Ref pTagKey1 Value: !Ref pTagValue1 @@ -112,10 +112,9 @@ Resources: Type: AWS::KMS::Alias Properties: AliasName: !Sub alias/${pGuardDutyDeliveryKeyAlias} - TargetKeyId: - !Ref rGuardDutyDeliveryKey + TargetKeyId: !Ref rGuardDutyDeliveryKey Outputs: oGuardDutyDeliveryKeyArn: Description: GuardDuty Delivery KMS Key ARN - Value: !GetAtt rGuardDutyDeliveryKey.Arn \ No newline at end of file + Value: !GetAtt rGuardDutyDeliveryKey.Arn diff --git a/solutions/guardduty/guardduty-org/templates/guardduty-org-delivery-s3-bucket.yaml b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-s3-bucket.yaml similarity index 71% rename from solutions/guardduty/guardduty-org/templates/guardduty-org-delivery-s3-bucket.yaml rename to aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-s3-bucket.yaml index dc0a0d44..4f4d0552 100644 --- a/solutions/guardduty/guardduty-org/templates/guardduty-org-delivery-s3-bucket.yaml +++ b/aws_sra_examples/solutions/guardduty/guardduty_org/templates/sra-guardduty-org-delivery-s3-bucket.yaml @@ -8,8 +8,7 @@ Description: Creates the GuardDuty delivery S3 bucket Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: GuardDuty Delivery S3 Attributes Parameters: - pGuardDutyDeliveryBucketPrefix @@ -29,43 +28,40 @@ Metadata: Parameters: pGuardDutyDeliveryBucketPrefix: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Default: guardduty-delivery Description: > - GuardDuty Delivery S3 bucket prefix. - The account and region will get added to the end. e.g. guardduty-delivery-123456789012-us-east-1 + GuardDuty Delivery S3 bucket prefix. The account and region will get added to the end. e.g. guardduty-delivery-123456789012-us-east-1 Type: String pGuardDutyDeliveryKMSKeyArn: - AllowedPattern: - '^arn:(aws[a-zA-Z-]*)?:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$' - ConstraintDescription: - 'Key ARN example: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab' + AllowedPattern: '^arn:(aws[a-zA-Z-]*)?:kms:[a-z0-9-]+:\d{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$' + ConstraintDescription: 'Key ARN example: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab' Description: KMS Key ARN to use for encrypting GuardDuty findings sent to S3 Type: String pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String Resources: rS3Bucket: DeletionPolicy: Retain + UpdateReplacePolicy: Retain Type: AWS::S3::Bucket Metadata: cfn_nag: @@ -78,6 +74,7 @@ Resources: - ServerSideEncryptionByDefault: KMSMasterKeyID: !Ref pGuardDutyDeliveryKMSKeyArn SSEAlgorithm: aws:kms + BucketKeyEnabled: True BucketName: !Sub ${pGuardDutyDeliveryBucketPrefix}-${AWS::AccountId}-${AWS::Region} OwnershipControls: Rules: @@ -100,73 +97,73 @@ Resources: PolicyDocument: Version: 2012-10-17 Statement: - - Action: s3:PutObject + - Sid: DenyPutObjectUnlessGuardDuty + Effect: Deny + Action: s3:PutObject Condition: ForAnyValue:StringNotEquals: aws:CalledVia: guardduty.amazonaws.com - Effect: Deny - Principal: "*" Resource: - !Sub arn:aws:s3:::${rS3Bucket} - !Sub arn:aws:s3:::${rS3Bucket}/* - Sid: DenyPutObjectUnlessGuardDuty + Principal: '*' - - Action: "s3:*" + - Sid: SecureTransport + Effect: Deny + Action: 's3:*' Condition: Bool: - "aws:SecureTransport": "false" - Effect: Deny - Principal: "*" + 'aws:SecureTransport': 'false' Resource: - !Sub arn:aws:s3:::${rS3Bucket} - !Sub arn:aws:s3:::${rS3Bucket}/* - Sid: SecureTransport + Principal: '*' - - Action: + - Sid: AWSBucketPermissionsCheck + Effect: Allow + Action: - s3:GetBucketAcl - s3:GetBucketLocation - s3:ListBucket - Effect: Allow + Resource: !Sub arn:aws:s3:::${rS3Bucket} Principal: Service: - guardduty.amazonaws.com - Resource: !Sub arn:aws:s3:::${rS3Bucket} - Sid: AWSBucketPermissionsCheck - - Action: s3:PutObject + - Sid: AWSBucketDelivery + Effect: Allow + Action: s3:PutObject Condition: StringEquals: - "s3:x-amz-acl": "bucket-owner-full-control" - Effect: Allow + 's3:x-amz-acl': 'bucket-owner-full-control' + Resource: !Sub arn:aws:s3:::${rS3Bucket}/* Principal: Service: - guardduty.amazonaws.com - Resource: !Sub arn:aws:s3:::${rS3Bucket}/* - Sid: AWSBucketDelivery - - Action: s3:PutObject + - Sid: DenyUnencryptedObjectUploads + Effect: Deny + Action: s3:PutObject Condition: StringNotEquals: - "s3:x-amz-server-side-encryption": "aws:kms" - Effect: Deny + 's3:x-amz-server-side-encryption': 'aws:kms' + Resource: !Sub arn:aws:s3:::${rS3Bucket}/* Principal: Service: - guardduty.amazonaws.com - Resource: !Sub arn:aws:s3:::${rS3Bucket}/* - Sid: DenyUnencryptedObjectUploads - - Action: s3:PutObject + - Sid: DenyIncorrectEncryptionHeader + Effect: Deny + Action: s3:PutObject Condition: StringNotEquals: - "s3:x-amz-server-side-encryption-aws-kms-key-id": !Sub ${pGuardDutyDeliveryKMSKeyArn} - Effect: Deny + 's3:x-amz-server-side-encryption-aws-kms-key-id': !Sub ${pGuardDutyDeliveryKMSKeyArn} + Resource: !Sub arn:aws:s3:::${rS3Bucket}/* Principal: Service: - guardduty.amazonaws.com - Resource: !Sub arn:aws:s3:::${rS3Bucket}/* - Sid: DenyIncorrectEncryptionHeader Outputs: oGuardDutyDeliveryS3Bucket: Description: GuardDuty Delivery S3 Bucket - Value: !Ref rS3Bucket \ No newline at end of file + Value: !Ref rS3Bucket diff --git a/aws_sra_examples/solutions/iam/iam_access_analyzer/README.md b/aws_sra_examples/solutions/iam/iam_access_analyzer/README.md new file mode 100644 index 00000000..7be3aa1a --- /dev/null +++ b/aws_sra_examples/solutions/iam/iam_access_analyzer/README.md @@ -0,0 +1,114 @@ +# Access Analyzer + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [References](#references) + +--- + +## Introduction + +The IAM Access Analyzer solution enables AWS IAM Access Analyzer by delegating administration to a member account within the Organization management account. It then configures Access Analyzer within the `delegated administrator account` for all the +existing and future AWS Organization accounts. + +In addition to the organization deployment, the solution deploys AWS Access Analyzer to all the member accounts and regions for analyzing account level permissions. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/iam-access-analyzer.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 AWS Organizations + +- AWS Organizations is used to delegate an administrator account for AWS Access Analyzer Delegated Administrator Account +- See [Common Register Delegated Administrator](../../common/common_register_delegated_administrator) + +#### 1.3 Account AWS IAM Access Analyzer + +AWS IAM Access Analyzer is configured to monitor [supported resources](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html) for the AWS Account zone of trust. + +--- + +### 2.0 Audit Account + +#### 2.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 2.2 Account AWS IAM Access Analyzer + +- See [1.2 Account AWS IAM Access Analyzer](#12-account-aws-iam-access-analyzer) + +#### 2.3 Organization AWS IAM Access Analyzer + +- AWS IAM Access Analyzer is configured to monitor supported resources for the AWS Organization zone of trust. + +--- + +### 3.0 All Existing and Future Organization Member Accounts + +#### 3.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 3.2 Account AWS IAM Access Analyzer + +- See [1.2 Account AWS IAM Access Analyzer](#12-account-aws-iam-access-analyzer) + +--- + +## Implementation Instructions + +### Pre-requisites + +1. Register a delegated administrator using the [Common Register Delegated Administrator](../../common/common_register_delegated_administrator) solution + 1. pServicePrincipalList = "access-analyzer.amazonaws.com" + +### [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +### CloudFormation StackSets + +### Solution Deployment + +#### AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to `All active accounts` in all `Governed Regions` using the [sra-iam-access-analyzer-account.yaml](templates/sra-iam-access-analyzer-account.yaml) + template file as the source. **Note:** Include the `management account` in the account list so that the IAM service-linked role is created, which is required for the next step. +2. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account` in all `Governed Regions` using the [sra-iam-access-analyzer-org.yaml](templates/sra-iam-access-analyzer-org.yaml) template + file as the source. + +#### Verify Solution Deployment + +1. Log into the Audit account and navigate to the IAM Access Analyzer page + 1. Verify that there are 2 Access Analyzers (account and organization) + 2. Verify all existing accounts/regions have an account Access Analyzer + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 2 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +2. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 1 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +3. Clean up the `delegated administrator` registered in the **Prerequisites** + +--- + +## References + +- [Using AWS IAM Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html) diff --git a/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..e17f9642 --- /dev/null +++ b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/solutions/iam/access-analyzer/aws-control-tower/manifest-v2.yaml b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/manifest-v2.yaml similarity index 53% rename from solutions/iam/access-analyzer/aws-control-tower/manifest-v2.yaml rename to aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/manifest-v2.yaml index 97607585..e91adf2c 100644 --- a/solutions/iam/access-analyzer/aws-control-tower/manifest-v2.yaml +++ b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/manifest-v2.yaml @@ -5,49 +5,48 @@ version: 2021-03-15 # Control Tower Custom Resources (Service Control Policies or CloudFormation) resources: -# ----------------------------------------------------------------------------- -# IAM Access Analyzer Solution -# ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- + # IAM Access Analyzer Solution + # ----------------------------------------------------------------------------- # Creates the service-linked role needed for the Organization Access Analyzer to work - - name: AccessAnalyzerAccount - resource_file: templates/access-analyzer-acct.yaml + - name: sra-iam-access-analyzer-account + resource_file: templates/sra-iam-access-analyzer-account.yaml parameters: - parameter_key: pAccessAnalyzerNamePrefix - parameter_value: cfct-account-access-analyzer + parameter_value: sra-account-access-analyzer - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: organizational_units: + # All OUs with Active Accounts - Core - management - workloads regions: - - ap-southeast-2 - - eu-west-1 + # All Governed AWS Control Tower Regions - us-east-1 - us-east-2 - us-west-2 - - name: AccessAnalyzerOrganization - resource_file: templates/access-analyzer-org.yaml + - name: sra-iam-access-analyzer-org + resource_file: templates/sra-iam-access-analyzer-org.yaml parameters: - parameter_key: pAccessAnalyzerName - parameter_value: cfct-organization-access-analyzer + parameter_value: sra-organization-access-analyzer - parameter_key: pTagKey1 - parameter_value: cfct + parameter_value: sra - parameter_key: pTagValue1 - parameter_value: managed-by-cfct + parameter_value: managed-by-sra deploy_method: stack_set deployment_targets: accounts: - Audit regions: - - ap-southeast-2 - - eu-west-1 + # All Governed AWS Control Tower Regions - us-east-1 - us-east-2 - - us-west-2 \ No newline at end of file + - us-west-2 diff --git a/solutions/iam/access-analyzer/aws-control-tower/manifest.yaml b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/manifest.yaml similarity index 63% rename from solutions/iam/access-analyzer/aws-control-tower/manifest.yaml rename to aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/manifest.yaml index 650f39d2..d804618b 100644 --- a/solutions/iam/access-analyzer/aws-control-tower/manifest.yaml +++ b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/manifest.yaml @@ -11,30 +11,29 @@ cloudformation_resources: # ----------------------------------------------------------------------------- # IAM Access Analyzer Solution # ----------------------------------------------------------------------------- - - name: AccessAnalyzerOrganization - template_file: templates/access-analyzer-org.yaml - parameter_file: parameters/access-analyzer-org.json + - name: sra-iam-access-analyzer-account + template_file: templates/sra-iam-access-analyzer-account.yaml + parameter_file: parameters/sra-iam-access-analyzer-account.json deploy_method: stack_set - deploy_to_account: - - Audit + deploy_to_ou: + # All OUs with Active Accounts + - Core + - management + - workloads regions: - - ap-southeast-2 - - eu-west-1 + # All Governed AWS Control Tower Regions - us-east-1 - us-east-2 - us-west-2 - - name: AccessAnalyzerAccount - template_file: templates/access-analyzer-acct.yaml - parameter_file: parameters/access-analyzer-acct.json + - name: sra-iam-access-analyzer-org + template_file: templates/sra-iam-access-analyzer-org.yaml + parameter_file: parameters/sra-iam-access-analyzer-org.json deploy_method: stack_set - deploy_to_ou: - - Core - - management - - workloads + deploy_to_account: + - Audit regions: - - ap-southeast-2 - - eu-west-1 + # All Governed AWS Control Tower Regions - us-east-1 - us-east-2 - us-west-2 diff --git a/solutions/iam/access-analyzer/aws-control-tower/parameters/access-analyzer-acct.json b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/parameters/sra-iam-access-analyzer-account.json similarity index 56% rename from solutions/iam/access-analyzer/aws-control-tower/parameters/access-analyzer-acct.json rename to aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/parameters/sra-iam-access-analyzer-account.json index 26bcc033..4d4dfaae 100644 --- a/solutions/iam/access-analyzer/aws-control-tower/parameters/access-analyzer-acct.json +++ b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/parameters/sra-iam-access-analyzer-account.json @@ -1,14 +1,14 @@ [ { "ParameterKey": "pAccessAnalyzerNamePrefix", - "ParameterValue": "cfct-account-access-analyzer" + "ParameterValue": "sra-account-access-analyzer" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] diff --git a/solutions/iam/access-analyzer/aws-control-tower/parameters/access-analyzer-org.json b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/parameters/sra-iam-access-analyzer-org.json similarity index 52% rename from solutions/iam/access-analyzer/aws-control-tower/parameters/access-analyzer-org.json rename to aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/parameters/sra-iam-access-analyzer-org.json index 419e1a49..bde015fa 100644 --- a/solutions/iam/access-analyzer/aws-control-tower/parameters/access-analyzer-org.json +++ b/aws_sra_examples/solutions/iam/iam_access_analyzer/customizations_for_aws_control_tower/parameters/sra-iam-access-analyzer-org.json @@ -1,14 +1,14 @@ [ { "ParameterKey": "pAccessAnalyzerName", - "ParameterValue": "cfct-organization-access-analyzer" + "ParameterValue": "sra-organization-access-analyzer" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] diff --git a/aws_sra_examples/solutions/iam/iam_access_analyzer/documentation/iam-access-analyzer.png b/aws_sra_examples/solutions/iam/iam_access_analyzer/documentation/iam-access-analyzer.png new file mode 100644 index 00000000..218080b9 Binary files /dev/null and b/aws_sra_examples/solutions/iam/iam_access_analyzer/documentation/iam-access-analyzer.png differ diff --git a/solutions/iam/access-analyzer/documentation/Access-Analyzer-Architecture.pptx b/aws_sra_examples/solutions/iam/iam_access_analyzer/documentation/iam-access-analyzer.pptx similarity index 76% rename from solutions/iam/access-analyzer/documentation/Access-Analyzer-Architecture.pptx rename to aws_sra_examples/solutions/iam/iam_access_analyzer/documentation/iam-access-analyzer.pptx index e16bcada..092c5554 100644 Binary files a/solutions/iam/access-analyzer/documentation/Access-Analyzer-Architecture.pptx and b/aws_sra_examples/solutions/iam/iam_access_analyzer/documentation/iam-access-analyzer.pptx differ diff --git a/solutions/iam/access-analyzer/templates/access-analyzer-acct.yaml b/aws_sra_examples/solutions/iam/iam_access_analyzer/templates/sra-iam-access-analyzer-account.yaml similarity index 75% rename from solutions/iam/access-analyzer/templates/access-analyzer-acct.yaml rename to aws_sra_examples/solutions/iam/iam_access_analyzer/templates/sra-iam-access-analyzer-account.yaml index f9ad9591..45c3881f 100644 --- a/solutions/iam/access-analyzer/templates/access-analyzer-acct.yaml +++ b/aws_sra_examples/solutions/iam/iam_access_analyzer/templates/sra-iam-access-analyzer-account.yaml @@ -3,13 +3,12 @@ # SPDX-License-Identifier: MIT-0 ######################################################################## AWSTemplateFormatVersion: 2010-09-09 -Description: Account IAM Access Analyzer +Description: SRA Account IAM Access Analyzer Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: IAM Access Analyzer Attributes Parameters: - pAccessAnalyzerNamePrefix @@ -19,40 +18,39 @@ Metadata: ParameterLabels: pAccessAnalyzerNamePrefix: default: Access Analyzer Name Prefix - pTagKey1: + pTagKey1: default: Access Analyzer Tag Key pTagValue1: default: Access Analyzer Tag Value Parameters: pAccessAnalyzerNamePrefix: - Default: account-access-analyzer + Default: sra-account-access-analyzer Description: Access Analyzer Name Prefix. The Account ID will be appended to the name. Type: String pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String -Resources: +Resources: rAccountAccessAnalyzer: Type: AWS::AccessAnalyzer::Analyzer Properties: AnalyzerName: !Sub ${pAccessAnalyzerNamePrefix}-${AWS::AccountId} Tags: - - - Key: !Ref pTagKey1 + - Key: !Ref pTagKey1 Value: !Ref pTagValue1 Type: ACCOUNT diff --git a/solutions/iam/access-analyzer/templates/access-analyzer-org.yaml b/aws_sra_examples/solutions/iam/iam_access_analyzer/templates/sra-iam-access-analyzer-org.yaml similarity index 73% rename from solutions/iam/access-analyzer/templates/access-analyzer-org.yaml rename to aws_sra_examples/solutions/iam/iam_access_analyzer/templates/sra-iam-access-analyzer-org.yaml index c41eff7b..fc56c2e9 100644 --- a/solutions/iam/access-analyzer/templates/access-analyzer-org.yaml +++ b/aws_sra_examples/solutions/iam/iam_access_analyzer/templates/sra-iam-access-analyzer-org.yaml @@ -3,13 +3,12 @@ # SPDX-License-Identifier: MIT-0 ######################################################################## AWSTemplateFormatVersion: 2010-09-09 -Description: Organization IAM Access Analyzer +Description: SRA Organization IAM Access Analyzer Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: IAM Access Analyzer Attributes Parameters: - pAccessAnalyzerName @@ -19,40 +18,39 @@ Metadata: ParameterLabels: pAccessAnalyzerName: default: Access Analyzer Name - pTagKey1: + pTagKey1: default: Access Analyzer Tag Key pTagValue1: default: Access Analyzer Tag Value Parameters: pAccessAnalyzerName: - Default: organization-access-analyzer + Default: sra-organization-access-analyzer Description: Organization Access Analyzer Name Type: String pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String -Resources: +Resources: rOrganizationAccessAnalyzer: Type: AWS::AccessAnalyzer::Analyzer Properties: AnalyzerName: !Sub ${pAccessAnalyzerName} Tags: - - - Key: !Ref pTagKey1 + - Key: !Ref pTagKey1 Value: !Ref pTagValue1 Type: ORGANIZATION diff --git a/aws_sra_examples/solutions/iam/iam_password_policy_acct/README.md b/aws_sra_examples/solutions/iam/iam_password_policy_acct/README.md new file mode 100644 index 00000000..71e2e45f --- /dev/null +++ b/aws_sra_examples/solutions/iam/iam_password_policy_acct/README.md @@ -0,0 +1,128 @@ +# IAM Password Policy + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [References](#references) + +--- + +## Introduction + +The IAM Password Policy solution updates the AWS account password policy within all accounts in an AWS Organization. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/iam-password-policy-acct.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 AWS Lambda Function + +- The Lambda function includes logic to set the account password policy + +#### 1.3 Amazon CloudWatch Log Group + +- All the `AWS Lambda Function` logs are sent to a CloudWatch Log Group `` to help with debugging and traceability of the actions performed. +- By default the `AWS Lambda Function` will create the CloudWatch Log Group and logs are encrypted with a CloudWatch Logs service managed encryption key. + +#### 1.4 Lambda Execution IAM Role + +- IAM role used by the Lambda function to update the account password policy + +#### 1.5 IAM Password Policy + +- AWS account password policy for IAM users + +--- + +### 2.0 All Organization Member Accounts + +Same configuration details as 1.0 Organization Management Account + +--- + +## Implementation Instructions + +### Staging + +1. In the `management account (home region)`, launch the AWS CloudFormation **Stack** using the [prereq-controltower-execution-role.yaml](../../../utils/aws_control_tower/prerequisites/prereq-controltower-execution-role.yaml) template file as the + source, to implement the `AWSControlTowerExecution` role pre-requisite. + - **Note:** Only do this step, if the `AWSControlTowerExecution` IAM role doesn't already exist in the Control Tower `management account`. +2. In the `management account (home region)`, launch the AWS CloudFormation **StackSet** targeting only the `management account` in all of the enabled regions (include home region) + [prereq-lambda-s3-bucket.yaml](../../../utils/aws_control_tower/prerequisites/prereq-lambda-s3-bucket.yaml) template file as the source, to implement an S3 bucket that will store the Lambda Zip files. (Example Bucket Name: + `lambda-zips--`) + - For additional guidance see [CloudFormation StackSet Instructions](#cloudformation-stackset-instructions) + - Take note of the S3 Bucket Name from the CloudFormation Outputs, as you will need it for both the packaging step, and the **Solution Deployment Order** section. + - **Note:** Only do this step if you don't already have an S3 bucket to store the Lambda zip files for CloudFormation custom resources in the Control Tower `management account`. + - Lambda functions can only access Zip files from an S3 bucket in the same AWS region as the where Lambda function resides. + - Although for this solution, S3 bucket is only needed in the `home region`, it is recommended to deploy the S3 bucket as a **stackset**, so that you can support future Lambda functions in other regions. +3. Package the Lambda code into a zip file and upload it to the S3 bucket (from above step), using the [Packaging script](../../../utils/packaging_scripts/package-lambda.sh). + - `SRA_REPO` environment variable should point to the folder where `aws-security-reference-architecture-examples` repository is stored. + - `BUCKET` environment variable should point to the S3 Bucket where the Lambda zip files are stored. + - See CloudFormation Output from Step 2 + - Or follow this syntax: `lambda-zips--` + +```bash +# Example (assumes repository was downloaded to your home directory) +export SRA_REPO="$HOME"/aws-security-reference-architecture-examples +export BUCKET=sra-staging-123456789012-us-east-1 +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name iam-password-policy-acct.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/iam/iam_password_policy_acct/lambda/src +``` + +```bash +# Export AWS CLI profile for the 'management account' +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= +export AWS_SESSION_TOKEN= + +# Use template below and set the 'SRA_REPO' and 'BUCKET' with your values. +export SRA_REPO= +export BUCKET= +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name iam-password-policy-acct.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/iam/iam_password_policy_acct/lambda/src +``` + +### Solution Deployment + +#### Customizations for AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to `All active accounts` within the `home region` using the [sra-iam-password-policy-acct.yaml](templates/sra-iam-password-policy-acct.yaml) + +#### Verify Solution Deployment + +1. Log into any account within the AWS Organization + 1. Navigate to the IAM -> Account settings page + 2. Verify the custom password policy settings + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 1 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. + +--- + +## References + +- [Setting an account password policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html) +- [CIS AWS Foundations Benchmark controls](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html) diff --git a/aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..e17f9642 --- /dev/null +++ b/aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/solutions/iam/password-policy-acct/aws-control-tower/manifest-v2.yaml b/aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/manifest-v2.yaml similarity index 67% rename from solutions/iam/password-policy-acct/aws-control-tower/manifest-v2.yaml rename to aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/manifest-v2.yaml index 6b0ed201..9c78db95 100644 --- a/solutions/iam/password-policy-acct/aws-control-tower/manifest-v2.yaml +++ b/aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/manifest-v2.yaml @@ -8,40 +8,41 @@ resources: # ----------------------------------------------------------------------------- # IAM Password Policy # ----------------------------------------------------------------------------- - - name: PasswordPolicy - resource_file: templates/password-policy-acct.yaml + - name: sra-iam-password-policy-acct + resource_file: templates/sra-iam-password-policy-acct.yaml parameters: - parameter_key: pAllowUsersToChangePassword - parameter_value: "true" + parameter_value: 'true' - parameter_key: pHardExpiry - parameter_value: "false" + parameter_value: 'false' - parameter_key: pMaxPasswordAge - parameter_value: "90" + parameter_value: '90' - parameter_key: pMinimumPasswordLength - parameter_value: "14" + parameter_value: '14' - parameter_key: pPasswordReusePrevention - parameter_value: "24" + parameter_value: '24' - parameter_key: pRequireLowercaseCharacters - parameter_value: "true" + parameter_value: 'true' - parameter_key: pRequireNumbers - parameter_value: "true" + parameter_value: 'true' - parameter_key: pRequireSymbols - parameter_value: "true" + parameter_value: 'true' - parameter_key: pRequireUppercaseCharacters - parameter_value: "true" + parameter_value: 'true' - parameter_key: pLambdaExecutionRoleName - parameter_value: "cfct-password-policy-acct-lambda" + parameter_value: 'sra-password-policy-acct-lambda' - parameter_key: pLambdaFunctionName - parameter_value: "cfct-password-policy-acct" + parameter_value: 'sra-password-policy-acct' - parameter_key: pLambdaS3BucketName parameter_value: $[alfred_ssm_/org/primary/lambda_zips_bucket/us-east-1] - parameter_key: pLambdaZipFileName - parameter_value: "password-policy-acct.zip" + parameter_value: 'iam-password-policy-acct.zip' - parameter_key: pLogLevel - parameter_value: "debug" + parameter_value: 'debug' deploy_method: stack_set deployment_targets: organizational_units: + # All OUs with Active Accounts - Core - management - workloads diff --git a/solutions/iam/password-policy-acct/aws-control-tower/manifest.yaml b/aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/manifest.yaml similarity index 74% rename from solutions/iam/password-policy-acct/aws-control-tower/manifest.yaml rename to aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/manifest.yaml index be98cda1..58602bec 100644 --- a/solutions/iam/password-policy-acct/aws-control-tower/manifest.yaml +++ b/aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/manifest.yaml @@ -11,11 +11,12 @@ cloudformation_resources: # ----------------------------------------------------------------------------- # IAM Password Policy # ----------------------------------------------------------------------------- - - name: PasswordPolicy - template_file: templates/password-policy-acct.yaml - parameter_file: parameters/password-policy-acct.json + - name: sra-iam-password-policy-acct + template_file: templates/sra-iam-password-policy-acct.yaml + parameter_file: parameters/sra-iam-password-policy-acct.json deploy_method: stack_set deploy_to_ou: + # All OUs with Active Accounts - Core - management - workloads diff --git a/solutions/iam/password-policy-acct/aws-control-tower/parameters/password-policy-acct.json b/aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/parameters/sra-iam-password-policy-acct.json similarity index 88% rename from solutions/iam/password-policy-acct/aws-control-tower/parameters/password-policy-acct.json rename to aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/parameters/sra-iam-password-policy-acct.json index cc592ed4..15c0c67a 100644 --- a/solutions/iam/password-policy-acct/aws-control-tower/parameters/password-policy-acct.json +++ b/aws_sra_examples/solutions/iam/iam_password_policy_acct/customizations_for_aws_control_tower/parameters/sra-iam-password-policy-acct.json @@ -37,11 +37,11 @@ }, { "ParameterKey": "pLambdaExecutionRoleName", - "ParameterValue": "cfct-password-policy-acct-lambda" + "ParameterValue": "sra-password-policy-acct-lambda" }, { "ParameterKey": "pLambdaFunctionName", - "ParameterValue": "cfct-password-policy-acct" + "ParameterValue": "sra-password-policy-acct" }, { "ParameterKey": "pLambdaS3BucketName", @@ -49,7 +49,7 @@ }, { "ParameterKey": "pLambdaZipFileName", - "ParameterValue": "password-policy-acct.zip" + "ParameterValue": "iam-password-policy-acct.zip" }, { "ParameterKey": "pLogLevel", diff --git a/aws_sra_examples/solutions/iam/iam_password_policy_acct/documentation/iam-password-policy-acct.png b/aws_sra_examples/solutions/iam/iam_password_policy_acct/documentation/iam-password-policy-acct.png new file mode 100644 index 00000000..f2a66198 Binary files /dev/null and b/aws_sra_examples/solutions/iam/iam_password_policy_acct/documentation/iam-password-policy-acct.png differ diff --git a/solutions/iam/password-policy-acct/documentation/Password-Policy-Architecture.pptx b/aws_sra_examples/solutions/iam/iam_password_policy_acct/documentation/iam-password-policy-acct.pptx similarity index 81% rename from solutions/iam/password-policy-acct/documentation/Password-Policy-Architecture.pptx rename to aws_sra_examples/solutions/iam/iam_password_policy_acct/documentation/iam-password-policy-acct.pptx index 311f5f53..20331dfa 100644 Binary files a/solutions/iam/password-policy-acct/documentation/Password-Policy-Architecture.pptx and b/aws_sra_examples/solutions/iam/iam_password_policy_acct/documentation/iam-password-policy-acct.pptx differ diff --git a/solutions/iam/password-policy-acct/code/src/app.py b/aws_sra_examples/solutions/iam/iam_password_policy_acct/lambda/src/app.py similarity index 100% rename from solutions/iam/password-policy-acct/code/src/app.py rename to aws_sra_examples/solutions/iam/iam_password_policy_acct/lambda/src/app.py diff --git a/solutions/iam/password-policy-acct/code/src/requirements.txt b/aws_sra_examples/solutions/iam/iam_password_policy_acct/lambda/src/requirements.txt similarity index 100% rename from solutions/iam/password-policy-acct/code/src/requirements.txt rename to aws_sra_examples/solutions/iam/iam_password_policy_acct/lambda/src/requirements.txt diff --git a/solutions/iam/password-policy-acct/templates/password-policy-acct.yaml b/aws_sra_examples/solutions/iam/iam_password_policy_acct/templates/sra-iam-password-policy-acct.yaml similarity index 84% rename from solutions/iam/password-policy-acct/templates/password-policy-acct.yaml rename to aws_sra_examples/solutions/iam/iam_password_policy_acct/templates/sra-iam-password-policy-acct.yaml index cca76011..524543f2 100644 --- a/solutions/iam/password-policy-acct/templates/password-policy-acct.yaml +++ b/aws_sra_examples/solutions/iam/iam_password_policy_acct/templates/sra-iam-password-policy-acct.yaml @@ -3,7 +3,7 @@ # SPDX-License-Identifier: MIT-0 ######################################################################## AWSTemplateFormatVersion: '2010-09-09' -Description: Account Password Policy +Description: SRA IAM Account Password Policy Metadata: AWS::CloudFormation::Interface: @@ -11,15 +11,15 @@ Metadata: - Label: default: Password Policy Parameters Parameters: - - pAllowUsersToChangePassword - - pHardExpiry - - pMaxPasswordAge - - pMinimumPasswordLength - - pPasswordReusePrevention - - pRequireLowercaseCharacters - - pRequireNumbers - - pRequireSymbols - - pRequireUppercaseCharacters + - pAllowUsersToChangePassword + - pHardExpiry + - pMaxPasswordAge + - pMinimumPasswordLength + - pPasswordReusePrevention + - pRequireLowercaseCharacters + - pRequireNumbers + - pRequireSymbols + - pRequireUppercaseCharacters - Label: default: Lambda Parameters @@ -78,7 +78,7 @@ Parameters: AllowedPattern: '^[\w+=,.@-]{1,64}$' ConstraintDescription: Max 64 alphanumeric characters. Also special characters supported [+, =, ., @, -] Description: Lambda execution role name - Default: password-policy-acct + Default: sra-iam-password-policy-acct Type: String pLambdaFunctionName: @@ -88,12 +88,10 @@ Parameters: Type: String pLambdaS3BucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). - Description: - The Amazon S3 bucket name where the lambda zip file is stored. Example Bucket Name = lambda-zips-us-east-1 + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). + Description: The Amazon S3 bucket name where the lambda zip file is stored. Example Bucket Name = lambda-zips-us-east-1 Type: String pLambdaZipFileName: @@ -101,7 +99,7 @@ Parameters: Type: String pLogLevel: - AllowedValues: [ debug, info, warning, error, critical ] + AllowedValues: [debug, info, warning, error, critical] Default: debug Description: Lambda Function Logging Level Type: String @@ -145,7 +143,9 @@ Parameters: pRequireSymbols: AllowedValues: [true, false] Default: true - Description: 'You can require that IAM user passwords contain at least one of the following nonalphanumeric characters: ! @ # $ % ^ & * ( ) _ + - = [ ] {} | ''' + Description: + "You can require that IAM user passwords contain at least one of the following nonalphanumeric characters: ! @ # $ % ^ & * ( ) _ + - = [ ] {} | + '" Type: String pRequireUppercaseCharacters: @@ -176,24 +176,20 @@ Resources: Path: '/' Policies: - PolicyDocument: + Version: 2012-10-17 Statement: - - Action: logs:CreateLogGroup + - Sid: CreateLogStreamAndEvents Effect: Allow - Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${pLambdaFunctionName}:* - Sid: CreateLogGroup - - - Action: + Action: + - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - Effect: Allow Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${pLambdaFunctionName}:log-stream:* - Sid: CreateLogStreamAndEvents - - Action: iam:UpdateAccountPasswordPolicy + - Sid: IAMUpdateAccountPasswordPolicy Effect: Allow + Action: iam:UpdateAccountPasswordPolicy Resource: '*' - Sid: IAMUpdateAccountPasswordPolicy - Version: 2012-10-17 PolicyName: update-iam-password-policy RoleName: !Ref pLambdaExecutionRoleName diff --git a/aws_sra_examples/solutions/macie/macie_org/README.md b/aws_sra_examples/solutions/macie/macie_org/README.md new file mode 100644 index 00000000..bb0242c4 --- /dev/null +++ b/aws_sra_examples/solutions/macie/macie_org/README.md @@ -0,0 +1,216 @@ +# Macie Organization + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [Appendix](#appendix) +- [References](#references) + +--- + +## Introduction + +The Macie Organization solution will enable Amazon Macie by delegating administration to a member account within the Organization Management Account and configuring Macie within the delegated administrator account for all the existing and future AWS +Organization accounts. Macie is also configured to send the findings to a central S3 bucket encrypted with a KMS key. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/macie-org.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 AWS Lambda Function + +The Lambda function is required to register the Macie delegated administrator account within each region provided + +#### 1.3 Lambda CloudWatch Log Group + +- All the `AWS Lambda Function` logs are sent to a CloudWatch Log Group `` to help with debugging and traceability of the actions performed. +- By default the `AWS Lambda Function` will create the CloudWatch Log Group and logs are encrypted with a CloudWatch Logs service managed encryption key. + +#### 1.4 Lambda Execution IAM Role + +- IAM role used by the Lambda function to register the Macie delegated administrator account within each region provided + +#### 1.5 Macie + +- Macie is enabled for each existing active account and region during the initial setup +- Macie will automatically enable new member accounts/regions when added to the AWS Organization + +--- + +### 2.0 Security Log Archive Account + +#### 2.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 2.2 Macie Delivery S3 Bucket + +- S3 bucket where Macie classifications are exported for each account/region within the AWS Organization + +#### 2.3 Macie + +- See [1.5 Macie](#15-macie) + +--- + +### 3.0 Audit Account + +#### 3.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 3.2 Macie KMS Key + +- Macie is configured to encrypt the exported findings with a customer managed KMS key + +#### 3.3 Configuration IAM Role + +- IAM role assumed by the Lambda function within the management account to configure Macie within each region provided + +#### 3.4 Macie + +- See [1.5 Macie](#15-macie) + +--- + +### 4.0 All Existing and Future Organization Member Accounts + +#### 4.1 Macie + +- See [1.5 Macie](#15-macie) + +#### 4.2 Disable Macie Role + +- An IAM role is created within all the accounts to disable Macie in a CloudFormation delete event + +--- + +## Implementation Instructions + +### Prerequisites + +- AWS Control Tower is deployed. +- `aws-security-reference-architecture-examples` repository is stored on your local machine or location where you will be deploying from. +- Macie is not enabled in any of the accounts within the AWS Organization + +### Staging + +1. In the `management account (home region)`, launch the AWS CloudFormation **Stack** using the [prereq-controltower-execution-role.yaml](../../../utils/aws_control_tower/prerequisites/prereq-controltower-execution-role.yaml) template file as the + source, to implement the `AWSControlTowerExecution` role pre-requisite. + - **Note:** Only do this step, if the `AWSControlTowerExecution` IAM role doesn't already exist in the Control Tower `management account`. +2. In the `management account (home region)`, launch the AWS CloudFormation **StackSet** targeting only the `management account` in all of the enabled regions (include home region) + [prereq-lambda-s3-bucket.yaml](../../../utils/aws_control_tower/prerequisites/prereq-lambda-s3-bucket.yaml) template file as the source, to implement an S3 bucket that will store the Lambda Zip files. (Example Bucket Name: + `lambda-zips--`) + - For additional guidance see [CloudFormation StackSet Instructions](#cloudformation-stackset-instructions) + - Take note of the S3 Bucket Name from the CloudFormation Outputs, as you will need it for both the packaging step, and the **Solution Deployment Order** section. + - **Note:** Only do this step if you don't already have an S3 bucket to store the Lambda zip files for CloudFormation custom resources in the Control Tower `management account`. + - Lambda functions can only access Zip files from an S3 bucket in the same AWS region as the where Lambda function resides. + - Although for this solution, S3 bucket is only needed in the `home region`, it is recommended to deploy the S3 bucket as a **stackset**, so that you can support future Lambda functions in other regions. +3. Package the Lambda code into a zip file and upload it to the S3 bucket (from above step), using the [Packaging script](../../../utils/packaging_scripts/package-lambda.sh). + - `SRA_REPO` environment variable should point to the folder where `aws-security-reference-architecture-examples` repository is stored. + - `BUCKET` environment variable should point to the S3 Bucket where the Lambda zip files are stored. + - See CloudFormation Output from Step 2 + - Or follow this syntax: `lambda-zips--` + +```bash +# Example (assumes repository was downloaded to your home directory) +export SRA_REPO="$HOME"/aws-security-reference-architecture-examples +export BUCKET=sra-staging-123456789012-us-east-1 +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name macie-org.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/macie/macie_org/lambda/src +``` + +```bash +# Export AWS CLI profile for the 'management account' +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= +export AWS_SESSION_TOKEN= + +# Use template below and set the 'SRA_REPO' and 'BUCKET' with your values. +export SRA_REPO= +export BUCKET= +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name macie-org.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/macie/macie_org/lambda/src +``` + +### Solution Deployment + +#### Customizations for AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account (home region)` using the [sra-macie-org-configuration-role.yaml](templates/sra-macie-org-configuration-role.yaml) template file + as the source. +2. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Audit account (home region)` using the [sra-macie-org-kms-key.yaml](templates/sra-macie-org-kms-key.yaml) template file as the source. +3. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to the `Log archive account (home region)` using the [sra-macie-org-s3-bucket.yaml](templates/sra-macie-org-s3-bucket.yaml) template file as the + source. +4. In the `management account (home region)`, launch an AWS CloudFormation **Stack** using the [sra-macie-org-configuration.yaml](templates/sra-macie-org-configuration.yaml) template file as the source. +5. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to `All active accounts (home region)` using the [sra-macie-org-member-disable-role.yaml](templates/sra-macie-org-member-disable-role.yaml) + +#### Verify Solution Deployment + +1. Log into the Management account and navigate to the Macie page + 1. Validate that the delegated admin account is set for each region +2. Log into the Audit account and navigate to the Macie page + 1. Verify the correct Macie configurations have been applied to each region + 2. Verify all existing accounts have been enabled + 3. Verify the findings export is configured for the S3 bucket + 4. Generate sample findings to verify S3 delivery +3. Log into the Log archive account and navigate to the S3 page + 1. Verify the sample findings have been delivered + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **Stack** created in step 4 of the solution deployment. +2. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 5 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +3. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 3 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. + 1. In the `Log Archive account (home region)`, empty and delete the S3 bucket created in step 3 +4. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 2 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +5. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 1 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. +6. In the `management account (home region)`, delete the AWS CloudWatch **Log Group** (e.g. /aws/lambda/) for the Lambda function deployed in step 4 of the solution deployment. + +--- + +## Appendix + +### CloudFormation StackSet Instructions + +If you need to launch an AWS CloudFormation **StackSet** in the `management account`, see below steps (for additional details, see +[Create a stack set with self-managed permissions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started-create.html#stacksets-getting-started-create-self-managed)) + +1. AWS CloudFormation -> StackSets -> Create StackSet +2. Choose a Template (upload template) +3. Specify StackSet Details (enter parameter values) +4. Configure StackSet Options -> Self-service permissions + - IAM Admin Role Name: `AWSControlTowerStackSetRole` + - IAM Execution Role Name: `AWSControlTowerExecution` +5. Set Deployment Options -> Deploy New Stacks + - Deploy Stacks in Accounts -> enter the AWS Control Tower Management Account ID + - Specify Regions: choose regions you want to deploy stacks too (include home region) +6. If in future, you need to update the Stack Set (e.g., add/remove a region), see [Getting Started with AWS CloudFormation StackSets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started.html) + +--- + +## References + +- [Managing multiple Amazon Macie accounts with AWS Organizations](https://docs.aws.amazon.com/macie/latest/user/macie-organizations.html) diff --git a/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..e17f9642 --- /dev/null +++ b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/solutions/macie/macie-org/aws-control-tower/manifest-v2.yaml b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/manifest-v2.yaml similarity index 60% rename from solutions/macie/macie-org/aws-control-tower/manifest-v2.yaml rename to aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/manifest-v2.yaml index 95996b00..1a79d54f 100644 --- a/solutions/macie/macie-org/aws-control-tower/manifest-v2.yaml +++ b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/manifest-v2.yaml @@ -6,39 +6,39 @@ version: 2021-03-15 # Control Tower Custom Resources (Service Control Policies or CloudFormation) resources: # ----------------------------------------------------------------------------- - # Amazon Macie + # Organization Macie # ----------------------------------------------------------------------------- - - name: MacieOrgConfigurationRole - resource_file: templates/macie-org-configuration-role.yaml + - name: sra-macie-org-configuration-role + resource_file: templates/sra-macie-org-configuration-role.yaml parameters: - parameter_key: pConfigurationRoleName - parameter_value: "cfct-macie-configuration" + parameter_value: 'sra-macie-configuration' - parameter_key: pOrgManagementAccountId - parameter_value: $[alfred_ssm_/org/member/Control-Tower-Management/account_id] + parameter_value: $[alfred_ssm_/org/primary/account_id] - parameter_key: pLambdaRoleName - parameter_value: "cfct-macie-org-lambda" + parameter_value: 'sra-macie-org-lambda' - parameter_key: pTagKey1 - parameter_value: "cfct" + parameter_value: 'sra' - parameter_key: pTagValue1 - parameter_value: "managed-by-cfct" + parameter_value: 'managed-by-sra' deploy_method: stack_set deployment_targets: accounts: - Audit - - name: MacieOrgDeliveryKMSKey - resource_file: templates/macie-org-kms-key.yaml + - name: sra-macie-org-kms-key + resource_file: templates/sra-macie-org-kms-key.yaml parameters: - parameter_key: pMacieDeliveryKeyAlias - parameter_value: "MacieDeliveryKMSKey" + parameter_value: 'MacieDeliveryKMSKey' - parameter_key: pLoggingAccountId - parameter_value: $[alfred_ssm_/org/member/Log-archive/account_id] + parameter_value: $[alfred_ssm_/org/member/logging/account_id] - parameter_key: pOrgManagementAccountId - parameter_value: $[alfred_ssm_/org/member/Control-Tower-Management/account_id] + parameter_value: $[alfred_ssm_/org/primary/account_id] - parameter_key: pTagKey1 - parameter_value: "cfct" + parameter_value: 'sra' - parameter_key: pTagValue1 - parameter_value: "managed-by-cfct" + parameter_value: 'managed-by-sra' deploy_method: stack_set export_outputs: - name: /org/macie/kms_key_arn @@ -47,21 +47,21 @@ resources: accounts: - Audit - - name: MacieOrgDeliveryS3Bucket - resource_file: templates/macie-org-s3-bucket.yaml + - name: sra-macie-org-s3-bucket + resource_file: templates/sra-macie-org-s3-bucket.yaml parameters: - parameter_key: pDelegatedAdminAccountId parameter_value: $[alfred_ssm_/org/member/Audit/account_id] - parameter_key: pMacieDeliveryBucketPrefix - parameter_value: "macie-delivery" + parameter_value: 'macie-delivery' - parameter_key: pMacieDeliveryKMSKeyArn parameter_value: $[alfred_ssm_/org/macie/kms_key_arn] - parameter_key: pOrganizationId parameter_value: $[alfred_ssm_/org/primary/organization_id] - parameter_key: pTagKey1 - parameter_value: "cfct" + parameter_value: 'sra' - parameter_key: pTagValue1 - parameter_value: "managed-by-cfct" + parameter_value: 'managed-by-sra' deploy_method: stack_set export_outputs: - name: /org/macie/s3_bucket @@ -70,63 +70,63 @@ resources: accounts: - Log archive - - name: MacieOrgConfiguration - resource_file: templates/macie-org-configuration.yaml + - name: sra-macie-org-configuration + resource_file: templates/sra-macie-org-configuration.yaml parameters: - parameter_key: pConfigurationRoleName - parameter_value: "cfct-macie-configuration" + parameter_value: 'sra-macie-configuration' - parameter_key: pControlTowerRegionsOnly - parameter_value: "true" + parameter_value: 'true' - parameter_key: pDelegatedAdminAccountId parameter_value: $[alfred_ssm_/org/member/Audit/account_id] - parameter_key: pDisableMacieRoleName - parameter_value: "cfct-disable-macie" + parameter_value: 'sra-disable-macie' - parameter_key: pEnabledRegions - parameter_value: "" + parameter_value: '' - parameter_key: pFindingPublishingFrequency - parameter_value: "FIFTEEN_MINUTES" + parameter_value: 'FIFTEEN_MINUTES' - parameter_key: pKMSKeyArn - parameter_value: "$[alfred_ssm_/org/macie/kms_key_arn]" + parameter_value: '$[alfred_ssm_/org/macie/kms_key_arn]' - parameter_key: pLambdaExecutionRoleName - parameter_value: "cfct-macie-org-lambda" + parameter_value: 'sra-macie-org-lambda' - parameter_key: pLambdaFunctionName - parameter_value: "cfct-macie-org-configuration" + parameter_value: 'sra-macie-org-configuration' - parameter_key: pLambdaS3BucketName parameter_value: $[alfred_ssm_/org/primary/lambda_zips_bucket/us-east-1] - parameter_key: pLambdaZipFileName - parameter_value: "macie-org-configuration.zip" + parameter_value: 'macie-org.zip' - parameter_key: pLogLevel - parameter_value: "debug" + parameter_value: 'debug' - parameter_key: pOrganizationId parameter_value: $[alfred_ssm_/org/primary/organization_id] - parameter_key: pPublishingDestinationBucketName - parameter_value: "$[alfred_ssm_/org/macie/s3_bucket]" + parameter_value: '$[alfred_ssm_/org/macie/s3_bucket]' - parameter_key: pTagKey1 - parameter_value: "cfct" + parameter_value: 'sra' - parameter_key: pTagValue1 - parameter_value: "managed-by-cfct" + parameter_value: 'managed-by-sra' deploy_method: stack_set deployment_targets: accounts: - - Management + - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME - - name: MacieOrgMemberDisableRole - resource_file: templates/macie-org-member-disable-role.yaml + - name: sra-macie-org-member-disable-role + resource_file: templates/sra-macie-org-member-disable-role.yaml parameters: - parameter_key: pDisableMacieRoleName - parameter_value: "cfct-disable-macie" + parameter_value: 'sra-disable-macie' - parameter_key: pOrgManagementAccountId - parameter_value: $[alfred_ssm_/org/member/Control-Tower-Management/account_id] + parameter_value: $[alfred_ssm_/org/primary/account_id] - parameter_key: pLambdaRoleName - parameter_value: "cfct-macie-org-lambda" + parameter_value: 'sra-macie-org-lambda' - parameter_key: pTagKey1 - parameter_value: "cfct" + parameter_value: 'sra' - parameter_key: pTagValue1 - parameter_value: "managed-by-cfct" + parameter_value: 'managed-by-sra' deploy_method: stack_set deployment_targets: organizational_units: - # ALL OU s + # ALL OUs with Active Accounts - Core - management - - workloads \ No newline at end of file + - workloads diff --git a/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/manifest.yaml b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/manifest.yaml new file mode 100644 index 00000000..171c6626 --- /dev/null +++ b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/manifest.yaml @@ -0,0 +1,56 @@ +--- +#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets +region: us-east-1 +version: 2020-01-01 + +# Control Tower Custom Service Control Policies +organization_policies: [] + +# Control Tower Custom CloudFormation Resources +cloudformation_resources: + # ----------------------------------------------------------------------------- + # Organization Macie + # ----------------------------------------------------------------------------- + - name: sra-macie-org-configuration-role + template_file: templates/sra-macie-org-configuration-role.yaml + parameter_file: parameters/sra-macie-org-configuration-role.json + deploy_method: stack_set + deploy_to_account: + - Audit + + - name: sra-macie-org-kms-key + template_file: templates/sra-macie-org-kms-key.yaml + parameter_file: parameters/sra-macie-org-kms-key.json + deploy_method: stack_set + ssm_parameters: + - name: /org/macie/kms_key_arn + value: $[output_oMacieDeliveryKeyArn] + deploy_to_account: + - Audit + + - name: sra-macie-org-s3-bucket + template_file: templates/sra-macie-org-s3-bucket.yaml + parameter_file: parameters/sra-macie-org-s3-bucket.json + deploy_method: stack_set + ssm_parameters: + - name: /org/macie/s3_bucket + value: $[output_oMacieDeliveryS3Bucket] + deploy_to_account: + - Log archive + + - name: sra-macie-org-configuration + template_file: templates/sra-macie-org-configuration.yaml + parameter_file: parameters/sra-macie-org-configuration.json + deploy_method: stack_set + deploy_to_account: + - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME + + - name: sra-macie-org-member-disable-role + template_file: templates/sra-macie-org-member-disable-role.yaml + parameter_file: parameters/sra-macie-org-member-disable-role.json + deploy_method: stack_set + deploy_to_ou: + # All OUs with active accounts + - Core + - management + - workloads diff --git a/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-configuration-role.json b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-configuration-role.json new file mode 100644 index 00000000..70e178d6 --- /dev/null +++ b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-configuration-role.json @@ -0,0 +1,22 @@ +[ + { + "ParameterKey": "pConfigurationRoleName", + "ParameterValue": "sra-macie-configuration" + }, + { + "ParameterKey": "pOrgManagementAccountId", + "ParameterValue": "$[alfred_ssm_/org/primary/account_id]" + }, + { + "ParameterKey": "pLambdaRoleName", + "ParameterValue": "sra-macie-org-lambda" + }, + { + "ParameterKey": "pTagKey1", + "ParameterValue": "sra" + }, + { + "ParameterKey": "pTagValue1", + "ParameterValue": "managed-by-sra" + } +] \ No newline at end of file diff --git a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-configuration.json b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-configuration.json similarity index 80% rename from solutions/macie/macie-org/aws-control-tower/parameters/macie-org-configuration.json rename to aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-configuration.json index 5c6d061c..89ecafb1 100644 --- a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-configuration.json +++ b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-configuration.json @@ -1,7 +1,7 @@ [ { "ParameterKey": "pConfigurationRoleName", - "ParameterValue": "cfct-macie-configuration" + "ParameterValue": "sra-macie-configuration" }, { "ParameterKey": "pControlTowerRegionsOnly", @@ -13,7 +13,7 @@ }, { "ParameterKey": "pDisableMacieRoleName", - "ParameterValue": "cfct-disable-macie" + "ParameterValue": "sra-disable-macie" }, { "ParameterKey": "pEnabledRegions", @@ -29,11 +29,11 @@ }, { "ParameterKey": "pLambdaExecutionRoleName", - "ParameterValue": "cfct-macie-org-lambda" + "ParameterValue": "sra-macie-org-lambda" }, { "ParameterKey": "pLambdaFunctionName", - "ParameterValue": "cfct-macie-org-configuration" + "ParameterValue": "sra-macie-org-configuration" }, { "ParameterKey": "pLambdaS3BucketName", @@ -41,7 +41,7 @@ }, { "ParameterKey": "pLambdaZipFileName", - "ParameterValue": "macie-org-configuration.zip" + "ParameterValue": "macie-org.zip" }, { "ParameterKey": "pLogLevel", @@ -57,10 +57,10 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-kms-key.json b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-kms-key.json similarity index 71% rename from solutions/macie/macie-org/aws-control-tower/parameters/macie-org-kms-key.json rename to aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-kms-key.json index 286ab5b1..32f81e75 100644 --- a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-kms-key.json +++ b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-kms-key.json @@ -9,14 +9,14 @@ }, { "ParameterKey": "pOrgManagementAccountId", - "ParameterValue": "$[alfred_ssm_/org/member/Control-Tower-Management/account_id]" + "ParameterValue": "$[alfred_ssm_/org/primary/account_id]" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-member-disable-role.json b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-member-disable-role.json similarity index 51% rename from solutions/macie/macie-org/aws-control-tower/parameters/macie-org-member-disable-role.json rename to aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-member-disable-role.json index 6b55bc53..7293b8af 100644 --- a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-member-disable-role.json +++ b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-member-disable-role.json @@ -1,22 +1,22 @@ [ { "ParameterKey": "pDisableMacieRoleName", - "ParameterValue": "cfct-disable-macie" + "ParameterValue": "sra-disable-macie" }, { "ParameterKey": "pOrgManagementAccountId", - "ParameterValue": "$[alfred_ssm_/org/member/Control-Tower-Management/account_id]" + "ParameterValue": "$[alfred_ssm_/org/primary/account_id]" }, { "ParameterKey": "pLambdaRoleName", - "ParameterValue": "cfct-macie-org-lambda" + "ParameterValue": "sra-macie-org-lambda" }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-s3-bucket.json b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-s3-bucket.json similarity index 88% rename from solutions/macie/macie-org/aws-control-tower/parameters/macie-org-s3-bucket.json rename to aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-s3-bucket.json index 56ab8105..76865b12 100644 --- a/solutions/macie/macie-org/aws-control-tower/parameters/macie-org-s3-bucket.json +++ b/aws_sra_examples/solutions/macie/macie_org/customizations_for_aws_control_tower/parameters/sra-macie-org-s3-bucket.json @@ -17,10 +17,10 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" + "ParameterValue": "managed-by-sra" } ] \ No newline at end of file diff --git a/aws_sra_examples/solutions/macie/macie_org/documentation/macie-org.png b/aws_sra_examples/solutions/macie/macie_org/documentation/macie-org.png new file mode 100644 index 00000000..450d28d6 Binary files /dev/null and b/aws_sra_examples/solutions/macie/macie_org/documentation/macie-org.png differ diff --git a/solutions/macie/macie-org/documentation/diagram/Macie-Architecture.pptx b/aws_sra_examples/solutions/macie/macie_org/documentation/macie-org.pptx similarity index 86% rename from solutions/macie/macie-org/documentation/diagram/Macie-Architecture.pptx rename to aws_sra_examples/solutions/macie/macie_org/documentation/macie-org.pptx index bca76ba6..a2e0d2bb 100644 Binary files a/solutions/macie/macie-org/documentation/diagram/Macie-Architecture.pptx and b/aws_sra_examples/solutions/macie/macie_org/documentation/macie-org.pptx differ diff --git a/solutions/macie/macie-org/code/src/app.py b/aws_sra_examples/solutions/macie/macie_org/lambda/src/app.py similarity index 100% rename from solutions/macie/macie-org/code/src/app.py rename to aws_sra_examples/solutions/macie/macie_org/lambda/src/app.py diff --git a/solutions/guardduty/guardduty-org/code/src/requirements.txt b/aws_sra_examples/solutions/macie/macie_org/lambda/src/requirements.txt similarity index 100% rename from solutions/guardduty/guardduty-org/code/src/requirements.txt rename to aws_sra_examples/solutions/macie/macie_org/lambda/src/requirements.txt diff --git a/solutions/macie/macie-org/templates/macie-org-configuration-role.yaml b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-configuration-role.yaml similarity index 82% rename from solutions/macie/macie-org/templates/macie-org-configuration-role.yaml rename to aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-configuration-role.yaml index a0c6a408..34fb40de 100644 --- a/solutions/macie/macie-org/templates/macie-org-configuration-role.yaml +++ b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-configuration-role.yaml @@ -1,11 +1,10 @@ AWSTemplateFormatVersion: 2010-09-09 -Description: Create an IAM role for configuration in the delegated administrator account +Description: Create an IAM role for Macie configuration in the delegated administrator account Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Role Attributes Parameters: - pConfigurationRoleName @@ -48,16 +47,16 @@ Parameters: pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -74,33 +73,35 @@ Resources: Properties: RoleName: !Ref pConfigurationRoleName AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - Action: sts:AssumeRole Condition: StringEquals: aws:PrincipalArn: !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:role/${pLambdaRoleName} - Effect: "Allow" + Effect: 'Allow' Principal: AWS: - !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:root - Path: "/" + Path: '/' Policies: - PolicyName: macie-org-policy-organizations PolicyDocument: Version: 2012-10-17 Statement: - - Action: organizations:ListAccounts + - Sid: Organizations Effect: Allow - Resource: "*" - Sid: Organizations + Action: organizations:ListAccounts + Resource: '*' - PolicyName: macie-org-policy-macie PolicyDocument: Version: 2012-10-17 Statement: - - Action: + - Sid: MacieNoResource + Effect: Allow + Action: - macie2:DescribeBuckets - macie2:DescribeOrganizationConfiguration - macie2:DisableMacie @@ -115,41 +116,39 @@ Resources: - macie2:PutClassificationExportConfiguration - macie2:UpdateMacieSession - macie2:UpdateOrganizationConfiguration - Effect: Allow - Resource: "*" - Sid: MacieNoResource + Resource: '*' - - Action: + - Sid: MacieMember + Effect: Allow + Action: - macie2:CreateMember - macie2:DeleteMember - macie2:DisassociateMember - macie2:GetMember - Effect: Allow Resource: !Sub arn:${AWS::Partition}:macie2:*:${AWS::AccountId}:* - Sid: MacieMember - PolicyName: macie-org-policy-iam PolicyDocument: Version: 2012-10-17 Statement: - - Action: iam:GetRole + - Sid: AllowReadIamActions Effect: Allow + Action: iam:GetRole Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/* - Sid: AllowReadIamActions - - Action: + - Sid: AllowCreateDeleteServiceLinkedRole + Effect: Allow + Action: - iam:CreateServiceLinkedRole - iam:DeleteServiceLinkedRole - Effect: Allow Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie - Sid: AllowCreateDeleteServiceLinkedRole - - Action: + - Sid: AllowPolicyActions + Effect: Allow + Action: - iam:DeleteRolePolicy - iam:PutRolePolicy - Effect: Allow Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie - Sid: AllowPolicyActions Tags: - Key: !Ref pTagKey1 diff --git a/solutions/macie/macie-org/templates/macie-org-configuration.yaml b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-configuration.yaml similarity index 72% rename from solutions/macie/macie-org/templates/macie-org-configuration.yaml rename to aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-configuration.yaml index bf6a8c75..f9a29f28 100644 --- a/solutions/macie/macie-org/templates/macie-org-configuration.yaml +++ b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-configuration.yaml @@ -4,8 +4,7 @@ Description: Organization delegated admin template for configuring Macie Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Lambda Function Attributes Parameters: - pLambdaExecutionRoleName @@ -14,8 +13,7 @@ Metadata: - pLambdaZipFileName - pLogLevel - pOrganizationId - - - Label: + - Label: default: Macie Attributes Parameters: - pConfigurationRoleName @@ -27,8 +25,7 @@ Metadata: - pKMSKeyArn - pPublishingDestinationBucketName - - - Label: + - Label: default: Resource Tags Parameters: - pTagKey1 @@ -80,7 +77,7 @@ Parameters: pControlTowerRegionsOnly: Description: Only enable Macie in the Control Tower regions Default: false - AllowedValues: [ true, false ] + AllowedValues: [true, false] Type: String pDelegatedAdminAccountId: @@ -125,12 +122,10 @@ Parameters: Type: String pLambdaS3BucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). - Description: - The Amazon S3 bucket name where the lambda zip file is stored. Example Bucket Name = lambda-zips-us-east-1 + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). + Description: The Amazon S3 bucket name where the lambda zip file is stored. Example Bucket Name = lambda-zips-us-east-1 Type: String pLambdaZipFileName: @@ -153,26 +148,25 @@ Parameters: Type: String pPublishingDestinationBucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: Macie classification export S3 bucket name Type: String pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -183,37 +177,35 @@ Resources: cfn_nag: rules_to_suppress: - id: W11 - reason: "Allow * in resource for read only actions" + reason: 'Allow * in resource for read only actions' - id: W28 reason: The role name is defined Properties: AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - - Action: sts:AssumeRole - Effect: Allow + - Effect: Allow + Action: sts:AssumeRole Principal: Service: - lambda.amazonaws.com - Path: "/" + Path: '/' Policies: - - PolicyDocument: + - PolicyName: macie-org-policy-logs + PolicyDocument: Statement: - - Action: logs:CreateLogGroup + - Sid: CreateLogStreamAndEvents Effect: Allow - Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${pLambdaFunctionName}:* - Sid: CreateLogGroup - - - Action: + Action: + - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - Effect: Allow Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${pLambdaFunctionName}:log-stream:* - Sid: CreateLogStreamAndEvents + Version: 2012-10-17 - PolicyName: macie-org-policy-logs - - PolicyDocument: + - PolicyName: macie-org-policy-organizations + PolicyDocument: Statement: - Sid: Organizations Effect: Allow @@ -225,10 +217,10 @@ Resources: - organizations:ListAWSServiceAccessForOrganization - organizations:ListDelegatedAdministrators - organizations:RegisterDelegatedAdministrator - Resource: "*" - PolicyName: macie-org-policy-organizations + Resource: '*' - - PolicyDocument: + - PolicyName: macie-org-policy-macie + PolicyDocument: Statement: - Sid: MacieNoResource Effect: Allow @@ -236,54 +228,54 @@ Resources: - macie2:DisableOrganizationAdminAccount - macie2:EnableOrganizationAdminAccount - macie2:ListOrganizationAdminAccounts - Resource: "*" + Resource: '*' Version: 2012-10-17 - PolicyName: macie-org-policy-macie - - PolicyDocument: + - PolicyName: macie-org-policy-iam + PolicyDocument: Statement: - - Action: iam:GetRole - Effect: Allow - Resource: - - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/AWSServiceRoleForAmazonMacie - - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie - Sid: AllowReadIamActions - - - Action: - - iam:CreateServiceLinkedRole - - iam:DeleteServiceLinkedRole - Condition: - StringLike: - iam:AWSServiceName: macie.amazonaws.com - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie - Sid: AllowCreateDeleteServiceLinkedRole - - - Action: - - iam:DeleteRolePolicy - - iam:PutRolePolicy - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie - Sid: AllowPolicyActions - - - Action: sts:AssumeRole - Condition: - StringEquals: - aws:PrincipalOrgId: !Ref pOrganizationId - Effect: Allow - Resource: - - !Sub arn:${AWS::Partition}:iam::*:role/${pConfigurationRoleName} - - !Sub arn:${AWS::Partition}:iam::*:role/${pDisableMacieRoleName} - Sid: AssumeRole + - Sid: AllowReadIamActions + Effect: Allow + Action: iam:GetRole + Resource: + - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/AWSServiceRoleForAmazonMacie + - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie + + - Sid: AllowCreateDeleteServiceLinkedRole + Condition: + StringLike: + iam:AWSServiceName: macie.amazonaws.com + Effect: Allow + Action: + - iam:CreateServiceLinkedRole + - iam:DeleteServiceLinkedRole + Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie + + - Sid: AllowPolicyActions + Effect: Allow + Action: + - iam:DeleteRolePolicy + - iam:PutRolePolicy + Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie + + - Sid: AssumeRole + Effect: Allow + Action: sts:AssumeRole + Condition: + StringEquals: + aws:PrincipalOrgId: !Ref pOrganizationId + Resource: + - !Sub arn:${AWS::Partition}:iam::*:role/${pConfigurationRoleName} + - !Sub arn:${AWS::Partition}:iam::*:role/${pDisableMacieRoleName} + Version: 2012-10-17 - PolicyName: macie-org-policy-iam - PolicyName: macie-org-policy-cloudformation PolicyDocument: Version: 2012-10-17 Statement: - - Action: cloudformation:ListStackInstances - Effect: Allow + - Effect: Allow + Action: cloudformation:ListStackInstances Resource: !Sub arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stackset/AWSControlTowerBP-* RoleName: !Ref pLambdaExecutionRoleName Tags: @@ -331,4 +323,4 @@ Resources: FINDING_PUBLISHING_FREQUENCY: !Ref pFindingPublishingFrequency KMS_KEY_ARN: !Ref pKMSKeyArn S3_BUCKET_NAME: !Ref pPublishingDestinationBucketName - Version: "1.0" \ No newline at end of file + Version: '1.0' diff --git a/solutions/macie/macie-org/templates/macie-org-kms-key.yaml b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-kms-key.yaml similarity index 79% rename from solutions/macie/macie-org/templates/macie-org-kms-key.yaml rename to aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-kms-key.yaml index bddf100b..accfb62e 100644 --- a/solutions/macie/macie-org/templates/macie-org-kms-key.yaml +++ b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-kms-key.yaml @@ -4,8 +4,7 @@ Description: Creates the Macie KMS Key Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: KMS Key Attributes Parameters: - pLoggingAccountId @@ -36,8 +35,7 @@ Parameters: pMacieDeliveryKeyAlias: AllowedPattern: '^[a-zA-Z0-9/_-]+$' ConstraintDescription: > - The alias must be string of 1-256 characters. - It can contain only alphanumeric characters, forward slashes (/), underscores (_), and dashes (-). + The alias must be string of 1-256 characters. It can contain only alphanumeric characters, forward slashes (/), underscores (_), and dashes (-). Default: MacieDeliveryKMSKey Description: Macie Delivery KMS Key Alias Type: String @@ -51,16 +49,16 @@ Parameters: pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -78,12 +76,12 @@ Resources: KeyPolicy: Id: !Sub ${pMacieDeliveryKeyAlias} Statement: - - Action: "kms:*" + - Action: 'kms:*' Effect: Allow Principal: AWS: - !Sub arn:aws:iam::${AWS::AccountId}:root - Resource: "*" + Resource: '*' Sid: Enable IAM User Permissions - Action: @@ -92,7 +90,7 @@ Resources: Effect: Allow Principal: Service: macie.amazonaws.com - Resource: "*" + Resource: '*' Sid: Allow Macie to use the key - Action: kms:CreateAlias @@ -103,29 +101,29 @@ Resources: Effect: Allow Principal: AWS: !Sub arn:aws:iam::${AWS::AccountId}:root - Resource: "*" + Resource: '*' Sid: Allow alias creation during setup - - Action: + - Sid: Allow log archive account access + Effect: Allow + Action: - kms:Decrypt - kms:DescribeKey - Effect: Allow + Resource: '*' Principal: AWS: - !Sub arn:aws:iam::${pLoggingAccountId}:root - !Sub arn:aws:iam::${pOrgManagementAccountId}:root - Resource: "*" - Sid: Allow log archive account access - - Action: + - Sid: Allow security account access + Effect: Allow + Action: - kms:DescribeKey - kms:Decrypt - Effect: Allow + Resource: '*' Principal: AWS: !Sub arn:aws:iam::${AWS::AccountId}:root - Resource: "*" - Sid: Allow security account access - Version: "2012-10-17" + Version: '2012-10-17' Tags: - Key: !Ref pTagKey1 Value: !Ref pTagValue1 @@ -134,10 +132,9 @@ Resources: Type: AWS::KMS::Alias Properties: AliasName: !Sub alias/${pMacieDeliveryKeyAlias} - TargetKeyId: - !Ref rMacieDeliveryKey + TargetKeyId: !Ref rMacieDeliveryKey Outputs: oMacieDeliveryKeyArn: Description: Macie Delivery KMS Key ARN - Value: !GetAtt rMacieDeliveryKey.Arn \ No newline at end of file + Value: !GetAtt rMacieDeliveryKey.Arn diff --git a/solutions/macie/macie-org/templates/macie-org-member-disable-role.yaml b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-member-disable-role.yaml similarity index 83% rename from solutions/macie/macie-org/templates/macie-org-member-disable-role.yaml rename to aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-member-disable-role.yaml index 37ff354f..42e560c1 100644 --- a/solutions/macie/macie-org/templates/macie-org-member-disable-role.yaml +++ b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-member-disable-role.yaml @@ -4,8 +4,7 @@ Description: Create an IAM role for disabling Macie Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Role Attributes Parameters: - pDisableMacieRoleName @@ -48,16 +47,16 @@ Parameters: pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -83,25 +82,26 @@ Resources: Principal: AWS: - !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:root - Version: "2012-10-17" - Path: "/" + Version: '2012-10-17' + Path: '/' Policies: - PolicyName: macie-org-policy-disable PolicyDocument: Version: 2012-10-17 Statement: - - Action: + - Sid: DisableMacie + Effect: Allow + Action: - macie2:DisableMacie - macie2:GetAdministratorAccount - Effect: Allow - Resource: "*" - Sid: DisableMacie + Resource: '*' - - Action: iam:DeleteServiceLinkedRole + - Sid: IAMDeleteMacieServiceLinkedRole Effect: Allow + Action: iam:DeleteServiceLinkedRole Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie - Sid: IAMDeleteMacieServiceLinkedRole + RoleName: !Ref pDisableMacieRoleName Tags: - Key: !Ref pTagKey1 - Value: !Ref pTagValue1 \ No newline at end of file + Value: !Ref pTagValue1 diff --git a/solutions/macie/macie-org/templates/macie-org-s3-bucket.yaml b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-s3-bucket.yaml similarity index 80% rename from solutions/macie/macie-org/templates/macie-org-s3-bucket.yaml rename to aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-s3-bucket.yaml index ac67d33d..c8c2970f 100644 --- a/solutions/macie/macie-org/templates/macie-org-s3-bucket.yaml +++ b/aws_sra_examples/solutions/macie/macie_org/templates/sra-macie-org-s3-bucket.yaml @@ -4,8 +4,7 @@ Description: Creates the Macie delivery S3 bucket Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Macie Delivery S3 Attributes Parameters: - pDelegatedAdminAccountId @@ -37,10 +36,9 @@ Parameters: Type: String pMacieDeliveryBucketPrefix: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" + AllowedPattern: '^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). + S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Description: Macie Delivery S3 bucket prefix. The account and region will get added to the end. e.g. macie-delivery-123456789012-us-east-1 Default: macie-delivery Type: String @@ -63,16 +61,16 @@ Parameters: pTagKey1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' + The string value can be Unicode characters and cannot be prefixed with "aws:". The string can contain only the set of Unicode letters, digits, + white-space, '_', '.', '/', '=', '+', '-'' Description: Tag key Type: String pTagValue1: AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' + The string value can be Unicode characters. The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', + '+', '-' Description: Tag key value Type: String @@ -92,6 +90,7 @@ Resources: - ServerSideEncryptionByDefault: KMSMasterKeyID: !Ref pMacieDeliveryKMSKeyArn SSEAlgorithm: aws:kms + BucketKeyEnabled: True BucketName: !Sub ${pMacieDeliveryBucketPrefix}-${AWS::AccountId}-${AWS::Region} OwnershipControls: Rules: @@ -114,88 +113,87 @@ Resources: PolicyDocument: Version: 2012-10-17 Statement: - - Action: s3:PutObject + - Sid: DenyPutObjectUnlessMacie + Effect: Deny + Action: s3:PutObject Condition: ForAnyValue:StringNotEquals: aws:CalledVia: macie.amazonaws.com - Effect: Deny - Principal: "*" Resource: - !Sub arn:${AWS::Partition}:s3:::${rS3Bucket} - !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* - Sid: DenyPutObjectUnlessMacie + Principal: '*' - - Action: "s3:*" + - Sid: SecureTransport + Effect: Deny + Action: 's3:*' Condition: Bool: - "aws:SecureTransport": "false" - Effect: Deny - Principal: "*" + 'aws:SecureTransport': 'false' Resource: - !Sub arn:${AWS::Partition}:s3:::${rS3Bucket} - !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* - Sid: SecureTransport + Principal: '*' - - Action: + - Sid: AWSBucketPermissionsCheck + Effect: Allow + Action: - s3:GetBucketAcl - s3:GetBucketLocation - s3:ListBucket - Effect: Allow + Resource: !Sub arn:${AWS::Partition}:s3:::${rS3Bucket} Principal: Service: - macie.amazonaws.com - Resource: !Sub arn:${AWS::Partition}:s3:::${rS3Bucket} - Sid: AWSBucketPermissionsCheck - - Action: s3:PutObject + - Sid: AWSBucketDelivery + Effect: Allow + Action: s3:PutObject Condition: StringEquals: - "s3:x-amz-acl": "bucket-owner-full-control" - Effect: Allow + 's3:x-amz-acl': 'bucket-owner-full-control' + Resource: !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* Principal: Service: - macie.amazonaws.com - Resource: !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* - Sid: AWSBucketDelivery - - - Action: s3:PutObject + - Sid: DenyUnencryptedObjectUploads + Effect: Deny + Action: s3:PutObject Condition: StringNotEquals: - "s3:x-amz-server-side-encryption": "aws:kms" - Effect: Deny + 's3:x-amz-server-side-encryption': 'aws:kms' + Resource: !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* Principal: Service: - macie.amazonaws.com - Resource: !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* - Sid: DenyUnencryptedObjectUploads - - Action: s3:PutObject + - Sid: DenyIncorrectEncryptionHeader + Effect: Deny + Action: s3:PutObject Condition: StringNotEquals: - "s3:x-amz-server-side-encryption-aws-kms-key-id": !Sub ${pMacieDeliveryKMSKeyArn} - Effect: Deny + 's3:x-amz-server-side-encryption-aws-kms-key-id': !Sub ${pMacieDeliveryKMSKeyArn} + Resource: !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* Principal: Service: - macie.amazonaws.com - Resource: !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* - Sid: DenyIncorrectEncryptionHeader - - Action: + - Sid: AllowDelegatedAdminReadAccess + Effect: Allow + Action: - s3:GetObject - s3:ListBucket Condition: StringEquals: aws:PrincipalOrgID: !Ref pOrganizationId - Effect: Allow - Principal: - AWS: !Sub arn:${AWS::Partition}:iam::${pDelegatedAdminAccountId}:root Resource: - !Sub arn:${AWS::Partition}:s3:::${rS3Bucket} - !Sub arn:${AWS::Partition}:s3:::${rS3Bucket}/* - Sid: AllowDelegatedAdminReadAccess + Principal: + AWS: !Sub arn:${AWS::Partition}:iam::${pDelegatedAdminAccountId}:root Outputs: oMacieDeliveryS3Bucket: Description: Macie Delivery S3 Bucket - Value: !Ref rS3Bucket \ No newline at end of file + Value: !Ref rS3Bucket diff --git a/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/README.md b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/README.md new file mode 100644 index 00000000..1d0a0304 --- /dev/null +++ b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/README.md @@ -0,0 +1,197 @@ +# SecurityHub Enabler Account + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +## Table of Contents + +- [Introduction](#introduction) +- [Deployed Resource Details](#deployed-resource-details) +- [Implementation Instructions](#implementation-instructions) +- [Appendix](#appendix) +- [References](#references) + +--- + +## Introduction + +The SecurityHub Enabler solution will enable SecurityHub within each AWS Organizations account configured with an admin account (e.g. Audit) and security standards enabled. Centralizing SecurityHub within the Security Tooling account provides a +cross-account view of security standards compliance and findings from AWS service integrations. + +The solution implements a SecurityHub Enabler Lambda function in the Organization Management account, which runs periodically to verify each account/region has been invited into the central SecurityHub account and that SecurityHub is enabled. +Optionally, security standards and integrations can be enabled as part of the solution deployment. + +This solution differs from that presented [here](https://github.com/awslabs/aws-securityhub-multiaccount-scripts) as it takes a serverless approach (vs. launching an EC2 instance) and auto enables new accounts added to the AWS Organization. + +--- + +## Deployed Resource Details + +![Architecture](./documentation/securityhub-enabler-acct.png) + +### 1.0 Organization Management Account + +#### 1.1 AWS CloudFormation + +- All resources are deployed via AWS CloudFormation as a `StackSet` and `Stack Instance` within the management account or a CloudFormation `Stack` within a specific account. +- The [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) solution deploys all templates as a CloudFormation `StackSet`. +- For parameter details, review the [AWS CloudFormation templates](templates/). + +#### 1.2 EventBridge Scheduled Rule + +- The scheduled rule triggers the Lambda Function between 1 and 3600 minutes to check organization compliance + +#### 1.3 SNS Topic + +- SNS Topic triggers the Lambda Function during initial setup to handle multiple accounts. +- The Lambda Function will publish all the AWS Organization accounts to the SNS Topic if it isn't triggered by SNS. + +#### 1.4 AWS Lambda Function + +- The Lambda Function enables Security Hub within all the active AWS Organizations accounts + +#### 1.5 Lambda CloudWatch Log Group + +- Contains the Lambda function execution logs + +#### 1.6 Lambda Execution IAM Role + +- Used by the custom CloudFormation Lambda function to enable Security Hub in all accounts and regions + +#### 1.7 Security Hub + +- Security Hub is enabled in all the active Organization accounts and regions via the Lambda Function. +- Each member account Security Hub is configured with the provided Security Hub master account. + +--- + +### 2.0 Audit Account + +#### 2.1 AWS CloudFormation + +- See [1.1 AWS CloudFormation](#11-aws-cloudformation) + +#### 2.2 Security Hub Enabler Role + +- IAM role assumed by the Management account Lambda function to enable Security Hub within each account and all the active regions + +#### 2.3 Security Hub + +- Security Hub provides visibility of all Security Hub member results + +--- + +### 3.0 All Existing and Future Organization Member Accounts + +#### 3.1 Security Hub Enabler Role + +- IAM role assumed by the Management account Lambda function to enable Security Hub within each account and all the active regions + +#### 3.2 Security Hub + +- Security Hub enabled within each account and all active regions + +--- + +## Implementation Instructions + +### Prerequisites + +- AWS Control Tower is deployed. +- `aws-security-reference-architecture-examples` repository is stored on your local machine or location where you will be deploying from. +- Security Hub is not enabled in any of the accounts within the AWS Organization + +### Staging + +1. In the `management account (home region)`, launch the AWS CloudFormation **Stack** using the [prereq-controltower-execution-role.yaml](../../../utils/aws_control_tower/prerequisites/prereq-controltower-execution-role.yaml) template file as the + source, to implement the `AWSControlTowerExecution` role pre-requisite. + - **Note:** Only do this step, if the `AWSControlTowerExecution` IAM role doesn't already exist in the Control Tower `management account`. +2. In the `management account (home region)`, launch the AWS CloudFormation **StackSet** targeting only the `management account` in all of the enabled regions (include home region) + [prereq-lambda-s3-bucket.yaml](../../../utils/aws_control_tower/prerequisites/prereq-lambda-s3-bucket.yaml) template file as the source, to implement an S3 bucket that will store the Lambda Zip files. (Example Bucket Name: + `lambda-zips--`) + - For additional guidance see [CloudFormation StackSet Instructions](#cloudformation-stackset-instructions) + - Take note of the S3 Bucket Name from the CloudFormation Outputs, as you will need it for both the packaging step, and the **Solution Deployment Order** section. + - **Note:** Only do this step if you don't already have an S3 bucket to store the Lambda zip files for CloudFormation custom resources in the Control Tower `management account`. + - Lambda functions can only access Zip files from an S3 bucket in the same AWS region as the where Lambda function resides. + - Although for this solution, S3 bucket is only needed in the `home region`, it is recommended to deploy the S3 bucket as a **stackset**, so that you can support future Lambda functions in other regions. +3. Package the Lambda code into a zip file and upload it to the S3 bucket (from above step), using the [Packaging script](../../../utils/packaging_scripts/package-lambda.sh). + - `SRA_REPO` environment variable should point to the folder where `aws-security-reference-architecture-examples` repository is stored. + - `BUCKET` environment variable should point to the S3 Bucket where the Lambda zip files are stored. + - See CloudFormation Output from Step 2 + - Or follow this syntax: `lambda-zips--` + +```bash +# Example (assumes repository was downloaded to your home directory) +export SRA_REPO="$HOME"/aws-security-reference-architecture-examples +export BUCKET=sra-staging-123456789012-us-east-1 +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name securityhub-enabler-acct.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/lambda/src +``` + +```bash +# Export AWS CLI profile for the 'management account' +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= +export AWS_SESSION_TOKEN= + +# Use template below and set the 'SRA_REPO' and 'BUCKET' with your values. +export SRA_REPO= +export BUCKET= +sh "$SRA_REPO"/aws_sra_examples/utils/packaging_scripts/package-lambda.sh \ +--file_name securityhub-enabler-acct.zip \ +--bucket $BUCKET \ +--src_dir "$SRA_REPO"/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/lambda/src +``` + +### Solution Deployment + +#### Customizations for AWS Control Tower + +- [Customizations for AWS Control Tower](./customizations_for_aws_control_tower) + +#### AWS CloudFormation + +1. In the `management account (home region)`, launch an AWS CloudFormation **Stack Set** and deploy to `All active accounts (home region)` using the [sra-securityhub-enabler-acct-role.yaml](templates/sra-securityhub-enabler-acct-role.yaml) template + file as the source. +2. In the `management account (home region)`, launch an AWS CloudFormation **Stack** using the [sra-securityhub-enabler-acct.yaml](templates/sra-securityhub-enabler-acct.yaml) template file as the source. + +#### Verify Solution Deployment + +1. Log into the Audit account and navigate to the Security Hub page +2. Verify the correct configurations have been applied to each region + 1. Security standards enabled + 2. Settings -> Accounts enabled + 3. Integrations enabled + +#### Solution Delete Instructions + +1. In the `management account (home region)`, delete the AWS CloudFormation **Stack** created in step 2 of the solution deployment. +2. In the `management account (home region)`, delete the AWS CloudWatch **Log Group** (e.g. /aws/lambda/) for the Lambda function deployed in step 2 of the solution deployment. +3. In the `management account (home region)`, delete the AWS CloudFormation **StackSet** created in step 1 of the solution deployment. **Note:** there should not be any `stack instances` associated with this StackSet. + +--- + +## Appendix + +### CloudFormation StackSet Instructions + +If you need to launch an AWS CloudFormation **StackSet** in the `management account`, see below steps (for additional details, see +[Create a stack set with self-managed permissions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started-create.html#stacksets-getting-started-create-self-managed)) + +1. AWS CloudFormation -> StackSets -> Create StackSet +2. Choose a Template (upload template) +3. Specify StackSet Details (enter parameter values) +4. Configure StackSet Options -> Self-service permissions + - IAM Admin Role Name: `AWSControlTowerStackSetRole` + - IAM Execution Role Name: `AWSControlTowerExecution` +5. Set Deployment Options -> Deploy New Stacks + - Deploy Stacks in Accounts -> enter the AWS Control Tower Management Account ID + - Specify Regions: choose regions you want to deploy stacks too (include home region) +6. If in future, you need to update the Stack Set (e.g., add/remove a region), see [Getting Started with AWS CloudFormation StackSets](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started.html) + +--- + +## References + +- [Setting up AWS Security Hub](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-settingup.html) diff --git a/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/README.md b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/README.md new file mode 100644 index 00000000..3d621646 --- /dev/null +++ b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/README.md @@ -0,0 +1,66 @@ +# Customizations for AWS Control Tower Implementation Instructions + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 + +--- + +## Table of Contents + +- [Version 1 Solution Deployment](#version-1-solution-deployment) +- [Version 2 Solution Deployment](#version-2-solution-deployment) +- [Solution Delete Instructions](#solution-delete-instructions) +- [How to check the solution version?](#how-to-check-the-solution-version) +- [References](#references) + +## Version 1 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - parameters [**required for manifest version 2020-01-01**] + - Copy the parameter files from the [parameters](./parameters) folder + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest.yaml) [**required**] + +2. Verify and update the parameters within each of the parameter json files to match the target environment +3. Update the manifest.yaml file with the `organizational unit names`, `account names` and `SSM parameters` for the target environment +4. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Version 2 Solution Deployment + +1. Copy the files to the Customizations for AWS Control Tower configuration + + - custom-control-tower-configuration + - policies [optional] + - service control policies files (\*.json) + - templates [**required**] + - Copy the template files from the [templates](../templates) folder + - [manifest.yaml](./manifest-v2.yaml) [**required**] + +2. Update the manifest.yaml file with the `parameters`, `organizational unit names`, `account names` and `SSM parameters` for the target environment +3. Deploy the Customizations for AWS Control Tower configuration by pushing the code to the `AWS CodeCommit` repository or uploading to the `AWS S3 Bucket` + +## Solution Delete Instructions + +1. Within the Customizations for AWS Control Tower configuration + 1. Remove the solution configuration from the `manifest.yaml` file + 2. (Optional) Delete the parameter (Version 1 only) and template files for the solution +2. Deploy the Customizations for AWS Control Tower configuration +3. After the pipeline completes, log into the `management account` and navigate to the `CloudFormation StackSet` page + 1. Delete the Stack Instances from the `CustomControlTower-*` CloudFormation StackSets + 2. After the Stack Instances are deleted, delete the `CustomControlTower-*` CloudFormation StackSets + +## How to check the solution version? + +1. Within the `management account (home region)` find the **CloudFormation Stack** for the Customizations for Control Tower (e.g. custom-control-tower-initiation) +2. Select the `Outputs` tab +3. The `CustomControlTowerSolutionVersion` **Value** is the version running in the environment + 1. v1.x.x = manifest.yaml version 2020-01-01 + 2. v2.x.x = manifest.yaml version 2021-03-15 + +## References + +- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) diff --git a/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/manifest.yaml b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/manifest.yaml new file mode 100644 index 00000000..02f4652a --- /dev/null +++ b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/manifest.yaml @@ -0,0 +1,29 @@ +--- +#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets +region: us-east-1 +version: 2020-01-01 + +# Control Tower Custom Service Control Policies +organization_policies: [] + +# Control Tower Custom CloudFormation Resources +cloudformation_resources: + # ----------------------------------------------------------------------------- + # Security Hub Account + # ----------------------------------------------------------------------------- + - name: sra-securityhub-enabler-acct-role + template_file: templates/sra-securityhub-enabler-acct-role.yaml + parameter_file: parameters/sra-securityhub-enabler-acct-role.json + deploy_method: stack_set + deploy_to_ou: + # Add all OUs with active accounts + - Core + - management + - workloads + + - name: sra-securityhub-enabler-acct + template_file: templates/sra-securityhub-enabler-acct.yaml + parameter_file: parameters/sra-securityhub-enabler-acct.json + deploy_method: stack_set + deploy_to_account: + - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME diff --git a/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/parameters/sra-securityhub-enabler-acct-role.json b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/parameters/sra-securityhub-enabler-acct-role.json new file mode 100644 index 00000000..11e93a63 --- /dev/null +++ b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/parameters/sra-securityhub-enabler-acct-role.json @@ -0,0 +1,22 @@ +[ + { + "ParameterKey": "pSecurityHubEnablerRoleName", + "ParameterValue": "sra-securityhub-enabler" + }, + { + "ParameterKey": "pSecurityHubEnablerLambdaRoleName", + "ParameterValue": "sra-securityhub-enabler-lambda" + }, + { + "ParameterKey": "pOrgManagementAccountId", + "ParameterValue": "$[alfred_ssm_/org/primary/account_id]" + }, + { + "ParameterKey": "pTagKey1", + "ParameterValue": "sra" + }, + { + "ParameterKey": "pTagValue1", + "ParameterValue": "managed-by-sra" + } +] \ No newline at end of file diff --git a/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/parameters/securityhub-enabler-acct.json b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/parameters/sra-securityhub-enabler-acct.json similarity index 82% rename from solutions/securityhub/securityhub-enabler-acct/aws-control-tower/parameters/securityhub-enabler-acct.json rename to aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/parameters/sra-securityhub-enabler-acct.json index 5564071a..3b3f1674 100644 --- a/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/parameters/securityhub-enabler-acct.json +++ b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/customizations_for_aws_control_tower/parameters/sra-securityhub-enabler-acct.json @@ -13,7 +13,7 @@ }, { "ParameterKey": "pLambdaZipFileName", - "ParameterValue": "securityhub-enabler-acct-v1.zip" + "ParameterValue": "securityhub-enabler-acct.zip" }, { "ParameterKey": "pComplianceFrequency", @@ -21,15 +21,15 @@ }, { "ParameterKey": "pLambdaFunctionName", - "ParameterValue": "control-tower-security-hub-enabler" + "ParameterValue": "sra-securityhub-enabler" }, { "ParameterKey": "pLambdaExecutionRoleName", - "ParameterValue": "control-tower-security-hub-enabler-lambda" + "ParameterValue": "sra-securityhub-enabler-lambda" }, { "ParameterKey": "pRoleToAssume", - "ParameterValue": "control-tower-security-hub-enabler" + "ParameterValue": "sra-securityhub-enabler" }, { "ParameterKey": "pEnableCISStandard", @@ -61,11 +61,11 @@ }, { "ParameterKey": "pTagKey1", - "ParameterValue": "control-tower" + "ParameterValue": "sra" }, { "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-control-tower" + "ParameterValue": "managed-by-sra" }, { "ParameterKey": "pRegionsToEnable", diff --git a/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/documentation/securityhub-enabler-acct.png b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/documentation/securityhub-enabler-acct.png new file mode 100644 index 00000000..c4551bbb Binary files /dev/null and b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/documentation/securityhub-enabler-acct.png differ diff --git a/solutions/securityhub/securityhub-enabler-acct/documentation/diagram/Centralized-SecurityHub-Architecture.pptx b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/documentation/securityhub-enabler-acct.pptx similarity index 87% rename from solutions/securityhub/securityhub-enabler-acct/documentation/diagram/Centralized-SecurityHub-Architecture.pptx rename to aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/documentation/securityhub-enabler-acct.pptx index 124dc447..109b9051 100644 Binary files a/solutions/securityhub/securityhub-enabler-acct/documentation/diagram/Centralized-SecurityHub-Architecture.pptx and b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/documentation/securityhub-enabler-acct.pptx differ diff --git a/solutions/securityhub/securityhub-enabler-acct/code/src/app.py b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/lambda/src/app.py similarity index 100% rename from solutions/securityhub/securityhub-enabler-acct/code/src/app.py rename to aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/lambda/src/app.py diff --git a/solutions/securityhub/securityhub-enabler-acct/code/src/requirements.txt b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/lambda/src/requirements.txt similarity index 80% rename from solutions/securityhub/securityhub-enabler-acct/code/src/requirements.txt rename to aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/lambda/src/requirements.txt index 1dc5b0cb..47525430 100644 --- a/solutions/securityhub/securityhub-enabler-acct/code/src/requirements.txt +++ b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/lambda/src/requirements.txt @@ -1,3 +1,2 @@ #install latest -boto3 requests diff --git a/solutions/securityhub/securityhub-enabler-acct/templates/securityhub-enabler-acct-role.yaml b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/templates/sra-securityhub-enabler-acct-role.yaml similarity index 94% rename from solutions/securityhub/securityhub-enabler-acct/templates/securityhub-enabler-acct-role.yaml rename to aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/templates/sra-securityhub-enabler-acct-role.yaml index f830baa4..c877e95d 100644 --- a/solutions/securityhub/securityhub-enabler-acct/templates/securityhub-enabler-acct-role.yaml +++ b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/templates/sra-securityhub-enabler-acct-role.yaml @@ -4,8 +4,7 @@ Description: Creates the Security Hub enabler IAM role Metadata: AWS::CloudFormation::Interface: ParameterGroups: - - - Label: + - Label: default: Security Hub Enabler Role Attributes Parameters: - pSecurityHubEnablerRoleName @@ -30,12 +29,12 @@ Parameters: pSecurityHubEnablerRoleName: Type: String Description: Security Hub Enabler Role Name - Default: security-hub-enabler + Default: sra-security-hub-enabler pSecurityHubEnablerLambdaRoleName: Type: String Description: Security Hub Enabler Role Name - Default: security-hub-enabler-lambda + Default: sra-security-hub-enabler-lambda pOrgManagementAccountId: Type: String @@ -60,17 +59,18 @@ Resources: Properties: RoleName: !Ref pSecurityHubEnablerRoleName AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - Effect: Allow - Principal: - AWS: - - !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:root Action: sts:AssumeRole Condition: StringEquals: aws:PrincipalArn: !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:role/${pSecurityHubEnablerLambdaRoleName} - Path: "/" + Principal: + AWS: + - !Sub arn:${AWS::Partition}:iam::${pOrgManagementAccountId}:root + + Path: '/' Policies: - PolicyName: !Ref pSecurityHubEnablerRoleName PolicyDocument: @@ -109,10 +109,11 @@ Resources: - Sid: CreateServiceLinkedRole Effect: Allow Action: iam:CreateServiceLinkedRole - Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/securityhub.amazonaws.com/AWSServiceRoleForSecurityHub Condition: StringEquals: - "iam:AWSServiceName": "securityhub.amazonaws.com" + 'iam:AWSServiceName': 'securityhub.amazonaws.com' + Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/securityhub.amazonaws.com/AWSServiceRoleForSecurityHub + Tags: - Key: !Ref pTagKey1 Value: !Ref pTagValue1 diff --git a/solutions/securityhub/securityhub-enabler-acct/templates/securityhub-enabler-acct.yaml b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/templates/sra-securityhub-enabler-acct.yaml similarity index 85% rename from solutions/securityhub/securityhub-enabler-acct/templates/securityhub-enabler-acct.yaml rename to aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/templates/sra-securityhub-enabler-acct.yaml index 4082b8b1..591e5253 100644 --- a/solutions/securityhub/securityhub-enabler-acct/templates/securityhub-enabler-acct.yaml +++ b/aws_sra_examples/solutions/securityhub/securityhub_enabler_acct/templates/sra-securityhub-enabler-acct.yaml @@ -120,13 +120,13 @@ Parameters: pRoleToAssume: Type: String - Default: security-hub-enabler + Default: sra-security-hub-enabler Description: > IAM role to be assumed in child accounts to enable SecurityHub. pLambdaExecutionRoleName: Type: String - Default: security-hub-enabler-lambda + Default: sra-security-hub-enabler-lambda pLambdaFunctionName: Type: String @@ -143,7 +143,7 @@ Parameters: pCISStandardVersion: Type: String Description: CIS Standard Version - Default: "1.2.0" + Default: '1.2.0' pEnablePCIStandard: Type: String @@ -156,7 +156,7 @@ Parameters: pPCIStandardVersion: Type: String Description: PCI Standard Version - Default: "3.2.1" + Default: '3.2.1' pEnableSBPStandard: Type: String @@ -169,13 +169,13 @@ Parameters: pSBPStandardVersion: Type: String Description: Security Best Practices Standard Version - Default: "1.0.0" + Default: '1.0.0' pDefaultLogGroupRetention: Type: String Default: 14 Description: Specifies the number of days you want to retain log events - AllowedValues: [ 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653 ] + AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653] pRegionsToEnable: Type: String @@ -208,12 +208,17 @@ Parameters: Resources: rLambdaLogGroup: Type: AWS::Logs::LogGroup + Metadata: + cfn_nag: + rules_to_suppress: + - id: W84 + reason: CloudWatch LogGroup does not specify a KMS Key Id Properties: RetentionInDays: !Ref pDefaultLogGroupRetention - LogGroupName: !Sub "/aws/lambda/${pLambdaFunctionName}" + LogGroupName: !Sub '/aws/lambda/${pLambdaFunctionName}' rSecurityHubEnablerLambdaRole: - Type: "AWS::IAM::Role" + Type: 'AWS::IAM::Role' Metadata: cfn_nag: rules_to_suppress: @@ -224,14 +229,14 @@ Resources: Properties: RoleName: !Ref pLambdaExecutionRoleName AssumeRolePolicyDocument: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - - Effect: "Allow" + - Effect: 'Allow' Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole - Path: "/" + Path: '/' Policies: - PolicyName: securityhub-acct-policy-organizations PolicyDocument: @@ -241,10 +246,10 @@ Resources: Action: - organizations:ListAccounts - organizations:DescribeAccount - Resource: "*" + Resource: '*' Condition: StringEquals: - "aws:PrincipalOrgId": !Ref pOrganizationId + 'aws:PrincipalOrgId': !Ref pOrganizationId - PolicyName: securityhub-acct-policy-sts PolicyDocument: @@ -255,7 +260,7 @@ Resources: Resource: !Sub arn:${AWS::Partition}:iam::*:role/${pRoleToAssume} Condition: StringEquals: - "aws:PrincipalOrgId": !Ref pOrganizationId + 'aws:PrincipalOrgId': !Ref pOrganizationId - PolicyName: securityhub-acct-policy-sns PolicyDocument: @@ -290,7 +295,7 @@ Resources: Resource: - !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup}:log-stream:* - - PolicyName: "securityhub-acct-policy-cloudformation" + - PolicyName: 'securityhub-acct-policy-cloudformation' PolicyDocument: Version: 2012-10-17 Statement: @@ -309,15 +314,17 @@ Resources: rules_to_suppress: - id: W58 reason: CloudWatch logs permissions provided by the role + - id: W89 + reason: Lambda function does not access any VPC resources Properties: Description: Enable SecurityHub in all accounts and regions FunctionName: !Ref pLambdaFunctionName - Handler: "app.lambda_handler" + Handler: 'app.lambda_handler' Role: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${rSecurityHubEnablerLambdaRole} Code: S3Bucket: !Ref pS3SourceBucket S3Key: !Ref pLambdaZipFileName - Runtime: "python3.8" + Runtime: 'python3.8' MemorySize: 512 Timeout: 900 Tags: @@ -366,24 +373,24 @@ Resources: Type: AWS::Events::Rule Properties: Description: SecurityHubEnablerTrigger - ScheduleExpression: !Sub "rate(${pComplianceFrequency} minutes)" - State: "ENABLED" + ScheduleExpression: !Sub 'rate(${pComplianceFrequency} minutes)' + State: 'ENABLED' Targets: - Arn: !GetAtt rSecurityHubEnablerLambda.Arn - Id: "DailyInvite" + Id: 'DailyInvite' rPermissionForEventsToInvokeLambda: Type: AWS::Lambda::Permission Properties: FunctionName: !GetAtt rSecurityHubEnablerLambda.Arn Action: lambda:InvokeFunction - Principal: "events.amazonaws.com" + Principal: 'events.amazonaws.com' SourceArn: !GetAtt rScheduledRule.Arn rSecurityHubEnablerLambdaCustomResource: Type: Custom::SecurityHubEnablerLambdaCustomResource Properties: - Version: "1.0" + Version: '1.0' ServiceToken: !GetAtt rSecurityHubEnablerLambda.Arn ENABLE_CIS_STANDARD: !Sub ${pEnableCISStandard} CIS_STANDARD_VERSION: !Sub ${pCISStandardVersion} @@ -395,29 +402,29 @@ Resources: CONTROL_TOWER_REGIONS_ONLY: !Sub ${pControlTowerRegionsOnly} ENABLE_PROWLER_INTEGRATION: !Sub ${pEnableProwlerIntegration} -# # Trigger Security Hub Enabler after account is vended by AWS Control Tower -# rControlTowerLifeCycleRule: -# Type: AWS::Events::Rule -# Properties: -# Name: cct-securityhub-enabler -# Description: "SecurityHubLifeCycleTrigger" -# EventPattern: -# source: -# - "aws.controltower" -# detail-type: -# - "AWS Service Event via CloudTrail" -# detail: -# eventName: -# - "CreateManagedAccount" -# State: "ENABLED" -# Targets: -# - Arn: !GetAtt rSecurityHubEnablerLambda.Arn -# Id: "SecurityHubEnabler" -# -# rPermissionForCTRuleToInvokeLambda: -# Type: AWS::Lambda::Permission -# Properties: -# FunctionName: !GetAtt rSecurityHubEnablerLambda.Arn -# Action: "lambda:InvokeFunction" -# Principal: "events.amazonaws.com" -# SourceArn: !GetAtt rControlTowerLifeCycleRule.Arn \ No newline at end of file + # Trigger Security Hub Enabler after account is vended by AWS Control Tower + rControlTowerLifeCycleRule: + Type: AWS::Events::Rule + Properties: + Name: sra-securityhub-enabler + Description: 'SecurityHubLifeCycleTrigger' + EventPattern: + source: + - 'aws.controltower' + detail-type: + - 'AWS Service Event via CloudTrail' + detail: + eventName: + - 'CreateManagedAccount' + State: 'ENABLED' + Targets: + - Arn: !GetAtt rSecurityHubEnablerLambda.Arn + Id: 'SecurityHubEnabler' + + rPermissionForCTRuleToInvokeLambda: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !GetAtt rSecurityHubEnablerLambda.Arn + Action: 'lambda:InvokeFunction' + Principal: 'events.amazonaws.com' + SourceArn: !GetAtt rControlTowerLifeCycleRule.Arn diff --git a/aws_sra_examples/utils/__init__.py b/aws_sra_examples/utils/__init__.py new file mode 100644 index 00000000..df600b3f --- /dev/null +++ b/aws_sra_examples/utils/__init__.py @@ -0,0 +1,5 @@ +"""__init__.py. + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: MIT-0 +""" diff --git a/extras/aws-control-tower/helper-scripts/list-config-recorder-status.py b/aws_sra_examples/utils/aws_control_tower/helper_scripts/list_config_recorder_status.py similarity index 100% rename from extras/aws-control-tower/helper-scripts/list-config-recorder-status.py rename to aws_sra_examples/utils/aws_control_tower/helper_scripts/list_config_recorder_status.py diff --git a/extras/aws-control-tower/prerequisites/README.md b/aws_sra_examples/utils/aws_control_tower/prerequisites/README.md similarity index 57% rename from extras/aws-control-tower/prerequisites/README.md rename to aws_sra_examples/utils/aws_control_tower/prerequisites/README.md index 9fa775ab..f96cabb9 100644 --- a/extras/aws-control-tower/prerequisites/README.md +++ b/aws_sra_examples/utils/aws_control_tower/prerequisites/README.md @@ -1,27 +1,19 @@ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 ----- +--- # Prerequisites for AWS Control Tower solutions -1. Deploy the [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) - Solution +1. Deploy the [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) Solution 2. Required steps to deploy resources into the AWS Control Tower Management account (e.g. Management Account) 1. Create an Organizational Unit (e.g. Management) for the Management account - 1. Review the [Manage Accounts Through AWS Organizations](https://docs.aws.amazon.com/controltower/latest/userguide/organizations.html) - documentation + 1. Review the [Manage Accounts Through AWS Organizations](https://docs.aws.amazon.com/controltower/latest/userguide/organizations.html) documentation 2. Move the Management account into the new Organizational Unit 3. Create the AWSControlTowerExecution IAM role in the Management account - 1. Use the [prereq-controltower-execution-role.yaml](prereq-controltower-execution-role.yaml) template to - create a CloudFormation stack in the Management account. + 1. Use the [prereq-controltower-execution-role.yaml](prereq-controltower-execution-role.yaml) template to create a CloudFormation stack in the Management account. 3. Create an S3 bucket for the Lambda source code - 1. Use the [prereq-lambda-s3-bucket.yaml](prereq-lambda-s3-bucket.yaml) template to create a CloudFormation - StackSet in the Management account for each region that will deploy custom resources. -4. Package the Lambda code and required libraries (e.g. solution/code/src) into a zip file and upload it to the - Lambda source S3 bucket. - 1. Use the [packaging script](../../packaging-scripts/package-lambda.sh) to download the required libraries, - create a zip file, and upload it to a provided S3 bucket. Usage details are at the top of the script. + 1. Use the [prereq-lambda-s3-bucket.yaml](prereq-lambda-s3-bucket.yaml) template to create a CloudFormation StackSet in the Management account for each region that will deploy custom resources. +4. Package the Lambda code and required libraries (e.g. solution/lambda/src) into a zip file and upload it to the Lambda source S3 bucket. + 1. Use the [packaging script](../../packaging_scripts/package-lambda.sh) to download the required libraries, create a zip file, and upload it to a provided S3 bucket. Usage details are at the top of the script. 5. (Optional) Create SSM parameters for the AWS Account IDs and AWS Organizations ID - 1. Use the [prereq-ssm-account-params.yaml](prereq-ssm-account-params.yaml) template to create a CloudFormation - stack in the Management account. - \ No newline at end of file + 1. Use the [prereq-ssm-account-params.yaml](prereq-ssm-account-params.yaml) template to create a CloudFormation stack in the Management account. diff --git a/extras/aws-control-tower/prerequisites/prereq-controltower-execution-role.yaml b/aws_sra_examples/utils/aws_control_tower/prerequisites/prereq-controltower-execution-role.yaml similarity index 100% rename from extras/aws-control-tower/prerequisites/prereq-controltower-execution-role.yaml rename to aws_sra_examples/utils/aws_control_tower/prerequisites/prereq-controltower-execution-role.yaml diff --git a/extras/aws-control-tower/prerequisites/prereq-lambda-s3-bucket.yaml b/aws_sra_examples/utils/aws_control_tower/prerequisites/prereq-lambda-s3-bucket.yaml similarity index 100% rename from extras/aws-control-tower/prerequisites/prereq-lambda-s3-bucket.yaml rename to aws_sra_examples/utils/aws_control_tower/prerequisites/prereq-lambda-s3-bucket.yaml diff --git a/extras/aws-control-tower/prerequisites/prereq-ssm-account-params.yaml b/aws_sra_examples/utils/aws_control_tower/prerequisites/prereq-ssm-account-params.yaml similarity index 100% rename from extras/aws-control-tower/prerequisites/prereq-ssm-account-params.yaml rename to aws_sra_examples/utils/aws_control_tower/prerequisites/prereq-ssm-account-params.yaml diff --git a/extras/lambda-s3-buckets.yaml b/aws_sra_examples/utils/lambda-s3-buckets.yaml similarity index 100% rename from extras/lambda-s3-buckets.yaml rename to aws_sra_examples/utils/lambda-s3-buckets.yaml diff --git a/extras/packaging-scripts/package-lambda.sh b/aws_sra_examples/utils/packaging_scripts/package-lambda.sh similarity index 73% rename from extras/packaging-scripts/package-lambda.sh rename to aws_sra_examples/utils/packaging_scripts/package-lambda.sh index 087be0fd..cec2879d 100755 --- a/extras/packaging-scripts/package-lambda.sh +++ b/aws_sra_examples/utils/packaging_scripts/package-lambda.sh @@ -14,7 +14,7 @@ # Example: ./package-lambda.sh \ # --file_name cloudtrail-org.zip \ # --bucket my-s3-bucket \ -# --src_dir ~/Security-Reference-Architecture/solutions/cloudtrail/cloudtrail-org/code/src +# --src_dir ~/aws_sra_examples/solutions/cloudtrail/cloudtrail_org/lambda/src ########################################################################################### usage="$(basename "$0") [-h] <--file_name s> [--bucket s] <--src_folder s> ---script to package lambda zip and upload to s3 @@ -37,45 +37,49 @@ src_dir=${src_dir:-none} # read input parameters while [ $# -gt 0 ]; do - if [[ $1 == *"--"* ]]; then - param="${1/--/}" - declare "$param"="$2" - # echo $1 $2 // Optional to see the parameter:value result - fi + if [[ $1 == *"--"* ]]; then + param="${1/--/}" + declare "$param"="$2" + # echo $1 $2 // Optional to see the parameter:value result + fi shift done if [ "$file_name" != "none" ] && [ "$src_dir" != "none" ]; then - HERE="${PWD}" # absolute path to this file's folder - DIST_FOLDER_NAME="$HERE/dist-XXXX" # dist folder for the zip file if bucket is not provided + HERE="${PWD}" # absolute path to this file's folder + DIST_FOLDER_NAME="$HERE/dist-XXXX" # dist folder for the zip file if bucket is not provided TMP_FOLDER_NAME="$HOME/tmp-sra-lambda-src-XXXX" # will be cleaned SRC_FOLDER=$src_dir # create the temp packaging folder and install python packages echo "...Creating the temporary packaging folder (tmp-sra-lambda-src-XXXX)" TMP_FOLDER=$(mktemp -d "$TMP_FOLDER_NAME") || exit 1 # create the temp folder - cp -r "$SRC_FOLDER"/* "$TMP_FOLDER" || exit 1 # copy lambda source to temp source folder + cp -r "$SRC_FOLDER"/* "$TMP_FOLDER" || exit 1 # copy lambda source to temp source folder pip3 install -t "$TMP_FOLDER" -r "$TMP_FOLDER/requirements.txt" -q || - { rm -rf "$TMP_FOLDER"; echo "Error: Python is required"; exit 1; } + { + rm -rf "$TMP_FOLDER" + echo "Error: Python is required" + exit 1 + } # prepare the dist folder echo "...Creating the temporary dist-XXXX folder" DIST_FOLDER=$(mktemp -d "$DIST_FOLDER_NAME") || exit 1 # create dist folder, if it doesn't exist - cd "$DIST_FOLDER" || exit 1 # change directory into dist folder - rm -f "$file_name" # remove zip file, if exists + cd "$DIST_FOLDER" || exit 1 # change directory into dist folder + rm -f "$file_name" # remove zip file, if exists # create zip file in the dist folder echo "...Creating zip file from the temp folder contents" cd "$TMP_FOLDER" || exit 1 # changed directory to temp folder zip -r -q "$DIST_FOLDER/$file_name" . -x .DS_Store || - 7z a -tzip "$DIST_FOLDER/$file_name" || - { - rm -rf "$DIST_FOLDER"; - echo "---> Zip and 7zip are not available. Manually create the zip file with the temporary folder contents. $TMP_FOLDER"; - exit 1; - } # zip source with packages + 7z a -tzip "$DIST_FOLDER/$file_name" || + { + rm -rf "$DIST_FOLDER" + echo "---> Zip and 7zip are not available. Manually create the zip file with the temporary folder contents. $TMP_FOLDER" + exit 1 + } # zip source with packages cd "$DIST_FOLDER" || exit 1 # change directory to dist folder diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..6384cde3 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,5899 @@ +[[package]] +name = "astor" +version = "0.8.1" +description = "Read/rewrite/write Python ASTs" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" + +[[package]] +name = "astpretty" +version = "2.1.0" +description = "Pretty print the output of python stdlib `ast.parse`." +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[package.extras] +typed = ["typed-ast"] + +[[package]] +name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "attrs" +version = "21.2.0" +description = "Classes Without Boilerplate" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] + +[[package]] +name = "aws-lambda-typing" +version = "2.9.2" +description = "A package that provides type hints for AWS Lambda event, context and response objects" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +typing-extensions = ">=3.10.0,<4.0.0" + +[[package]] +name = "bandit" +version = "1.7.0" +description = "Security oriented static analyser for python code." +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} +GitPython = ">=1.0.1" +PyYAML = ">=5.3.1" +six = ">=1.10.0" +stevedore = ">=1.20.0" + +[[package]] +name = "black" +version = "21.10b0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +click = ">=7.1.2" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0,<1" +platformdirs = ">=2" +regex = ">=2020.1.8" +tomli = ">=0.2.6,<2.0.0" +typing-extensions = [ + {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, + {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, +] + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +python2 = ["typed-ast (>=1.4.3)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "boto3" +version = "1.20.2" +description = "The AWS SDK for Python" +category = "main" +optional = false +python-versions = ">= 3.6" + +[package.dependencies] +botocore = ">=1.23.2,<1.24.0" +jmespath = ">=0.7.1,<1.0.0" +s3transfer = ">=0.5.0,<0.6.0" + +[package.extras] +crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] + +[[package]] +name = "boto3-stubs" +version = "1.20.2" +description = "Type annotations for boto3 1.20.2, generated by mypy-boto3-builder 6.2.0" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +botocore-stubs = "*" +mypy-boto3-accessanalyzer = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-account = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-acm = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-acm-pca = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-alexaforbusiness = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-amp = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-amplify = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-amplifybackend = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-apigateway = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-apigatewaymanagementapi = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-apigatewayv2 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-appconfig = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-appflow = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-appintegrations = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-application-autoscaling = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-application-insights = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-applicationcostprofiler = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-appmesh = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-apprunner = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-appstream = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-appsync = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-athena = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-auditmanager = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-autoscaling = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-autoscaling-plans = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-backup = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-batch = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-braket = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-budgets = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ce = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-chime = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-chime-sdk-identity = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-chime-sdk-meetings = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-chime-sdk-messaging = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloud9 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloudcontrol = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-clouddirectory = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloudformation = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloudfront = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloudhsm = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloudhsmv2 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloudsearch = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloudsearchdomain = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloudtrail = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cloudwatch = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codeartifact = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codebuild = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codecommit = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codedeploy = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codeguru-reviewer = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codeguruprofiler = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codepipeline = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codestar = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codestar-connections = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-codestar-notifications = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cognito-identity = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cognito-idp = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cognito-sync = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-comprehend = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-comprehendmedical = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-compute-optimizer = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-config = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-connect = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-connect-contact-lens = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-connectparticipant = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-cur = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-customer-profiles = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-databrew = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-dataexchange = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-datapipeline = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-datasync = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-dax = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-detective = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-devicefarm = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-devops-guru = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-directconnect = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-discovery = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-dlm = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-dms = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-docdb = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ds = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-dynamodb = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-dynamodbstreams = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ebs = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ec2 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ec2-instance-connect = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ecr = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ecr-public = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ecs = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-efs = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-eks = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-elastic-inference = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-elasticache = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-elasticbeanstalk = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-elastictranscoder = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-elb = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-elbv2 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-emr = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-emr-containers = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-es = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-events = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-finspace = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-finspace-data = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-firehose = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-fis = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-fms = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-forecast = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-forecastquery = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-frauddetector = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-fsx = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-gamelift = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-glacier = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-globalaccelerator = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-glue = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-grafana = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-greengrass = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-greengrassv2 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-groundstation = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-guardduty = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-health = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-healthlake = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-honeycode = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iam = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-identitystore = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-imagebuilder = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-importexport = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-inspector = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iot = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iot-data = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iot-jobs-data = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iot1click-devices = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iot1click-projects = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iotanalytics = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iotdeviceadvisor = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iotevents = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iotevents-data = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iotfleethub = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iotsecuretunneling = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iotsitewise = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iotthingsgraph = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-iotwireless = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ivs = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kafka = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kafkaconnect = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kendra = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kinesis = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kinesis-video-archived-media = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kinesis-video-media = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kinesis-video-signaling = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kinesisanalytics = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kinesisanalyticsv2 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kinesisvideo = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-kms = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lakeformation = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lambda = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lex-models = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lex-runtime = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lexv2-models = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lexv2-runtime = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-license-manager = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lightsail = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-location = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-logs = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lookoutequipment = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lookoutmetrics = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-lookoutvision = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-machinelearning = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-macie = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-macie2 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-managedblockchain = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-marketplace-catalog = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-marketplace-entitlement = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-marketplacecommerceanalytics = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mediaconnect = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mediaconvert = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-medialive = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mediapackage = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mediapackage-vod = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mediastore = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mediastore-data = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mediatailor = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-memorydb = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-meteringmarketplace = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mgh = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mgn = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-migrationhub-config = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mobile = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mq = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mturk = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-mwaa = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-neptune = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-network-firewall = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-networkmanager = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-nimble = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-opensearch = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-opsworks = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-opsworkscm = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-organizations = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-outposts = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-panorama = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-personalize = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-personalize-events = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-personalize-runtime = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-pi = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-pinpoint = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-pinpoint-email = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-pinpoint-sms-voice = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-polly = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-pricing = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-proton = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-qldb = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-qldb-session = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-quicksight = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ram = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-rds = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-rds-data = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-redshift = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-redshift-data = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-rekognition = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-resource-groups = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-resourcegroupstaggingapi = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-robomaker = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-route53 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-route53-recovery-cluster = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-route53-recovery-control-config = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-route53-recovery-readiness = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-route53domains = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-route53resolver = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-s3 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-s3control = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-s3outposts = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sagemaker = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sagemaker-a2i-runtime = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sagemaker-edge = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sagemaker-featurestore-runtime = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sagemaker-runtime = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-savingsplans = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-schemas = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sdb = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-secretsmanager = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-securityhub = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-serverlessrepo = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-service-quotas = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-servicecatalog = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-servicecatalog-appregistry = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-servicediscovery = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ses = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sesv2 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-shield = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-signer = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sms = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sms-voice = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-snow-device-management = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-snowball = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sns = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sqs = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ssm = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ssm-contacts = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-ssm-incidents = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sso = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sso-admin = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sso-oidc = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-stepfunctions = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-storagegateway = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-sts = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-support = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-swf = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-synthetics = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-textract = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-timestream-query = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-timestream-write = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-transcribe = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-transfer = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-translate = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-voice-id = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-waf = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-waf-regional = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-wafv2 = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-wellarchitected = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-wisdom = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-workdocs = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-worklink = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-workmail = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-workmailmessageflow = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-workspaces = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} +mypy-boto3-xray = {version = ">=1.20.0", optional = true, markers = "extra == \"all\""} + +[package.extras] +accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.20.0)"] +account = ["mypy-boto3-account (>=1.20.0)"] +acm = ["mypy-boto3-acm (>=1.20.0)"] +acm-pca = ["mypy-boto3-acm-pca (>=1.20.0)"] +alexaforbusiness = ["mypy-boto3-alexaforbusiness (>=1.20.0)"] +all = ["mypy-boto3-accessanalyzer (>=1.20.0)", "mypy-boto3-account (>=1.20.0)", "mypy-boto3-acm (>=1.20.0)", "mypy-boto3-acm-pca (>=1.20.0)", "mypy-boto3-alexaforbusiness (>=1.20.0)", "mypy-boto3-amp (>=1.20.0)", "mypy-boto3-amplify (>=1.20.0)", "mypy-boto3-amplifybackend (>=1.20.0)", "mypy-boto3-apigateway (>=1.20.0)", "mypy-boto3-apigatewaymanagementapi (>=1.20.0)", "mypy-boto3-apigatewayv2 (>=1.20.0)", "mypy-boto3-appconfig (>=1.20.0)", "mypy-boto3-appflow (>=1.20.0)", "mypy-boto3-appintegrations (>=1.20.0)", "mypy-boto3-application-autoscaling (>=1.20.0)", "mypy-boto3-application-insights (>=1.20.0)", "mypy-boto3-applicationcostprofiler (>=1.20.0)", "mypy-boto3-appmesh (>=1.20.0)", "mypy-boto3-apprunner (>=1.20.0)", "mypy-boto3-appstream (>=1.20.0)", "mypy-boto3-appsync (>=1.20.0)", "mypy-boto3-athena (>=1.20.0)", "mypy-boto3-auditmanager (>=1.20.0)", "mypy-boto3-autoscaling (>=1.20.0)", "mypy-boto3-autoscaling-plans (>=1.20.0)", "mypy-boto3-backup (>=1.20.0)", "mypy-boto3-batch (>=1.20.0)", "mypy-boto3-braket (>=1.20.0)", "mypy-boto3-budgets (>=1.20.0)", "mypy-boto3-ce (>=1.20.0)", "mypy-boto3-chime (>=1.20.0)", "mypy-boto3-chime-sdk-identity (>=1.20.0)", "mypy-boto3-chime-sdk-meetings (>=1.20.0)", "mypy-boto3-chime-sdk-messaging (>=1.20.0)", "mypy-boto3-cloud9 (>=1.20.0)", "mypy-boto3-cloudcontrol (>=1.20.0)", "mypy-boto3-clouddirectory (>=1.20.0)", "mypy-boto3-cloudformation (>=1.20.0)", "mypy-boto3-cloudfront (>=1.20.0)", "mypy-boto3-cloudhsm (>=1.20.0)", "mypy-boto3-cloudhsmv2 (>=1.20.0)", "mypy-boto3-cloudsearch (>=1.20.0)", "mypy-boto3-cloudsearchdomain (>=1.20.0)", "mypy-boto3-cloudtrail (>=1.20.0)", "mypy-boto3-cloudwatch (>=1.20.0)", "mypy-boto3-codeartifact (>=1.20.0)", "mypy-boto3-codebuild (>=1.20.0)", "mypy-boto3-codecommit (>=1.20.0)", "mypy-boto3-codedeploy (>=1.20.0)", "mypy-boto3-codeguru-reviewer (>=1.20.0)", "mypy-boto3-codeguruprofiler (>=1.20.0)", "mypy-boto3-codepipeline (>=1.20.0)", "mypy-boto3-codestar (>=1.20.0)", "mypy-boto3-codestar-connections (>=1.20.0)", "mypy-boto3-codestar-notifications (>=1.20.0)", "mypy-boto3-cognito-identity (>=1.20.0)", "mypy-boto3-cognito-idp (>=1.20.0)", "mypy-boto3-cognito-sync (>=1.20.0)", "mypy-boto3-comprehend (>=1.20.0)", "mypy-boto3-comprehendmedical (>=1.20.0)", "mypy-boto3-compute-optimizer (>=1.20.0)", "mypy-boto3-config (>=1.20.0)", "mypy-boto3-connect (>=1.20.0)", "mypy-boto3-connect-contact-lens (>=1.20.0)", "mypy-boto3-connectparticipant (>=1.20.0)", "mypy-boto3-cur (>=1.20.0)", "mypy-boto3-customer-profiles (>=1.20.0)", "mypy-boto3-databrew (>=1.20.0)", "mypy-boto3-dataexchange (>=1.20.0)", "mypy-boto3-datapipeline (>=1.20.0)", "mypy-boto3-datasync (>=1.20.0)", "mypy-boto3-dax (>=1.20.0)", "mypy-boto3-detective (>=1.20.0)", "mypy-boto3-devicefarm (>=1.20.0)", "mypy-boto3-devops-guru (>=1.20.0)", "mypy-boto3-directconnect (>=1.20.0)", "mypy-boto3-discovery (>=1.20.0)", "mypy-boto3-dlm (>=1.20.0)", "mypy-boto3-dms (>=1.20.0)", "mypy-boto3-docdb (>=1.20.0)", "mypy-boto3-ds (>=1.20.0)", "mypy-boto3-dynamodb (>=1.20.0)", "mypy-boto3-dynamodbstreams (>=1.20.0)", "mypy-boto3-ebs (>=1.20.0)", "mypy-boto3-ec2 (>=1.20.0)", "mypy-boto3-ec2-instance-connect (>=1.20.0)", "mypy-boto3-ecr (>=1.20.0)", "mypy-boto3-ecr-public (>=1.20.0)", "mypy-boto3-ecs (>=1.20.0)", "mypy-boto3-efs (>=1.20.0)", "mypy-boto3-eks (>=1.20.0)", "mypy-boto3-elastic-inference (>=1.20.0)", "mypy-boto3-elasticache (>=1.20.0)", "mypy-boto3-elasticbeanstalk (>=1.20.0)", "mypy-boto3-elastictranscoder (>=1.20.0)", "mypy-boto3-elb (>=1.20.0)", "mypy-boto3-elbv2 (>=1.20.0)", "mypy-boto3-emr (>=1.20.0)", "mypy-boto3-emr-containers (>=1.20.0)", "mypy-boto3-es (>=1.20.0)", "mypy-boto3-events (>=1.20.0)", "mypy-boto3-finspace (>=1.20.0)", "mypy-boto3-finspace-data (>=1.20.0)", "mypy-boto3-firehose (>=1.20.0)", "mypy-boto3-fis (>=1.20.0)", "mypy-boto3-fms (>=1.20.0)", "mypy-boto3-forecast (>=1.20.0)", "mypy-boto3-forecastquery (>=1.20.0)", "mypy-boto3-frauddetector (>=1.20.0)", "mypy-boto3-fsx (>=1.20.0)", "mypy-boto3-gamelift (>=1.20.0)", "mypy-boto3-glacier (>=1.20.0)", "mypy-boto3-globalaccelerator (>=1.20.0)", "mypy-boto3-glue (>=1.20.0)", "mypy-boto3-grafana (>=1.20.0)", "mypy-boto3-greengrass (>=1.20.0)", "mypy-boto3-greengrassv2 (>=1.20.0)", "mypy-boto3-groundstation (>=1.20.0)", "mypy-boto3-guardduty (>=1.20.0)", "mypy-boto3-health (>=1.20.0)", "mypy-boto3-healthlake (>=1.20.0)", "mypy-boto3-honeycode (>=1.20.0)", "mypy-boto3-iam (>=1.20.0)", "mypy-boto3-identitystore (>=1.20.0)", "mypy-boto3-imagebuilder (>=1.20.0)", "mypy-boto3-importexport (>=1.20.0)", "mypy-boto3-inspector (>=1.20.0)", "mypy-boto3-iot (>=1.20.0)", "mypy-boto3-iot-data (>=1.20.0)", "mypy-boto3-iot-jobs-data (>=1.20.0)", "mypy-boto3-iot1click-devices (>=1.20.0)", "mypy-boto3-iot1click-projects (>=1.20.0)", "mypy-boto3-iotanalytics (>=1.20.0)", "mypy-boto3-iotdeviceadvisor (>=1.20.0)", "mypy-boto3-iotevents (>=1.20.0)", "mypy-boto3-iotevents-data (>=1.20.0)", "mypy-boto3-iotfleethub (>=1.20.0)", "mypy-boto3-iotsecuretunneling (>=1.20.0)", "mypy-boto3-iotsitewise (>=1.20.0)", "mypy-boto3-iotthingsgraph (>=1.20.0)", "mypy-boto3-iotwireless (>=1.20.0)", "mypy-boto3-ivs (>=1.20.0)", "mypy-boto3-kafka (>=1.20.0)", "mypy-boto3-kafkaconnect (>=1.20.0)", "mypy-boto3-kendra (>=1.20.0)", "mypy-boto3-kinesis (>=1.20.0)", "mypy-boto3-kinesis-video-archived-media (>=1.20.0)", "mypy-boto3-kinesis-video-media (>=1.20.0)", "mypy-boto3-kinesis-video-signaling (>=1.20.0)", "mypy-boto3-kinesisanalytics (>=1.20.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.20.0)", "mypy-boto3-kinesisvideo (>=1.20.0)", "mypy-boto3-kms (>=1.20.0)", "mypy-boto3-lakeformation (>=1.20.0)", "mypy-boto3-lambda (>=1.20.0)", "mypy-boto3-lex-models (>=1.20.0)", "mypy-boto3-lex-runtime (>=1.20.0)", "mypy-boto3-lexv2-models (>=1.20.0)", "mypy-boto3-lexv2-runtime (>=1.20.0)", "mypy-boto3-license-manager (>=1.20.0)", "mypy-boto3-lightsail (>=1.20.0)", "mypy-boto3-location (>=1.20.0)", "mypy-boto3-logs (>=1.20.0)", "mypy-boto3-lookoutequipment (>=1.20.0)", "mypy-boto3-lookoutmetrics (>=1.20.0)", "mypy-boto3-lookoutvision (>=1.20.0)", "mypy-boto3-machinelearning (>=1.20.0)", "mypy-boto3-macie (>=1.20.0)", "mypy-boto3-macie2 (>=1.20.0)", "mypy-boto3-managedblockchain (>=1.20.0)", "mypy-boto3-marketplace-catalog (>=1.20.0)", "mypy-boto3-marketplace-entitlement (>=1.20.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.20.0)", "mypy-boto3-mediaconnect (>=1.20.0)", "mypy-boto3-mediaconvert (>=1.20.0)", "mypy-boto3-medialive (>=1.20.0)", "mypy-boto3-mediapackage (>=1.20.0)", "mypy-boto3-mediapackage-vod (>=1.20.0)", "mypy-boto3-mediastore (>=1.20.0)", "mypy-boto3-mediastore-data (>=1.20.0)", "mypy-boto3-mediatailor (>=1.20.0)", "mypy-boto3-memorydb (>=1.20.0)", "mypy-boto3-meteringmarketplace (>=1.20.0)", "mypy-boto3-mgh (>=1.20.0)", "mypy-boto3-mgn (>=1.20.0)", "mypy-boto3-migrationhub-config (>=1.20.0)", "mypy-boto3-mobile (>=1.20.0)", "mypy-boto3-mq (>=1.20.0)", "mypy-boto3-mturk (>=1.20.0)", "mypy-boto3-mwaa (>=1.20.0)", "mypy-boto3-neptune (>=1.20.0)", "mypy-boto3-network-firewall (>=1.20.0)", "mypy-boto3-networkmanager (>=1.20.0)", "mypy-boto3-nimble (>=1.20.0)", "mypy-boto3-opensearch (>=1.20.0)", "mypy-boto3-opsworks (>=1.20.0)", "mypy-boto3-opsworkscm (>=1.20.0)", "mypy-boto3-organizations (>=1.20.0)", "mypy-boto3-outposts (>=1.20.0)", "mypy-boto3-panorama (>=1.20.0)", "mypy-boto3-personalize (>=1.20.0)", "mypy-boto3-personalize-events (>=1.20.0)", "mypy-boto3-personalize-runtime (>=1.20.0)", "mypy-boto3-pi (>=1.20.0)", "mypy-boto3-pinpoint (>=1.20.0)", "mypy-boto3-pinpoint-email (>=1.20.0)", "mypy-boto3-pinpoint-sms-voice (>=1.20.0)", "mypy-boto3-polly (>=1.20.0)", "mypy-boto3-pricing (>=1.20.0)", "mypy-boto3-proton (>=1.20.0)", "mypy-boto3-qldb (>=1.20.0)", "mypy-boto3-qldb-session (>=1.20.0)", "mypy-boto3-quicksight (>=1.20.0)", "mypy-boto3-ram (>=1.20.0)", "mypy-boto3-rds (>=1.20.0)", "mypy-boto3-rds-data (>=1.20.0)", "mypy-boto3-redshift (>=1.20.0)", "mypy-boto3-redshift-data (>=1.20.0)", "mypy-boto3-rekognition (>=1.20.0)", "mypy-boto3-resource-groups (>=1.20.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.20.0)", "mypy-boto3-robomaker (>=1.20.0)", "mypy-boto3-route53 (>=1.20.0)", "mypy-boto3-route53-recovery-cluster (>=1.20.0)", "mypy-boto3-route53-recovery-control-config (>=1.20.0)", "mypy-boto3-route53-recovery-readiness (>=1.20.0)", "mypy-boto3-route53domains (>=1.20.0)", "mypy-boto3-route53resolver (>=1.20.0)", "mypy-boto3-s3 (>=1.20.0)", "mypy-boto3-s3control (>=1.20.0)", "mypy-boto3-s3outposts (>=1.20.0)", "mypy-boto3-sagemaker (>=1.20.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.20.0)", "mypy-boto3-sagemaker-edge (>=1.20.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.20.0)", "mypy-boto3-sagemaker-runtime (>=1.20.0)", "mypy-boto3-savingsplans (>=1.20.0)", "mypy-boto3-schemas (>=1.20.0)", "mypy-boto3-sdb (>=1.20.0)", "mypy-boto3-secretsmanager (>=1.20.0)", "mypy-boto3-securityhub (>=1.20.0)", "mypy-boto3-serverlessrepo (>=1.20.0)", "mypy-boto3-service-quotas (>=1.20.0)", "mypy-boto3-servicecatalog (>=1.20.0)", "mypy-boto3-servicecatalog-appregistry (>=1.20.0)", "mypy-boto3-servicediscovery (>=1.20.0)", "mypy-boto3-ses (>=1.20.0)", "mypy-boto3-sesv2 (>=1.20.0)", "mypy-boto3-shield (>=1.20.0)", "mypy-boto3-signer (>=1.20.0)", "mypy-boto3-sms (>=1.20.0)", "mypy-boto3-sms-voice (>=1.20.0)", "mypy-boto3-snow-device-management (>=1.20.0)", "mypy-boto3-snowball (>=1.20.0)", "mypy-boto3-sns (>=1.20.0)", "mypy-boto3-sqs (>=1.20.0)", "mypy-boto3-ssm (>=1.20.0)", "mypy-boto3-ssm-contacts (>=1.20.0)", "mypy-boto3-ssm-incidents (>=1.20.0)", "mypy-boto3-sso (>=1.20.0)", "mypy-boto3-sso-admin (>=1.20.0)", "mypy-boto3-sso-oidc (>=1.20.0)", "mypy-boto3-stepfunctions (>=1.20.0)", "mypy-boto3-storagegateway (>=1.20.0)", "mypy-boto3-sts (>=1.20.0)", "mypy-boto3-support (>=1.20.0)", "mypy-boto3-swf (>=1.20.0)", "mypy-boto3-synthetics (>=1.20.0)", "mypy-boto3-textract (>=1.20.0)", "mypy-boto3-timestream-query (>=1.20.0)", "mypy-boto3-timestream-write (>=1.20.0)", "mypy-boto3-transcribe (>=1.20.0)", "mypy-boto3-transfer (>=1.20.0)", "mypy-boto3-translate (>=1.20.0)", "mypy-boto3-voice-id (>=1.20.0)", "mypy-boto3-waf (>=1.20.0)", "mypy-boto3-waf-regional (>=1.20.0)", "mypy-boto3-wafv2 (>=1.20.0)", "mypy-boto3-wellarchitected (>=1.20.0)", "mypy-boto3-wisdom (>=1.20.0)", "mypy-boto3-workdocs (>=1.20.0)", "mypy-boto3-worklink (>=1.20.0)", "mypy-boto3-workmail (>=1.20.0)", "mypy-boto3-workmailmessageflow (>=1.20.0)", "mypy-boto3-workspaces (>=1.20.0)", "mypy-boto3-xray (>=1.20.0)"] +amp = ["mypy-boto3-amp (>=1.20.0)"] +amplify = ["mypy-boto3-amplify (>=1.20.0)"] +amplifybackend = ["mypy-boto3-amplifybackend (>=1.20.0)"] +apigateway = ["mypy-boto3-apigateway (>=1.20.0)"] +apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (>=1.20.0)"] +apigatewayv2 = ["mypy-boto3-apigatewayv2 (>=1.20.0)"] +appconfig = ["mypy-boto3-appconfig (>=1.20.0)"] +appflow = ["mypy-boto3-appflow (>=1.20.0)"] +appintegrations = ["mypy-boto3-appintegrations (>=1.20.0)"] +application-autoscaling = ["mypy-boto3-application-autoscaling (>=1.20.0)"] +application-insights = ["mypy-boto3-application-insights (>=1.20.0)"] +applicationcostprofiler = ["mypy-boto3-applicationcostprofiler (>=1.20.0)"] +appmesh = ["mypy-boto3-appmesh (>=1.20.0)"] +apprunner = ["mypy-boto3-apprunner (>=1.20.0)"] +appstream = ["mypy-boto3-appstream (>=1.20.0)"] +appsync = ["mypy-boto3-appsync (>=1.20.0)"] +athena = ["mypy-boto3-athena (>=1.20.0)"] +auditmanager = ["mypy-boto3-auditmanager (>=1.20.0)"] +autoscaling = ["mypy-boto3-autoscaling (>=1.20.0)"] +autoscaling-plans = ["mypy-boto3-autoscaling-plans (>=1.20.0)"] +backup = ["mypy-boto3-backup (>=1.20.0)"] +batch = ["mypy-boto3-batch (>=1.20.0)"] +braket = ["mypy-boto3-braket (>=1.20.0)"] +budgets = ["mypy-boto3-budgets (>=1.20.0)"] +ce = ["mypy-boto3-ce (>=1.20.0)"] +chime = ["mypy-boto3-chime (>=1.20.0)"] +chime-sdk-identity = ["mypy-boto3-chime-sdk-identity (>=1.20.0)"] +chime-sdk-meetings = ["mypy-boto3-chime-sdk-meetings (>=1.20.0)"] +chime-sdk-messaging = ["mypy-boto3-chime-sdk-messaging (>=1.20.0)"] +cloud9 = ["mypy-boto3-cloud9 (>=1.20.0)"] +cloudcontrol = ["mypy-boto3-cloudcontrol (>=1.20.0)"] +clouddirectory = ["mypy-boto3-clouddirectory (>=1.20.0)"] +cloudformation = ["mypy-boto3-cloudformation (>=1.20.0)"] +cloudfront = ["mypy-boto3-cloudfront (>=1.20.0)"] +cloudhsm = ["mypy-boto3-cloudhsm (>=1.20.0)"] +cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (>=1.20.0)"] +cloudsearch = ["mypy-boto3-cloudsearch (>=1.20.0)"] +cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.20.0)"] +cloudtrail = ["mypy-boto3-cloudtrail (>=1.20.0)"] +cloudwatch = ["mypy-boto3-cloudwatch (>=1.20.0)"] +codeartifact = ["mypy-boto3-codeartifact (>=1.20.0)"] +codebuild = ["mypy-boto3-codebuild (>=1.20.0)"] +codecommit = ["mypy-boto3-codecommit (>=1.20.0)"] +codedeploy = ["mypy-boto3-codedeploy (>=1.20.0)"] +codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (>=1.20.0)"] +codeguruprofiler = ["mypy-boto3-codeguruprofiler (>=1.20.0)"] +codepipeline = ["mypy-boto3-codepipeline (>=1.20.0)"] +codestar = ["mypy-boto3-codestar (>=1.20.0)"] +codestar-connections = ["mypy-boto3-codestar-connections (>=1.20.0)"] +codestar-notifications = ["mypy-boto3-codestar-notifications (>=1.20.0)"] +cognito-identity = ["mypy-boto3-cognito-identity (>=1.20.0)"] +cognito-idp = ["mypy-boto3-cognito-idp (>=1.20.0)"] +cognito-sync = ["mypy-boto3-cognito-sync (>=1.20.0)"] +comprehend = ["mypy-boto3-comprehend (>=1.20.0)"] +comprehendmedical = ["mypy-boto3-comprehendmedical (>=1.20.0)"] +compute-optimizer = ["mypy-boto3-compute-optimizer (>=1.20.0)"] +config = ["mypy-boto3-config (>=1.20.0)"] +connect = ["mypy-boto3-connect (>=1.20.0)"] +connect-contact-lens = ["mypy-boto3-connect-contact-lens (>=1.20.0)"] +connectparticipant = ["mypy-boto3-connectparticipant (>=1.20.0)"] +cur = ["mypy-boto3-cur (>=1.20.0)"] +customer-profiles = ["mypy-boto3-customer-profiles (>=1.20.0)"] +databrew = ["mypy-boto3-databrew (>=1.20.0)"] +dataexchange = ["mypy-boto3-dataexchange (>=1.20.0)"] +datapipeline = ["mypy-boto3-datapipeline (>=1.20.0)"] +datasync = ["mypy-boto3-datasync (>=1.20.0)"] +dax = ["mypy-boto3-dax (>=1.20.0)"] +detective = ["mypy-boto3-detective (>=1.20.0)"] +devicefarm = ["mypy-boto3-devicefarm (>=1.20.0)"] +devops-guru = ["mypy-boto3-devops-guru (>=1.20.0)"] +directconnect = ["mypy-boto3-directconnect (>=1.20.0)"] +discovery = ["mypy-boto3-discovery (>=1.20.0)"] +dlm = ["mypy-boto3-dlm (>=1.20.0)"] +dms = ["mypy-boto3-dms (>=1.20.0)"] +docdb = ["mypy-boto3-docdb (>=1.20.0)"] +ds = ["mypy-boto3-ds (>=1.20.0)"] +dynamodb = ["mypy-boto3-dynamodb (>=1.20.0)"] +dynamodbstreams = ["mypy-boto3-dynamodbstreams (>=1.20.0)"] +ebs = ["mypy-boto3-ebs (>=1.20.0)"] +ec2 = ["mypy-boto3-ec2 (>=1.20.0)"] +ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (>=1.20.0)"] +ecr = ["mypy-boto3-ecr (>=1.20.0)"] +ecr-public = ["mypy-boto3-ecr-public (>=1.20.0)"] +ecs = ["mypy-boto3-ecs (>=1.20.0)"] +efs = ["mypy-boto3-efs (>=1.20.0)"] +eks = ["mypy-boto3-eks (>=1.20.0)"] +elastic-inference = ["mypy-boto3-elastic-inference (>=1.20.0)"] +elasticache = ["mypy-boto3-elasticache (>=1.20.0)"] +elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (>=1.20.0)"] +elastictranscoder = ["mypy-boto3-elastictranscoder (>=1.20.0)"] +elb = ["mypy-boto3-elb (>=1.20.0)"] +elbv2 = ["mypy-boto3-elbv2 (>=1.20.0)"] +emr = ["mypy-boto3-emr (>=1.20.0)"] +emr-containers = ["mypy-boto3-emr-containers (>=1.20.0)"] +es = ["mypy-boto3-es (>=1.20.0)"] +essential = ["mypy-boto3-cloudformation (>=1.20.0)", "mypy-boto3-dynamodb (>=1.20.0)", "mypy-boto3-ec2 (>=1.20.0)", "mypy-boto3-lambda (>=1.20.0)", "mypy-boto3-rds (>=1.20.0)", "mypy-boto3-s3 (>=1.20.0)", "mypy-boto3-sqs (>=1.20.0)"] +events = ["mypy-boto3-events (>=1.20.0)"] +finspace = ["mypy-boto3-finspace (>=1.20.0)"] +finspace-data = ["mypy-boto3-finspace-data (>=1.20.0)"] +firehose = ["mypy-boto3-firehose (>=1.20.0)"] +fis = ["mypy-boto3-fis (>=1.20.0)"] +fms = ["mypy-boto3-fms (>=1.20.0)"] +forecast = ["mypy-boto3-forecast (>=1.20.0)"] +forecastquery = ["mypy-boto3-forecastquery (>=1.20.0)"] +frauddetector = ["mypy-boto3-frauddetector (>=1.20.0)"] +fsx = ["mypy-boto3-fsx (>=1.20.0)"] +gamelift = ["mypy-boto3-gamelift (>=1.20.0)"] +glacier = ["mypy-boto3-glacier (>=1.20.0)"] +globalaccelerator = ["mypy-boto3-globalaccelerator (>=1.20.0)"] +glue = ["mypy-boto3-glue (>=1.20.0)"] +grafana = ["mypy-boto3-grafana (>=1.20.0)"] +greengrass = ["mypy-boto3-greengrass (>=1.20.0)"] +greengrassv2 = ["mypy-boto3-greengrassv2 (>=1.20.0)"] +groundstation = ["mypy-boto3-groundstation (>=1.20.0)"] +guardduty = ["mypy-boto3-guardduty (>=1.20.0)"] +health = ["mypy-boto3-health (>=1.20.0)"] +healthlake = ["mypy-boto3-healthlake (>=1.20.0)"] +honeycode = ["mypy-boto3-honeycode (>=1.20.0)"] +iam = ["mypy-boto3-iam (>=1.20.0)"] +identitystore = ["mypy-boto3-identitystore (>=1.20.0)"] +imagebuilder = ["mypy-boto3-imagebuilder (>=1.20.0)"] +importexport = ["mypy-boto3-importexport (>=1.20.0)"] +inspector = ["mypy-boto3-inspector (>=1.20.0)"] +iot = ["mypy-boto3-iot (>=1.20.0)"] +iot-data = ["mypy-boto3-iot-data (>=1.20.0)"] +iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.20.0)"] +iot1click-devices = ["mypy-boto3-iot1click-devices (>=1.20.0)"] +iot1click-projects = ["mypy-boto3-iot1click-projects (>=1.20.0)"] +iotanalytics = ["mypy-boto3-iotanalytics (>=1.20.0)"] +iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.20.0)"] +iotevents = ["mypy-boto3-iotevents (>=1.20.0)"] +iotevents-data = ["mypy-boto3-iotevents-data (>=1.20.0)"] +iotfleethub = ["mypy-boto3-iotfleethub (>=1.20.0)"] +iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.20.0)"] +iotsitewise = ["mypy-boto3-iotsitewise (>=1.20.0)"] +iotthingsgraph = ["mypy-boto3-iotthingsgraph (>=1.20.0)"] +iotwireless = ["mypy-boto3-iotwireless (>=1.20.0)"] +ivs = ["mypy-boto3-ivs (>=1.20.0)"] +kafka = ["mypy-boto3-kafka (>=1.20.0)"] +kafkaconnect = ["mypy-boto3-kafkaconnect (>=1.20.0)"] +kendra = ["mypy-boto3-kendra (>=1.20.0)"] +kinesis = ["mypy-boto3-kinesis (>=1.20.0)"] +kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (>=1.20.0)"] +kinesis-video-media = ["mypy-boto3-kinesis-video-media (>=1.20.0)"] +kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (>=1.20.0)"] +kinesisanalytics = ["mypy-boto3-kinesisanalytics (>=1.20.0)"] +kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (>=1.20.0)"] +kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.20.0)"] +kms = ["mypy-boto3-kms (>=1.20.0)"] +lakeformation = ["mypy-boto3-lakeformation (>=1.20.0)"] +lambda = ["mypy-boto3-lambda (>=1.20.0)"] +lex-models = ["mypy-boto3-lex-models (>=1.20.0)"] +lex-runtime = ["mypy-boto3-lex-runtime (>=1.20.0)"] +lexv2-models = ["mypy-boto3-lexv2-models (>=1.20.0)"] +lexv2-runtime = ["mypy-boto3-lexv2-runtime (>=1.20.0)"] +license-manager = ["mypy-boto3-license-manager (>=1.20.0)"] +lightsail = ["mypy-boto3-lightsail (>=1.20.0)"] +location = ["mypy-boto3-location (>=1.20.0)"] +logs = ["mypy-boto3-logs (>=1.20.0)"] +lookoutequipment = ["mypy-boto3-lookoutequipment (>=1.20.0)"] +lookoutmetrics = ["mypy-boto3-lookoutmetrics (>=1.20.0)"] +lookoutvision = ["mypy-boto3-lookoutvision (>=1.20.0)"] +machinelearning = ["mypy-boto3-machinelearning (>=1.20.0)"] +macie = ["mypy-boto3-macie (>=1.20.0)"] +macie2 = ["mypy-boto3-macie2 (>=1.20.0)"] +managedblockchain = ["mypy-boto3-managedblockchain (>=1.20.0)"] +marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.20.0)"] +marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.20.0)"] +marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.20.0)"] +mediaconnect = ["mypy-boto3-mediaconnect (>=1.20.0)"] +mediaconvert = ["mypy-boto3-mediaconvert (>=1.20.0)"] +medialive = ["mypy-boto3-medialive (>=1.20.0)"] +mediapackage = ["mypy-boto3-mediapackage (>=1.20.0)"] +mediapackage-vod = ["mypy-boto3-mediapackage-vod (>=1.20.0)"] +mediastore = ["mypy-boto3-mediastore (>=1.20.0)"] +mediastore-data = ["mypy-boto3-mediastore-data (>=1.20.0)"] +mediatailor = ["mypy-boto3-mediatailor (>=1.20.0)"] +memorydb = ["mypy-boto3-memorydb (>=1.20.0)"] +meteringmarketplace = ["mypy-boto3-meteringmarketplace (>=1.20.0)"] +mgh = ["mypy-boto3-mgh (>=1.20.0)"] +mgn = ["mypy-boto3-mgn (>=1.20.0)"] +migrationhub-config = ["mypy-boto3-migrationhub-config (>=1.20.0)"] +mobile = ["mypy-boto3-mobile (>=1.20.0)"] +mq = ["mypy-boto3-mq (>=1.20.0)"] +mturk = ["mypy-boto3-mturk (>=1.20.0)"] +mwaa = ["mypy-boto3-mwaa (>=1.20.0)"] +neptune = ["mypy-boto3-neptune (>=1.20.0)"] +network-firewall = ["mypy-boto3-network-firewall (>=1.20.0)"] +networkmanager = ["mypy-boto3-networkmanager (>=1.20.0)"] +nimble = ["mypy-boto3-nimble (>=1.20.0)"] +opensearch = ["mypy-boto3-opensearch (>=1.20.0)"] +opsworks = ["mypy-boto3-opsworks (>=1.20.0)"] +opsworkscm = ["mypy-boto3-opsworkscm (>=1.20.0)"] +organizations = ["mypy-boto3-organizations (>=1.20.0)"] +outposts = ["mypy-boto3-outposts (>=1.20.0)"] +panorama = ["mypy-boto3-panorama (>=1.20.0)"] +personalize = ["mypy-boto3-personalize (>=1.20.0)"] +personalize-events = ["mypy-boto3-personalize-events (>=1.20.0)"] +personalize-runtime = ["mypy-boto3-personalize-runtime (>=1.20.0)"] +pi = ["mypy-boto3-pi (>=1.20.0)"] +pinpoint = ["mypy-boto3-pinpoint (>=1.20.0)"] +pinpoint-email = ["mypy-boto3-pinpoint-email (>=1.20.0)"] +pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (>=1.20.0)"] +polly = ["mypy-boto3-polly (>=1.20.0)"] +pricing = ["mypy-boto3-pricing (>=1.20.0)"] +proton = ["mypy-boto3-proton (>=1.20.0)"] +qldb = ["mypy-boto3-qldb (>=1.20.0)"] +qldb-session = ["mypy-boto3-qldb-session (>=1.20.0)"] +quicksight = ["mypy-boto3-quicksight (>=1.20.0)"] +ram = ["mypy-boto3-ram (>=1.20.0)"] +rds = ["mypy-boto3-rds (>=1.20.0)"] +rds-data = ["mypy-boto3-rds-data (>=1.20.0)"] +redshift = ["mypy-boto3-redshift (>=1.20.0)"] +redshift-data = ["mypy-boto3-redshift-data (>=1.20.0)"] +rekognition = ["mypy-boto3-rekognition (>=1.20.0)"] +resource-groups = ["mypy-boto3-resource-groups (>=1.20.0)"] +resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (>=1.20.0)"] +robomaker = ["mypy-boto3-robomaker (>=1.20.0)"] +route53 = ["mypy-boto3-route53 (>=1.20.0)"] +route53-recovery-cluster = ["mypy-boto3-route53-recovery-cluster (>=1.20.0)"] +route53-recovery-control-config = ["mypy-boto3-route53-recovery-control-config (>=1.20.0)"] +route53-recovery-readiness = ["mypy-boto3-route53-recovery-readiness (>=1.20.0)"] +route53domains = ["mypy-boto3-route53domains (>=1.20.0)"] +route53resolver = ["mypy-boto3-route53resolver (>=1.20.0)"] +s3 = ["mypy-boto3-s3 (>=1.20.0)"] +s3control = ["mypy-boto3-s3control (>=1.20.0)"] +s3outposts = ["mypy-boto3-s3outposts (>=1.20.0)"] +sagemaker = ["mypy-boto3-sagemaker (>=1.20.0)"] +sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (>=1.20.0)"] +sagemaker-edge = ["mypy-boto3-sagemaker-edge (>=1.20.0)"] +sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (>=1.20.0)"] +sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (>=1.20.0)"] +savingsplans = ["mypy-boto3-savingsplans (>=1.20.0)"] +schemas = ["mypy-boto3-schemas (>=1.20.0)"] +sdb = ["mypy-boto3-sdb (>=1.20.0)"] +secretsmanager = ["mypy-boto3-secretsmanager (>=1.20.0)"] +securityhub = ["mypy-boto3-securityhub (>=1.20.0)"] +serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.20.0)"] +service-quotas = ["mypy-boto3-service-quotas (>=1.20.0)"] +servicecatalog = ["mypy-boto3-servicecatalog (>=1.20.0)"] +servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (>=1.20.0)"] +servicediscovery = ["mypy-boto3-servicediscovery (>=1.20.0)"] +ses = ["mypy-boto3-ses (>=1.20.0)"] +sesv2 = ["mypy-boto3-sesv2 (>=1.20.0)"] +shield = ["mypy-boto3-shield (>=1.20.0)"] +signer = ["mypy-boto3-signer (>=1.20.0)"] +sms = ["mypy-boto3-sms (>=1.20.0)"] +sms-voice = ["mypy-boto3-sms-voice (>=1.20.0)"] +snow-device-management = ["mypy-boto3-snow-device-management (>=1.20.0)"] +snowball = ["mypy-boto3-snowball (>=1.20.0)"] +sns = ["mypy-boto3-sns (>=1.20.0)"] +sqs = ["mypy-boto3-sqs (>=1.20.0)"] +ssm = ["mypy-boto3-ssm (>=1.20.0)"] +ssm-contacts = ["mypy-boto3-ssm-contacts (>=1.20.0)"] +ssm-incidents = ["mypy-boto3-ssm-incidents (>=1.20.0)"] +sso = ["mypy-boto3-sso (>=1.20.0)"] +sso-admin = ["mypy-boto3-sso-admin (>=1.20.0)"] +sso-oidc = ["mypy-boto3-sso-oidc (>=1.20.0)"] +stepfunctions = ["mypy-boto3-stepfunctions (>=1.20.0)"] +storagegateway = ["mypy-boto3-storagegateway (>=1.20.0)"] +sts = ["mypy-boto3-sts (>=1.20.0)"] +support = ["mypy-boto3-support (>=1.20.0)"] +swf = ["mypy-boto3-swf (>=1.20.0)"] +synthetics = ["mypy-boto3-synthetics (>=1.20.0)"] +textract = ["mypy-boto3-textract (>=1.20.0)"] +timestream-query = ["mypy-boto3-timestream-query (>=1.20.0)"] +timestream-write = ["mypy-boto3-timestream-write (>=1.20.0)"] +transcribe = ["mypy-boto3-transcribe (>=1.20.0)"] +transfer = ["mypy-boto3-transfer (>=1.20.0)"] +translate = ["mypy-boto3-translate (>=1.20.0)"] +voice-id = ["mypy-boto3-voice-id (>=1.20.0)"] +waf = ["mypy-boto3-waf (>=1.20.0)"] +waf-regional = ["mypy-boto3-waf-regional (>=1.20.0)"] +wafv2 = ["mypy-boto3-wafv2 (>=1.20.0)"] +wellarchitected = ["mypy-boto3-wellarchitected (>=1.20.0)"] +wisdom = ["mypy-boto3-wisdom (>=1.20.0)"] +workdocs = ["mypy-boto3-workdocs (>=1.20.0)"] +worklink = ["mypy-boto3-worklink (>=1.20.0)"] +workmail = ["mypy-boto3-workmail (>=1.20.0)"] +workmailmessageflow = ["mypy-boto3-workmailmessageflow (>=1.20.0)"] +workspaces = ["mypy-boto3-workspaces (>=1.20.0)"] +xray = ["mypy-boto3-xray (>=1.20.0)"] + +[[package]] +name = "botocore" +version = "1.23.2" +description = "Low-level, data-driven core of boto 3." +category = "main" +optional = false +python-versions = ">= 3.6" + +[package.dependencies] +jmespath = ">=0.7.1,<1.0.0" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = ">=1.25.4,<1.27" + +[package.extras] +crt = ["awscrt (==0.12.5)"] + +[[package]] +name = "botocore-stubs" +version = "1.23.2" +description = "Type annotations for botocore 1.23.2, generated by mypy-boto3-builder 6.2.0" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "certifi" +version = "2021.10.8" +description = "Python package for providing Mozilla's CA Bundle." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "charset-normalizer" +version = "2.0.7" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "dev" +optional = false +python-versions = ">=3.5.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + +[[package]] +name = "cleo" +version = "0.8.1" +description = "Cleo allows you to create beautiful and testable command-line interfaces." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +clikit = ">=0.6.0,<0.7.0" + +[[package]] +name = "click" +version = "8.0.3" +description = "Composable command line interface toolkit" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "clikit" +version = "0.6.2" +description = "CliKit is a group of utilities to build beautiful and testable command line interfaces." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +crashtest = {version = ">=0.3.0,<0.4.0", markers = "python_version >= \"3.6\" and python_version < \"4.0\""} +pastel = ">=0.2.0,<0.3.0" +pylev = ">=1.3,<2.0" + +[[package]] +name = "cognitive-complexity" +version = "1.2.0" +description = "Library to calculate Python functions cognitive complexity via code" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "colorama" +version = "0.4.4" +description = "Cross-platform colored terminal text." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "coverage" +version = "6.1.1" +description = "Code coverage measurement for Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "crashtest" +version = "0.3.1" +description = "Manage Python errors with ease" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[[package]] +name = "crhelper" +version = "2.0.10" +description = "crhelper simplifies authoring CloudFormation Custom Resources" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "darglint" +version = "1.8.1" +description = "A utility for ensuring Google-style docstrings stay up to date with the source code." +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[[package]] +name = "dlint" +version = "0.11.0" +description = "Dlint is a tool for encouraging best coding practices and helping ensure Python code is secure." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = ">=3.6.0,<4.0.0" + +[[package]] +name = "dparse" +version = "0.5.1" +description = "A parser for Python dependency files" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +packaging = "*" +pyyaml = "*" +toml = "*" + +[package.extras] +pipenv = ["pipenv"] + +[[package]] +name = "eradicate" +version = "2.0.0" +description = "Removes commented-out code." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "execnet" +version = "1.9.0" +description = "execnet: rapid multi-Python deployment" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +testing = ["pre-commit"] + +[[package]] +name = "flake8" +version = "3.9.2" +description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[package.dependencies] +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.7.0,<2.8.0" +pyflakes = ">=2.3.0,<2.4.0" + +[[package]] +name = "flake8-2020" +version = "1.6.0" +description = "flake8 plugin which checks for misuse of `sys.version` or `sys.version_info`" +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[package.dependencies] +flake8 = ">=3.7" + +[[package]] +name = "flake8-annotations-complexity" +version = "0.0.6" +description = "A flake8 extension that checks for type annotations complexity" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "flake8-bandit" +version = "2.1.2" +description = "Automated security testing with bandit and flake8." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +bandit = "*" +flake8 = "*" +flake8-polyfill = "*" +pycodestyle = "*" + +[[package]] +name = "flake8-breakpoint" +version = "1.1.0" +description = "Flake8 plugin that check forgotten breakpoints" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +flake8-plugin-utils = ">=1.0,<2.0" + +[[package]] +name = "flake8-broken-line" +version = "0.3.0" +description = "Flake8 plugin to forbid backslashes for line breaks" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +flake8 = ">=3.5,<4.0" + +[[package]] +name = "flake8-bugbear" +version = "21.9.2" +description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +attrs = ">=19.2.0" +flake8 = ">=3.0.0" + +[package.extras] +dev = ["coverage", "black", "hypothesis", "hypothesmith"] + +[[package]] +name = "flake8-builtins" +version = "1.5.3" +description = "Check for python builtins being used as variables or parameters." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" + +[package.extras] +test = ["coverage", "coveralls", "mock", "pytest", "pytest-cov"] + +[[package]] +name = "flake8-cognitive-complexity" +version = "0.1.0" +description = "An extension for flake8 that validates cognitive functions complexity" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +cognitive_complexity = "*" + +[[package]] +name = "flake8-comprehensions" +version = "3.7.0" +description = "A flake8 plugin to help you write better list/set/dict comprehensions." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +flake8 = ">=3.0,<3.2.0 || >3.2.0,<5" + +[[package]] +name = "flake8-copyright" +version = "0.2.2" +description = "Adds copyright checks to flake8" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "flake8-docstrings" +version = "1.6.0" +description = "Extension for flake8 which uses pydocstyle to check docstrings" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = ">=3" +pydocstyle = ">=2.1" + +[[package]] +name = "flake8-eradicate" +version = "1.2.0" +description = "Flake8 plugin to find commented out code" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +attrs = "*" +eradicate = ">=2.0,<3.0" +flake8 = ">=3.5,<5" + +[[package]] +name = "flake8-executable" +version = "2.1.1" +description = "A Flake8 plugin for checking executable permissions and shebangs." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +flake8 = ">=3.0.0" + +[[package]] +name = "flake8-expression-complexity" +version = "0.0.9" +description = "A flake8 extension that checks expressions complexity" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +astpretty = "*" +flake8 = "*" + +[[package]] +name = "flake8-fixme" +version = "1.1.1" +description = "Check for FIXME, TODO and other temporary developer notes. Plugin for flake8." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "flake8-functions" +version = "0.0.6" +description = "A flake8 extension that checks functions" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +mr-proper = "*" +pytest = "*" + +[[package]] +name = "flake8-helper" +version = "0.2.0" +description = "A helper library for Flake8 plugins." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +flake8 = ">=3.8.4" + +[[package]] +name = "flake8-markdown" +version = "0.2.0" +description = "Lints Python code blocks in Markdown files using flake8" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +flake8 = ">=3.7,<4.0" + +[[package]] +name = "flake8-mock" +version = "0.3" +description = "Provides checking for non-existent mock methods" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "flake8-mutable" +version = "1.2.0" +description = "mutable defaults flake8 extension" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-no-implicit-concat" +version = "0.2.1" +description = "Flake8 plugin that forbids implicit string literal concatenations" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" +more-itertools = {version = "*", markers = "python_version < \"3.10\""} + +[package.extras] +dev = ["black", "isort", "flake8", "hacking", "flake8-black", "flake8-isort", "pep8-naming", "flake8-broken-line", "flake8-builtins", "flake8-docstrings", "flake8-rst-docstrings", "darglint", "mypy", "coverage", "codecov"] + +[[package]] +name = "flake8-plugin-utils" +version = "1.3.2" +description = "The package provides base classes and utils for flake8 plugin writing" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[[package]] +name = "flake8-polyfill" +version = "1.0.2" +description = "Polyfill package for Flake8 plugins" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-print" +version = "4.0.0" +description = "print statement checker plugin for flake8" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +flake8 = ">=3.0" +pycodestyle = "*" +six = "*" + +[[package]] +name = "flake8-printf-formatting" +version = "1.1.2" +description = "flake8 plugin which forbids printf-style string formatting" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-pytest-style" +version = "1.5.1" +description = "A flake8 plugin checking common style issues or inconsistencies with pytest-based tests." +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +flake8-plugin-utils = ">=1.3.2,<2.0.0" + +[[package]] +name = "flake8-raise" +version = "0.0.5" +description = "A flake8 plugin that finds that finds improvements for raise statements." +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +flake8 = ">=3.2.0" + +[[package]] +name = "flake8-return" +version = "1.1.3" +description = "Flake8 plugin that checks return values" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +flake8-plugin-utils = ">=1.0,<2.0" + +[[package]] +name = "flake8-scrapy" +version = "0.0.1" +description = "" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-simplify" +version = "0.14.2" +description = "flake8 plugin which checks for code that can be simplified" +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[package.dependencies] +astor = ">=0.1" +flake8 = ">=3.7" + +[[package]] +name = "flake8-sql" +version = "0.4.1" +description = "Flake8 plugin that checks SQL code against opinionated style rules" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" +sqlparse = "*" + +[[package]] +name = "flake8-strftime" +version = "0.3.2" +description = "A flake8 plugin which checks for use of platform specific strftime codes." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +flake8 = ">=3.7" +flake8-helper = ">=0.1.1" + +[[package]] +name = "flake8-todos" +version = "0.1.5" +description = "None" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +flake8 = "*" +pycodestyle = "*" + +[package.extras] +dev = ["isort", "pytest"] + +[[package]] +name = "flake8-tuple" +version = "0.4.1" +description = "Check code for 1 element tuple." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" +six = "*" + +[[package]] +name = "flake8-typing-imports" +version = "1.11.0" +description = "flake8 plugin which checks that typing imports are properly guarded" +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[package.dependencies] +flake8 = ">=3.7" + +[[package]] +name = "flake8-unused-arguments" +version = "0.0.6" +description = "flake8 extension to warn on unused function arguments" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = ">3.0.0" + +[[package]] +name = "flake8-use-fstring" +version = "1.3" +description = "Flake8 plugin for string formatting style." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +flake8 = ">=3" + +[package.extras] +ci = ["coverage (>=4.0.0,<5.0.0)", "pytest (>=4)", "pytest-cov (>=2)", "flake8-builtins", "flake8-commas", "flake8-fixme", "flake8-print", "flake8-quotes", "flake8-todo", "coveralls"] +dev = ["coverage (>=4.0.0,<5.0.0)", "pytest (>=4)", "pytest-cov (>=2)", "flake8-builtins", "flake8-commas", "flake8-fixme", "flake8-print", "flake8-quotes", "flake8-todo"] +test = ["coverage (>=4.0.0,<5.0.0)", "pytest (>=4)", "pytest-cov (>=2)", "flake8-builtins", "flake8-commas", "flake8-fixme", "flake8-print", "flake8-quotes", "flake8-todo"] + +[[package]] +name = "flake8-use-pathlib" +version = "0.2.0" +description = "A plugin for flake8 finding use of functions that can be replaced by pathlib module." +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +flake8 = ">=3.8.3,<4.0.0" + +[[package]] +name = "flake8-variables-names" +version = "0.0.4" +description = "A flake8 extension that helps to make more readable variables names" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "gitdb" +version = "4.0.9" +description = "Git Object Database" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.24" +description = "GitPython is a python library used to interact with Git repositories" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +gitdb = ">=4.0.1,<5" +typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.10\""} + +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "importlib-metadata" +version = "4.8.2" +description = "Read metadata from Python packages" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +perf = ["ipython"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] + +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "isort" +version = "5.10.1" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.6.1,<4.0" + +[package.extras] +pipfile_deprecated_finder = ["pipreqs", "requirementslib"] +requirements_deprecated_finder = ["pipreqs", "pip-api"] +colors = ["colorama (>=0.4.3,<0.5.0)"] +plugins = ["setuptools"] + +[[package]] +name = "jmespath" +version = "0.10.0" +description = "JSON Matching Expressions" +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "mccabe" +version = "0.6.1" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "more-itertools" +version = "8.11.0" +description = "More routines for operating on iterables, beyond itertools" +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "mr-proper" +version = "0.0.7" +description = "Static Python code analyzer, that tries to check if functions in code are pure or not and why." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +click = ">=7.1.2" +stdlib-list = ">=0.5.0" + +[[package]] +name = "mypy" +version = "0.910" +description = "Optional static typing for Python" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +mypy-extensions = ">=0.4.3,<0.5.0" +toml = "*" +typing-extensions = ">=3.7.4" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +python2 = ["typed-ast (>=1.4.0,<1.5.0)"] + +[[package]] +name = "mypy-boto3-accessanalyzer" +version = "1.20.1" +description = "Type annotations for boto3.AccessAnalyzer 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-account" +version = "1.20.1" +description = "Type annotations for boto3.Account 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-acm" +version = "1.20.1" +description = "Type annotations for boto3.ACM 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-acm-pca" +version = "1.20.1" +description = "Type annotations for boto3.ACMPCA 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-alexaforbusiness" +version = "1.20.1" +description = "Type annotations for boto3.AlexaForBusiness 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-amp" +version = "1.20.1" +description = "Type annotations for boto3.PrometheusService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-amplify" +version = "1.20.1" +description = "Type annotations for boto3.Amplify 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-amplifybackend" +version = "1.20.1" +description = "Type annotations for boto3.AmplifyBackend 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-apigateway" +version = "1.20.1" +description = "Type annotations for boto3.APIGateway 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-apigatewaymanagementapi" +version = "1.20.1" +description = "Type annotations for boto3.ApiGatewayManagementApi 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-apigatewayv2" +version = "1.20.1" +description = "Type annotations for boto3.ApiGatewayV2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-appconfig" +version = "1.20.1" +description = "Type annotations for boto3.AppConfig 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-appflow" +version = "1.20.1" +description = "Type annotations for boto3.Appflow 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-appintegrations" +version = "1.20.1" +description = "Type annotations for boto3.AppIntegrationsService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-application-autoscaling" +version = "1.20.1" +description = "Type annotations for boto3.ApplicationAutoScaling 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-application-insights" +version = "1.20.1" +description = "Type annotations for boto3.ApplicationInsights 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-applicationcostprofiler" +version = "1.20.1" +description = "Type annotations for boto3.ApplicationCostProfiler 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-appmesh" +version = "1.20.1" +description = "Type annotations for boto3.AppMesh 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-apprunner" +version = "1.20.1" +description = "Type annotations for boto3.AppRunner 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-appstream" +version = "1.20.1" +description = "Type annotations for boto3.AppStream 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-appsync" +version = "1.20.1" +description = "Type annotations for boto3.AppSync 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-athena" +version = "1.20.1" +description = "Type annotations for boto3.Athena 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-auditmanager" +version = "1.20.1" +description = "Type annotations for boto3.AuditManager 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-autoscaling" +version = "1.20.1" +description = "Type annotations for boto3.AutoScaling 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-autoscaling-plans" +version = "1.20.1" +description = "Type annotations for boto3.AutoScalingPlans 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-backup" +version = "1.20.1" +description = "Type annotations for boto3.Backup 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-batch" +version = "1.20.2" +description = "Type annotations for boto3.Batch 1.20.2 service, generated by mypy-boto3-builder 6.2.0" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-braket" +version = "1.20.1" +description = "Type annotations for boto3.Braket 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-budgets" +version = "1.20.1" +description = "Type annotations for boto3.Budgets 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ce" +version = "1.20.1" +description = "Type annotations for boto3.CostExplorer 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-chime" +version = "1.20.1" +description = "Type annotations for boto3.Chime 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-chime-sdk-identity" +version = "1.20.1" +description = "Type annotations for boto3.ChimeSDKIdentity 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-chime-sdk-meetings" +version = "1.20.1" +description = "Type annotations for boto3.ChimeSDKMeetings 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-chime-sdk-messaging" +version = "1.20.1" +description = "Type annotations for boto3.ChimeSDKMessaging 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloud9" +version = "1.20.1" +description = "Type annotations for boto3.Cloud9 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloudcontrol" +version = "1.20.1" +description = "Type annotations for boto3.CloudControlApi 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-clouddirectory" +version = "1.20.1" +description = "Type annotations for boto3.CloudDirectory 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloudformation" +version = "1.20.1" +description = "Type annotations for boto3.CloudFormation 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloudfront" +version = "1.20.1" +description = "Type annotations for boto3.CloudFront 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloudhsm" +version = "1.20.1" +description = "Type annotations for boto3.CloudHSM 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloudhsmv2" +version = "1.20.1" +description = "Type annotations for boto3.CloudHSMV2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloudsearch" +version = "1.20.1" +description = "Type annotations for boto3.CloudSearch 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloudsearchdomain" +version = "1.20.1" +description = "Type annotations for boto3.CloudSearchDomain 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloudtrail" +version = "1.20.1" +description = "Type annotations for boto3.CloudTrail 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cloudwatch" +version = "1.20.1" +description = "Type annotations for boto3.CloudWatch 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codeartifact" +version = "1.20.1" +description = "Type annotations for boto3.CodeArtifact 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codebuild" +version = "1.20.1" +description = "Type annotations for boto3.CodeBuild 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codecommit" +version = "1.20.1" +description = "Type annotations for boto3.CodeCommit 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codedeploy" +version = "1.20.1" +description = "Type annotations for boto3.CodeDeploy 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codeguru-reviewer" +version = "1.20.1" +description = "Type annotations for boto3.CodeGuruReviewer 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codeguruprofiler" +version = "1.20.1" +description = "Type annotations for boto3.CodeGuruProfiler 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codepipeline" +version = "1.20.1" +description = "Type annotations for boto3.CodePipeline 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codestar" +version = "1.20.1" +description = "Type annotations for boto3.CodeStar 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codestar-connections" +version = "1.20.1" +description = "Type annotations for boto3.CodeStarconnections 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-codestar-notifications" +version = "1.20.1" +description = "Type annotations for boto3.CodeStarNotifications 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cognito-identity" +version = "1.20.1" +description = "Type annotations for boto3.CognitoIdentity 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cognito-idp" +version = "1.20.1" +description = "Type annotations for boto3.CognitoIdentityProvider 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cognito-sync" +version = "1.20.1" +description = "Type annotations for boto3.CognitoSync 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-comprehend" +version = "1.20.1" +description = "Type annotations for boto3.Comprehend 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-comprehendmedical" +version = "1.20.1" +description = "Type annotations for boto3.ComprehendMedical 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-compute-optimizer" +version = "1.20.1" +description = "Type annotations for boto3.ComputeOptimizer 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-config" +version = "1.20.1" +description = "Type annotations for boto3.ConfigService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-connect" +version = "1.20.1" +description = "Type annotations for boto3.Connect 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-connect-contact-lens" +version = "1.20.1" +description = "Type annotations for boto3.ConnectContactLens 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-connectparticipant" +version = "1.20.1" +description = "Type annotations for boto3.ConnectParticipant 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-cur" +version = "1.20.1" +description = "Type annotations for boto3.CostandUsageReportService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-customer-profiles" +version = "1.20.1" +description = "Type annotations for boto3.CustomerProfiles 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-databrew" +version = "1.20.1" +description = "Type annotations for boto3.GlueDataBrew 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-dataexchange" +version = "1.20.1" +description = "Type annotations for boto3.DataExchange 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-datapipeline" +version = "1.20.1" +description = "Type annotations for boto3.DataPipeline 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-datasync" +version = "1.20.1" +description = "Type annotations for boto3.DataSync 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-dax" +version = "1.20.1" +description = "Type annotations for boto3.DAX 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-detective" +version = "1.20.1" +description = "Type annotations for boto3.Detective 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-devicefarm" +version = "1.20.1" +description = "Type annotations for boto3.DeviceFarm 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-devops-guru" +version = "1.20.1" +description = "Type annotations for boto3.DevOpsGuru 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-directconnect" +version = "1.20.1" +description = "Type annotations for boto3.DirectConnect 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-discovery" +version = "1.20.1" +description = "Type annotations for boto3.ApplicationDiscoveryService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-dlm" +version = "1.20.1" +description = "Type annotations for boto3.DLM 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-dms" +version = "1.20.1" +description = "Type annotations for boto3.DatabaseMigrationService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-docdb" +version = "1.20.1" +description = "Type annotations for boto3.DocDB 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ds" +version = "1.20.1" +description = "Type annotations for boto3.DirectoryService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-dynamodb" +version = "1.20.1" +description = "Type annotations for boto3.DynamoDB 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-dynamodbstreams" +version = "1.20.1" +description = "Type annotations for boto3.DynamoDBStreams 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ebs" +version = "1.20.1" +description = "Type annotations for boto3.EBS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ec2" +version = "1.20.1" +description = "Type annotations for boto3.EC2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ec2-instance-connect" +version = "1.20.1" +description = "Type annotations for boto3.EC2InstanceConnect 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ecr" +version = "1.20.1" +description = "Type annotations for boto3.ECR 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ecr-public" +version = "1.20.1" +description = "Type annotations for boto3.ECRPublic 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ecs" +version = "1.20.1" +description = "Type annotations for boto3.ECS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-efs" +version = "1.20.1" +description = "Type annotations for boto3.EFS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-eks" +version = "1.20.1" +description = "Type annotations for boto3.EKS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-elastic-inference" +version = "1.20.1" +description = "Type annotations for boto3.ElasticInference 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-elasticache" +version = "1.20.1" +description = "Type annotations for boto3.ElastiCache 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-elasticbeanstalk" +version = "1.20.1" +description = "Type annotations for boto3.ElasticBeanstalk 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-elastictranscoder" +version = "1.20.1" +description = "Type annotations for boto3.ElasticTranscoder 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-elb" +version = "1.20.1" +description = "Type annotations for boto3.ElasticLoadBalancing 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-elbv2" +version = "1.20.1" +description = "Type annotations for boto3.ElasticLoadBalancingv2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-emr" +version = "1.20.1" +description = "Type annotations for boto3.EMR 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-emr-containers" +version = "1.20.1" +description = "Type annotations for boto3.EMRContainers 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-es" +version = "1.20.1" +description = "Type annotations for boto3.ElasticsearchService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-events" +version = "1.20.1" +description = "Type annotations for boto3.EventBridge 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-finspace" +version = "1.20.1" +description = "Type annotations for boto3.finspace 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-finspace-data" +version = "1.20.1" +description = "Type annotations for boto3.FinSpaceData 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-firehose" +version = "1.20.1" +description = "Type annotations for boto3.Firehose 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-fis" +version = "1.20.1" +description = "Type annotations for boto3.FIS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-fms" +version = "1.20.1" +description = "Type annotations for boto3.FMS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-forecast" +version = "1.20.1" +description = "Type annotations for boto3.ForecastService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-forecastquery" +version = "1.20.1" +description = "Type annotations for boto3.ForecastQueryService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-frauddetector" +version = "1.20.1" +description = "Type annotations for boto3.FraudDetector 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-fsx" +version = "1.20.1" +description = "Type annotations for boto3.FSx 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-gamelift" +version = "1.20.1" +description = "Type annotations for boto3.GameLift 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-glacier" +version = "1.20.1" +description = "Type annotations for boto3.Glacier 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-globalaccelerator" +version = "1.20.1" +description = "Type annotations for boto3.GlobalAccelerator 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-glue" +version = "1.20.1" +description = "Type annotations for boto3.Glue 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-grafana" +version = "1.20.1" +description = "Type annotations for boto3.ManagedGrafana 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-greengrass" +version = "1.20.1" +description = "Type annotations for boto3.Greengrass 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-greengrassv2" +version = "1.20.2" +description = "Type annotations for boto3.GreengrassV2 1.20.2 service, generated by mypy-boto3-builder 6.2.0" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-groundstation" +version = "1.20.1" +description = "Type annotations for boto3.GroundStation 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-guardduty" +version = "1.20.1" +description = "Type annotations for boto3.GuardDuty 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-health" +version = "1.20.2" +description = "Type annotations for boto3.Health 1.20.2 service, generated by mypy-boto3-builder 6.2.0" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-healthlake" +version = "1.20.1" +description = "Type annotations for boto3.HealthLake 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-honeycode" +version = "1.20.1" +description = "Type annotations for boto3.Honeycode 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iam" +version = "1.20.1" +description = "Type annotations for boto3.IAM 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-identitystore" +version = "1.20.1" +description = "Type annotations for boto3.IdentityStore 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-imagebuilder" +version = "1.20.1" +description = "Type annotations for boto3.imagebuilder 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-importexport" +version = "1.20.1" +description = "Type annotations for boto3.ImportExport 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-inspector" +version = "1.20.1" +description = "Type annotations for boto3.Inspector 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iot" +version = "1.20.1" +description = "Type annotations for boto3.IoT 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iot-data" +version = "1.20.1" +description = "Type annotations for boto3.IoTDataPlane 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iot-jobs-data" +version = "1.20.1" +description = "Type annotations for boto3.IoTJobsDataPlane 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iot1click-devices" +version = "1.20.1" +description = "Type annotations for boto3.IoT1ClickDevicesService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iot1click-projects" +version = "1.20.1" +description = "Type annotations for boto3.IoT1ClickProjects 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iotanalytics" +version = "1.20.1" +description = "Type annotations for boto3.IoTAnalytics 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iotdeviceadvisor" +version = "1.20.1" +description = "Type annotations for boto3.IoTDeviceAdvisor 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iotevents" +version = "1.20.1" +description = "Type annotations for boto3.IoTEvents 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iotevents-data" +version = "1.20.1" +description = "Type annotations for boto3.IoTEventsData 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iotfleethub" +version = "1.20.1" +description = "Type annotations for boto3.IoTFleetHub 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iotsecuretunneling" +version = "1.20.1" +description = "Type annotations for boto3.IoTSecureTunneling 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iotsitewise" +version = "1.20.1" +description = "Type annotations for boto3.IoTSiteWise 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iotthingsgraph" +version = "1.20.1" +description = "Type annotations for boto3.IoTThingsGraph 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-iotwireless" +version = "1.20.1" +description = "Type annotations for boto3.IoTWireless 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ivs" +version = "1.20.1" +description = "Type annotations for boto3.IVS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kafka" +version = "1.20.1" +description = "Type annotations for boto3.Kafka 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kafkaconnect" +version = "1.20.1" +description = "Type annotations for boto3.KafkaConnect 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kendra" +version = "1.20.1" +description = "Type annotations for boto3.kendra 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kinesis" +version = "1.20.1" +description = "Type annotations for boto3.Kinesis 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kinesis-video-archived-media" +version = "1.20.1" +description = "Type annotations for boto3.KinesisVideoArchivedMedia 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kinesis-video-media" +version = "1.20.1" +description = "Type annotations for boto3.KinesisVideoMedia 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kinesis-video-signaling" +version = "1.20.1" +description = "Type annotations for boto3.KinesisVideoSignalingChannels 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kinesisanalytics" +version = "1.20.1" +description = "Type annotations for boto3.KinesisAnalytics 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kinesisanalyticsv2" +version = "1.20.1" +description = "Type annotations for boto3.KinesisAnalyticsV2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kinesisvideo" +version = "1.20.1" +description = "Type annotations for boto3.KinesisVideo 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-kms" +version = "1.20.1" +description = "Type annotations for boto3.KMS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lakeformation" +version = "1.20.1" +description = "Type annotations for boto3.LakeFormation 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lambda" +version = "1.20.1" +description = "Type annotations for boto3.Lambda 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lex-models" +version = "1.20.1" +description = "Type annotations for boto3.LexModelBuildingService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lex-runtime" +version = "1.20.1" +description = "Type annotations for boto3.LexRuntimeService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lexv2-models" +version = "1.20.1" +description = "Type annotations for boto3.LexModelsV2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lexv2-runtime" +version = "1.20.1" +description = "Type annotations for boto3.LexRuntimeV2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-license-manager" +version = "1.20.1" +description = "Type annotations for boto3.LicenseManager 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lightsail" +version = "1.20.1" +description = "Type annotations for boto3.Lightsail 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-location" +version = "1.20.1" +description = "Type annotations for boto3.LocationService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-logs" +version = "1.20.1" +description = "Type annotations for boto3.CloudWatchLogs 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lookoutequipment" +version = "1.20.1" +description = "Type annotations for boto3.LookoutEquipment 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lookoutmetrics" +version = "1.20.1" +description = "Type annotations for boto3.LookoutMetrics 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-lookoutvision" +version = "1.20.1" +description = "Type annotations for boto3.LookoutforVision 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-machinelearning" +version = "1.20.1" +description = "Type annotations for boto3.MachineLearning 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-macie" +version = "1.20.1" +description = "Type annotations for boto3.Macie 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-macie2" +version = "1.20.1" +description = "Type annotations for boto3.Macie2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-managedblockchain" +version = "1.20.1" +description = "Type annotations for boto3.ManagedBlockchain 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-marketplace-catalog" +version = "1.20.1" +description = "Type annotations for boto3.MarketplaceCatalog 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-marketplace-entitlement" +version = "1.20.1" +description = "Type annotations for boto3.MarketplaceEntitlementService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-marketplacecommerceanalytics" +version = "1.20.1" +description = "Type annotations for boto3.MarketplaceCommerceAnalytics 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mediaconnect" +version = "1.20.1" +description = "Type annotations for boto3.MediaConnect 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mediaconvert" +version = "1.20.1" +description = "Type annotations for boto3.MediaConvert 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-medialive" +version = "1.20.1" +description = "Type annotations for boto3.MediaLive 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mediapackage" +version = "1.20.1" +description = "Type annotations for boto3.MediaPackage 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mediapackage-vod" +version = "1.20.1" +description = "Type annotations for boto3.MediaPackageVod 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mediastore" +version = "1.20.1" +description = "Type annotations for boto3.MediaStore 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mediastore-data" +version = "1.20.1" +description = "Type annotations for boto3.MediaStoreData 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mediatailor" +version = "1.20.1" +description = "Type annotations for boto3.MediaTailor 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-memorydb" +version = "1.20.1" +description = "Type annotations for boto3.MemoryDB 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-meteringmarketplace" +version = "1.20.1" +description = "Type annotations for boto3.MarketplaceMetering 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mgh" +version = "1.20.1" +description = "Type annotations for boto3.MigrationHub 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mgn" +version = "1.20.1" +description = "Type annotations for boto3.mgn 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-migrationhub-config" +version = "1.20.1" +description = "Type annotations for boto3.MigrationHubConfig 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mobile" +version = "1.20.1" +description = "Type annotations for boto3.Mobile 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mq" +version = "1.20.1" +description = "Type annotations for boto3.MQ 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mturk" +version = "1.20.1" +description = "Type annotations for boto3.MTurk 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-mwaa" +version = "1.20.1" +description = "Type annotations for boto3.MWAA 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-neptune" +version = "1.20.1" +description = "Type annotations for boto3.Neptune 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-network-firewall" +version = "1.20.1" +description = "Type annotations for boto3.NetworkFirewall 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-networkmanager" +version = "1.20.1" +description = "Type annotations for boto3.NetworkManager 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-nimble" +version = "1.20.1" +description = "Type annotations for boto3.NimbleStudio 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-opensearch" +version = "1.20.1" +description = "Type annotations for boto3.OpenSearchService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-opsworks" +version = "1.20.1" +description = "Type annotations for boto3.OpsWorks 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-opsworkscm" +version = "1.20.1" +description = "Type annotations for boto3.OpsWorksCM 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-organizations" +version = "1.20.1" +description = "Type annotations for boto3.Organizations 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-outposts" +version = "1.20.1" +description = "Type annotations for boto3.Outposts 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-panorama" +version = "1.20.1" +description = "Type annotations for boto3.Panorama 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-personalize" +version = "1.20.1" +description = "Type annotations for boto3.Personalize 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-personalize-events" +version = "1.20.1" +description = "Type annotations for boto3.PersonalizeEvents 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-personalize-runtime" +version = "1.20.1" +description = "Type annotations for boto3.PersonalizeRuntime 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-pi" +version = "1.20.1" +description = "Type annotations for boto3.PI 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-pinpoint" +version = "1.20.1" +description = "Type annotations for boto3.Pinpoint 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-pinpoint-email" +version = "1.20.1" +description = "Type annotations for boto3.PinpointEmail 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-pinpoint-sms-voice" +version = "1.20.1" +description = "Type annotations for boto3.PinpointSMSVoice 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-polly" +version = "1.20.1" +description = "Type annotations for boto3.Polly 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-pricing" +version = "1.20.1" +description = "Type annotations for boto3.Pricing 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-proton" +version = "1.20.1" +description = "Type annotations for boto3.Proton 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-qldb" +version = "1.20.1" +description = "Type annotations for boto3.QLDB 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-qldb-session" +version = "1.20.1" +description = "Type annotations for boto3.QLDBSession 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-quicksight" +version = "1.20.1" +description = "Type annotations for boto3.QuickSight 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ram" +version = "1.20.1" +description = "Type annotations for boto3.RAM 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-rds" +version = "1.20.1" +description = "Type annotations for boto3.RDS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-rds-data" +version = "1.20.1" +description = "Type annotations for boto3.RDSDataService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-redshift" +version = "1.20.1" +description = "Type annotations for boto3.Redshift 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-redshift-data" +version = "1.20.1" +description = "Type annotations for boto3.RedshiftDataAPIService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-rekognition" +version = "1.20.1" +description = "Type annotations for boto3.Rekognition 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-resource-groups" +version = "1.20.1" +description = "Type annotations for boto3.ResourceGroups 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-resourcegroupstaggingapi" +version = "1.20.1" +description = "Type annotations for boto3.ResourceGroupsTaggingAPI 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-robomaker" +version = "1.20.1" +description = "Type annotations for boto3.RoboMaker 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-route53" +version = "1.20.1" +description = "Type annotations for boto3.Route53 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-route53-recovery-cluster" +version = "1.20.1" +description = "Type annotations for boto3.Route53RecoveryCluster 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-route53-recovery-control-config" +version = "1.20.1" +description = "Type annotations for boto3.Route53RecoveryControlConfig 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-route53-recovery-readiness" +version = "1.20.1" +description = "Type annotations for boto3.Route53RecoveryReadiness 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-route53domains" +version = "1.20.1" +description = "Type annotations for boto3.Route53Domains 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-route53resolver" +version = "1.20.1" +description = "Type annotations for boto3.Route53Resolver 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-s3" +version = "1.20.1" +description = "Type annotations for boto3.S3 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-s3control" +version = "1.20.1" +description = "Type annotations for boto3.S3Control 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-s3outposts" +version = "1.20.1" +description = "Type annotations for boto3.S3Outposts 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sagemaker" +version = "1.20.1" +description = "Type annotations for boto3.SageMaker 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sagemaker-a2i-runtime" +version = "1.20.1" +description = "Type annotations for boto3.AugmentedAIRuntime 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sagemaker-edge" +version = "1.20.1" +description = "Type annotations for boto3.SagemakerEdgeManager 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sagemaker-featurestore-runtime" +version = "1.20.1" +description = "Type annotations for boto3.SageMakerFeatureStoreRuntime 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sagemaker-runtime" +version = "1.20.1" +description = "Type annotations for boto3.SageMakerRuntime 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-savingsplans" +version = "1.20.1" +description = "Type annotations for boto3.SavingsPlans 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-schemas" +version = "1.20.1" +description = "Type annotations for boto3.Schemas 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sdb" +version = "1.20.1" +description = "Type annotations for boto3.SimpleDB 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-secretsmanager" +version = "1.20.1" +description = "Type annotations for boto3.SecretsManager 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-securityhub" +version = "1.20.1" +description = "Type annotations for boto3.SecurityHub 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-serverlessrepo" +version = "1.20.1" +description = "Type annotations for boto3.ServerlessApplicationRepository 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-service-quotas" +version = "1.20.1" +description = "Type annotations for boto3.ServiceQuotas 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-servicecatalog" +version = "1.20.1" +description = "Type annotations for boto3.ServiceCatalog 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-servicecatalog-appregistry" +version = "1.20.1" +description = "Type annotations for boto3.AppRegistry 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-servicediscovery" +version = "1.20.1" +description = "Type annotations for boto3.ServiceDiscovery 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ses" +version = "1.20.1" +description = "Type annotations for boto3.SES 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sesv2" +version = "1.20.1" +description = "Type annotations for boto3.SESV2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-shield" +version = "1.20.1" +description = "Type annotations for boto3.Shield 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-signer" +version = "1.20.1" +description = "Type annotations for boto3.signer 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sms" +version = "1.20.1" +description = "Type annotations for boto3.SMS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sms-voice" +version = "1.20.1" +description = "Type annotations for boto3.PinpointSMSVoice 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-snow-device-management" +version = "1.20.1" +description = "Type annotations for boto3.SnowDeviceManagement 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-snowball" +version = "1.20.1" +description = "Type annotations for boto3.Snowball 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sns" +version = "1.20.1" +description = "Type annotations for boto3.SNS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sqs" +version = "1.20.1" +description = "Type annotations for boto3.SQS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ssm" +version = "1.20.1" +description = "Type annotations for boto3.SSM 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ssm-contacts" +version = "1.20.1" +description = "Type annotations for boto3.SSMContacts 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-ssm-incidents" +version = "1.20.1" +description = "Type annotations for boto3.SSMIncidents 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sso" +version = "1.20.1" +description = "Type annotations for boto3.SSO 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sso-admin" +version = "1.20.1" +description = "Type annotations for boto3.SSOAdmin 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sso-oidc" +version = "1.20.1" +description = "Type annotations for boto3.SSOOIDC 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-stepfunctions" +version = "1.20.1" +description = "Type annotations for boto3.SFN 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-storagegateway" +version = "1.20.1" +description = "Type annotations for boto3.StorageGateway 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-sts" +version = "1.20.1" +description = "Type annotations for boto3.STS 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-support" +version = "1.20.1" +description = "Type annotations for boto3.Support 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-swf" +version = "1.20.1" +description = "Type annotations for boto3.SWF 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-synthetics" +version = "1.20.1" +description = "Type annotations for boto3.Synthetics 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-textract" +version = "1.20.1" +description = "Type annotations for boto3.Textract 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-timestream-query" +version = "1.20.1" +description = "Type annotations for boto3.TimestreamQuery 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-timestream-write" +version = "1.20.1" +description = "Type annotations for boto3.TimestreamWrite 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-transcribe" +version = "1.20.1" +description = "Type annotations for boto3.TranscribeService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-transfer" +version = "1.20.1" +description = "Type annotations for boto3.Transfer 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-translate" +version = "1.20.1" +description = "Type annotations for boto3.Translate 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-voice-id" +version = "1.20.1" +description = "Type annotations for boto3.VoiceID 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-waf" +version = "1.20.1" +description = "Type annotations for boto3.WAF 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-waf-regional" +version = "1.20.1" +description = "Type annotations for boto3.WAFRegional 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-wafv2" +version = "1.20.1" +description = "Type annotations for boto3.WAFV2 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-wellarchitected" +version = "1.20.1" +description = "Type annotations for boto3.WellArchitected 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-wisdom" +version = "1.20.1" +description = "Type annotations for boto3.ConnectWisdomService 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-workdocs" +version = "1.20.1" +description = "Type annotations for boto3.WorkDocs 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-worklink" +version = "1.20.1" +description = "Type annotations for boto3.WorkLink 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-workmail" +version = "1.20.1" +description = "Type annotations for boto3.WorkMail 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-workmailmessageflow" +version = "1.20.1" +description = "Type annotations for boto3.WorkMailMessageFlow 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-workspaces" +version = "1.20.1" +description = "Type annotations for boto3.WorkSpaces 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-boto3-xray" +version = "1.20.1" +description = "Type annotations for boto3.XRay 1.20.1 service, generated by mypy-boto3-builder 6.1.2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-extensions" +version = "0.4.3" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "packaging" +version = "21.2" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3" + +[[package]] +name = "pastel" +version = "0.2.1" +description = "Bring colors to your terminal." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pathspec" +version = "0.9.0" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[[package]] +name = "pbr" +version = "5.7.0" +description = "Python Build Reasonableness" +category = "dev" +optional = false +python-versions = ">=2.6" + +[[package]] +name = "pep8-naming" +version = "0.12.1" +description = "Check PEP-8 naming conventions, plugin for flake8" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = ">=3.9.1" +flake8-polyfill = ">=1.0.2,<2" + +[[package]] +name = "platformdirs" +version = "2.4.0" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] + +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pycodestyle" +version = "2.7.0" +description = "Python style guide checker" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pydocstyle" +version = "6.1.1" +description = "Python docstring style checker" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +snowballstemmer = "*" + +[package.extras] +toml = ["toml"] + +[[package]] +name = "pyflakes" +version = "2.3.1" +description = "passive checker of Python programs" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pylev" +version = "1.4.0" +description = "A pure Python Levenshtein implementation that's not freaking GPL'd." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "pylic" +version = "2.1.0" +description = "A Python license checker" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +cleo = ">=0.8.1,<0.9.0" +importlib-metadata = ">=4.8.1,<5.0.0" +toml = ">=0.10.2,<0.11.0" + +[[package]] +name = "pyparsing" +version = "2.4.7" +description = "Python parsing module" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "pytest" +version = "6.2.5" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +toml = "*" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "2.12.1" +description = "Pytest plugin for measuring coverage." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.dependencies] +coverage = ">=5.2.1" +pytest = ">=4.6" +toml = "*" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] + +[[package]] +name = "pytest-forked" +version = "1.3.0" +description = "run tests in isolated forked subprocesses" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.dependencies] +py = "*" +pytest = ">=3.10" + +[[package]] +name = "pytest-mock" +version = "3.6.1" +description = "Thin-wrapper around the mock package for easier use with pytest" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pytest = ">=5.0" + +[package.extras] +dev = ["pre-commit", "tox", "pytest-asyncio"] + +[[package]] +name = "pytest-xdist" +version = "2.4.0" +description = "pytest xdist plugin for distributed testing and loop-on-failing modes" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +execnet = ">=1.1" +pytest = ">=6.0.0" +pytest-forked = "*" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "regex" +version = "2021.11.10" +description = "Alternative regular expression module, to replace re." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "requests" +version = "2.26.0" +description = "Python HTTP for Humans." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} +idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] + +[[package]] +name = "rope" +version = "0.19.0" +description = "a python refactoring library..." +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +dev = ["pytest"] + +[[package]] +name = "s3transfer" +version = "0.5.0" +description = "An Amazon S3 Transfer Manager" +category = "main" +optional = false +python-versions = ">= 3.6" + +[package.dependencies] +botocore = ">=1.12.36,<2.0a.0" + +[package.extras] +crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] + +[[package]] +name = "safety" +version = "1.10.3" +description = "Checks installed dependencies for known vulnerabilities." +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +Click = ">=6.0" +dparse = ">=0.5.1" +packaging = "*" +requests = "*" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "smmap" +version = "5.0.0" +description = "A pure Python implementation of a sliding window memory map manager" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "snowballstemmer" +version = "2.1.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "sqlparse" +version = "0.4.2" +description = "A non-validating SQL parser." +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "stdlib-list" +version = "0.8.0" +description = "A list of Python Standard Libraries (2.6-7, 3.2-9)." +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +develop = ["sphinx"] + +[[package]] +name = "stevedore" +version = "3.5.0" +description = "Manage dynamic plugins for Python applications" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pbr = ">=2.0.0,<2.1.0 || >2.1.0" + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "tomli" +version = "1.2.2" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "typing-extensions" +version = "3.10.0.2" +description = "Backported and Experimental Type Hints for Python 3.5+" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "urllib3" +version = "1.26.7" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "zipp" +version = "3.6.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.9" +content-hash = "687d5b8e9746e2db41b5378cf839f775deb0a2f36d5a753839990d0d71b47253" + +[metadata.files] +astor = [ + {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, + {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, +] +astpretty = [ + {file = "astpretty-2.1.0-py2.py3-none-any.whl", hash = "sha256:f81f14b5636f7af81fadb1e3c09ca7702ce4615500d9cc6d6829befb2dec2e3c"}, + {file = "astpretty-2.1.0.tar.gz", hash = "sha256:8a801fcda604ec741f010bb36d7cbadc3ec8a182ea6fb83e20ab663463e75ff6"}, +] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] +attrs = [ + {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, + {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, +] +aws-lambda-typing = [ + {file = "aws-lambda-typing-2.9.2.tar.gz", hash = "sha256:7109f41449bbf5a433cb840a26d00e85e35472041002bca525a76703efb7f60a"}, + {file = "aws_lambda_typing-2.9.2-py3-none-any.whl", hash = "sha256:97bf336753434bbb0f9af0058a95176e6e080c1e9f3cd28cef4529a39bdd979b"}, +] +bandit = [ + {file = "bandit-1.7.0-py3-none-any.whl", hash = "sha256:216be4d044209fa06cf2a3e51b319769a51be8318140659719aa7a115c35ed07"}, + {file = "bandit-1.7.0.tar.gz", hash = "sha256:8a4c7415254d75df8ff3c3b15cfe9042ecee628a1e40b44c15a98890fbfc2608"}, +] +black = [ + {file = "black-21.10b0-py3-none-any.whl", hash = "sha256:6eb7448da9143ee65b856a5f3676b7dda98ad9abe0f87fce8c59291f15e82a5b"}, + {file = "black-21.10b0.tar.gz", hash = "sha256:a9952229092e325fe5f3dae56d81f639b23f7131eb840781947e4b2886030f33"}, +] +boto3 = [ + {file = "boto3-1.20.2-py3-none-any.whl", hash = "sha256:3735a29512db2a64e4cf2087f55f9a8f96472ec97a2aa2801be0b90db8de1af2"}, + {file = "boto3-1.20.2.tar.gz", hash = "sha256:905a213c8ca1f148c872b79849e04741ba9e648348bbe23726e98dd3fdacc574"}, +] +boto3-stubs = [ + {file = "boto3-stubs-1.20.2.tar.gz", hash = "sha256:004acb8cb172ca17fa51b9ed8bba4e695b086178daab397c021b16378236663e"}, + {file = "boto3_stubs-1.20.2-py3-none-any.whl", hash = "sha256:3b63fa21f70d941e511aa3b44da3112202ca54793761e6f50484a5265f31c4ed"}, +] +botocore = [ + {file = "botocore-1.23.2-py3-none-any.whl", hash = "sha256:0a0e7fde67c9aa75ce9013ef7d26597daa474bb606d3dc013e1c2384b7cf095b"}, + {file = "botocore-1.23.2.tar.gz", hash = "sha256:274475867c3bdc7124b7e47ce4e1adac6461a0e9c2fdfd93913f41cfd3a897cf"}, +] +botocore-stubs = [ + {file = "botocore-stubs-1.23.2.tar.gz", hash = "sha256:7b8a3b09d86cf24a376a8f264c8ce23eeb616de6e1b56985648afbf0332a6227"}, + {file = "botocore_stubs-1.23.2-py3-none-any.whl", hash = "sha256:e1fd32dab630b7740ea977c115b315d057bc28aefc869b8ef009779f5186713d"}, +] +certifi = [ + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.0.7.tar.gz", hash = "sha256:e019de665e2bcf9c2b64e2e5aa025fa991da8720daa3c1138cadd2fd1856aed0"}, + {file = "charset_normalizer-2.0.7-py3-none-any.whl", hash = "sha256:f7af805c321bfa1ce6714c51f254e0d5bb5e5834039bc17db7ebe3a4cec9492b"}, +] +cleo = [ + {file = "cleo-0.8.1-py2.py3-none-any.whl", hash = "sha256:141cda6dc94a92343be626bb87a0b6c86ae291dfc732a57bf04310d4b4201753"}, + {file = "cleo-0.8.1.tar.gz", hash = "sha256:3d0e22d30117851b45970b6c14aca4ab0b18b1b53c8af57bed13208147e4069f"}, +] +click = [ + {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, + {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, +] +clikit = [ + {file = "clikit-0.6.2-py2.py3-none-any.whl", hash = "sha256:71268e074e68082306e23d7369a7b99f824a0ef926e55ba2665e911f7208489e"}, + {file = "clikit-0.6.2.tar.gz", hash = "sha256:442ee5db9a14120635c5990bcdbfe7c03ada5898291f0c802f77be71569ded59"}, +] +cognitive-complexity = [ + {file = "cognitive_complexity-1.2.0.tar.gz", hash = "sha256:3c2b433a9e41502932f6aa629e1f57a5e8f145956c54facbb5241a9492af6fb7"}, +] +colorama = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] +coverage = [ + {file = "coverage-6.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:42a1fb5dee3355df90b635906bb99126faa7936d87dfc97eacc5293397618cb7"}, + {file = "coverage-6.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a00284dbfb53b42e35c7dd99fc0e26ef89b4a34efff68078ed29d03ccb28402a"}, + {file = "coverage-6.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:51a441011a30d693e71dea198b2a6f53ba029afc39f8e2aeb5b77245c1b282ef"}, + {file = "coverage-6.1.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e76f017b6d4140a038c5ff12be1581183d7874e41f1c0af58ecf07748d36a336"}, + {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7833c872718dc913f18e51ee97ea0dece61d9930893a58b20b3daf09bb1af6b6"}, + {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8186b5a4730c896cbe1e4b645bdc524e62d874351ae50e1db7c3e9f5dc81dc26"}, + {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bbca34dca5a2d60f81326d908d77313816fad23d11b6069031a3d6b8c97a54f9"}, + {file = "coverage-6.1.1-cp310-cp310-win32.whl", hash = "sha256:72bf437d54186d104388cbae73c9f2b0f8a3e11b6e8d7deb593bd14625c96026"}, + {file = "coverage-6.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:994ce5a7b3d20981b81d83618aa4882f955bfa573efdbef033d5632b58597ba9"}, + {file = "coverage-6.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ab6a0fe4c96f8058d41948ddf134420d3ef8c42d5508b5a341a440cce7a37a1d"}, + {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10ab138b153e4cc408b43792cb7f518f9ee02f4ff55cd1ab67ad6fd7e9905c7e"}, + {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7e083d32965d2eb6638a77e65b622be32a094fdc0250f28ce6039b0732fbcaa8"}, + {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:359a32515e94e398a5c0fa057e5887a42e647a9502d8e41165cf5cb8d3d1ca67"}, + {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:bf656cd74ff7b4ed7006cdb2a6728150aaad69c7242b42a2a532f77b63ea233f"}, + {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:dc5023be1c2a8b0a0ab5e31389e62c28b2453eb31dd069f4b8d1a0f9814d951a"}, + {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:557594a50bfe3fb0b1b57460f6789affe8850ad19c1acf2d14a3e12b2757d489"}, + {file = "coverage-6.1.1-cp36-cp36m-win32.whl", hash = "sha256:9eb0a1923354e0fdd1c8a6f53f5db2e6180d670e2b587914bf2e79fa8acfd003"}, + {file = "coverage-6.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:04a92a6cf9afd99f9979c61348ec79725a9f9342fb45e63c889e33c04610d97b"}, + {file = "coverage-6.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:479228e1b798d3c246ac89b09897ee706c51b3e5f8f8d778067f38db73ccc717"}, + {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78287731e3601ea5ce9d6468c82d88a12ef8fe625d6b7bdec9b45d96c1ad6533"}, + {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c95257aa2ccf75d3d91d772060538d5fea7f625e48157f8ca44594f94d41cb33"}, + {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9ad5895938a894c368d49d8470fe9f519909e5ebc6b8f8ea5190bd0df6aa4271"}, + {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:326d944aad0189603733d646e8d4a7d952f7145684da973c463ec2eefe1387c2"}, + {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e7d5606b9240ed4def9cbdf35be4308047d11e858b9c88a6c26974758d6225ce"}, + {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:572f917267f363101eec375c109c9c1118037c7cc98041440b5eabda3185ac7b"}, + {file = "coverage-6.1.1-cp37-cp37m-win32.whl", hash = "sha256:35cd2230e1ed76df7d0081a997f0fe705be1f7d8696264eb508076e0d0b5a685"}, + {file = "coverage-6.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:65ad3ff837c89a229d626b8004f0ee32110f9bfdb6a88b76a80df36ccc60d926"}, + {file = "coverage-6.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:977ce557d79577a3dd510844904d5d968bfef9489f512be65e2882e1c6eed7d8"}, + {file = "coverage-6.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62512c0ec5d307f56d86504c58eace11c1bc2afcdf44e3ff20de8ca427ca1d0e"}, + {file = "coverage-6.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2e5b9c17a56b8bf0c0a9477fcd30d357deb486e4e1b389ed154f608f18556c8a"}, + {file = "coverage-6.1.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:666c6b32b69e56221ad1551d377f718ed00e6167c7a1b9257f780b105a101271"}, + {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fb2fa2f6506c03c48ca42e3fe5a692d7470d290c047ee6de7c0f3e5fa7639ac9"}, + {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f0f80e323a17af63eac6a9db0c9188c10f1fd815c3ab299727150cc0eb92c7a4"}, + {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:738e823a746841248b56f0f3bd6abf3b73af191d1fd65e4c723b9c456216f0ad"}, + {file = "coverage-6.1.1-cp38-cp38-win32.whl", hash = "sha256:8605add58e6a960729aa40c0fd9a20a55909dd9b586d3e8104cc7f45869e4c6b"}, + {file = "coverage-6.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:6e994003e719458420e14ffb43c08f4c14990e20d9e077cb5cad7a3e419bbb54"}, + {file = "coverage-6.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e3c4f5211394cd0bf6874ac5d29684a495f9c374919833dcfff0bd6d37f96201"}, + {file = "coverage-6.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e14bceb1f3ae8a14374be2b2d7bc12a59226872285f91d66d301e5f41705d4d6"}, + {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0147f7833c41927d84f5af9219d9b32f875c0689e5e74ac8ca3cb61e73a698f9"}, + {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b1d0a1bce919de0dd8da5cff4e616b2d9e6ebf3bd1410ff645318c3dd615010a"}, + {file = "coverage-6.1.1-cp39-cp39-win32.whl", hash = "sha256:a11a2c019324fc111485e79d55907e7289e53d0031275a6c8daed30690bc50c0"}, + {file = "coverage-6.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:4d8b453764b9b26b0dd2afb83086a7c3f9379134e340288d2a52f8a91592394b"}, + {file = "coverage-6.1.1-pp36-none-any.whl", hash = "sha256:3b270c6b48d3ff5a35deb3648028ba2643ad8434b07836782b1139cf9c66313f"}, + {file = "coverage-6.1.1-pp37-none-any.whl", hash = "sha256:ffa8fee2b1b9e60b531c4c27cf528d6b5d5da46b1730db1f4d6eee56ff282e07"}, + {file = "coverage-6.1.1-pp38-none-any.whl", hash = "sha256:4cd919057636f63ab299ccb86ea0e78b87812400c76abab245ca385f17d19fb5"}, + {file = "coverage-6.1.1.tar.gz", hash = "sha256:b8e4f15b672c9156c1154249a9c5746e86ac9ae9edc3799ee3afebc323d9d9e0"}, +] +crashtest = [ + {file = "crashtest-0.3.1-py3-none-any.whl", hash = "sha256:300f4b0825f57688b47b6d70c6a31de33512eb2fa1ac614f780939aa0cf91680"}, + {file = "crashtest-0.3.1.tar.gz", hash = "sha256:42ca7b6ce88b6c7433e2ce47ea884e91ec93104a4b754998be498a8e6c3d37dd"}, +] +crhelper = [ + {file = "crhelper-2.0.10-py3-none-any.whl", hash = "sha256:8f05516ca8b7a340fbaedbc1a463e2cb8d53c0670cd2f7723c8b8098c65bf27d"}, + {file = "crhelper-2.0.10.tar.gz", hash = "sha256:1ed61609dd81439b5f3f5e716e690604f8535b9f640149342ef3a89c8e0ab7bd"}, +] +darglint = [ + {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, + {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, +] +dlint = [ + {file = "dlint-0.11.0-py2.py3-none-any.whl", hash = "sha256:e7297325f57e6b5318d88fba2497f9fea6830458cd5aecb36150856db010f409"}, +] +dparse = [ + {file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"}, + {file = "dparse-0.5.1.tar.gz", hash = "sha256:a1b5f169102e1c894f9a7d5ccf6f9402a836a5d24be80a986c7ce9eaed78f367"}, +] +eradicate = [ + {file = "eradicate-2.0.0.tar.gz", hash = "sha256:27434596f2c5314cc9b31410c93d8f7e8885747399773cd088d3adea647a60c8"}, +] +execnet = [ + {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"}, + {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"}, +] +flake8 = [ + {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, + {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, +] +flake8-2020 = [ + {file = "flake8_2020-1.6.0-py2.py3-none-any.whl", hash = "sha256:e464cef7889117e7ae7253e35fcb8272bd8ae68fc10bb3399ef85b036c092528"}, + {file = "flake8_2020-1.6.0.tar.gz", hash = "sha256:3e438d9d531577fbb9332bbd0bf394eca890f3b7a5311e2278fb3582381a2f13"}, +] +flake8-annotations-complexity = [ + {file = "flake8_annotations_complexity-0.0.6-py3-none-any.whl", hash = "sha256:078a84e8269ef82c4c9de5198638e9a91a2089307d4e559666464a87b528ea69"}, + {file = "flake8_annotations_complexity-0.0.6.tar.gz", hash = "sha256:32dfc8f42df3b16fb4fbc66a287433e176ae1bd39894d9aec898cfc70aef25cb"}, +] +flake8-bandit = [ + {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, +] +flake8-breakpoint = [ + {file = "flake8-breakpoint-1.1.0.tar.gz", hash = "sha256:5bc70d478f0437a3655d094e1d2fca81ddacabaa84d99db45ad3630bf2004064"}, + {file = "flake8_breakpoint-1.1.0-py3-none-any.whl", hash = "sha256:27e0cb132647f9ef348b4a3c3126e7350bedbb22e8e221cd11712a223855ea0b"}, +] +flake8-broken-line = [ + {file = "flake8-broken-line-0.3.0.tar.gz", hash = "sha256:f74e052833324a9e5f0055032f7ccc54b23faabafe5a26241c2f977e70b10b50"}, + {file = "flake8_broken_line-0.3.0-py3-none-any.whl", hash = "sha256:611f79c7f27118e7e5d3dc098ef7681c40aeadf23783700c5dbee840d2baf3af"}, +] +flake8-bugbear = [ + {file = "flake8-bugbear-21.9.2.tar.gz", hash = "sha256:db9a09893a6c649a197f5350755100bb1dd84f110e60cf532fdfa07e41808ab2"}, + {file = "flake8_bugbear-21.9.2-py36.py37.py38-none-any.whl", hash = "sha256:4f7eaa6f05b7d7ea4cbbde93f7bcdc5438e79320fa1ec420d860c181af38b769"}, +] +flake8-builtins = [ + {file = "flake8-builtins-1.5.3.tar.gz", hash = "sha256:09998853b2405e98e61d2ff3027c47033adbdc17f9fe44ca58443d876eb00f3b"}, + {file = "flake8_builtins-1.5.3-py2.py3-none-any.whl", hash = "sha256:7706babee43879320376861897e5d1468e396a40b8918ed7bccf70e5f90b8687"}, +] +flake8-cognitive-complexity = [ + {file = "flake8_cognitive_complexity-0.1.0.tar.gz", hash = "sha256:f202df054e4f6ff182b659c261922b9c684628a47beb19cb0973c50d6a7831c1"}, +] +flake8-comprehensions = [ + {file = "flake8-comprehensions-3.7.0.tar.gz", hash = "sha256:6b3218b2dde8ac5959c6476cde8f41a79e823c22feb656be2710cd2a3232cef9"}, + {file = "flake8_comprehensions-3.7.0-py3-none-any.whl", hash = "sha256:a5d7aea6315bbbd6fbcb2b4e80bff6a54d1600155e26236e555d0c6fe1d62522"}, +] +flake8-copyright = [ + {file = "flake8-copyright-0.2.2.tar.gz", hash = "sha256:5c3632dd8c586547b25fff4272282005fdbcba56eeb77b7487564aa636b6e533"}, + {file = "flake8_copyright-0.2.2-py2.py3-none-any.whl", hash = "sha256:616a960c9602ad2d0136bf3f12564e253caffe82f151d2982f78a12a42e1faa0"}, + {file = "flake8_copyright-0.2.2-py3-none-any.whl", hash = "sha256:dbad92ee5f51398722cd571b6e36cc3651914bf1b286b0e638bba1f4af0b6f5b"}, +] +flake8-docstrings = [ + {file = "flake8-docstrings-1.6.0.tar.gz", hash = "sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b"}, + {file = "flake8_docstrings-1.6.0-py2.py3-none-any.whl", hash = "sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde"}, +] +flake8-eradicate = [ + {file = "flake8-eradicate-1.2.0.tar.gz", hash = "sha256:acaa1b6839ff00d284b805c432fdfa6047262bd15a5504ec945797e87b4de1fa"}, + {file = "flake8_eradicate-1.2.0-py3-none-any.whl", hash = "sha256:51dc660d0c1c1ed93af0f813540bbbf72ab2d3466c14e3f3bac371c618b6042f"}, +] +flake8-executable = [ + {file = "flake8-executable-2.1.1.tar.gz", hash = "sha256:c6230a089ad49dbeef049d8e1e89591d9823f06c829cd9d6b1ca83b4b1d7f54f"}, + {file = "flake8_executable-2.1.1-py3-none-any.whl", hash = "sha256:c1df78bf4eff1b75bff0a3d29609d096d61ccfd703a4a9485019af9a640d6e2b"}, +] +flake8-expression-complexity = [ + {file = "flake8_expression_complexity-0.0.9.tar.gz", hash = "sha256:1ae325880a5dbfef60a35eaa8bb5351d5c5102774a41d4ed7059bc093a95955b"}, +] +flake8-fixme = [ + {file = "flake8-fixme-1.1.1.tar.gz", hash = "sha256:50cade07d27a4c30d4f12351478df87339e67640c83041b664724bda6d16f33a"}, + {file = "flake8_fixme-1.1.1-py2.py3-none-any.whl", hash = "sha256:226a6f2ef916730899f29ac140bed5d4a17e5aba79f00a0e3ae1eff1997cb1ac"}, +] +flake8-functions = [ + {file = "flake8_functions-0.0.6-py3-none-any.whl", hash = "sha256:7afa7979d20d28a3cde0c14b3fddf42beef23232620a641ad20dcc2de49eddf3"}, + {file = "flake8_functions-0.0.6.tar.gz", hash = "sha256:6d42da93c4b13354a3973da7bf4e239225f9dba167e8a099fd647ae483ac3e24"}, +] +flake8-helper = [ + {file = "flake8_helper-0.2.0-py3-none-any.whl", hash = "sha256:f21290581389027a75a9c70de6b1147c3d073fa6d1bdbe577593ec22faff8ece"}, + {file = "flake8_helper-0.2.0.tar.gz", hash = "sha256:8939b234dfde12a927fb10b14c3b980e28c17615cdac51595323d7e330704552"}, +] +flake8-markdown = [ + {file = "flake8-markdown-0.2.0.tar.gz", hash = "sha256:bca29422c66815c2f360fea3efce7356d42832e925d8ceb0525983f4e94a591c"}, + {file = "flake8_markdown-0.2.0-py3-none-any.whl", hash = "sha256:6727f28c71b941f0026bc7e08675a71002bfbf69018317bcec81e0502a33db3f"}, +] +flake8-mock = [ + {file = "flake8-mock-0.3.tar.gz", hash = "sha256:2fa775e7589f4e1ad74f35d60953eb20937f5d7355235e54bf852c6837f2bede"}, +] +flake8-mutable = [ + {file = "flake8-mutable-1.2.0.tar.gz", hash = "sha256:ee9b77111b867d845177bbc289d87d541445ffcc6029a0c5c65865b42b18c6a6"}, + {file = "flake8_mutable-1.2.0-py2-none-any.whl", hash = "sha256:38fd9dadcbcda6550a916197bc40ed76908119dabb37fbcca30873666c31d2d5"}, +] +flake8-no-implicit-concat = [ + {file = "flake8-no-implicit-concat-0.2.1.tar.gz", hash = "sha256:4c81f69bf09c94a5c9b8e620203e7022bc585c973356d103130552eea80b13de"}, + {file = "flake8_no_implicit_concat-0.2.1-py3-none-any.whl", hash = "sha256:aa49fc2533ef96691346eb9488cc0bd6dfcab23668ce97e12223fd79992c7016"}, +] +flake8-plugin-utils = [ + {file = "flake8-plugin-utils-1.3.2.tar.gz", hash = "sha256:20fa2a8ca2decac50116edb42e6af0a1253ef639ad79941249b840531889c65a"}, + {file = "flake8_plugin_utils-1.3.2-py3-none-any.whl", hash = "sha256:1fe43e3e9acf3a7c0f6b88f5338cad37044d2f156c43cb6b080b5f9da8a76f06"}, +] +flake8-polyfill = [ + {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, + {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, +] +flake8-print = [ + {file = "flake8-print-4.0.0.tar.gz", hash = "sha256:5afac374b7dc49aac2c36d04b5eb1d746d72e6f5df75a6ecaecd99e9f79c6516"}, + {file = "flake8_print-4.0.0-py3-none-any.whl", hash = "sha256:6c0efce658513169f96d7a24cf136c434dc711eb00ebd0a985eb1120103fe584"}, +] +flake8-printf-formatting = [ + {file = "flake8-printf-formatting-1.1.2.tar.gz", hash = "sha256:0f9e1308ac290356e4b271d4f26adfc3f9165680a7b6c221503b0f3e155a2784"}, + {file = "flake8_printf_formatting-1.1.2-py2.py3-none-any.whl", hash = "sha256:d908ffabdf08581043a50572744fd60563d82386630b0335445894120089d2df"}, +] +flake8-pytest-style = [ + {file = "flake8-pytest-style-1.5.1.tar.gz", hash = "sha256:56af62da468a547560a9f455c7f205449ed03e8f8a42f85373180e91c1031c40"}, + {file = "flake8_pytest_style-1.5.1-py3-none-any.whl", hash = "sha256:ae62f8db8ad0ea7d90695deb6dbbacfc67d45cb83a7c360388b34a9705786114"}, +] +flake8-raise = [ + {file = "flake8-raise-0.0.5.tar.gz", hash = "sha256:0a9890e16b851402d9b0d4fafe6c34890eab73835a2c2079c3850a25be575623"}, + {file = "flake8_raise-0.0.5-py3-none-any.whl", hash = "sha256:df26e5c542a58c8f8786d978e18ad7e54126a0ef5c6241c35dafaca7e2bbb808"}, +] +flake8-return = [ + {file = "flake8-return-1.1.3.tar.gz", hash = "sha256:13a31edeb0c6157dd4f77166cdaa6141703d2b8b24def5558ae659852a003cb4"}, + {file = "flake8_return-1.1.3-py3-none-any.whl", hash = "sha256:4a266191f7ed69aa26b835ec90c5a5522fa8f79f5cf6363a877ac499f8eb418b"}, +] +flake8-scrapy = [ + {file = "flake8-scrapy-0.0.1.tar.gz", hash = "sha256:3757080162c2f464d7deb422ff76530bcb577665b16772d795f79a0b6a79c807"}, + {file = "flake8_scrapy-0.0.1-py3-none-any.whl", hash = "sha256:b33bdec20ac560f80808abb1256cf686a0302e4b9f5adad340377063564ad841"}, +] +flake8-simplify = [ + {file = "flake8_simplify-0.14.2-py3-none-any.whl", hash = "sha256:6584f3d49350659caaf2a42129f820dc64e60d4bdcb316f621b4e1cfae27e33a"}, + {file = "flake8_simplify-0.14.2.tar.gz", hash = "sha256:4a8f103607195c3d0743a2fd8beeebe24926e19fb3e24521042cfc35771a8d4d"}, +] +flake8-sql = [ + {file = "flake8-SQL-0.4.1.tar.gz", hash = "sha256:a8cdd689a5549c6ec73b4478aae152d5e3199270d23a371653f260f7a0e9dedd"}, + {file = "flake8_SQL-0.4.1-py2.py3-none-any.whl", hash = "sha256:25cd0485ba5feb5b1abfdd0c5b607e014300bcc3fa2a416a18cf62ecdbaaea96"}, +] +flake8-strftime = [ + {file = "flake8_strftime-0.3.2-py3-none-any.whl", hash = "sha256:39e64d9635c18a367526e02c2d3db06664dd00eccc78ebc16ebe57dcc9b7d355"}, + {file = "flake8_strftime-0.3.2.tar.gz", hash = "sha256:81a6ab503a0958d2b0c8476b108afb1baf0a82ead3bdab167e511205331aa28f"}, +] +flake8-todos = [ + {file = "flake8-todos-0.1.5.tar.gz", hash = "sha256:8541033429e7d0c3271104bfd5f74bfa81e07b76b0667cf8b2cd830419638e0d"}, + {file = "flake8_todos-0.1.5-py3-none-any.whl", hash = "sha256:19a37b521caedb00619c357279d8dc05807ea7a1c02f15cd0475752efc96f9a1"}, +] +flake8-tuple = [ + {file = "flake8_tuple-0.4.1-py2.py3-none-any.whl", hash = "sha256:d828cc8e461c50cacca116e9abb0c9e3be565e8451d3f5c00578c63670aae680"}, + {file = "flake8_tuple-0.4.1.tar.gz", hash = "sha256:8a1b42aab134ef4c3fef13c6a8f383363f158b19fbc165bd91aed9c51851a61d"}, +] +flake8-typing-imports = [ + {file = "flake8_typing_imports-1.11.0-py2.py3-none-any.whl", hash = "sha256:65ac067a41a68fd5e23fcbe75eab2179f53693f5f68eb9052dd7cc87b7d3b358"}, + {file = "flake8_typing_imports-1.11.0.tar.gz", hash = "sha256:337b8be2fe28467143cbd86619906ce4c8bbdf9018866cbbd854b6c3c65e2582"}, +] +flake8-unused-arguments = [ + {file = "flake8-unused-arguments-0.0.6.tar.gz", hash = "sha256:1134b19e9be5b8a608b5097f65ab81b2d029509e4dbf1c093ecc5d449fbba0cc"}, + {file = "flake8_unused_arguments-0.0.6-py3-none-any.whl", hash = "sha256:5e71dac90cdf3476aabe5d56f791957ce4e075cbda9b10f94c3000168b5f637c"}, +] +flake8-use-fstring = [ + {file = "flake8-use-fstring-1.3.tar.gz", hash = "sha256:1bd4a409adbb93e64e711fdd26b88759c33792e3899f174edc68ddf7307e81b6"}, +] +flake8-use-pathlib = [ + {file = "flake8-use-pathlib-0.2.0.tar.gz", hash = "sha256:fe178e060f2185afc6e71adaa19598e0dc90e65bb09b1ab9b729673dc4e8d7cc"}, + {file = "flake8_use_pathlib-0.2.0-py3-none-any.whl", hash = "sha256:7aabe903482e90aae671e28a81525affb8c3d4ab3453ccf8f05fbc9fdd70b7f4"}, +] +flake8-variables-names = [ + {file = "flake8_variables_names-0.0.4.tar.gz", hash = "sha256:d6fa0571a807c72940b5773827c5760421ea6f8206595ff0a8ecfa01e42bf2cf"}, +] +gitdb = [ + {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, + {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, +] +gitpython = [ + {file = "GitPython-3.1.24-py3-none-any.whl", hash = "sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647"}, + {file = "GitPython-3.1.24.tar.gz", hash = "sha256:df83fdf5e684fef7c6ee2c02fc68a5ceb7e7e759d08b694088d0cacb4eba59e5"}, +] +idna = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +importlib-metadata = [ + {file = "importlib_metadata-4.8.2-py3-none-any.whl", hash = "sha256:53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100"}, + {file = "importlib_metadata-4.8.2.tar.gz", hash = "sha256:75bdec14c397f528724c1bfd9709d660b33a4d2e77387a3358f20b848bb5e5fb"}, +] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +isort = [ + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, +] +jmespath = [ + {file = "jmespath-0.10.0-py2.py3-none-any.whl", hash = "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f"}, + {file = "jmespath-0.10.0.tar.gz", hash = "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"}, +] +mccabe = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] +more-itertools = [ + {file = "more-itertools-8.11.0.tar.gz", hash = "sha256:0a2fd25d343c08d7e7212071820e7e7ea2f41d8fb45d6bc8a00cd6ce3b7aab88"}, + {file = "more_itertools-8.11.0-py3-none-any.whl", hash = "sha256:88afff98d83d08fe5e4049b81e2b54c06ebb6b3871a600040865c7a592061cbb"}, +] +mr-proper = [ + {file = "mr_proper-0.0.7-py3-none-any.whl", hash = "sha256:74a1b60240c46f10ba518707ef72811a01e5c270da0a78b5dd2dd923d99fdb14"}, + {file = "mr_proper-0.0.7.tar.gz", hash = "sha256:03b517b19e617537f711ce418b125e5f2efd82ec881539cdee83195c78c14a02"}, +] +mypy = [ + {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"}, + {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"}, + {file = "mypy-0.910-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9"}, + {file = "mypy-0.910-cp35-cp35m-win_amd64.whl", hash = "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e"}, + {file = "mypy-0.910-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921"}, + {file = "mypy-0.910-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6"}, + {file = "mypy-0.910-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212"}, + {file = "mypy-0.910-cp36-cp36m-win_amd64.whl", hash = "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885"}, + {file = "mypy-0.910-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0"}, + {file = "mypy-0.910-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de"}, + {file = "mypy-0.910-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703"}, + {file = "mypy-0.910-cp37-cp37m-win_amd64.whl", hash = "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a"}, + {file = "mypy-0.910-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504"}, + {file = "mypy-0.910-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9"}, + {file = "mypy-0.910-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072"}, + {file = "mypy-0.910-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811"}, + {file = "mypy-0.910-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e"}, + {file = "mypy-0.910-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b"}, + {file = "mypy-0.910-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2"}, + {file = "mypy-0.910-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97"}, + {file = "mypy-0.910-cp39-cp39-win_amd64.whl", hash = "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8"}, + {file = "mypy-0.910-py3-none-any.whl", hash = "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"}, + {file = "mypy-0.910.tar.gz", hash = "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150"}, +] +mypy-boto3-accessanalyzer = [ + {file = "mypy-boto3-accessanalyzer-1.20.1.tar.gz", hash = "sha256:646f95a38586a8d17c4253859f30897141869e4eab65d3790c8fe1bb581aee64"}, + {file = "mypy_boto3_accessanalyzer-1.20.1-py3-none-any.whl", hash = "sha256:31656fa0f3876af071f7eabf99218ee6f3c40deab57d241136b3764273fc1aaf"}, +] +mypy-boto3-account = [ + {file = "mypy-boto3-account-1.20.1.tar.gz", hash = "sha256:611e8a99e1638ba6dab17a39bd5364061ac257aea2751ec8e5de076facd1ac70"}, + {file = "mypy_boto3_account-1.20.1-py3-none-any.whl", hash = "sha256:1b6a739cfe74f3df43206b5de019850a744fa0959511257051df995420d2a3ac"}, +] +mypy-boto3-acm = [ + {file = "mypy-boto3-acm-1.20.1.tar.gz", hash = "sha256:05aaf0801f6ce0b0966be9e3f297607f3e499595e4be88b1f42b47463818548d"}, + {file = "mypy_boto3_acm-1.20.1-py3-none-any.whl", hash = "sha256:13dbba7b9ccd1727bf5b8191b5298fe818a4568643170a5f47d0530ffdfaec84"}, +] +mypy-boto3-acm-pca = [ + {file = "mypy-boto3-acm-pca-1.20.1.tar.gz", hash = "sha256:ddc24c6ae087dcd3dbbd7aa5bdb24d426ae3ae5427046913dac84b6378c3aa94"}, + {file = "mypy_boto3_acm_pca-1.20.1-py3-none-any.whl", hash = "sha256:ab95644ffa2a4b966e1855deac23b56d4ffb7db43619debd97bf4e372d8fb2ad"}, +] +mypy-boto3-alexaforbusiness = [ + {file = "mypy-boto3-alexaforbusiness-1.20.1.tar.gz", hash = "sha256:2b71a8769ee25651ec536b2e5460b54e4636877ea1aa5ae146112f58a732de2a"}, + {file = "mypy_boto3_alexaforbusiness-1.20.1-py3-none-any.whl", hash = "sha256:4e6dc94ca7daf2a471a4b6491797fc5900b195dc1efc9990151abfa06d4e5e6b"}, +] +mypy-boto3-amp = [ + {file = "mypy-boto3-amp-1.20.1.tar.gz", hash = "sha256:f387cbe8b741240047f3a29f1f8aff511b6f281debd116182f6131adf96b672c"}, + {file = "mypy_boto3_amp-1.20.1-py3-none-any.whl", hash = "sha256:eb21e13e539791f19b309cf95dab577665ece1181acef26711053a734c7ea525"}, +] +mypy-boto3-amplify = [ + {file = "mypy-boto3-amplify-1.20.1.tar.gz", hash = "sha256:ba4700419924cf5fdb7e1d0a4c3194a77410682835982f670ca1314a61c9ad56"}, + {file = "mypy_boto3_amplify-1.20.1-py3-none-any.whl", hash = "sha256:45354093c122e22e3905ed9b1a835e58aa658d6943e4b4cd7369434f722b6a0c"}, +] +mypy-boto3-amplifybackend = [ + {file = "mypy-boto3-amplifybackend-1.20.1.tar.gz", hash = "sha256:636b2b8c3da1d6728db5fa23c3c8a29484ce514ff70a7a40d54c70b2bee7e4c0"}, + {file = "mypy_boto3_amplifybackend-1.20.1-py3-none-any.whl", hash = "sha256:aa4f978e623de0cd89c4ae5f9fe230173a7d9e33c20fc17d886e92289ef534a6"}, +] +mypy-boto3-apigateway = [ + {file = "mypy-boto3-apigateway-1.20.1.tar.gz", hash = "sha256:6bf1f49b63af78234f84430a6e891a07bf2198ee92d66482decaa16ca863edd2"}, + {file = "mypy_boto3_apigateway-1.20.1-py3-none-any.whl", hash = "sha256:ede7e54ac369a2baa535995209501414630a4b37e0134b4c69c574db9f7d6fd0"}, +] +mypy-boto3-apigatewaymanagementapi = [ + {file = "mypy-boto3-apigatewaymanagementapi-1.20.1.tar.gz", hash = "sha256:72572180f3ceeefd185f35e64940ce210e2dcfd00fd9346dffe9b44a3f2efae4"}, + {file = "mypy_boto3_apigatewaymanagementapi-1.20.1-py3-none-any.whl", hash = "sha256:dca27173f0a1e5e0306308548347341b550a671d7665767cdf76c01b81cb1f5e"}, +] +mypy-boto3-apigatewayv2 = [ + {file = "mypy-boto3-apigatewayv2-1.20.1.tar.gz", hash = "sha256:fbfcae0e529111dfdb79ae9d66743f9dc2f5ec3fe712d6d5f0e6f2465e37d5cb"}, + {file = "mypy_boto3_apigatewayv2-1.20.1-py3-none-any.whl", hash = "sha256:58be9057b8e3637325824e2f32049d4dd04c816802d570073561283cbde13f03"}, +] +mypy-boto3-appconfig = [ + {file = "mypy-boto3-appconfig-1.20.1.tar.gz", hash = "sha256:b3ff7714e985f9d844fb44cb1732b54d5d7be41d686ed873cb356f87ca254802"}, + {file = "mypy_boto3_appconfig-1.20.1-py3-none-any.whl", hash = "sha256:a47e20f23fe558b25a4a579b86d751ec2120faa40a9b3d56113866734640bb8c"}, +] +mypy-boto3-appflow = [ + {file = "mypy-boto3-appflow-1.20.1.tar.gz", hash = "sha256:f03ecc1ec32e4fe25bee55410549ea5967d84da8f5b90ed166251c104032337b"}, + {file = "mypy_boto3_appflow-1.20.1-py3-none-any.whl", hash = "sha256:9d06c640e9d9ecd59d82ebf2e96973283690c4498a39b9927bf10b8eee7f0cdb"}, +] +mypy-boto3-appintegrations = [ + {file = "mypy-boto3-appintegrations-1.20.1.tar.gz", hash = "sha256:3dbb9ea587418f8a9356409051ac02c088b3731389491a406b1fc0c3df25b9ae"}, + {file = "mypy_boto3_appintegrations-1.20.1-py3-none-any.whl", hash = "sha256:864a77062cbdfd41a297df80c94ea65faa28846e11df36c3f377eb6966e56486"}, +] +mypy-boto3-application-autoscaling = [ + {file = "mypy-boto3-application-autoscaling-1.20.1.tar.gz", hash = "sha256:0413dc0b2348f1bbc28301d5f6886e498888e62518e039a25678e2399f7500bc"}, + {file = "mypy_boto3_application_autoscaling-1.20.1-py3-none-any.whl", hash = "sha256:4052906cd01d87c066b472ec2ff9c870b6a6ff01bcb93ae8e35f94a5da467230"}, +] +mypy-boto3-application-insights = [ + {file = "mypy-boto3-application-insights-1.20.1.tar.gz", hash = "sha256:697c7b571d67edb496f0041f02889440bddae46a0de91ed99e3b355366073334"}, + {file = "mypy_boto3_application_insights-1.20.1-py3-none-any.whl", hash = "sha256:5b2ab28b696096f9a44b0d088b9dbda5d29e1c72d7a0f1d69792aa65ca122ef5"}, +] +mypy-boto3-applicationcostprofiler = [ + {file = "mypy-boto3-applicationcostprofiler-1.20.1.tar.gz", hash = "sha256:b8443df192805a56949efac0e177772a1023525d71fe3bfe4cfdc8e89f143621"}, + {file = "mypy_boto3_applicationcostprofiler-1.20.1-py3-none-any.whl", hash = "sha256:a790f2e693c1f6e0221a6323f2e299535ce956da0708735f86ffa36bdde05b86"}, +] +mypy-boto3-appmesh = [ + {file = "mypy-boto3-appmesh-1.20.1.tar.gz", hash = "sha256:b5ae34e18c33d0bde121f64b1fdc6a265437fc797ab8d6f9f4285da5d78f20f9"}, + {file = "mypy_boto3_appmesh-1.20.1-py3-none-any.whl", hash = "sha256:acee4f8c6e2ef72dec7c45fce51b0b55c12c5e9c71c89a2b55ac3f57f31a2c1e"}, +] +mypy-boto3-apprunner = [ + {file = "mypy-boto3-apprunner-1.20.1.tar.gz", hash = "sha256:7f41edf220fc5bd6d65949b862ae89a2ab6dae262849b202fb6c42d76d964cd1"}, + {file = "mypy_boto3_apprunner-1.20.1-py3-none-any.whl", hash = "sha256:8b451cf274b4dad92ef29511555bd1ccbeccdff2acdf8d479b529183fe688dab"}, +] +mypy-boto3-appstream = [ + {file = "mypy-boto3-appstream-1.20.1.tar.gz", hash = "sha256:abffad5bfcde7289e91869c9e5cd65fbd50096e7fa9c5eaa832cbbd5a41c168f"}, + {file = "mypy_boto3_appstream-1.20.1-py3-none-any.whl", hash = "sha256:5ba212111a38a0f6ac9281b1138c6647f6ab0ba8cbbc03737d902d3e0e99c6fd"}, +] +mypy-boto3-appsync = [ + {file = "mypy-boto3-appsync-1.20.1.tar.gz", hash = "sha256:8cefb3635c53bfbbbaee3b3eacd51df173446e38adc363c9b0359731ee8b2694"}, + {file = "mypy_boto3_appsync-1.20.1-py3-none-any.whl", hash = "sha256:4775d085aca452be7a53ddcc195fbc792cc803d786119c7507ca2a04c5c14e7a"}, +] +mypy-boto3-athena = [ + {file = "mypy-boto3-athena-1.20.1.tar.gz", hash = "sha256:747b7167a9656a7aebb0b8b2483f8521767489b42bc47017171c8d73fa699428"}, + {file = "mypy_boto3_athena-1.20.1-py3-none-any.whl", hash = "sha256:890a99a1f9c25b46c79ba9936aa3ed5fbd654cdfd02a1a82f221ee85a6f761ea"}, +] +mypy-boto3-auditmanager = [ + {file = "mypy-boto3-auditmanager-1.20.1.tar.gz", hash = "sha256:8c0823e12482c8bb95ac7c5fca63bc2811780bcefd067c4d4aa52387eb5ab989"}, + {file = "mypy_boto3_auditmanager-1.20.1-py3-none-any.whl", hash = "sha256:f8f98b7b503b49ba24ec868e6340d3d3259958a98e43859d67dd59ae36307e55"}, +] +mypy-boto3-autoscaling = [ + {file = "mypy-boto3-autoscaling-1.20.1.tar.gz", hash = "sha256:bd54230521676ed736264ff9f782016b8617453f121c755cc4b26befe5648b47"}, + {file = "mypy_boto3_autoscaling-1.20.1-py3-none-any.whl", hash = "sha256:63babec396e6d7d821a7537748580254ee11af4e49b4b2b2c6b2e8e52ca967e6"}, +] +mypy-boto3-autoscaling-plans = [ + {file = "mypy-boto3-autoscaling-plans-1.20.1.tar.gz", hash = "sha256:c29c508f92bc0ed1ea362d34697509cf3bb974a4657758ad814fdd7ecad9dfdd"}, + {file = "mypy_boto3_autoscaling_plans-1.20.1-py3-none-any.whl", hash = "sha256:b6110e49e2bf6e08927fb5932afcc0ad98fd0415fd263fadafae246d12b8e42c"}, +] +mypy-boto3-backup = [ + {file = "mypy-boto3-backup-1.20.1.tar.gz", hash = "sha256:c7a50e7894646768b1ed2b8f8d81a6cc90b5362d2ae1499973b91244890aa8cf"}, + {file = "mypy_boto3_backup-1.20.1-py3-none-any.whl", hash = "sha256:c3416022f701173c6e5e155f5d983ce35f5cc1d35be9793ba16bd09a84a0d465"}, +] +mypy-boto3-batch = [ + {file = "mypy-boto3-batch-1.20.2.tar.gz", hash = "sha256:86f3e122b33e63c2c7b2ffb178c7833b6f36f84c20620e71102db7c537108863"}, + {file = "mypy_boto3_batch-1.20.2-py3-none-any.whl", hash = "sha256:9305c539bb069b20731755a8c33012546a1194875914abb2ba7a59e5c7b6b6bb"}, +] +mypy-boto3-braket = [ + {file = "mypy-boto3-braket-1.20.1.tar.gz", hash = "sha256:c8ccd04acd92388b8a29fc74beb86833deac219ae9942dd5598ecf9aacdc70cb"}, + {file = "mypy_boto3_braket-1.20.1-py3-none-any.whl", hash = "sha256:9ba58bdeeee94af757f2592918ce615fc7a88b256c6919be4df0f22cb1c074c3"}, +] +mypy-boto3-budgets = [ + {file = "mypy-boto3-budgets-1.20.1.tar.gz", hash = "sha256:f7316a02649d386c2d354fe8b865206bbf31e42b0f3688afdc133fe72b45141d"}, + {file = "mypy_boto3_budgets-1.20.1-py3-none-any.whl", hash = "sha256:11f02e1fefabfd3ac5958fad05be553a304d1a75de109ad70899c1e54b6a6ae4"}, +] +mypy-boto3-ce = [ + {file = "mypy-boto3-ce-1.20.1.tar.gz", hash = "sha256:2b9ac0ef0fde37f999cb0df9bb8624e5a8a80aafde4bea15cd8b5fba14c31ced"}, + {file = "mypy_boto3_ce-1.20.1-py3-none-any.whl", hash = "sha256:46c5de361a4f1bc80e468473565aa55aa231601b15fcd4c97bad6a153992bb10"}, +] +mypy-boto3-chime = [ + {file = "mypy-boto3-chime-1.20.1.tar.gz", hash = "sha256:51f8bee55fc5907b5734a4790f23586a045e0bbc1b7a2d8975ba16f6e60f160a"}, + {file = "mypy_boto3_chime-1.20.1-py3-none-any.whl", hash = "sha256:ba95b4bf366946a4060a16023dc9f745643cee405711786709b899770375bf0c"}, +] +mypy-boto3-chime-sdk-identity = [ + {file = "mypy-boto3-chime-sdk-identity-1.20.1.tar.gz", hash = "sha256:b88b218bee646046a424e81cfd69fc5846aaa59e25dc5982aa90265759e18baf"}, + {file = "mypy_boto3_chime_sdk_identity-1.20.1-py3-none-any.whl", hash = "sha256:4ba3345c00ed6db96c02195586079ab78f93e1bf812d3b32225963c2c7111273"}, +] +mypy-boto3-chime-sdk-meetings = [ + {file = "mypy-boto3-chime-sdk-meetings-1.20.1.tar.gz", hash = "sha256:cd0eb6a034e5a81a723362c1b682aa38940e729982248652361ca65b6b3cb415"}, + {file = "mypy_boto3_chime_sdk_meetings-1.20.1-py3-none-any.whl", hash = "sha256:d922fa54272ccf28a6f12171f0de007181216e225e068268f04e43d4be8849e1"}, +] +mypy-boto3-chime-sdk-messaging = [ + {file = "mypy-boto3-chime-sdk-messaging-1.20.1.tar.gz", hash = "sha256:b65895e96f9f402fd7bcc4b120dfa1f2a32dfb405fbebc718d0af3690764ae2c"}, + {file = "mypy_boto3_chime_sdk_messaging-1.20.1-py3-none-any.whl", hash = "sha256:d7edc85762463982287d19d5121a49d00510fbcc8f639f037ee1bc18f6211f67"}, +] +mypy-boto3-cloud9 = [ + {file = "mypy-boto3-cloud9-1.20.1.tar.gz", hash = "sha256:7a874e2f84bf3923dd43679a94730da18761497e459c182442c2ec44c8a24619"}, + {file = "mypy_boto3_cloud9-1.20.1-py3-none-any.whl", hash = "sha256:c0bf96d638eb19d7da93d24975dd27a70d62c43858d0b58558f2864a5d58d9a0"}, +] +mypy-boto3-cloudcontrol = [ + {file = "mypy-boto3-cloudcontrol-1.20.1.tar.gz", hash = "sha256:d9b4863ac07c8967108695509f25ce1a98062483390e4479483ea648ea2d5a6d"}, + {file = "mypy_boto3_cloudcontrol-1.20.1-py3-none-any.whl", hash = "sha256:66ae048e63bab177a3821bfa29bffffedad28bededa9945087c0bb1af81f382d"}, +] +mypy-boto3-clouddirectory = [ + {file = "mypy-boto3-clouddirectory-1.20.1.tar.gz", hash = "sha256:6e120fa7a9ae1ed28ab601520e78d060e0a5ef14bd6995866a30d56b935c9f8b"}, + {file = "mypy_boto3_clouddirectory-1.20.1-py3-none-any.whl", hash = "sha256:fb4b0e6bfe791e047ddafffc78a4e6afe1bae16cd257f0c53909ab378c25dfef"}, +] +mypy-boto3-cloudformation = [ + {file = "mypy-boto3-cloudformation-1.20.1.tar.gz", hash = "sha256:9f7b0aa89c6f7a645c46ac89589462bcc2bbe61eecf706c1d444e1f80ee28b45"}, + {file = "mypy_boto3_cloudformation-1.20.1-py3-none-any.whl", hash = "sha256:023ea6701da97ff2e26db05456e29f0c33dddaedac97f66a2a773e7f82ba2595"}, +] +mypy-boto3-cloudfront = [ + {file = "mypy-boto3-cloudfront-1.20.1.tar.gz", hash = "sha256:01b2c65fa522c56bf15f540558d6a15465591a0b8848e417c877628c5299accd"}, + {file = "mypy_boto3_cloudfront-1.20.1-py3-none-any.whl", hash = "sha256:2f14aaa5e61309bfcc0601977ff4221a79972cc9e36ceb0f8bbc6fcb8de5bccc"}, +] +mypy-boto3-cloudhsm = [ + {file = "mypy-boto3-cloudhsm-1.20.1.tar.gz", hash = "sha256:ade511556cc3113c5e4f46f52f343ca7be58ef823aa3241b896f34c609430106"}, + {file = "mypy_boto3_cloudhsm-1.20.1-py3-none-any.whl", hash = "sha256:56214d0acce07e15a2d867d427339446cafa1c824b8bbf97cd60d2a1f7ba9460"}, +] +mypy-boto3-cloudhsmv2 = [ + {file = "mypy-boto3-cloudhsmv2-1.20.1.tar.gz", hash = "sha256:badd96e849f6d8ccff67a9f872abb0e3e44feee44cec24e05ddcd9859448d24b"}, + {file = "mypy_boto3_cloudhsmv2-1.20.1-py3-none-any.whl", hash = "sha256:e92d5d165467ded86003db54e61f1f930935bd2403d237f7e0f5694d45891326"}, +] +mypy-boto3-cloudsearch = [ + {file = "mypy-boto3-cloudsearch-1.20.1.tar.gz", hash = "sha256:412a38fbec033a05ecdf82af7bf92211eb222a78a6e681ff929e3a5e455124a4"}, + {file = "mypy_boto3_cloudsearch-1.20.1-py3-none-any.whl", hash = "sha256:c773316bfa489b0b49002b9c351cff942bc87965369628051af62832bb012867"}, +] +mypy-boto3-cloudsearchdomain = [ + {file = "mypy-boto3-cloudsearchdomain-1.20.1.tar.gz", hash = "sha256:257d0f9287b38beb8e72350fbbae21d47e99d6c68269fe9595cf43848b7faf22"}, + {file = "mypy_boto3_cloudsearchdomain-1.20.1-py3-none-any.whl", hash = "sha256:25804b26bca77c22cb7aadc33e494d150bb29f10af1d644bd2ac8880a4426e39"}, +] +mypy-boto3-cloudtrail = [ + {file = "mypy-boto3-cloudtrail-1.20.1.tar.gz", hash = "sha256:b3327cc447455e10c1c72cd03c57768ced0634aa52f5fb31f312a8e2347f7b00"}, + {file = "mypy_boto3_cloudtrail-1.20.1-py3-none-any.whl", hash = "sha256:650f474403501f45c84b5bf15748228d19aa2ff01281c1bd7ff6a295eb514741"}, +] +mypy-boto3-cloudwatch = [ + {file = "mypy-boto3-cloudwatch-1.20.1.tar.gz", hash = "sha256:b2e9bef9ebed026c54f8df1659b8d299307f486cfee4a39e2beda87107809c6d"}, + {file = "mypy_boto3_cloudwatch-1.20.1-py3-none-any.whl", hash = "sha256:2b7bcb8960ebde3bd6a61c3993093998d8cb6e2cd1bcfe8eed93ec95d1a11d07"}, +] +mypy-boto3-codeartifact = [ + {file = "mypy-boto3-codeartifact-1.20.1.tar.gz", hash = "sha256:46c0a974ca5ea7c991536f368cc871f0864f51fbe4fe0f82a173e3541c9cd607"}, + {file = "mypy_boto3_codeartifact-1.20.1-py3-none-any.whl", hash = "sha256:97df22c163fea06d1a7ff3b38fa72cc1d3418d8a610ce7ca8afddba813c89023"}, +] +mypy-boto3-codebuild = [ + {file = "mypy-boto3-codebuild-1.20.1.tar.gz", hash = "sha256:6f84fedf305d01e3e98f54fb1e473acf5f510b6ac8a54abf6aee5cdad216df69"}, + {file = "mypy_boto3_codebuild-1.20.1-py3-none-any.whl", hash = "sha256:6472d864ab297c293809f3485b03b2bd5cc652e468ce9fce76776270f29e045b"}, +] +mypy-boto3-codecommit = [ + {file = "mypy-boto3-codecommit-1.20.1.tar.gz", hash = "sha256:7eeecd330166f18fa0793359fa2a427da8a8efe924c00edada9a663f7ed74622"}, + {file = "mypy_boto3_codecommit-1.20.1-py3-none-any.whl", hash = "sha256:ba1b558b0beeda99df527112681528945400f8ec867c53d9d1ea37ce65d2ddca"}, +] +mypy-boto3-codedeploy = [ + {file = "mypy-boto3-codedeploy-1.20.1.tar.gz", hash = "sha256:1c071f20328dd5af26f8d6d8394af51b9ae90ac20035eb6051c1de43212257ab"}, + {file = "mypy_boto3_codedeploy-1.20.1-py3-none-any.whl", hash = "sha256:48cfbd7f7c4c6af014dc21d06fed1446179b142c05903dcdf2b44fbc7d15ffca"}, +] +mypy-boto3-codeguru-reviewer = [ + {file = "mypy-boto3-codeguru-reviewer-1.20.1.tar.gz", hash = "sha256:e35171615de4731ca30e0261213fd4dfcc69d98f215bb6ae43d4489860a82d7e"}, + {file = "mypy_boto3_codeguru_reviewer-1.20.1-py3-none-any.whl", hash = "sha256:b36fc61f8bd00c525be340f4103b371486a4792952ead0fdf68a5605419aa42a"}, +] +mypy-boto3-codeguruprofiler = [ + {file = "mypy-boto3-codeguruprofiler-1.20.1.tar.gz", hash = "sha256:9a238b367d93c0daef0c15b71a94600ec4856765906d221ffb521d1e5727457d"}, + {file = "mypy_boto3_codeguruprofiler-1.20.1-py3-none-any.whl", hash = "sha256:9df38c83aeb18825953279e5e2c3d5a7cfa7d984c4921c15b6eb55a5d99b2643"}, +] +mypy-boto3-codepipeline = [ + {file = "mypy-boto3-codepipeline-1.20.1.tar.gz", hash = "sha256:6b731cbc45c685c04705ee92d4b03bbc20cde9ef8c4db90c5b5fdc71c31d918c"}, + {file = "mypy_boto3_codepipeline-1.20.1-py3-none-any.whl", hash = "sha256:28be962c435fd6b973d2b5545ed282a95789470ec74a4569f36305639b774b5f"}, +] +mypy-boto3-codestar = [ + {file = "mypy-boto3-codestar-1.20.1.tar.gz", hash = "sha256:97a6a8471116ef317cc4e633167bce2ed6a36be935538bf3eecad6795f549e52"}, + {file = "mypy_boto3_codestar-1.20.1-py3-none-any.whl", hash = "sha256:c81654a79f573d1bd1a195adcb94f0b79708494f2762a3ea3162ecbfabbcfe34"}, +] +mypy-boto3-codestar-connections = [ + {file = "mypy-boto3-codestar-connections-1.20.1.tar.gz", hash = "sha256:24936872b17cf8e436c1ed1ff2aa77404f217a66ad0b7c5d7a0589e032c16211"}, + {file = "mypy_boto3_codestar_connections-1.20.1-py3-none-any.whl", hash = "sha256:0d91ab8fc397dcbf3ea7caa04e17406ff37be50f0b5d86dc764d4fbb064cee55"}, +] +mypy-boto3-codestar-notifications = [ + {file = "mypy-boto3-codestar-notifications-1.20.1.tar.gz", hash = "sha256:8218cfa72649b7482cde2015a450d3f38d703878adab16534f95edc3a384219e"}, + {file = "mypy_boto3_codestar_notifications-1.20.1-py3-none-any.whl", hash = "sha256:f1ad64ba37e3ed33a383099d2ceb7626deb9e70593f2ad5f8f2ff534f9309b29"}, +] +mypy-boto3-cognito-identity = [ + {file = "mypy-boto3-cognito-identity-1.20.1.tar.gz", hash = "sha256:be5fa3237fcf1494808df459eb0e26196c7b178aae2496f73c1a3bbb1d5c29ab"}, + {file = "mypy_boto3_cognito_identity-1.20.1-py3-none-any.whl", hash = "sha256:2d636ced82ccff0b565c07ca7e8aa745fa8e0ef36791758f40b06c8725e26404"}, +] +mypy-boto3-cognito-idp = [ + {file = "mypy-boto3-cognito-idp-1.20.1.tar.gz", hash = "sha256:102171f63db717f75111ba9308f36e4d292b46bdf2039a4dc69e85bba2be5620"}, + {file = "mypy_boto3_cognito_idp-1.20.1-py3-none-any.whl", hash = "sha256:b4f06c6733a4b9b60f1f097e644ab7aaf5b6807dc551da428289aaae119f636e"}, +] +mypy-boto3-cognito-sync = [ + {file = "mypy-boto3-cognito-sync-1.20.1.tar.gz", hash = "sha256:1a463b554250a0dad1bb226958e027e1dadaa9387c089a07517cd0a796887cc1"}, + {file = "mypy_boto3_cognito_sync-1.20.1-py3-none-any.whl", hash = "sha256:13593a7248978e6842cc41c947c275ff4738bddba43788b7c9459ffab61f1077"}, +] +mypy-boto3-comprehend = [ + {file = "mypy-boto3-comprehend-1.20.1.tar.gz", hash = "sha256:6cc5447a861cf1e26d515f1a506271ad6b3dd48489dc75836be3af17c1b622f1"}, + {file = "mypy_boto3_comprehend-1.20.1-py3-none-any.whl", hash = "sha256:16e4fd9db16f60d70abfdec7b5d7c535073e011a7986f2836ec8692e0e537dbb"}, +] +mypy-boto3-comprehendmedical = [ + {file = "mypy-boto3-comprehendmedical-1.20.1.tar.gz", hash = "sha256:7bf6a8fcc01bd2b1ef881eb92449f20982597fa67ed625e3193d69d9fe7c7cde"}, + {file = "mypy_boto3_comprehendmedical-1.20.1-py3-none-any.whl", hash = "sha256:0bc9204c37c977c5b3d68a581f6107dd5c15043b714d557b2e9b8a4be763578c"}, +] +mypy-boto3-compute-optimizer = [ + {file = "mypy-boto3-compute-optimizer-1.20.1.tar.gz", hash = "sha256:b5a3a73fe8b65c16847cc051a7043a5b830d5fbfc3559ce6d25fedd7968a7af1"}, + {file = "mypy_boto3_compute_optimizer-1.20.1-py3-none-any.whl", hash = "sha256:f3eef02fc822ec737e2fe8fc394b2cae92abb75814cd0a6af05e0d84e9635c68"}, +] +mypy-boto3-config = [ + {file = "mypy-boto3-config-1.20.1.tar.gz", hash = "sha256:7ca4ad191d303185f2a261034ef45df6cb253d17eb700c0b522f9a3835fdd33f"}, + {file = "mypy_boto3_config-1.20.1-py3-none-any.whl", hash = "sha256:5d642abd8293d3ca081f2177f1409ff0f7a8850a52e55c858892176c741f43fb"}, +] +mypy-boto3-connect = [ + {file = "mypy-boto3-connect-1.20.1.tar.gz", hash = "sha256:eb51c24386609c58adcaccd2eb1200a663bae16c7852b0baab680c4803cdf834"}, + {file = "mypy_boto3_connect-1.20.1-py3-none-any.whl", hash = "sha256:26eae34107e842aa70f94110e9c294566a5820d84d718924f9bfde5b07ff1f37"}, +] +mypy-boto3-connect-contact-lens = [ + {file = "mypy-boto3-connect-contact-lens-1.20.1.tar.gz", hash = "sha256:c04df80e93ba63f12d34d40adaa76c24b25c68271cb052d47140fceebf77b14f"}, + {file = "mypy_boto3_connect_contact_lens-1.20.1-py3-none-any.whl", hash = "sha256:db28360fdac02a85523a5b7ff525f4ed96f3a6a623f1a780cfc11fe3f2ba9aad"}, +] +mypy-boto3-connectparticipant = [ + {file = "mypy-boto3-connectparticipant-1.20.1.tar.gz", hash = "sha256:1e69c58b3a52c68a382b9337742f13cd8c23a3fc283d765ce8e00bbbe620db24"}, + {file = "mypy_boto3_connectparticipant-1.20.1-py3-none-any.whl", hash = "sha256:1b831ad2c02730888abb6aa7b070e227761c61cbb4ced3e2c4b934ca7569fc02"}, +] +mypy-boto3-cur = [ + {file = "mypy-boto3-cur-1.20.1.tar.gz", hash = "sha256:ca3c57e0857a059b8bbc780e8949109120af9d7405a01137ef9da9d10a843de4"}, + {file = "mypy_boto3_cur-1.20.1-py3-none-any.whl", hash = "sha256:659525122936e00d9d122e064d728c83e9f01c15940ea4ba677fff78fe4f4357"}, +] +mypy-boto3-customer-profiles = [ + {file = "mypy-boto3-customer-profiles-1.20.1.tar.gz", hash = "sha256:66468e296fe72772696352fad458bdebb56ed1889f5a225e9eb9a152623bd814"}, + {file = "mypy_boto3_customer_profiles-1.20.1-py3-none-any.whl", hash = "sha256:bf368a7986bb89f94f89a213c70780dd1df59e522909622d4a86ea4a926d154c"}, +] +mypy-boto3-databrew = [ + {file = "mypy-boto3-databrew-1.20.1.tar.gz", hash = "sha256:d67172f8b36bed6934331563c16b07f6c53316aa216f74faea5e109a5c9d92cb"}, + {file = "mypy_boto3_databrew-1.20.1-py3-none-any.whl", hash = "sha256:7f34dbc7db1d62100158c62ac1efe073eb982b997a9f19760ad21160f65299fa"}, +] +mypy-boto3-dataexchange = [ + {file = "mypy-boto3-dataexchange-1.20.1.tar.gz", hash = "sha256:015470cee97decacdb8bd2f6a32a0a47b9c43a70914e054103887c1eaea6c713"}, + {file = "mypy_boto3_dataexchange-1.20.1-py3-none-any.whl", hash = "sha256:e9c7dbf37bcf6e5d7fa6e09839f8e04a20f13fab8d452745334ef4d285c8739c"}, +] +mypy-boto3-datapipeline = [ + {file = "mypy-boto3-datapipeline-1.20.1.tar.gz", hash = "sha256:2874a7f6208a878c97f6035a5948df0b7f2a45410c683434919f1323cd88d4a2"}, + {file = "mypy_boto3_datapipeline-1.20.1-py3-none-any.whl", hash = "sha256:2725bb98f03907155d09006b1c2cc55717f176f817fe14663682d5bb7bff5262"}, +] +mypy-boto3-datasync = [ + {file = "mypy-boto3-datasync-1.20.1.tar.gz", hash = "sha256:5c324c4f922d1b730805b73f17b968555a3cdb7946b2d1ed63e259be3d5d7199"}, + {file = "mypy_boto3_datasync-1.20.1-py3-none-any.whl", hash = "sha256:70bc974889a7e3e087469be2447cb785cf8f6bd6fed99ca2451722b937edbc8f"}, +] +mypy-boto3-dax = [ + {file = "mypy-boto3-dax-1.20.1.tar.gz", hash = "sha256:82551deb2ef9769c3417d0804647895990ce4837497d36366c00e063f45a8e58"}, + {file = "mypy_boto3_dax-1.20.1-py3-none-any.whl", hash = "sha256:bf95d52f73dc7a35c22e60f4dfec105cd01c68d1b7b35d54271a2caabe601c09"}, +] +mypy-boto3-detective = [ + {file = "mypy-boto3-detective-1.20.1.tar.gz", hash = "sha256:cd9eececff786495f099fd7830ab33448e7d08d2ee3fd5f0929016d47df52a8d"}, + {file = "mypy_boto3_detective-1.20.1-py3-none-any.whl", hash = "sha256:2bd53a5423cd0421aa26e287c144e808ed495cc2710c34452a7e8e2583167970"}, +] +mypy-boto3-devicefarm = [ + {file = "mypy-boto3-devicefarm-1.20.1.tar.gz", hash = "sha256:0486f5c8ddcdf99b085ad76b6863e3b5621e9214664e042412ee0c65d9370979"}, + {file = "mypy_boto3_devicefarm-1.20.1-py3-none-any.whl", hash = "sha256:b7ba9bdda3565113a6a3393c2eb6dbbf2c394c41b4f1e7b4115ff9f5b935015a"}, +] +mypy-boto3-devops-guru = [ + {file = "mypy-boto3-devops-guru-1.20.1.tar.gz", hash = "sha256:bada7a215baf034a800e5efe3d3612af7c0ce40604dcbbecdaf6d099a7a85cab"}, + {file = "mypy_boto3_devops_guru-1.20.1-py3-none-any.whl", hash = "sha256:17121250e7098929ccc21f4b822b2899e0b745a3670ffcf3ac9631a403243055"}, +] +mypy-boto3-directconnect = [ + {file = "mypy-boto3-directconnect-1.20.1.tar.gz", hash = "sha256:078566fdc289b40e30a671699e0818e6c5d70dc926a5272f2bcd3fd1eebaea24"}, + {file = "mypy_boto3_directconnect-1.20.1-py3-none-any.whl", hash = "sha256:d9c3f4e5ed8682786aded8c7086353df1c174b7613f8e94115c38cf216385874"}, +] +mypy-boto3-discovery = [ + {file = "mypy-boto3-discovery-1.20.1.tar.gz", hash = "sha256:155eac55e97a9101a024d64c35e9413ae64b9a40fbf2e1a975715d7367f7ff5d"}, + {file = "mypy_boto3_discovery-1.20.1-py3-none-any.whl", hash = "sha256:36f4697d6ec74c609275ab6270ea9b4b9589ac4423478bee651675510a1e6857"}, +] +mypy-boto3-dlm = [ + {file = "mypy-boto3-dlm-1.20.1.tar.gz", hash = "sha256:769b07f00e8ce7569cc75436239ae2adc755e81dd988ef649e7ef0923bc52261"}, + {file = "mypy_boto3_dlm-1.20.1-py3-none-any.whl", hash = "sha256:c4276a3d5b916f8e4c239b9dc6c31ba65c4611fc2d96571ac50dd53379c07739"}, +] +mypy-boto3-dms = [ + {file = "mypy-boto3-dms-1.20.1.tar.gz", hash = "sha256:ce58284ebdce3dc24af8a7281d8b1454af7f9ea99bc710fc95b3a98a74a1795a"}, + {file = "mypy_boto3_dms-1.20.1-py3-none-any.whl", hash = "sha256:86e47bc61ea7ae0051a53ef16fb21b73dc50aa19a16f0b5dddc1ae0d27b87431"}, +] +mypy-boto3-docdb = [ + {file = "mypy-boto3-docdb-1.20.1.tar.gz", hash = "sha256:8f0e894de5600c205e3655b4698469fdbf4b4c4725de97e6632df17294688936"}, + {file = "mypy_boto3_docdb-1.20.1-py3-none-any.whl", hash = "sha256:0f189f38f4391b69987bd2e525c1601037ad1d0010a101a90bbb62910dc422eb"}, +] +mypy-boto3-ds = [ + {file = "mypy-boto3-ds-1.20.1.tar.gz", hash = "sha256:8a215b904e1dc2fca25e8b9902ae6013be143486d9033cf3112b052ae5119131"}, + {file = "mypy_boto3_ds-1.20.1-py3-none-any.whl", hash = "sha256:ebe5645da27579eeb8666817039fd15e937cf943ab70d75db2163b7649c9e180"}, +] +mypy-boto3-dynamodb = [ + {file = "mypy-boto3-dynamodb-1.20.1.tar.gz", hash = "sha256:77b4271254fb2a98766b4e0657714511fb7bf03bed1d69599ef7e3cfe4cac5d3"}, + {file = "mypy_boto3_dynamodb-1.20.1-py3-none-any.whl", hash = "sha256:95588f4650f32488ff6a081c6b555bdecea0efd558068d11a26969e71ea83913"}, +] +mypy-boto3-dynamodbstreams = [ + {file = "mypy-boto3-dynamodbstreams-1.20.1.tar.gz", hash = "sha256:819abc44725ad02be5c7fec73a3723b39bf84d713c19593d91a923f1cf946054"}, + {file = "mypy_boto3_dynamodbstreams-1.20.1-py3-none-any.whl", hash = "sha256:940d8bd506632ef1fcced5303d243b55379a3d6a28bcabcc19bb9e4106de30c8"}, +] +mypy-boto3-ebs = [ + {file = "mypy-boto3-ebs-1.20.1.tar.gz", hash = "sha256:3b477c268eb24a82f547c4df6859b3f4697d98c1f932a6f0bb65db78e41ad12f"}, + {file = "mypy_boto3_ebs-1.20.1-py3-none-any.whl", hash = "sha256:4ee35353f67fece81291673b2a982fb6507c153c692643b48d7f7e15c3bdc55c"}, +] +mypy-boto3-ec2 = [ + {file = "mypy-boto3-ec2-1.20.1.tar.gz", hash = "sha256:07af70f4f0abc78a326a08e4bacd78dcc2d71fb367e3409e878af880a57d3f0d"}, + {file = "mypy_boto3_ec2-1.20.1-py3-none-any.whl", hash = "sha256:26156d0fbced5017bc7b4d593ce3da824f9444b2cca4907e520585c187916c73"}, +] +mypy-boto3-ec2-instance-connect = [ + {file = "mypy-boto3-ec2-instance-connect-1.20.1.tar.gz", hash = "sha256:e09e0a93ab476758c5f02f112eba23347c105e1a68feb622eda440b0dbd03b7c"}, + {file = "mypy_boto3_ec2_instance_connect-1.20.1-py3-none-any.whl", hash = "sha256:63a12a70c2273a7ef47f3f29bd246fdd743f8c6f8ab78579c599841b098cf971"}, +] +mypy-boto3-ecr = [ + {file = "mypy-boto3-ecr-1.20.1.tar.gz", hash = "sha256:87d24d8ee7600c6baf4b02c4cf4e34de39713b2b7e3fd59abda708ba72bc0397"}, + {file = "mypy_boto3_ecr-1.20.1-py3-none-any.whl", hash = "sha256:012bc549f8e679332de9bea4a07b33f64b7553a4cc320ee49e92ca15616eb5d2"}, +] +mypy-boto3-ecr-public = [ + {file = "mypy-boto3-ecr-public-1.20.1.tar.gz", hash = "sha256:03829f55784e6c749f95611f5b9e68d5afc5a451089931bae753522d27d6cf93"}, + {file = "mypy_boto3_ecr_public-1.20.1-py3-none-any.whl", hash = "sha256:d4be5897563dcec316ae3a8e468fbbb816c68431b3f755e7ef0e112635573f91"}, +] +mypy-boto3-ecs = [ + {file = "mypy-boto3-ecs-1.20.1.tar.gz", hash = "sha256:40f29cb51432c32ecb24f820d4dbc32d98d9ecdd1cd074717052c331c6efba76"}, + {file = "mypy_boto3_ecs-1.20.1-py3-none-any.whl", hash = "sha256:9fa500b287abd2f8ea9796b2f50f9f5f13fdeae9c4462629ce2694589fd6ccf0"}, +] +mypy-boto3-efs = [ + {file = "mypy-boto3-efs-1.20.1.tar.gz", hash = "sha256:5947930d5721c7d0c5a188f9f88cef3623b5c63155472aa8516eb08837b529f6"}, + {file = "mypy_boto3_efs-1.20.1-py3-none-any.whl", hash = "sha256:a026d95a67450ef3b4f03d798b0d5c4e268726e08a28a93054d30b27fe34f80b"}, +] +mypy-boto3-eks = [ + {file = "mypy-boto3-eks-1.20.1.tar.gz", hash = "sha256:dabe42d69289f13848b4c4a1aebd6ed98d23f8bb747a4123cc45b0fec675c9c6"}, + {file = "mypy_boto3_eks-1.20.1-py3-none-any.whl", hash = "sha256:313dce73124a6f9087e34141071529587c281331d64ffe12b3f3ff24d03adf61"}, +] +mypy-boto3-elastic-inference = [ + {file = "mypy-boto3-elastic-inference-1.20.1.tar.gz", hash = "sha256:203e8c718b62c581d87d751d03fcecfc1bc0ad7233b5adf0cb1c179342d4bb7a"}, + {file = "mypy_boto3_elastic_inference-1.20.1-py3-none-any.whl", hash = "sha256:7f276a45b3129dbe0cac75fec717f69544ce79b211ecf8a5c8be569377f6e2ac"}, +] +mypy-boto3-elasticache = [ + {file = "mypy-boto3-elasticache-1.20.1.tar.gz", hash = "sha256:1d4fccc8cdee90b1e7d1f7103d8f2ebaf441398455ca7d0ff6435665de68bb59"}, + {file = "mypy_boto3_elasticache-1.20.1-py3-none-any.whl", hash = "sha256:a908a170da42b25dbb469a1c87d4ce6d521becebc414feb98ad17808bef92823"}, +] +mypy-boto3-elasticbeanstalk = [ + {file = "mypy-boto3-elasticbeanstalk-1.20.1.tar.gz", hash = "sha256:3306bd514919f65f4fbeeff79e3004d1fdef1693a28ef766d9e713a97aacda61"}, + {file = "mypy_boto3_elasticbeanstalk-1.20.1-py3-none-any.whl", hash = "sha256:69be8be5b0ae0592b54f43cea9aea9aa49b5fa7a8668c88188f389d35176c286"}, +] +mypy-boto3-elastictranscoder = [ + {file = "mypy-boto3-elastictranscoder-1.20.1.tar.gz", hash = "sha256:11cc40fea1eac3e397453743b5358e56338f922e74d79560d94f21ac6fed1ca8"}, + {file = "mypy_boto3_elastictranscoder-1.20.1-py3-none-any.whl", hash = "sha256:17b6261869cac8d08dd76903f151f44cda537374f740177966a7fe9594aaad99"}, +] +mypy-boto3-elb = [ + {file = "mypy-boto3-elb-1.20.1.tar.gz", hash = "sha256:a353fa01978e0f740673352b48fdca103692266f6e32a6f2bd1f00b1f45d2a4f"}, + {file = "mypy_boto3_elb-1.20.1-py3-none-any.whl", hash = "sha256:9788c342147a01acd0aa2f1f0bf2a91d71e51a9fd77df2cb2e1de4836e84fb86"}, +] +mypy-boto3-elbv2 = [ + {file = "mypy-boto3-elbv2-1.20.1.tar.gz", hash = "sha256:b14dc362d845c2b4d4b2bdb4fa650f6cf4e31303657cea4ff6046492f582a3fa"}, + {file = "mypy_boto3_elbv2-1.20.1-py3-none-any.whl", hash = "sha256:8bc79af33c569f64ad9588a0b1416b35a311a7e05a3fa7d89ac02a2bbf38cd11"}, +] +mypy-boto3-emr = [ + {file = "mypy-boto3-emr-1.20.1.tar.gz", hash = "sha256:20ff48769291e49945b655253c4c0d2f39a1106c362129ed3148f4d20f262249"}, + {file = "mypy_boto3_emr-1.20.1-py3-none-any.whl", hash = "sha256:5407403cf404763a93e82cc3b71134c1a93ceed98ffa6f70df4ee3b9bdd5da52"}, +] +mypy-boto3-emr-containers = [ + {file = "mypy-boto3-emr-containers-1.20.1.tar.gz", hash = "sha256:1ae268e910ea90050bb3215a303c543f7bef231a3ed5d181ea9dd385f65b51cb"}, + {file = "mypy_boto3_emr_containers-1.20.1-py3-none-any.whl", hash = "sha256:5372cce246bdf10e747b299a1d293b8bac7afdc4eed80cc57847408da8336300"}, +] +mypy-boto3-es = [ + {file = "mypy-boto3-es-1.20.1.tar.gz", hash = "sha256:56c9ab212c3c34709d639d550d39da25f666d24fc49a9ac8ada59911b9917688"}, + {file = "mypy_boto3_es-1.20.1-py3-none-any.whl", hash = "sha256:0b6706f891554a1a4d8d35a976a4c16acbd9d51c9f3dbedd033d47a39ad89a08"}, +] +mypy-boto3-events = [ + {file = "mypy-boto3-events-1.20.1.tar.gz", hash = "sha256:00404cf50f2d1edae472aa5a23be0d84ca8d3cc9f7e1beff2fb28d31737ba70d"}, + {file = "mypy_boto3_events-1.20.1-py3-none-any.whl", hash = "sha256:09cea9995432ca96177ee2e76090c1a4b964d77cc87c0c39c57a114ec4da4ac6"}, +] +mypy-boto3-finspace = [ + {file = "mypy-boto3-finspace-1.20.1.tar.gz", hash = "sha256:c4f5167e2d7588c55345d268b208e2e17906087f7f869278213d464935f5e784"}, + {file = "mypy_boto3_finspace-1.20.1-py3-none-any.whl", hash = "sha256:603d351e489f31dc795989475f5417265b55e61aa05b36d219e00113a36343d8"}, +] +mypy-boto3-finspace-data = [ + {file = "mypy-boto3-finspace-data-1.20.1.tar.gz", hash = "sha256:3a3dc7060d1727faad2dda19ad135e8d3821bb195293d0e72da42ede9de8b9a3"}, + {file = "mypy_boto3_finspace_data-1.20.1-py3-none-any.whl", hash = "sha256:e773ef112c2183a272e8266b2caa5d4b1ea8d8f24fa757fb26de0067df917d72"}, +] +mypy-boto3-firehose = [ + {file = "mypy-boto3-firehose-1.20.1.tar.gz", hash = "sha256:af1800d5a1c33762ba40e698928294d6860ec9a4864694741a2496e11c67ef03"}, + {file = "mypy_boto3_firehose-1.20.1-py3-none-any.whl", hash = "sha256:12d3adcd4717ba1df35d8842f4c16f7b5018d61af0c389d1aafc8770696d8acf"}, +] +mypy-boto3-fis = [ + {file = "mypy-boto3-fis-1.20.1.tar.gz", hash = "sha256:c32034f19b5dfd048dc6f06d6b032e73756a009481bed413fdf9bf01e69aa50b"}, + {file = "mypy_boto3_fis-1.20.1-py3-none-any.whl", hash = "sha256:4e6e0cc3960799a993a5cf7348af5d650e0d95e15fbb805619aa31c8c08ae0dc"}, +] +mypy-boto3-fms = [ + {file = "mypy-boto3-fms-1.20.1.tar.gz", hash = "sha256:259377c6c98a804fa0a32a169c537ba2625572aaa740088589c95307eac3ac74"}, + {file = "mypy_boto3_fms-1.20.1-py3-none-any.whl", hash = "sha256:f661106b018ec1f0530f2ccf0a4f4ada1427143c13aecc917f3b1b140aee5fc1"}, +] +mypy-boto3-forecast = [ + {file = "mypy-boto3-forecast-1.20.1.tar.gz", hash = "sha256:46ca536eb3f079ebc762a1649c52cc110706bd811159892be9ea77cc90ffd17d"}, + {file = "mypy_boto3_forecast-1.20.1-py3-none-any.whl", hash = "sha256:340f9fb0fe9b96a4156032c01f377d5d761d08e2ece680454f999e97932463c3"}, +] +mypy-boto3-forecastquery = [ + {file = "mypy-boto3-forecastquery-1.20.1.tar.gz", hash = "sha256:cbd900abab6f3edd8dc42cff9595375d94cfe02bd5ba651cb6bee7fe0bbcefa5"}, + {file = "mypy_boto3_forecastquery-1.20.1-py3-none-any.whl", hash = "sha256:2753c94e6b05cbf6707bf40efad37ec3228a8cb886bf07f301f4388d3853e56d"}, +] +mypy-boto3-frauddetector = [ + {file = "mypy-boto3-frauddetector-1.20.1.tar.gz", hash = "sha256:52f9938ea93bda9b5855625c4c1c1ed95d74bebadd5b53bcc52b6afdeb2dd377"}, + {file = "mypy_boto3_frauddetector-1.20.1-py3-none-any.whl", hash = "sha256:10245c46675785c1658c2f6e441b41616f58d38a3d8d843f6b9f89063e2bb500"}, +] +mypy-boto3-fsx = [ + {file = "mypy-boto3-fsx-1.20.1.tar.gz", hash = "sha256:efb4d2dc55353b501c0d04578fd69646892b21a51dce3e8032a20425ef554104"}, + {file = "mypy_boto3_fsx-1.20.1-py3-none-any.whl", hash = "sha256:cddfe43bf0456aa2b79d00607e24d4fefedda382867327404abfe8cdf73d4bdc"}, +] +mypy-boto3-gamelift = [ + {file = "mypy-boto3-gamelift-1.20.1.tar.gz", hash = "sha256:519ac6e654167892d8be97655e6dce4f4a4b8a44b7862b088df5a9f05772db7a"}, + {file = "mypy_boto3_gamelift-1.20.1-py3-none-any.whl", hash = "sha256:5a57d82f59628da16a214a0c1d58c3ce7feacc6ba8b3d79559d09208d74d1f9d"}, +] +mypy-boto3-glacier = [ + {file = "mypy-boto3-glacier-1.20.1.tar.gz", hash = "sha256:226762bc4bd4547e545422ac43ab94b437277574738948ecc6165a6bad87de3c"}, + {file = "mypy_boto3_glacier-1.20.1-py3-none-any.whl", hash = "sha256:774410f4dc7eb6439706952d823709333da1d1b1df211fe87caae54ee1c6e29a"}, +] +mypy-boto3-globalaccelerator = [ + {file = "mypy-boto3-globalaccelerator-1.20.1.tar.gz", hash = "sha256:fecb107440cc9adf08fc9234d6c5477114eec99659b7f7312933ae49c2dd4557"}, + {file = "mypy_boto3_globalaccelerator-1.20.1-py3-none-any.whl", hash = "sha256:239010655f9ffe4803289ecd235d1794814d13a3a236e95a88515bb1b68dee69"}, +] +mypy-boto3-glue = [ + {file = "mypy-boto3-glue-1.20.1.tar.gz", hash = "sha256:b33a9193d2ecf96fa66c75b051695838c35588bb33233dfd0ee9e95ce847aad4"}, + {file = "mypy_boto3_glue-1.20.1-py3-none-any.whl", hash = "sha256:a150ec2bd1a099609ec5fe414f0bedbfaa6f5083ca9e6f21cf3cc868bff7b991"}, +] +mypy-boto3-grafana = [ + {file = "mypy-boto3-grafana-1.20.1.tar.gz", hash = "sha256:629f89d5098863e3f451a2b6c06d9788c77d7c799572a31dfefc08a81924afa5"}, + {file = "mypy_boto3_grafana-1.20.1-py3-none-any.whl", hash = "sha256:704028f55b00a82b26375241725551f2c80930ff2a9165cef430a41bb8bdd9bd"}, +] +mypy-boto3-greengrass = [ + {file = "mypy-boto3-greengrass-1.20.1.tar.gz", hash = "sha256:2d4b2ba5f74700f835340db2a83f31b162a8957da28f74ef26f47a9148cedd87"}, + {file = "mypy_boto3_greengrass-1.20.1-py3-none-any.whl", hash = "sha256:4e2e59ae95cb259ae757cf48ac2900e9568ea17da8f54d06b6cb84aa73fb8533"}, +] +mypy-boto3-greengrassv2 = [ + {file = "mypy-boto3-greengrassv2-1.20.2.tar.gz", hash = "sha256:51e6d3b9e59e89ad4383992c9a78675dc309b30f52ae40da41a5c9a8e1ec4889"}, + {file = "mypy_boto3_greengrassv2-1.20.2-py3-none-any.whl", hash = "sha256:25f74612ba470f8cf1214c4d91496d15ba84fd530e9edb738736ece8c4b91e0f"}, +] +mypy-boto3-groundstation = [ + {file = "mypy-boto3-groundstation-1.20.1.tar.gz", hash = "sha256:270226758380fb74cede00ccf50572c822edb7509cd1e9cdb89a21db10e9115b"}, + {file = "mypy_boto3_groundstation-1.20.1-py3-none-any.whl", hash = "sha256:48ccbfa2e915034cd53303e65f70db14d68760a0ac726f7aedb87316cfb3b32a"}, +] +mypy-boto3-guardduty = [ + {file = "mypy-boto3-guardduty-1.20.1.tar.gz", hash = "sha256:2be97b5204243da145a9accb47464d0c17d7bb01d97f1331bf57d5a67d620bc5"}, + {file = "mypy_boto3_guardduty-1.20.1-py3-none-any.whl", hash = "sha256:dfba4bb04d8791e4ea554c2c63ba495c550fa85f3df7ca92015e80e04ace00bb"}, +] +mypy-boto3-health = [ + {file = "mypy-boto3-health-1.20.2.tar.gz", hash = "sha256:c83a4a7e3a5a806793a2025b603a6d72ad38f2d21f3664640a1395dde1bcb4d2"}, + {file = "mypy_boto3_health-1.20.2-py3-none-any.whl", hash = "sha256:e5f6b01ffa1059a7e3715444e959876ab35288df960e3cf8792104d5de487f54"}, +] +mypy-boto3-healthlake = [ + {file = "mypy-boto3-healthlake-1.20.1.tar.gz", hash = "sha256:2fb62c20a9159691c7862f789b5cb9753620128354a71c7f658a75679ec0b7a8"}, + {file = "mypy_boto3_healthlake-1.20.1-py3-none-any.whl", hash = "sha256:abc201d7fd618cbda7336dea82486a60b3f6087a26731652db01c07977f2d884"}, +] +mypy-boto3-honeycode = [ + {file = "mypy-boto3-honeycode-1.20.1.tar.gz", hash = "sha256:e61f18efe282862ec0630978d2d4e073c0c913a5624bb913fd36af5062e49cb8"}, + {file = "mypy_boto3_honeycode-1.20.1-py3-none-any.whl", hash = "sha256:fb45c996c7e1a34093e0f6b843ebd6abd9d5910d90d5eb9bb0bb574119520882"}, +] +mypy-boto3-iam = [ + {file = "mypy-boto3-iam-1.20.1.tar.gz", hash = "sha256:b675ae01a6c38bf6e18c5e4101b1b848a4d91a9598ec191b404ce70197590427"}, + {file = "mypy_boto3_iam-1.20.1-py3-none-any.whl", hash = "sha256:8d8dbe1b3eb566931a059468c1c09625f35aa3bd5b8050f065a9a4d119a27712"}, +] +mypy-boto3-identitystore = [ + {file = "mypy-boto3-identitystore-1.20.1.tar.gz", hash = "sha256:cdf26a8ae847dd80270436b411ac0e22e61346fbe2aa2c61bfc68b80dc36ba8b"}, + {file = "mypy_boto3_identitystore-1.20.1-py3-none-any.whl", hash = "sha256:ec1cb9acedf879ff1f1adfa0debc884b075773614db1281d93e83847ff34e97c"}, +] +mypy-boto3-imagebuilder = [ + {file = "mypy-boto3-imagebuilder-1.20.1.tar.gz", hash = "sha256:a8d016aaaed010a767402a5b370afe68458505181e059ef0733ecb1d1c2b5ae0"}, + {file = "mypy_boto3_imagebuilder-1.20.1-py3-none-any.whl", hash = "sha256:cbf940bb9fa3c579ad23db862adc9d1d01548358fb4ea87e7d639adf7013922d"}, +] +mypy-boto3-importexport = [ + {file = "mypy-boto3-importexport-1.20.1.tar.gz", hash = "sha256:4b68419d434ebc3a41c062bce3da543ee671bfe9815f8c8f28247d83693a1611"}, + {file = "mypy_boto3_importexport-1.20.1-py3-none-any.whl", hash = "sha256:3ec2a2b2dc37f477c8dfba7d0e25babd601d3146b81bc26a65cb6e9a90914b45"}, +] +mypy-boto3-inspector = [ + {file = "mypy-boto3-inspector-1.20.1.tar.gz", hash = "sha256:d6d82e1d4f15bc4f5e7d9787f9125c3bb188608ab3cd69186620f4261a7adc18"}, + {file = "mypy_boto3_inspector-1.20.1-py3-none-any.whl", hash = "sha256:49f940f2940cc0805ec9cc2eb56f99aaa3d29e82f82e15f47e8b97f29c6ac677"}, +] +mypy-boto3-iot = [ + {file = "mypy-boto3-iot-1.20.1.tar.gz", hash = "sha256:d01f018e99e9b0774f1ab54319511a3947cec1a3a1152be9d4edf926d64be97f"}, + {file = "mypy_boto3_iot-1.20.1-py3-none-any.whl", hash = "sha256:271df647247cf5705a86bb1a377eee34d386e170ec4b742d11a77a577e85d47a"}, +] +mypy-boto3-iot-data = [ + {file = "mypy-boto3-iot-data-1.20.1.tar.gz", hash = "sha256:23cbd27c40f9d7aecc333b113a48919a72b61fb7113ca351d69cfa4cabbcf42a"}, + {file = "mypy_boto3_iot_data-1.20.1-py3-none-any.whl", hash = "sha256:123dbff170bb3ec91fa308828cd49e9299d6a026d9abea2434e4ff04205a815a"}, +] +mypy-boto3-iot-jobs-data = [ + {file = "mypy-boto3-iot-jobs-data-1.20.1.tar.gz", hash = "sha256:21a4f126bcd3ceeba16ff25b52056c2ee26528dab95850eba45ee83069a64e97"}, + {file = "mypy_boto3_iot_jobs_data-1.20.1-py3-none-any.whl", hash = "sha256:cff6ea60223a8d7a18fa98448d23707a4e2afde4545e1bfadd02f537ef189003"}, +] +mypy-boto3-iot1click-devices = [ + {file = "mypy-boto3-iot1click-devices-1.20.1.tar.gz", hash = "sha256:5f3ee565c95d112dd54d649914ccecffe8bcc29b2da4c8332827f95747ff4cab"}, + {file = "mypy_boto3_iot1click_devices-1.20.1-py3-none-any.whl", hash = "sha256:b3eeffd69e18d8979e46a7aaa527f96025c28cfa32d1ed5cc37a47606a388c4f"}, +] +mypy-boto3-iot1click-projects = [ + {file = "mypy-boto3-iot1click-projects-1.20.1.tar.gz", hash = "sha256:94b652e87fd6356b1fadaa5d1b232181765d6504952f4d10470862647bf1033a"}, + {file = "mypy_boto3_iot1click_projects-1.20.1-py3-none-any.whl", hash = "sha256:bb299bee81b6a239e79713367603638e29b8c8ea8708d5f8aaf510bcf3816767"}, +] +mypy-boto3-iotanalytics = [ + {file = "mypy-boto3-iotanalytics-1.20.1.tar.gz", hash = "sha256:c89dbd5bd745da8d124ce9795f60afff71e3abfb2c11338ab2c58c5a9ab8f519"}, + {file = "mypy_boto3_iotanalytics-1.20.1-py3-none-any.whl", hash = "sha256:28c64f10be5d439bdbde4b0e041b2f2be74594cb8ed32fec540338f607861771"}, +] +mypy-boto3-iotdeviceadvisor = [ + {file = "mypy-boto3-iotdeviceadvisor-1.20.1.tar.gz", hash = "sha256:856233811dcece351777d4b22a46b51bee3f76619a5c737e08d0f897cc4e9bf6"}, + {file = "mypy_boto3_iotdeviceadvisor-1.20.1-py3-none-any.whl", hash = "sha256:7ad2b31728f326696590f72d182520cf8502182e903635249506aa4a746e3a88"}, +] +mypy-boto3-iotevents = [ + {file = "mypy-boto3-iotevents-1.20.1.tar.gz", hash = "sha256:1a785e85a52efa7ee090438b6a472d7f258f73b11d04627bc5d7af4f2267b157"}, + {file = "mypy_boto3_iotevents-1.20.1-py3-none-any.whl", hash = "sha256:7a44ac6d1744f9992e9e70186440968ca31e461d60f51246b0eeca3ba713be55"}, +] +mypy-boto3-iotevents-data = [ + {file = "mypy-boto3-iotevents-data-1.20.1.tar.gz", hash = "sha256:060be2cb3ee1b56b74f04ac70ef1f761427acc3295275259458051353f7d11a8"}, + {file = "mypy_boto3_iotevents_data-1.20.1-py3-none-any.whl", hash = "sha256:5fac1117e8441c3d25fed40055d30bf7db79275baa7286cd4e66f70813736f54"}, +] +mypy-boto3-iotfleethub = [ + {file = "mypy-boto3-iotfleethub-1.20.1.tar.gz", hash = "sha256:e31b7ae8d95f44672363fe7af57461900acd3a41fb4e38dcae489d01426093c5"}, + {file = "mypy_boto3_iotfleethub-1.20.1-py3-none-any.whl", hash = "sha256:d84068181381a011c9f119e2c4edde3c4d072f17f2faca82a865b916209a4e94"}, +] +mypy-boto3-iotsecuretunneling = [ + {file = "mypy-boto3-iotsecuretunneling-1.20.1.tar.gz", hash = "sha256:65d9d24427151628df0012542686f4d43249a1e3d326a6c143747d0ffe052e29"}, + {file = "mypy_boto3_iotsecuretunneling-1.20.1-py3-none-any.whl", hash = "sha256:a12df6badf87a8c15fb9bf781aa001b27714486435fecaed6774c4383dcce5a3"}, +] +mypy-boto3-iotsitewise = [ + {file = "mypy-boto3-iotsitewise-1.20.1.tar.gz", hash = "sha256:926f08a29f52ac593fd36587696b7ffe520c2f7fd9ea3ef37865e56f49d25e20"}, + {file = "mypy_boto3_iotsitewise-1.20.1-py3-none-any.whl", hash = "sha256:356839c60419b320f9c33ab76d387d3513e2c9d0040792dfd343d43f9d064a6f"}, +] +mypy-boto3-iotthingsgraph = [ + {file = "mypy-boto3-iotthingsgraph-1.20.1.tar.gz", hash = "sha256:cfa6646e94443db3971ed679f6fb931f0559ccc4692d8bb2fad923189ebbb4f8"}, + {file = "mypy_boto3_iotthingsgraph-1.20.1-py3-none-any.whl", hash = "sha256:2e21c9b0b9a3c78c1dda4083677b0a2fd949abcb49aa7a0e15e707d6583ee7d3"}, +] +mypy-boto3-iotwireless = [ + {file = "mypy-boto3-iotwireless-1.20.1.tar.gz", hash = "sha256:89900b67b6dc7e40f35b4cb1af57462af172c46983a46dca056e1d98898f4530"}, + {file = "mypy_boto3_iotwireless-1.20.1-py3-none-any.whl", hash = "sha256:fd2710a82f75ae25091bd8f586947553f030ea4d5a5ba362c981343cdc8fe70d"}, +] +mypy-boto3-ivs = [ + {file = "mypy-boto3-ivs-1.20.1.tar.gz", hash = "sha256:d01d5988dcbd4e6c8829aa6980848ef99c1dd46c0c319852d64a95c18bbc81b8"}, + {file = "mypy_boto3_ivs-1.20.1-py3-none-any.whl", hash = "sha256:698e2a340e53d26b9c9d9e4a7f04987a8eec7f185f61bf2ef027f083ed33ffbb"}, +] +mypy-boto3-kafka = [ + {file = "mypy-boto3-kafka-1.20.1.tar.gz", hash = "sha256:97f00713e173cc0ddfee528ad07ed19e6d80c959bcc8a75283dd8e3cfeecddbf"}, + {file = "mypy_boto3_kafka-1.20.1-py3-none-any.whl", hash = "sha256:b44a1db833ef2af7cc4c054201e0349fae2b5a7158854aaf068b976bfbd5194f"}, +] +mypy-boto3-kafkaconnect = [ + {file = "mypy-boto3-kafkaconnect-1.20.1.tar.gz", hash = "sha256:c4fe5fc8ae1060c69d238d367f8b687c44c2dbb77bf36f969a2265dd7dd51420"}, + {file = "mypy_boto3_kafkaconnect-1.20.1-py3-none-any.whl", hash = "sha256:48a2fc822771e0ed5bb62d964d0e7003464a9b6413d0f6cd7aecec5d922b9179"}, +] +mypy-boto3-kendra = [ + {file = "mypy-boto3-kendra-1.20.1.tar.gz", hash = "sha256:f7bb37fc7e72a1ed522016a99736d266900f7ad8bc864e53b8b8a67f1f5e974d"}, + {file = "mypy_boto3_kendra-1.20.1-py3-none-any.whl", hash = "sha256:13d3463ec6f962aca5caffb47cc18d393b8bd8d9f5b20bea2eb725d241d007c5"}, +] +mypy-boto3-kinesis = [ + {file = "mypy-boto3-kinesis-1.20.1.tar.gz", hash = "sha256:c4aa47db47c01f5d32844a0d98de7e4ef14885f82c0bf894d2a16890d46cd44c"}, + {file = "mypy_boto3_kinesis-1.20.1-py3-none-any.whl", hash = "sha256:4940f3f09ece0d100f32129bc4a9f18529d27f53ececf23dd793df9ec2f12e6c"}, +] +mypy-boto3-kinesis-video-archived-media = [ + {file = "mypy-boto3-kinesis-video-archived-media-1.20.1.tar.gz", hash = "sha256:34bce8d66fcd047c3b3314a2f3950d325a221bf734fe08b53f4093ea05e358e8"}, + {file = "mypy_boto3_kinesis_video_archived_media-1.20.1-py3-none-any.whl", hash = "sha256:068ff920929d6c0ad35eca73d9a9ce9f610850978b6e7b454b723d6485c86a36"}, +] +mypy-boto3-kinesis-video-media = [ + {file = "mypy-boto3-kinesis-video-media-1.20.1.tar.gz", hash = "sha256:f53acae59a1ab3526d27ce6bae8a964bf03ad9e487b7c671a43e2767b3348641"}, + {file = "mypy_boto3_kinesis_video_media-1.20.1-py3-none-any.whl", hash = "sha256:0d79906bd022de3c9e35f3d4d49505f19c4f37821b737c3b38c3b6805f1a07c2"}, +] +mypy-boto3-kinesis-video-signaling = [ + {file = "mypy-boto3-kinesis-video-signaling-1.20.1.tar.gz", hash = "sha256:af406892f34d3efd95bdf8f36f9ace8f9aa00246d0ae69b30761868f786291b9"}, + {file = "mypy_boto3_kinesis_video_signaling-1.20.1-py3-none-any.whl", hash = "sha256:a942e86da5050724bc792b5c7eb82a71ed89d34a2700ff0c4c7395618814f86c"}, +] +mypy-boto3-kinesisanalytics = [ + {file = "mypy-boto3-kinesisanalytics-1.20.1.tar.gz", hash = "sha256:93156f255792918b50253af7a9a21ca1cc8264eca8a2225fcc133644d5a3dbc8"}, + {file = "mypy_boto3_kinesisanalytics-1.20.1-py3-none-any.whl", hash = "sha256:e5ac05ed83e9bf803c79ce50c3d77344ed7c2445a22a25e0c53d9370dd1b0da9"}, +] +mypy-boto3-kinesisanalyticsv2 = [ + {file = "mypy-boto3-kinesisanalyticsv2-1.20.1.tar.gz", hash = "sha256:c294cb5faef804fd2a7f9319250de876639500e377d871bfa1b8407f6bc40719"}, + {file = "mypy_boto3_kinesisanalyticsv2-1.20.1-py3-none-any.whl", hash = "sha256:705e15a6660af7681314852c53d7dfa63b581ffdb473a6357a24ddb4c58b20fc"}, +] +mypy-boto3-kinesisvideo = [ + {file = "mypy-boto3-kinesisvideo-1.20.1.tar.gz", hash = "sha256:adebdf717a552c3ecbd50dfc47916fef9653c5ea051b7e080dd394589d025b74"}, + {file = "mypy_boto3_kinesisvideo-1.20.1-py3-none-any.whl", hash = "sha256:80b9e82c41af605567352e63bab45be3cdacdd8b6871fe1ef322ec3f939c6311"}, +] +mypy-boto3-kms = [ + {file = "mypy-boto3-kms-1.20.1.tar.gz", hash = "sha256:6d6da41144878dcb6bdf29eb52c9b212466bc82119e276cef02b2f0716292df8"}, + {file = "mypy_boto3_kms-1.20.1-py3-none-any.whl", hash = "sha256:39c10228d7668b75fe18d790d04cd3ab364f2cb0319e3a9d7eb6641be98ac87c"}, +] +mypy-boto3-lakeformation = [ + {file = "mypy-boto3-lakeformation-1.20.1.tar.gz", hash = "sha256:c72b2bdf25f7524cae672529e5c805f6b6ff9bad92efa42262b0a36331d4a908"}, + {file = "mypy_boto3_lakeformation-1.20.1-py3-none-any.whl", hash = "sha256:ed6d21e43695c20858531e18d4a28487cf1ce2133a8338903226ee20e05026fe"}, +] +mypy-boto3-lambda = [ + {file = "mypy-boto3-lambda-1.20.1.tar.gz", hash = "sha256:1cd6c3cf0bc0a47ed0b12982591b87c22338322ceae959d7a2177ce97d12ebf7"}, + {file = "mypy_boto3_lambda-1.20.1-py3-none-any.whl", hash = "sha256:0d32003d53d8c76fd138c624bc49d24aed74177d573f23e448601017cd247dc8"}, +] +mypy-boto3-lex-models = [ + {file = "mypy-boto3-lex-models-1.20.1.tar.gz", hash = "sha256:8cd0b6ae5354cc0474154b915bd9e40334f9159bc86cbcc845c9d2502b8df7f9"}, + {file = "mypy_boto3_lex_models-1.20.1-py3-none-any.whl", hash = "sha256:85a63ac9fbb1df4151cef9e06de614e8057db188e14372905c4b58b8e70f49be"}, +] +mypy-boto3-lex-runtime = [ + {file = "mypy-boto3-lex-runtime-1.20.1.tar.gz", hash = "sha256:134add956fc7e27186b5b2c056178a2a2d5c105c352258c53a623578831b8515"}, + {file = "mypy_boto3_lex_runtime-1.20.1-py3-none-any.whl", hash = "sha256:7cb648ea350f6bb9fc417d2325ca6322396bb63e7452eaea2869bae90bbf30ea"}, +] +mypy-boto3-lexv2-models = [ + {file = "mypy-boto3-lexv2-models-1.20.1.tar.gz", hash = "sha256:1c55c73ccad7a63ea563748de043dd01796e0b568d1dce253d974c8c0ba328c4"}, + {file = "mypy_boto3_lexv2_models-1.20.1-py3-none-any.whl", hash = "sha256:6e2be3ba4a0b8aa6a9bac50c4f930a0598b6b1225802c52b65967f2a3f51d48b"}, +] +mypy-boto3-lexv2-runtime = [ + {file = "mypy-boto3-lexv2-runtime-1.20.1.tar.gz", hash = "sha256:23f5ba6f7217a1e40c41e306913ff93dd06cb0415805ab4b815668bdd1e23674"}, + {file = "mypy_boto3_lexv2_runtime-1.20.1-py3-none-any.whl", hash = "sha256:7c964df077e2b59870cc3164d5cbbb3059172c9c3ad1f24e56172f76a83fe809"}, +] +mypy-boto3-license-manager = [ + {file = "mypy-boto3-license-manager-1.20.1.tar.gz", hash = "sha256:264b9a674ce5b902e6e205b50a60db9badf4bd0a65d543bbd51c0d8a9a67b59f"}, + {file = "mypy_boto3_license_manager-1.20.1-py3-none-any.whl", hash = "sha256:11b49520be6a8260c5abe87fabe2c9ac500717a9d2dda0dd1ad116940ec77588"}, +] +mypy-boto3-lightsail = [ + {file = "mypy-boto3-lightsail-1.20.1.tar.gz", hash = "sha256:c9449db26fd18fd68a9914830d491e55f2444a38dc97f8618ef9822f134d9a14"}, + {file = "mypy_boto3_lightsail-1.20.1-py3-none-any.whl", hash = "sha256:8dabc200be9d41043697090ba799d3c55b84b94d0a3eb86f3b0b3d1d6d16ab3e"}, +] +mypy-boto3-location = [ + {file = "mypy-boto3-location-1.20.1.tar.gz", hash = "sha256:e134dd2b5faa2521d74a6c0c5c66c1f1b6354b162cd4f20f1c6241b79e6235b2"}, + {file = "mypy_boto3_location-1.20.1-py3-none-any.whl", hash = "sha256:50f718d263c94557d9b044ed0c4a1ef73bd72fa3a5fe1143c80e2c2a86205c31"}, +] +mypy-boto3-logs = [ + {file = "mypy-boto3-logs-1.20.1.tar.gz", hash = "sha256:e2cb94da2c228c96577dd92e49a363fd4dc761f8a615516ae1960f113a48715f"}, + {file = "mypy_boto3_logs-1.20.1-py3-none-any.whl", hash = "sha256:11ad54e4b1daf63334c8006e2fe3749e142580f7a47701758f11372da4c15341"}, +] +mypy-boto3-lookoutequipment = [ + {file = "mypy-boto3-lookoutequipment-1.20.1.tar.gz", hash = "sha256:177df3c1eeb20d172f4a0d471a103fe635831f114104871ea106abe8ec8ef1a5"}, + {file = "mypy_boto3_lookoutequipment-1.20.1-py3-none-any.whl", hash = "sha256:ba5400d61ec5d521a227b538a7dc89a29c4bdffa12277105087b6f92e6c793c1"}, +] +mypy-boto3-lookoutmetrics = [ + {file = "mypy-boto3-lookoutmetrics-1.20.1.tar.gz", hash = "sha256:a3f93d09bf83141b9209c350417f83d5a3a05f6a30857aa2aea27ac336823113"}, + {file = "mypy_boto3_lookoutmetrics-1.20.1-py3-none-any.whl", hash = "sha256:2d9750a5a009837a479b9cfe0c32df0fc3d76184e72773fb5b97038e7c064778"}, +] +mypy-boto3-lookoutvision = [ + {file = "mypy-boto3-lookoutvision-1.20.1.tar.gz", hash = "sha256:1150b8a7cb2e411e59c00d13ebaf03ebb8efcb9060daaa2235fd9b7bb9c2dbe7"}, + {file = "mypy_boto3_lookoutvision-1.20.1-py3-none-any.whl", hash = "sha256:e987717246c48e332d1d6e5c058576612db4861f02290149ed6dc1d509bc0c11"}, +] +mypy-boto3-machinelearning = [ + {file = "mypy-boto3-machinelearning-1.20.1.tar.gz", hash = "sha256:347c37286a9a60ffe17f75e9e3c2fa3ce6702773ddf287495af62589e77c3330"}, + {file = "mypy_boto3_machinelearning-1.20.1-py3-none-any.whl", hash = "sha256:e65052cd58bd64da8a5d569d137552254e6ae39e9d45039687bb80c812eceecc"}, +] +mypy-boto3-macie = [ + {file = "mypy-boto3-macie-1.20.1.tar.gz", hash = "sha256:38152e9514c335924f78a29993b92e47e93aebd19f30f65bfb4382e252ca308e"}, + {file = "mypy_boto3_macie-1.20.1-py3-none-any.whl", hash = "sha256:2f093a37f33a449329ea3611892c1ff4b4ae589f23df6b7b8bd77f2cc9182416"}, +] +mypy-boto3-macie2 = [ + {file = "mypy-boto3-macie2-1.20.1.tar.gz", hash = "sha256:f477215ba936c0306943183125d2e44f46bb99c53e487b70a90d26696ef724a7"}, + {file = "mypy_boto3_macie2-1.20.1-py3-none-any.whl", hash = "sha256:5a759ed8b50d4466b2d16c5f26da6e1a186407dc320133a3a17344ef90e00ce3"}, +] +mypy-boto3-managedblockchain = [ + {file = "mypy-boto3-managedblockchain-1.20.1.tar.gz", hash = "sha256:c9e4c69d558eb90b23cb088b2e89488853f26973b46889161059a436f99e8de4"}, + {file = "mypy_boto3_managedblockchain-1.20.1-py3-none-any.whl", hash = "sha256:cf70b261a269cd0d653f7e83c300919a556b9c7c265f8789c9c49109cba6efd2"}, +] +mypy-boto3-marketplace-catalog = [ + {file = "mypy-boto3-marketplace-catalog-1.20.1.tar.gz", hash = "sha256:221871452f55851913d49122982b314d43026a12b4a15c11381528a4bda55a76"}, + {file = "mypy_boto3_marketplace_catalog-1.20.1-py3-none-any.whl", hash = "sha256:d7d45095c2eb84fd9c578ce685c4ee384179f03dde90470e56fc285b100a2529"}, +] +mypy-boto3-marketplace-entitlement = [ + {file = "mypy-boto3-marketplace-entitlement-1.20.1.tar.gz", hash = "sha256:cc5e5acc12f4c922ee04cebb56cd6a4260fda027354c57fe438e67a5b3b28855"}, + {file = "mypy_boto3_marketplace_entitlement-1.20.1-py3-none-any.whl", hash = "sha256:a818aaca66effef318f5912605ead8a93d40530cd0c8a645682d97684847f703"}, +] +mypy-boto3-marketplacecommerceanalytics = [ + {file = "mypy-boto3-marketplacecommerceanalytics-1.20.1.tar.gz", hash = "sha256:5a220599460af0628ebf0c878708a2564ff1d4a32e3212ab98eb81c495e88e61"}, + {file = "mypy_boto3_marketplacecommerceanalytics-1.20.1-py3-none-any.whl", hash = "sha256:4de1e0f3d4801022b882415455dc5496a1502799242e199281eb735fe2248812"}, +] +mypy-boto3-mediaconnect = [ + {file = "mypy-boto3-mediaconnect-1.20.1.tar.gz", hash = "sha256:f1c0843a2b466a060b1e6a4eed43301bcb97671e9d7f1c4d53af37f197412c01"}, + {file = "mypy_boto3_mediaconnect-1.20.1-py3-none-any.whl", hash = "sha256:fd074f576501a9fefe04bac3dcaf316115919d850540f937dc9cd20514bfaed7"}, +] +mypy-boto3-mediaconvert = [ + {file = "mypy-boto3-mediaconvert-1.20.1.tar.gz", hash = "sha256:379bc0a1ca137f6404a839bc40d0c37d36e9743d995932b8f6a7ad2551f8dd44"}, + {file = "mypy_boto3_mediaconvert-1.20.1-py3-none-any.whl", hash = "sha256:3efc3db1c5a85df241fd3fde2930f5b27567fc56351d2d15ed12ef4937da93e1"}, +] +mypy-boto3-medialive = [ + {file = "mypy-boto3-medialive-1.20.1.tar.gz", hash = "sha256:a987355ef7e51d468cbc625db6f2f4de4e8ade640cb306083dee25b8c4f9a6a5"}, + {file = "mypy_boto3_medialive-1.20.1-py3-none-any.whl", hash = "sha256:28ff5640102648a5415ad20f37bc35e8fc3f49e23ea6c2fb09f06331ec0a0bb2"}, +] +mypy-boto3-mediapackage = [ + {file = "mypy-boto3-mediapackage-1.20.1.tar.gz", hash = "sha256:38bc7446e0496e81c0a391bdea0cb3ffa1de2e3d36bb716c3d43b0d48a64820d"}, + {file = "mypy_boto3_mediapackage-1.20.1-py3-none-any.whl", hash = "sha256:0bb1cf32e8f2c89dca1902f4dec4de759e32281ea6e47dc649ac6ba08f9a3cbb"}, +] +mypy-boto3-mediapackage-vod = [ + {file = "mypy-boto3-mediapackage-vod-1.20.1.tar.gz", hash = "sha256:8b4d418b63813944b65a05cfca21352e71541ddbc87b2811f0ae90a9490bca08"}, + {file = "mypy_boto3_mediapackage_vod-1.20.1-py3-none-any.whl", hash = "sha256:e70caa46bc9b055c69edb6bd32e3048f3a901b0f69e83b45213faa9acc820068"}, +] +mypy-boto3-mediastore = [ + {file = "mypy-boto3-mediastore-1.20.1.tar.gz", hash = "sha256:b12cba6df2016e279a29bc4593b5bb20ad0f023254a4684ff6e35afa2c4360db"}, + {file = "mypy_boto3_mediastore-1.20.1-py3-none-any.whl", hash = "sha256:39001dcd1be9b493fb15d6db0faf9a939514cd484f9c0d728e5f14ce0cd6550b"}, +] +mypy-boto3-mediastore-data = [ + {file = "mypy-boto3-mediastore-data-1.20.1.tar.gz", hash = "sha256:7e26891c644f1f4831bb6dbd8241fd15924622d20af99e67f5b57a92bc30f8e2"}, + {file = "mypy_boto3_mediastore_data-1.20.1-py3-none-any.whl", hash = "sha256:e0a6f7563363fa1e179785893baf9ab2faa629fe25900b5f0dcdbde7119f7f95"}, +] +mypy-boto3-mediatailor = [ + {file = "mypy-boto3-mediatailor-1.20.1.tar.gz", hash = "sha256:856c02f63449d5b10ebd07d3c8d97478aa75622afd6f793656e32024099ac49d"}, + {file = "mypy_boto3_mediatailor-1.20.1-py3-none-any.whl", hash = "sha256:207352e2e48edd22bba45beb696ea8ff9e4f08ced51acc80ddc5abbc808fed42"}, +] +mypy-boto3-memorydb = [ + {file = "mypy-boto3-memorydb-1.20.1.tar.gz", hash = "sha256:5b6dc3ab1439e847a6e8758c83d8ec6286f16f9a480aadcbe319ec3fe1b011dc"}, + {file = "mypy_boto3_memorydb-1.20.1-py3-none-any.whl", hash = "sha256:b86aec0cd2e21d59db034c923b5c737eea12b63aa06b5ad5ce67c8eb6e1b5e34"}, +] +mypy-boto3-meteringmarketplace = [ + {file = "mypy-boto3-meteringmarketplace-1.20.1.tar.gz", hash = "sha256:fed279e03d1c1652301f10b607126a865acd5d8b569739b7f36624bde518f90e"}, + {file = "mypy_boto3_meteringmarketplace-1.20.1-py3-none-any.whl", hash = "sha256:897d0582d44767a5911d2bd0fd25f087df7a633b215a3211a4d07438a53fb43f"}, +] +mypy-boto3-mgh = [ + {file = "mypy-boto3-mgh-1.20.1.tar.gz", hash = "sha256:903405eb737148160fa6ce5069a76fb773b66348208424d16e7ffe1c8974d498"}, + {file = "mypy_boto3_mgh-1.20.1-py3-none-any.whl", hash = "sha256:b0c3e9f98ff2191bb9745acb3380c30855c0687fd7dc386e9d17fd609457c8ba"}, +] +mypy-boto3-mgn = [ + {file = "mypy-boto3-mgn-1.20.1.tar.gz", hash = "sha256:e1325742146a8fea2ac906c4f636e80d26ba409491330d9e4d7f136f88a89e0d"}, + {file = "mypy_boto3_mgn-1.20.1-py3-none-any.whl", hash = "sha256:0da37c7f8c6b6a7de8934757e4f80729cd55e8acb24c80dfc7d919efa35580a1"}, +] +mypy-boto3-migrationhub-config = [ + {file = "mypy-boto3-migrationhub-config-1.20.1.tar.gz", hash = "sha256:179cb5f113ce616f86f71b28e189a899f01f1644ae3d25dfe27f3013e4717db2"}, + {file = "mypy_boto3_migrationhub_config-1.20.1-py3-none-any.whl", hash = "sha256:af00debd491bb3f434cb6b8d476b742c1c6192e1969a27ddd17de5bf11fb8b2b"}, +] +mypy-boto3-mobile = [ + {file = "mypy-boto3-mobile-1.20.1.tar.gz", hash = "sha256:ef012e054117a8efde33942a674e9464e14b6c2df03c66a16a5d7989f775b3e7"}, + {file = "mypy_boto3_mobile-1.20.1-py3-none-any.whl", hash = "sha256:03444c4de2c5021c0986ab8b8f68eefc88315824c4ff0329a1c302f465872c73"}, +] +mypy-boto3-mq = [ + {file = "mypy-boto3-mq-1.20.1.tar.gz", hash = "sha256:7a13bf48e502640d00b1fd5ff9a9908b1e2bdd60d0a0eab26eaf517a2484f8c1"}, + {file = "mypy_boto3_mq-1.20.1-py3-none-any.whl", hash = "sha256:be817ad63dcbec65e8699a0971674111efd6e3595d667e062380569783a7181f"}, +] +mypy-boto3-mturk = [ + {file = "mypy-boto3-mturk-1.20.1.tar.gz", hash = "sha256:8705887cb82598a3ed0f5db4c5ca376f45f2f13081267996a5ee44252c9d4b49"}, + {file = "mypy_boto3_mturk-1.20.1-py3-none-any.whl", hash = "sha256:f27910918048d6952b9e9d6e9ac93685d894d381e116f78d025c49b665a7dcea"}, +] +mypy-boto3-mwaa = [ + {file = "mypy-boto3-mwaa-1.20.1.tar.gz", hash = "sha256:5238dd7d6c1e01e7aa1b0be5217779d232c2fcdaad5fcfc649cee09fa67ce84b"}, + {file = "mypy_boto3_mwaa-1.20.1-py3-none-any.whl", hash = "sha256:dd57aac9a4b6e1fee190127f24420d084d6a7d97cb4616c48be042d19d54bbc9"}, +] +mypy-boto3-neptune = [ + {file = "mypy-boto3-neptune-1.20.1.tar.gz", hash = "sha256:b0ac9d0204f206b9a7154075385e95e1f6c1d2ba33355143d0faa8fa815364d8"}, + {file = "mypy_boto3_neptune-1.20.1-py3-none-any.whl", hash = "sha256:4a25db724ec9a1658e5488fef1a1cea6c94f1670033a3f136cd18564a59085cd"}, +] +mypy-boto3-network-firewall = [ + {file = "mypy-boto3-network-firewall-1.20.1.tar.gz", hash = "sha256:169544c7bf7041e09d5273b9159871f13f8472f743f041532f62cf655ab54292"}, + {file = "mypy_boto3_network_firewall-1.20.1-py3-none-any.whl", hash = "sha256:42af7aa483555c968cb516a9ed77143323d8c5f62208c0dbbdc6963df4143aa7"}, +] +mypy-boto3-networkmanager = [ + {file = "mypy-boto3-networkmanager-1.20.1.tar.gz", hash = "sha256:03f76a686037fc8c5e3545bdb0440321cf012a37f89ccf5f7e944a66c348a46c"}, + {file = "mypy_boto3_networkmanager-1.20.1-py3-none-any.whl", hash = "sha256:a1cad97c415127a8182ab9254f381048061fad258fc23379e0efee361ec92792"}, +] +mypy-boto3-nimble = [ + {file = "mypy-boto3-nimble-1.20.1.tar.gz", hash = "sha256:5ce33f82546f355b9d212606fbaf82ba45477e5714680959344db56a340e49e7"}, + {file = "mypy_boto3_nimble-1.20.1-py3-none-any.whl", hash = "sha256:8a5589aaa3fca24f938ab233e2e632400dc7359887aaa45a88645785eea24250"}, +] +mypy-boto3-opensearch = [ + {file = "mypy-boto3-opensearch-1.20.1.tar.gz", hash = "sha256:99089d69cdb42a01d5850d4b9addc39993be0ce6fbbbc28447ac6367f0d6afcd"}, + {file = "mypy_boto3_opensearch-1.20.1-py3-none-any.whl", hash = "sha256:7b276ae5afba59482f7b681e76700bbd4c91206c23f258739e5fad259479613e"}, +] +mypy-boto3-opsworks = [ + {file = "mypy-boto3-opsworks-1.20.1.tar.gz", hash = "sha256:10703a90a2bc7a9b836eec24c650aaebeebd4d79998a055f2c1b3d3ddc4a766f"}, + {file = "mypy_boto3_opsworks-1.20.1-py3-none-any.whl", hash = "sha256:dd5da853fd76dbcbe387355c0c3595394b4c49b9abf5d18d87ff85d3b361bc69"}, +] +mypy-boto3-opsworkscm = [ + {file = "mypy-boto3-opsworkscm-1.20.1.tar.gz", hash = "sha256:2212788b2a591087f10566b82208c18361cc0ed18916261bb6633a5ccff31452"}, + {file = "mypy_boto3_opsworkscm-1.20.1-py3-none-any.whl", hash = "sha256:5a8aff2dff95942773c9e885f4028880823df69fd967851a8149614d73573bbd"}, +] +mypy-boto3-organizations = [ + {file = "mypy-boto3-organizations-1.20.1.tar.gz", hash = "sha256:eb60553fb688a1fb7700c755e7df78019374cb131914de314cda746984ac5610"}, + {file = "mypy_boto3_organizations-1.20.1-py3-none-any.whl", hash = "sha256:fd2d33665762017df59e04c05f42a2c995c590e2803bdc99538beaf6635bbda2"}, +] +mypy-boto3-outposts = [ + {file = "mypy-boto3-outposts-1.20.1.tar.gz", hash = "sha256:6cc858d6f8e79c621ba1d9f6211979358dd58e512128821faf625d8380e48462"}, + {file = "mypy_boto3_outposts-1.20.1-py3-none-any.whl", hash = "sha256:9ee6e2ffa3598dc69b1f3ad4adbf74a016f153a2a2240210a7a54683ea8ad82b"}, +] +mypy-boto3-panorama = [ + {file = "mypy-boto3-panorama-1.20.1.tar.gz", hash = "sha256:030bdf046462366b9f79cf8e178dd8f410171f46383230c5abb7f53ad815897b"}, + {file = "mypy_boto3_panorama-1.20.1-py3-none-any.whl", hash = "sha256:05148e9192c83971a27f436eb09f0c3f8a5e0127f87475d7645015e0e5429fce"}, +] +mypy-boto3-personalize = [ + {file = "mypy-boto3-personalize-1.20.1.tar.gz", hash = "sha256:51b7d6089b1b7b25dd91a66cd6de1465e35c83e6e79a16818873589d6600febf"}, + {file = "mypy_boto3_personalize-1.20.1-py3-none-any.whl", hash = "sha256:099ca3c4567557eee65d91ac4e3d6b4862938cca8d3707302c63402fe92d32e3"}, +] +mypy-boto3-personalize-events = [ + {file = "mypy-boto3-personalize-events-1.20.1.tar.gz", hash = "sha256:8d423448fca40b699a0c4614d074e29c56bc3cb2b7e63012d1cf84010cd81a12"}, + {file = "mypy_boto3_personalize_events-1.20.1-py3-none-any.whl", hash = "sha256:cf33b0a6ee55484a0b91469ed5a4b2892d9d6d939584fa4e53a10a5a4d3d1a1c"}, +] +mypy-boto3-personalize-runtime = [ + {file = "mypy-boto3-personalize-runtime-1.20.1.tar.gz", hash = "sha256:1636a0eada1c3003d9d9691f339e30a36b670a303bf5c571b3b3a36a4ba38fd5"}, + {file = "mypy_boto3_personalize_runtime-1.20.1-py3-none-any.whl", hash = "sha256:40e8af4bdaa8254075e3bd9afc7f28308cabf094882f9e8851be5b84a9a9ebf2"}, +] +mypy-boto3-pi = [ + {file = "mypy-boto3-pi-1.20.1.tar.gz", hash = "sha256:9345304b4d758dceb037a5bd2b1d9e5521b75d76b4c95c6657584f9a64ae095c"}, + {file = "mypy_boto3_pi-1.20.1-py3-none-any.whl", hash = "sha256:6bd486fadc618be6dce36a69f8831da0782da22b6ebf233969a963de2b3993e2"}, +] +mypy-boto3-pinpoint = [ + {file = "mypy-boto3-pinpoint-1.20.1.tar.gz", hash = "sha256:42aacd5e20a45f321499ff340b8abdf7724f32a11d2573f82eb9c7266fcdc757"}, + {file = "mypy_boto3_pinpoint-1.20.1-py3-none-any.whl", hash = "sha256:10ccf5b0d0b4dda47c6e4ce79cc19393658e28dcbefbdd2b4272387b6f42429f"}, +] +mypy-boto3-pinpoint-email = [ + {file = "mypy-boto3-pinpoint-email-1.20.1.tar.gz", hash = "sha256:c365660a1c30de0a992daccc478a5e568ae34719364ad48037de5b2de9d4dd5f"}, + {file = "mypy_boto3_pinpoint_email-1.20.1-py3-none-any.whl", hash = "sha256:d4222dffa4fff9af5b52b692886d22aea1b0a3870ed34e8bff43e0b18df930b8"}, +] +mypy-boto3-pinpoint-sms-voice = [ + {file = "mypy-boto3-pinpoint-sms-voice-1.20.1.tar.gz", hash = "sha256:2b68e453be9b5830a49fd90d5e9be64c1ea68bf9caf89534927f82bb4410e7df"}, + {file = "mypy_boto3_pinpoint_sms_voice-1.20.1-py3-none-any.whl", hash = "sha256:a7c6caff1d0428d821a6bff4c31a983a81debc58b8cc4fdb2d284e463561f66c"}, +] +mypy-boto3-polly = [ + {file = "mypy-boto3-polly-1.20.1.tar.gz", hash = "sha256:fcf7e6c95dc6e957071fb787228d18f84cfa4e6c0a72acb870a967af017be184"}, + {file = "mypy_boto3_polly-1.20.1-py3-none-any.whl", hash = "sha256:76a05620cf56dfde4d7c469b50bd4dbb0e5664156b53eb4963387ff9e32c08ee"}, +] +mypy-boto3-pricing = [ + {file = "mypy-boto3-pricing-1.20.1.tar.gz", hash = "sha256:a3b947e2e2aafd2ed05765e5fc709dba8a7fad3aa2683057651b37e81aa991c7"}, + {file = "mypy_boto3_pricing-1.20.1-py3-none-any.whl", hash = "sha256:b08c4aba9da4a669726ccbe40b60a6141dff377b4a22859b588adce4e05181c8"}, +] +mypy-boto3-proton = [ + {file = "mypy-boto3-proton-1.20.1.tar.gz", hash = "sha256:09c66672f2d89b9d0cfebbde83cdf90bef35d4337ac3104e91d4da00b74f829b"}, + {file = "mypy_boto3_proton-1.20.1-py3-none-any.whl", hash = "sha256:f1a1b7c0c8b4e4b43e3be7d114e2e321e0ac795774212d2e354a02b7c30c5c41"}, +] +mypy-boto3-qldb = [ + {file = "mypy-boto3-qldb-1.20.1.tar.gz", hash = "sha256:fe102bd56267519924fab55e3a014bd2152ef4f7fa745866ac58c82bbc5c9a5c"}, + {file = "mypy_boto3_qldb-1.20.1-py3-none-any.whl", hash = "sha256:c4622a01b462a61e3c60ce9417471cb16643c085df93e45aec83555b79a1ce06"}, +] +mypy-boto3-qldb-session = [ + {file = "mypy-boto3-qldb-session-1.20.1.tar.gz", hash = "sha256:bb72885facdad5cc781d285fc008c464ed9654a2bd6aae290454d9905382a247"}, + {file = "mypy_boto3_qldb_session-1.20.1-py3-none-any.whl", hash = "sha256:89fe36266997a82837849880b0e2a5c746df00329e0b612eaf9588db99256a88"}, +] +mypy-boto3-quicksight = [ + {file = "mypy-boto3-quicksight-1.20.1.tar.gz", hash = "sha256:8a690f40c97915a7c520aecb43212b756a6f7566d9396e05a4c620620edb4ccd"}, + {file = "mypy_boto3_quicksight-1.20.1-py3-none-any.whl", hash = "sha256:07cb4a4ca0171272ba7614ae2e8bc975b38e40190931f304efd6171cde14f30a"}, +] +mypy-boto3-ram = [ + {file = "mypy-boto3-ram-1.20.1.tar.gz", hash = "sha256:0925cb82cce1f22e93af551b6f6adf17c80ad9e8aa77634be05b373f32e27f44"}, + {file = "mypy_boto3_ram-1.20.1-py3-none-any.whl", hash = "sha256:c5467e840387a8ac402248c530d5d7d824dcc9ae1133085cb1de8d66f62fda16"}, +] +mypy-boto3-rds = [ + {file = "mypy-boto3-rds-1.20.1.tar.gz", hash = "sha256:d6c10fa2a91399b9d1841f15598942df1d6aab6921186c1166540e80897d3fb7"}, + {file = "mypy_boto3_rds-1.20.1-py3-none-any.whl", hash = "sha256:b471c03bc5f8ee6adbd4c7ee0404dee2001994f1d28eb514264e2ce25afd6588"}, +] +mypy-boto3-rds-data = [ + {file = "mypy-boto3-rds-data-1.20.1.tar.gz", hash = "sha256:b57a4ba42a3471b49fd1306d467cc59b9cc03c0626180a55fcfa31d9362436c9"}, + {file = "mypy_boto3_rds_data-1.20.1-py3-none-any.whl", hash = "sha256:8b0287fad26a4658eae7ed43ae67ee3481f2ba8fd39555ebe130ed890e316a44"}, +] +mypy-boto3-redshift = [ + {file = "mypy-boto3-redshift-1.20.1.tar.gz", hash = "sha256:c518b5c37c2c128eeffaffa14c0bc69ff69726e4ecfd112997336fdd9c746513"}, + {file = "mypy_boto3_redshift-1.20.1-py3-none-any.whl", hash = "sha256:1e318a8fc145c19ea76ad815d080e591424b3f23410ae7e5d3675967321b55a0"}, +] +mypy-boto3-redshift-data = [ + {file = "mypy-boto3-redshift-data-1.20.1.tar.gz", hash = "sha256:afe59de6efe6615f45cd6222dea0edc8b6d6a688c235ba73f1dadee9f2dea9a7"}, + {file = "mypy_boto3_redshift_data-1.20.1-py3-none-any.whl", hash = "sha256:6b701fcb6e362230f0edc2a8687fed2197a4b1c087bce4ec485a825d93128ae0"}, +] +mypy-boto3-rekognition = [ + {file = "mypy-boto3-rekognition-1.20.1.tar.gz", hash = "sha256:6d733299689d7d6ef2909b89e6dfbf8666f60bb754d26637479c623615f13cb3"}, + {file = "mypy_boto3_rekognition-1.20.1-py3-none-any.whl", hash = "sha256:25661d445564c66bd87eb09113d7d187a2835b68463582234aa0daf5432928ae"}, +] +mypy-boto3-resource-groups = [ + {file = "mypy-boto3-resource-groups-1.20.1.tar.gz", hash = "sha256:79f4f9982daf43f495e173602f508613358c7baff77916b37c57b2e8d39e9013"}, + {file = "mypy_boto3_resource_groups-1.20.1-py3-none-any.whl", hash = "sha256:de6cb82d26ca55c517093f6cfee34a698c318b2cb1f1805e4a9e712fad56e62c"}, +] +mypy-boto3-resourcegroupstaggingapi = [ + {file = "mypy-boto3-resourcegroupstaggingapi-1.20.1.tar.gz", hash = "sha256:6abf6150d28478ad77ac2ba819b4e358c4f7d9bc640e70b5acd71095a3e8ecca"}, + {file = "mypy_boto3_resourcegroupstaggingapi-1.20.1-py3-none-any.whl", hash = "sha256:5f31a72a925bfbb7557310ab6364f3c0ccb31adb81da75ed9070d0bfd910d0f0"}, +] +mypy-boto3-robomaker = [ + {file = "mypy-boto3-robomaker-1.20.1.tar.gz", hash = "sha256:c4a0ff04434bdd1a9b33707acadfc99f25437fd8ffeed575032fcde2e5400176"}, + {file = "mypy_boto3_robomaker-1.20.1-py3-none-any.whl", hash = "sha256:d2b4641d42669ac46b013098122bc12d31b48ee8b6f1febd7409ff9df1f7b5c8"}, +] +mypy-boto3-route53 = [ + {file = "mypy-boto3-route53-1.20.1.tar.gz", hash = "sha256:20a968db08a4baed6ef47e7b978e3dec7c164dc162cd16c09e16d82314009206"}, + {file = "mypy_boto3_route53-1.20.1-py3-none-any.whl", hash = "sha256:931a1da8c25d83260f690648d11351207d39657993bce9537ade04dad1f79622"}, +] +mypy-boto3-route53-recovery-cluster = [ + {file = "mypy-boto3-route53-recovery-cluster-1.20.1.tar.gz", hash = "sha256:1f3e52f983e22198d1a854be11fe2566382d803abce43e4edbd381a8b3db12c6"}, + {file = "mypy_boto3_route53_recovery_cluster-1.20.1-py3-none-any.whl", hash = "sha256:8bc0c17ca9d0456ea4ea90e7bf619c615146abe9f88ebfd9e929e4660bd88862"}, +] +mypy-boto3-route53-recovery-control-config = [ + {file = "mypy-boto3-route53-recovery-control-config-1.20.1.tar.gz", hash = "sha256:2662e6d93d07e477fcbbefd2e296ee5d37c0fa91a999fdf266b4f620e4c6ddf5"}, + {file = "mypy_boto3_route53_recovery_control_config-1.20.1-py3-none-any.whl", hash = "sha256:af411e2be006e0fa2d0519c0bffee7d758380d4b0cda770a3d5def1c2cd18a12"}, +] +mypy-boto3-route53-recovery-readiness = [ + {file = "mypy-boto3-route53-recovery-readiness-1.20.1.tar.gz", hash = "sha256:e72c5c46d3cb12bb96c985c9f1e7c19d407cb003dd4a8407b553675c93349522"}, + {file = "mypy_boto3_route53_recovery_readiness-1.20.1-py3-none-any.whl", hash = "sha256:5d52d3f5a899ff10db400fe037c930c1a81a62a55030099dba6d0c68bbd74fe4"}, +] +mypy-boto3-route53domains = [ + {file = "mypy-boto3-route53domains-1.20.1.tar.gz", hash = "sha256:6871f5571d9eeb66434f1b593e5b012c1e5b87e0470d6f5c2c80da8339bbe96d"}, + {file = "mypy_boto3_route53domains-1.20.1-py3-none-any.whl", hash = "sha256:0dffb067b44d2a69eb66c237c8855f4fe365500f124074d5aaad8fa62ed71041"}, +] +mypy-boto3-route53resolver = [ + {file = "mypy-boto3-route53resolver-1.20.1.tar.gz", hash = "sha256:d0db0fed5e60cc20b3048babe733b66b068985e2f9ffcf05406e3016b66f8737"}, + {file = "mypy_boto3_route53resolver-1.20.1-py3-none-any.whl", hash = "sha256:58460452541e5905eb1e5c12e819e1d6af288adc290c4583734cd8cff08d5d4b"}, +] +mypy-boto3-s3 = [ + {file = "mypy-boto3-s3-1.20.1.tar.gz", hash = "sha256:4675a50e25e8974ef8822920f22e38f6bc7810d1bb01cee4cfd94c8b5dab92ec"}, + {file = "mypy_boto3_s3-1.20.1-py3-none-any.whl", hash = "sha256:44276f3efb51c5299652882b348df28da376667303fedfd49d40fca0b9146d9d"}, +] +mypy-boto3-s3control = [ + {file = "mypy-boto3-s3control-1.20.1.tar.gz", hash = "sha256:bd0fa272a254685191e0395bc925296299b5fd96069b4fe73c78dc3a0491782e"}, + {file = "mypy_boto3_s3control-1.20.1-py3-none-any.whl", hash = "sha256:1ecfc4b61ce647b09fa7df4a9e4e08051c5e1f913bd441830f252853ccbc0a71"}, +] +mypy-boto3-s3outposts = [ + {file = "mypy-boto3-s3outposts-1.20.1.tar.gz", hash = "sha256:0114cb8058888e26c5619fcab2f1e028833e8acaf55ea16cd8f513d977429efc"}, + {file = "mypy_boto3_s3outposts-1.20.1-py3-none-any.whl", hash = "sha256:3517329d1dd66d916bbf8c0cfd1b63a3f8e0c971c49b651e280836f08a4598f5"}, +] +mypy-boto3-sagemaker = [ + {file = "mypy-boto3-sagemaker-1.20.1.tar.gz", hash = "sha256:274526ffe0b9f8db20da850c419613d88c0e785145f4508f8e76017ba228d398"}, + {file = "mypy_boto3_sagemaker-1.20.1-py3-none-any.whl", hash = "sha256:6a6a2fa66681585c6d11b06f576edcee5e37f25df2e2cbad64ad957fc394b115"}, +] +mypy-boto3-sagemaker-a2i-runtime = [ + {file = "mypy-boto3-sagemaker-a2i-runtime-1.20.1.tar.gz", hash = "sha256:74d98e9d7bbafc8b679d38802cc80584f589f1cad804680bfacf33c9b92c3aff"}, + {file = "mypy_boto3_sagemaker_a2i_runtime-1.20.1-py3-none-any.whl", hash = "sha256:5322b09f39da3d924cf7dc2c9fb6279611be4d06cdd7b9fe6f193d5dfaad6026"}, +] +mypy-boto3-sagemaker-edge = [ + {file = "mypy-boto3-sagemaker-edge-1.20.1.tar.gz", hash = "sha256:30cadceda81dd019cb6b532fb013b235df251f4120226ad9f48c5e29fdaa2109"}, + {file = "mypy_boto3_sagemaker_edge-1.20.1-py3-none-any.whl", hash = "sha256:99222fee013a7bc1e440575e21fd48aaffd294065bad239d2262f0149c6ba501"}, +] +mypy-boto3-sagemaker-featurestore-runtime = [ + {file = "mypy-boto3-sagemaker-featurestore-runtime-1.20.1.tar.gz", hash = "sha256:0fd3b839120418015a0ddb8120531bf6b38b4f5b0b965f44fc881acbecb019b6"}, + {file = "mypy_boto3_sagemaker_featurestore_runtime-1.20.1-py3-none-any.whl", hash = "sha256:270f16d96f775153c2a1c326dd66810a387347f34e46399c6823866343fa601a"}, +] +mypy-boto3-sagemaker-runtime = [ + {file = "mypy-boto3-sagemaker-runtime-1.20.1.tar.gz", hash = "sha256:c71b04f6115cb78bcffa14664f7cc721f41249875b37805b46360da9310b3136"}, + {file = "mypy_boto3_sagemaker_runtime-1.20.1-py3-none-any.whl", hash = "sha256:7991a9895d9dfa978f360fa697e22cdf3dd8b02b25a9b179ac5f02c9a9d2831e"}, +] +mypy-boto3-savingsplans = [ + {file = "mypy-boto3-savingsplans-1.20.1.tar.gz", hash = "sha256:24e4676b934fe6bde2b64cb89971d178dd3898655bf8c86aba9aa038fab39e00"}, + {file = "mypy_boto3_savingsplans-1.20.1-py3-none-any.whl", hash = "sha256:8adf5559806ab6903ec10864ac2992f59a6bb092e2dd33d940982408bd1f87a1"}, +] +mypy-boto3-schemas = [ + {file = "mypy-boto3-schemas-1.20.1.tar.gz", hash = "sha256:9c3fc745c79b8faee8dee2a5de0d6dbe63e69c0eeb32a238b74ad20f3e9220bd"}, + {file = "mypy_boto3_schemas-1.20.1-py3-none-any.whl", hash = "sha256:009c0d764bfac0da67ec6f4ed7002b61a71142fc636e866653f4f82d6308ca97"}, +] +mypy-boto3-sdb = [ + {file = "mypy-boto3-sdb-1.20.1.tar.gz", hash = "sha256:dedb1e818df5670bcc9e42fa4f37dadba93e7980dbdba5f129faea9fbd7cf7d6"}, + {file = "mypy_boto3_sdb-1.20.1-py3-none-any.whl", hash = "sha256:b56d6b732b893f6dacfb1dd87e05ad6efc8e40f6bb208518bc5afdce74e01dec"}, +] +mypy-boto3-secretsmanager = [ + {file = "mypy-boto3-secretsmanager-1.20.1.tar.gz", hash = "sha256:44b001ee7cc3d69b749be64c714457da9b4fd529ba19c29eddfb793edc3c2699"}, + {file = "mypy_boto3_secretsmanager-1.20.1-py3-none-any.whl", hash = "sha256:87514e4cf2d3f718120b99cd9d8ad7c039a0a8c78c5c091c6cd3333697e1648b"}, +] +mypy-boto3-securityhub = [ + {file = "mypy-boto3-securityhub-1.20.1.tar.gz", hash = "sha256:d13f31d1608af94b736f609bc2c6fffcc5c26a03082e3c8583b20a7fb3808b82"}, + {file = "mypy_boto3_securityhub-1.20.1-py3-none-any.whl", hash = "sha256:42218e9c2537c22b6cebe98c21a11960a90123403ae0d67c5d8222e2409892de"}, +] +mypy-boto3-serverlessrepo = [ + {file = "mypy-boto3-serverlessrepo-1.20.1.tar.gz", hash = "sha256:bde34026d1d141dae9798ad3bc74cd3978ffa77543aa755c8aab230f91a9124e"}, + {file = "mypy_boto3_serverlessrepo-1.20.1-py3-none-any.whl", hash = "sha256:4f0669f09b4ea4423e766d90b2e067a4967be974f14a2db71d877e866eb2acc2"}, +] +mypy-boto3-service-quotas = [ + {file = "mypy-boto3-service-quotas-1.20.1.tar.gz", hash = "sha256:90f77a279a2a83817be0d275cca543d6eec371a3f3f56df27e7bb0ccbaac6ddc"}, + {file = "mypy_boto3_service_quotas-1.20.1-py3-none-any.whl", hash = "sha256:e4c7ae5bdbacfa8ab416b436457b9ff8d4331af0e71d5342619d09b9df1660cb"}, +] +mypy-boto3-servicecatalog = [ + {file = "mypy-boto3-servicecatalog-1.20.1.tar.gz", hash = "sha256:d49b392efe78bed2ac0cb5a56f503166ce5b978427ac88352a1dc9c619061fac"}, + {file = "mypy_boto3_servicecatalog-1.20.1-py3-none-any.whl", hash = "sha256:bd99124247c7a0f4cf5966918fc2b7d01d5cb25b93b3c4e8e5fc7bf068c7d6cc"}, +] +mypy-boto3-servicecatalog-appregistry = [ + {file = "mypy-boto3-servicecatalog-appregistry-1.20.1.tar.gz", hash = "sha256:fd3955cee4bdad30fc5fa18f71259bc01acf2ae88d4b8788dc6336877a3e1130"}, + {file = "mypy_boto3_servicecatalog_appregistry-1.20.1-py3-none-any.whl", hash = "sha256:d7fadf4298a622c23ab404c8b7096f58ccccd0d158995c5718fc1bf4125084e3"}, +] +mypy-boto3-servicediscovery = [ + {file = "mypy-boto3-servicediscovery-1.20.1.tar.gz", hash = "sha256:0f4729db346cbb98e26f40f81c06362bd1deba7e011a8cba10b9e8b29ce2385f"}, + {file = "mypy_boto3_servicediscovery-1.20.1-py3-none-any.whl", hash = "sha256:ed41122efb560ee9468281ea5e0e732891a6560aa9279129ab675d6a524efbb5"}, +] +mypy-boto3-ses = [ + {file = "mypy-boto3-ses-1.20.1.tar.gz", hash = "sha256:73d77461a411f8f49baa1ad69423d765d080c703bd00686e1082ecbe216c7b19"}, + {file = "mypy_boto3_ses-1.20.1-py3-none-any.whl", hash = "sha256:1fd3ca442edb3a6e48689928ebcf50551b38950bd301d1698b84148b02b7073c"}, +] +mypy-boto3-sesv2 = [ + {file = "mypy-boto3-sesv2-1.20.1.tar.gz", hash = "sha256:0d1cdc28ea1787a8df9f9232ffdbc943dc38230f23a96827b9ab7d2a07b29417"}, + {file = "mypy_boto3_sesv2-1.20.1-py3-none-any.whl", hash = "sha256:0d1ac36b02b711c85b37981966e1935bd4079ecf5924e27dc104710b4437333a"}, +] +mypy-boto3-shield = [ + {file = "mypy-boto3-shield-1.20.1.tar.gz", hash = "sha256:ffa449bbe476faea7c86d487d0a89145aa88ad1371f0e37ef8e8429c4cda0a3c"}, + {file = "mypy_boto3_shield-1.20.1-py3-none-any.whl", hash = "sha256:140eb1c2fcf8ddeaa333f967a0262e29482173fe20dd912937d74c6eda46ed08"}, +] +mypy-boto3-signer = [ + {file = "mypy-boto3-signer-1.20.1.tar.gz", hash = "sha256:c6f817037aa4ec054e8d1c843edaee51b907ce167d76209dca6d0f077ad1c2e3"}, + {file = "mypy_boto3_signer-1.20.1-py3-none-any.whl", hash = "sha256:fccf79e2afb842b1d4e98393f0aebe74a62887dcf54a293d2040bfe63b919358"}, +] +mypy-boto3-sms = [ + {file = "mypy-boto3-sms-1.20.1.tar.gz", hash = "sha256:7d4628a6e5d0f3f8e36411084a54cd2f876cd143d712575053716f3889604440"}, + {file = "mypy_boto3_sms-1.20.1-py3-none-any.whl", hash = "sha256:088e379e1791d96c74a0c78693311857d1b6eb919fffa363ccc87ce24f1e8b77"}, +] +mypy-boto3-sms-voice = [ + {file = "mypy-boto3-sms-voice-1.20.1.tar.gz", hash = "sha256:93aef85a75d6410cc9af4faf8042faecc0f1b0b508b769ca68e9214d928af798"}, + {file = "mypy_boto3_sms_voice-1.20.1-py3-none-any.whl", hash = "sha256:96796a83f415838bda2337f0af21d04fd69e7e26871c05346b51a46f93cfd50d"}, +] +mypy-boto3-snow-device-management = [ + {file = "mypy-boto3-snow-device-management-1.20.1.tar.gz", hash = "sha256:c1f006983d043a936b8b5efd20c7bb4e5efe0e72d9c5450c59ee3088c01d541f"}, + {file = "mypy_boto3_snow_device_management-1.20.1-py3-none-any.whl", hash = "sha256:f9bd4eb76b893cee3d289a9c615d306be8369ae92a945e5958ab1487a1ae5bc9"}, +] +mypy-boto3-snowball = [ + {file = "mypy-boto3-snowball-1.20.1.tar.gz", hash = "sha256:40cc7a024be93bc92b673b20eb17938b0715e39dcb1ceafebd4bb0def5c1ff14"}, + {file = "mypy_boto3_snowball-1.20.1-py3-none-any.whl", hash = "sha256:0eaca1d7c68d52a9ee6509878ff4822bbe93e5498eba91c57dcc1318aa212829"}, +] +mypy-boto3-sns = [ + {file = "mypy-boto3-sns-1.20.1.tar.gz", hash = "sha256:592ace516e20386c8694f4bfd51dcfe009736b787a0afcc7a216caabcd6cd8a7"}, + {file = "mypy_boto3_sns-1.20.1-py3-none-any.whl", hash = "sha256:42eb473c601f46a0eee8777de8ef0f2737e36b30135722ffff00a8cfa20888ad"}, +] +mypy-boto3-sqs = [ + {file = "mypy-boto3-sqs-1.20.1.tar.gz", hash = "sha256:b1113241704a1015c63add947654571a8b67ade7895fd11a79282b9a1d65b5bc"}, + {file = "mypy_boto3_sqs-1.20.1-py3-none-any.whl", hash = "sha256:b12c71cbad7976aa83dcb2c41c227dc5b520555bf2022c825044568be3e45f82"}, +] +mypy-boto3-ssm = [ + {file = "mypy-boto3-ssm-1.20.1.tar.gz", hash = "sha256:ee09bc60a4f84f60b32cb1f984a1d01223f1963435ca5acde012184251de4c96"}, + {file = "mypy_boto3_ssm-1.20.1-py3-none-any.whl", hash = "sha256:32b4b1a01ab4f639bf1959f1399d73a71ceff1888d781174215a73750116e2bb"}, +] +mypy-boto3-ssm-contacts = [ + {file = "mypy-boto3-ssm-contacts-1.20.1.tar.gz", hash = "sha256:14f0be049151c7b04ac0a9afafc8689783ffcba8123d74583356904f6bc7cd79"}, + {file = "mypy_boto3_ssm_contacts-1.20.1-py3-none-any.whl", hash = "sha256:8a027e716e7d473d398350c9496269bc46fc44c51a2f491a0130c03e1759ba07"}, +] +mypy-boto3-ssm-incidents = [ + {file = "mypy-boto3-ssm-incidents-1.20.1.tar.gz", hash = "sha256:f8a605d4dc4cacb4c0fb1dfb51a616d1b25ee748664f21d27a57d3e337446f84"}, + {file = "mypy_boto3_ssm_incidents-1.20.1-py3-none-any.whl", hash = "sha256:3bc95e40bd612562db990e1ec6db23f8b82d1cc35be34e75c88d91d06acfbf80"}, +] +mypy-boto3-sso = [ + {file = "mypy-boto3-sso-1.20.1.tar.gz", hash = "sha256:dc99e9bf41468f94412d027aafbb5b86a5f921cfca339b65673b62353d32f644"}, + {file = "mypy_boto3_sso-1.20.1-py3-none-any.whl", hash = "sha256:169a2c35b319ffef073d4de64861717affc8b5fe3804d61bc733fca17469afe5"}, +] +mypy-boto3-sso-admin = [ + {file = "mypy-boto3-sso-admin-1.20.1.tar.gz", hash = "sha256:865265d220e8b6a681bfa9c6a2139d641045320d62d42e4d58846f818a09b975"}, + {file = "mypy_boto3_sso_admin-1.20.1-py3-none-any.whl", hash = "sha256:c5f94f415eab26608fff99b88b16ec5abc9b27cbb6fc5b9c9580e904af8dc7eb"}, +] +mypy-boto3-sso-oidc = [ + {file = "mypy-boto3-sso-oidc-1.20.1.tar.gz", hash = "sha256:0c1f37d7965f48995ecc4309942227f9cdb277dbb92900debabdfcf27324ec93"}, + {file = "mypy_boto3_sso_oidc-1.20.1-py3-none-any.whl", hash = "sha256:f8e7beb177b2a1414f7da93b1de0c961ffee477ae3f8bfc58830b6e2b5ff229a"}, +] +mypy-boto3-stepfunctions = [ + {file = "mypy-boto3-stepfunctions-1.20.1.tar.gz", hash = "sha256:368c552f6260ac47ec40574eb8effcdf53be5742f336fbaf712d90b56abcc21e"}, + {file = "mypy_boto3_stepfunctions-1.20.1-py3-none-any.whl", hash = "sha256:437a875c2752018ba858cf29315e1519fc66908a17e1ef499506401a6930651f"}, +] +mypy-boto3-storagegateway = [ + {file = "mypy-boto3-storagegateway-1.20.1.tar.gz", hash = "sha256:e83183935825183da654a41e380454c51c7ded09328cff9b1ab8b8ef47ecbe5d"}, + {file = "mypy_boto3_storagegateway-1.20.1-py3-none-any.whl", hash = "sha256:9d2c6e658d5d16e01f94809b2a20617f1b13cdb9fc427632f04d7f4eda7ac990"}, +] +mypy-boto3-sts = [ + {file = "mypy-boto3-sts-1.20.1.tar.gz", hash = "sha256:b2e0afbea858a1be9f4cc35e7b9b3dbce46c8bd8dd4f5946a1de650a6afcd617"}, + {file = "mypy_boto3_sts-1.20.1-py3-none-any.whl", hash = "sha256:261a6febafcde2ad8554b2a37f60396edd51af01143e3b98e4e94a581ef14226"}, +] +mypy-boto3-support = [ + {file = "mypy-boto3-support-1.20.1.tar.gz", hash = "sha256:e93ec71141e9621e79e0be8728794114b80e6c7e49e22d9e5fef5cba0875c1a2"}, + {file = "mypy_boto3_support-1.20.1-py3-none-any.whl", hash = "sha256:af448053d2de0fafec1bc0f231d8ec2624bb4f9c12785af2cf1a17c8e5b6165c"}, +] +mypy-boto3-swf = [ + {file = "mypy-boto3-swf-1.20.1.tar.gz", hash = "sha256:ad847e5d5d6523ba5a2c2ee2fa636d37c4dbaa53c50c5534604040c1b540d7b5"}, + {file = "mypy_boto3_swf-1.20.1-py3-none-any.whl", hash = "sha256:e17a810b0ee1d1805770b35623f7afa85d4e1cd7c16ee2e0d534cc6fa76e098f"}, +] +mypy-boto3-synthetics = [ + {file = "mypy-boto3-synthetics-1.20.1.tar.gz", hash = "sha256:e272c8c5e8473a335dd54b210048f7e23bd4ff87ded10f0d39a8f285a257c64d"}, + {file = "mypy_boto3_synthetics-1.20.1-py3-none-any.whl", hash = "sha256:cde898aee47f3804d77c1af71ac58943e3cac5dd238305d5b6a3c952d9e0101b"}, +] +mypy-boto3-textract = [ + {file = "mypy-boto3-textract-1.20.1.tar.gz", hash = "sha256:dc8d2490a6f9034142a6867353c07d494bc5109c1e64fd88334a4627bfa284f1"}, + {file = "mypy_boto3_textract-1.20.1-py3-none-any.whl", hash = "sha256:fab708cf2d4641c1c565fab1b7f44f70f3fa44ca7f123f7177fb58aaf31602b2"}, +] +mypy-boto3-timestream-query = [ + {file = "mypy-boto3-timestream-query-1.20.1.tar.gz", hash = "sha256:48fa87b13e96c59eedac5ff36998f5d6a9092a10c87fed566281459ed0bf7c93"}, + {file = "mypy_boto3_timestream_query-1.20.1-py3-none-any.whl", hash = "sha256:20950fd608ddda653c7bf493363e21e947274583c8b1f06a1a302a10d57f4a0c"}, +] +mypy-boto3-timestream-write = [ + {file = "mypy-boto3-timestream-write-1.20.1.tar.gz", hash = "sha256:7ba259c72cd7a706d79d334f44257ce0645930f16e1d8997180c5a39d6cbbddd"}, + {file = "mypy_boto3_timestream_write-1.20.1-py3-none-any.whl", hash = "sha256:de05bb182889ef93496e5a988c86662c0344548e54399adc3db5520835e75e0f"}, +] +mypy-boto3-transcribe = [ + {file = "mypy-boto3-transcribe-1.20.1.tar.gz", hash = "sha256:0a8158148d628b74e15a4980e68c36b181a7c77122aee03a84bea868c3d37959"}, + {file = "mypy_boto3_transcribe-1.20.1-py3-none-any.whl", hash = "sha256:2a2669cf4b5257dd061d026d5c1be3015227ad5be95d7c3af9ac4bb29362f077"}, +] +mypy-boto3-transfer = [ + {file = "mypy-boto3-transfer-1.20.1.tar.gz", hash = "sha256:e81136f560c49c4899ff972115662a85fd3dceb19003ef688623593aaec7a962"}, + {file = "mypy_boto3_transfer-1.20.1-py3-none-any.whl", hash = "sha256:886612cc976873a6803994fb9d093e67c046af81244b9b34bb79ad5243597cff"}, +] +mypy-boto3-translate = [ + {file = "mypy-boto3-translate-1.20.1.tar.gz", hash = "sha256:19d019b927d2380df6cb153e87966115a15c5bec13ec08c0802adb32aedaf061"}, + {file = "mypy_boto3_translate-1.20.1-py3-none-any.whl", hash = "sha256:5bb4c1fe6fe230e929e838df90dd6a3a7876ca95b3412725e278cc315e1623f5"}, +] +mypy-boto3-voice-id = [ + {file = "mypy-boto3-voice-id-1.20.1.tar.gz", hash = "sha256:b84b2acc76b91a3378c384986baead9996d2d44feca67d158cb7555d479f46cf"}, + {file = "mypy_boto3_voice_id-1.20.1-py3-none-any.whl", hash = "sha256:08ffda78b5d59a84adbbed618384c88b83c3043dd120b251dea4edd7dd05a81d"}, +] +mypy-boto3-waf = [ + {file = "mypy-boto3-waf-1.20.1.tar.gz", hash = "sha256:01aa52bc6b472a895c3c4c01064c9f1c9e294c1d12c0e82f94b2d1e7d502adc7"}, + {file = "mypy_boto3_waf-1.20.1-py3-none-any.whl", hash = "sha256:628931c573a783f29ccfff357419956c23b6bcda114a474d1f58ca21f8d2ac54"}, +] +mypy-boto3-waf-regional = [ + {file = "mypy-boto3-waf-regional-1.20.1.tar.gz", hash = "sha256:8b18a2215cd5d43b76012d83a9da91928f768dc33551adcd4c114d8d5f88d472"}, + {file = "mypy_boto3_waf_regional-1.20.1-py3-none-any.whl", hash = "sha256:992a8567acaa924ad11f26b194856f36043a60b58308a6bfb3697b655d2be46e"}, +] +mypy-boto3-wafv2 = [ + {file = "mypy-boto3-wafv2-1.20.1.tar.gz", hash = "sha256:ca102193b7066716a1a4a6c27baf45eb5aa8edc22d31b38895c9b104dd587dd1"}, + {file = "mypy_boto3_wafv2-1.20.1-py3-none-any.whl", hash = "sha256:0b8450562566a6857e79667445cd9fb2c09f0dc7bedab7f26c77bb9f79f7a782"}, +] +mypy-boto3-wellarchitected = [ + {file = "mypy-boto3-wellarchitected-1.20.1.tar.gz", hash = "sha256:dea90a239683324af26be8a57873e6658bdebbe90b6f9f212a710e86d94d9a66"}, + {file = "mypy_boto3_wellarchitected-1.20.1-py3-none-any.whl", hash = "sha256:c8b36b76b6dcd12a3fbe71b69aa223a63589ab2199300076557042cb7d855c5c"}, +] +mypy-boto3-wisdom = [ + {file = "mypy-boto3-wisdom-1.20.1.tar.gz", hash = "sha256:49a2d775b83c2f823864d8ffe3fd993f5ec2bc8deeece8b9db4e554c099701e7"}, + {file = "mypy_boto3_wisdom-1.20.1-py3-none-any.whl", hash = "sha256:29a082b8a5ee6e1c3c63a7ea3173a17704ef12831348b1e40cb3796e7c6d7958"}, +] +mypy-boto3-workdocs = [ + {file = "mypy-boto3-workdocs-1.20.1.tar.gz", hash = "sha256:4e4cda98e18f370b1dc0e931991cb22cf02f0beadb9ad758db078586649f832d"}, + {file = "mypy_boto3_workdocs-1.20.1-py3-none-any.whl", hash = "sha256:66f57d258346f1bf345fc8cf072372d3ea34f84fae54485b93d66a026416d03b"}, +] +mypy-boto3-worklink = [ + {file = "mypy-boto3-worklink-1.20.1.tar.gz", hash = "sha256:f1ea036bc1a41548c303c4afba6e74ec98317461926910a4305ee14b121082b8"}, + {file = "mypy_boto3_worklink-1.20.1-py3-none-any.whl", hash = "sha256:58778bb70bc811feb2aa0edf7d6ec2c09b22cdf7697df1aebdbfb7cbd508bcce"}, +] +mypy-boto3-workmail = [ + {file = "mypy-boto3-workmail-1.20.1.tar.gz", hash = "sha256:4ccb3e7287016e3448153fa242ff69f67f00ce54cd5a264747d61990ee5816e7"}, + {file = "mypy_boto3_workmail-1.20.1-py3-none-any.whl", hash = "sha256:391c2a7af76cd79f1602dfc1baf16a5fb132c57801565d6388badc1482716720"}, +] +mypy-boto3-workmailmessageflow = [ + {file = "mypy-boto3-workmailmessageflow-1.20.1.tar.gz", hash = "sha256:aecba86cf32c73d71a9b7fc85d3a171e1b25be1aa329c635c8fc4e21762a9b6f"}, + {file = "mypy_boto3_workmailmessageflow-1.20.1-py3-none-any.whl", hash = "sha256:32b2ed2afd0ada1ed3be9062d9a77211a670ae40521d2d043b5112a796aceded"}, +] +mypy-boto3-workspaces = [ + {file = "mypy-boto3-workspaces-1.20.1.tar.gz", hash = "sha256:528829c23dcec1354b262fd16616b1dfccf6081fec56c452e53ef96cc4b53f69"}, + {file = "mypy_boto3_workspaces-1.20.1-py3-none-any.whl", hash = "sha256:39b2378d3ac10f1f41a3111d8b7435b53f66c4b15254f126342c255d16a1fb90"}, +] +mypy-boto3-xray = [ + {file = "mypy-boto3-xray-1.20.1.tar.gz", hash = "sha256:3d5c6d0be7af0165879a9bccec62b684c957a1fa3e6dceb2f558a8640b44501c"}, + {file = "mypy_boto3_xray-1.20.1-py3-none-any.whl", hash = "sha256:346fd06c2dc37befebfb7a56157d80e848a9b443b8fe588e0b1aea67b0344ccd"}, +] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] +packaging = [ + {file = "packaging-21.2-py3-none-any.whl", hash = "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0"}, + {file = "packaging-21.2.tar.gz", hash = "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966"}, +] +pastel = [ + {file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"}, + {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"}, +] +pathspec = [ + {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, + {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, +] +pbr = [ + {file = "pbr-5.7.0-py2.py3-none-any.whl", hash = "sha256:60002958e459b195e8dbe61bf22bcf344eedf1b4e03a321a5414feb15566100c"}, + {file = "pbr-5.7.0.tar.gz", hash = "sha256:4651ca1445e80f2781827305de3d76b3ce53195f2227762684eb08f17bc473b7"}, +] +pep8-naming = [ + {file = "pep8-naming-0.12.1.tar.gz", hash = "sha256:bb2455947757d162aa4cad55dba4ce029005cd1692f2899a21d51d8630ca7841"}, + {file = "pep8_naming-0.12.1-py2.py3-none-any.whl", hash = "sha256:4a8daeaeb33cfcde779309fc0c9c0a68a3bbe2ad8a8308b763c5068f86eb9f37"}, +] +platformdirs = [ + {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, + {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +pycodestyle = [ + {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, + {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, +] +pydocstyle = [ + {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, + {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"}, +] +pyflakes = [ + {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, + {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, +] +pylev = [ + {file = "pylev-1.4.0-py2.py3-none-any.whl", hash = "sha256:7b2e2aa7b00e05bb3f7650eb506fc89f474f70493271a35c242d9a92188ad3dd"}, + {file = "pylev-1.4.0.tar.gz", hash = "sha256:9e77e941042ad3a4cc305dcdf2b2dec1aec2fbe3dd9015d2698ad02b173006d1"}, +] +pylic = [ + {file = "pylic-2.1.0-py3-none-any.whl", hash = "sha256:40becc545f841dc66779a478321e9430756546e6843f348eea7a95a66d9a6aca"}, + {file = "pylic-2.1.0.tar.gz", hash = "sha256:0d927629cff3771b3f81842ded334eb07d610cd31b9c93957a73dc35a85f6440"}, +] +pyparsing = [ + {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, + {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, +] +pytest = [ + {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, + {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, +] +pytest-cov = [ + {file = "pytest-cov-2.12.1.tar.gz", hash = "sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7"}, + {file = "pytest_cov-2.12.1-py2.py3-none-any.whl", hash = "sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a"}, +] +pytest-forked = [ + {file = "pytest-forked-1.3.0.tar.gz", hash = "sha256:6aa9ac7e00ad1a539c41bec6d21011332de671e938c7637378ec9710204e37ca"}, + {file = "pytest_forked-1.3.0-py2.py3-none-any.whl", hash = "sha256:dc4147784048e70ef5d437951728825a131b81714b398d5d52f17c7c144d8815"}, +] +pytest-mock = [ + {file = "pytest-mock-3.6.1.tar.gz", hash = "sha256:40217a058c52a63f1042f0784f62009e976ba824c418cced42e88d5f40ab0e62"}, + {file = "pytest_mock-3.6.1-py3-none-any.whl", hash = "sha256:30c2f2cc9759e76eee674b81ea28c9f0b94f8f0445a1b87762cadf774f0df7e3"}, +] +pytest-xdist = [ + {file = "pytest-xdist-2.4.0.tar.gz", hash = "sha256:89b330316f7fc475f999c81b577c2b926c9569f3d397ae432c0c2e2496d61ff9"}, + {file = "pytest_xdist-2.4.0-py3-none-any.whl", hash = "sha256:7b61ebb46997a0820a263553179d6d1e25a8c50d8a8620cd1aa1e20e3be99168"}, +] +python-dateutil = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +regex = [ + {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"}, + {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4"}, + {file = "regex-2021.11.10-cp310-cp310-win32.whl", hash = "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a"}, + {file = "regex-2021.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12"}, + {file = "regex-2021.11.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e"}, + {file = "regex-2021.11.10-cp36-cp36m-win32.whl", hash = "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4"}, + {file = "regex-2021.11.10-cp36-cp36m-win_amd64.whl", hash = "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e"}, + {file = "regex-2021.11.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f"}, + {file = "regex-2021.11.10-cp37-cp37m-win32.whl", hash = "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec"}, + {file = "regex-2021.11.10-cp37-cp37m-win_amd64.whl", hash = "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4"}, + {file = "regex-2021.11.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83"}, + {file = "regex-2021.11.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94"}, + {file = "regex-2021.11.10-cp38-cp38-win32.whl", hash = "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc"}, + {file = "regex-2021.11.10-cp38-cp38-win_amd64.whl", hash = "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d"}, + {file = "regex-2021.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b"}, + {file = "regex-2021.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef"}, + {file = "regex-2021.11.10-cp39-cp39-win32.whl", hash = "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a"}, + {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"}, + {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"}, +] +requests = [ + {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, + {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, +] +rope = [ + {file = "rope-0.19.0.tar.gz", hash = "sha256:64e6d747532e1f5c8009ec5aae3e5523a5bcedf516f39a750d57d8ed749d90da"}, +] +s3transfer = [ + {file = "s3transfer-0.5.0-py3-none-any.whl", hash = "sha256:9c1dc369814391a6bda20ebbf4b70a0f34630592c9aa520856bf384916af2803"}, + {file = "s3transfer-0.5.0.tar.gz", hash = "sha256:50ed823e1dc5868ad40c8dc92072f757aa0e653a192845c94a3b676f4a62da4c"}, +] +safety = [ + {file = "safety-1.10.3-py2.py3-none-any.whl", hash = "sha256:5f802ad5df5614f9622d8d71fedec2757099705c2356f862847c58c6dfe13e84"}, + {file = "safety-1.10.3.tar.gz", hash = "sha256:30e394d02a20ac49b7f65292d19d38fa927a8f9582cdfd3ad1adbbc66c641ad5"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +smmap = [ + {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, + {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, +] +snowballstemmer = [ + {file = "snowballstemmer-2.1.0-py2.py3-none-any.whl", hash = "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2"}, + {file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"}, +] +sqlparse = [ + {file = "sqlparse-0.4.2-py3-none-any.whl", hash = "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"}, + {file = "sqlparse-0.4.2.tar.gz", hash = "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae"}, +] +stdlib-list = [ + {file = "stdlib-list-0.8.0.tar.gz", hash = "sha256:a1e503719720d71e2ed70ed809b385c60cd3fb555ba7ec046b96360d30b16d9f"}, + {file = "stdlib_list-0.8.0-py3-none-any.whl", hash = "sha256:2ae0712a55b68f3fbbc9e58d6fa1b646a062188f49745b495f94d3310a9fdd3e"}, +] +stevedore = [ + {file = "stevedore-3.5.0-py3-none-any.whl", hash = "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c"}, + {file = "stevedore-3.5.0.tar.gz", hash = "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"}, +] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +tomli = [ + {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"}, + {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, +] +typing-extensions = [ + {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, + {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, + {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, +] +urllib3 = [ + {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"}, + {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, +] +zipp = [ + {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, + {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..0309bb63 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,130 @@ +[tool.poetry] +name = "aws_sra_examples" +version = "1.1.0" +description = "AWS Security Reference Architecture Examples" +authors = ["Amazon Web Services "] + +[tool.poetry.dependencies] +python = "^3.9" +boto3 = "^1.18.42" +crhelper = "^2.0.10" + +[tool.poetry.dev-dependencies] +pytest = "^6.2.5" +pytest-cov = "^2.12.1" +pytest-mock = "^3.6.1" +pytest-xdist = "^2.3.0" +black = "^21.9b0" +isort = "^5.9.2" +rope = "^0.19.0" +mypy = "^0.910" +boto3-stubs = { extras = ["all"], version = "^1.18.62" } +flake8 = "^3.9.2" +darglint = "^1.8.0" +dlint = "^0.11.0" +flake8-2020 = "^1.6.0" +flake8-SQL = "^0.4.1" +flake8-annotations-complexity = "^0.0.6" +flake8-bandit = "^2.1.2" +flake8-breakpoint = "^1.1.0" +flake8-broken-line = "^0.3.0" +flake8-bugbear = "^21.4.3" +flake8-builtins = "^1.5.3" +flake8-cognitive-complexity = "^0.1.0" +flake8-comprehensions = "^3.6.1" +flake8-copyright = "^0.2.2" +flake8-docstrings = "^1.6.0" +flake8-eradicate = "^1.1.0" +flake8-executable = "^2.1.1" +flake8-expression-complexity = "^0.0.9" +flake8-fixme = "^1.1.1" +flake8-functions = "^0.0.6" +flake8-markdown = "^0.2.0" +flake8-mock = "^0.3" +flake8-mutable = "^1.2.0" +flake8-no-implicit-concat = "^0.2.1" +flake8-print = "^4.0.0" +flake8-printf-formatting = "^1.1.2" +flake8-pytest-style = "^1.5.0" +flake8-raise = "^0.0.5" +flake8-return = "^1.1.3" +flake8-scrapy = "^0.0.1" +flake8-simplify = "^0.14.1" +flake8-strftime = "^0.3.2" +flake8-todos = "^0.1.5" +flake8-tuple = "^0.4.1" +flake8-typing-imports = "^1.10.1" +flake8-unused-arguments = "^0.0.6" +flake8-use-fstring = "^1.1" +flake8-use-pathlib = "^0.2.0" +flake8-variables-names = "^0.0.4" +pep8-naming = "^0.12.1" +aws-lambda-typing = "^2.4.1" +safety = "^1.10.3" +pylic = "^2.1.0" + + +[tool.black] +line-length = 150 + +[tool.isort] +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true +ensure_newline_before_comments = true +line_length = 150 + +[tool.mypy] +ignore_missing_imports = true +show_error_codes = true +warn_unused_configs = true +warn_unused_ignores = true +warn_no_return = true +show_none_errors = true +check_untyped_defs = true +warn_redundant_casts = true +strict_equality = true +show_column_numbers = true +show_error_context = true +disallow_untyped_calls = true +disallow_untyped_defs = true +disallow_incomplete_defs = true + +[tool.coverage.report] +exclude_lines = ["pragma: no cover"] +show_missing = true + +[tool.coverage.run] +branch = true +omit = ["tests/*"] +source = ["."] + +[tool.pytest.ini_options] +addopts = [ + # "--cov=./", + "--cov-report=xml", + "--cov-report=term", + "--durations=5", + "--numprocesses=auto", + "-rA", + "--ignore-glob=old/*", +] +python_files = ["test_*.py"] +xfail_strict = true + +[tool.pyright] +stubPath = "./typings" +exclude = ["**/node_modules", "**/__pycache__"] +pythonVersion = "3.9" +typeCheckingMode = "basic" +useLibraryCodeForTypes = true +reportGeneralTypeIssues = "none" +reportTypedDictNotRequiredAccess = "none" + +[tool.pylic] +safe_licenses = ["MIT License", "MIT", "BSD License", "Apache Software License"] + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/solutions/README.md b/solutions/README.md deleted file mode 100644 index 2919231b..00000000 --- a/solutions/README.md +++ /dev/null @@ -1,28 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# Solutions - -The structure of the Security Reference Architecture solution folders are in the below format and include the files -needed to deploy the solutions using different deployment platforms including the AWS Control Tower and -CloudFormation StackSets. - -#### Solutions Folder layout - -- AWS Service Name - - AWS Service Solution - - documentation - - diagram (architecture diagram files) - - setup (setup files to help with solution deployment) - - code - - src (Lambda source code) - - templates (CloudFormation template files for deploying resources) - - aws-control-tower - - parameters (provides customizable parameter values that are passed to the template) - > **Update the values to align with your deployment** - - manifest.yaml - > **Update the OU and account names to align with your deployment** - -#### Resources - -- [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) -- [Customizations for AWS Control Tower](https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/) \ No newline at end of file diff --git a/solutions/cloudtrail/cloudtrail-org/README.md b/solutions/cloudtrail/cloudtrail-org/README.md deleted file mode 100644 index 9962b841..00000000 --- a/solutions/cloudtrail/cloudtrail-org/README.md +++ /dev/null @@ -1,276 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# Organization CloudTrail - -The Organization CloudTrail solution will create an Organization CloudTrail within the Organization Management Account -that is encrypted with a Customer Managed KMS Key managed in the Security Account and logs delivered to the Log -Archive Account. An Organization CloudTrail logs all events for all AWS accounts in the AWS Organization. - -When you create an organization trail, a trail with the name that you give it will be created in every AWS account -that belongs to your organization. Users with CloudTrail permissions in member accounts will be able to see this trail -when they log into the AWS CloudTrail console from their AWS accounts, or when they run AWS CLI commands such as -describe-trail. However, users in member accounts will not have sufficient permissions to delete the organization -trail, turn logging on or off, change what types of events are logged, or otherwise alter the organization trail -in any way. - -#### Resources Deployed: -- **Organization CloudTrail** (Primary Account) - - Data events enabled for all S3 buckets (Optional) - - Data events enabled for all Lambda functions (Optional) - - Encrypt log files with SSE-KMS - - Enable log file validation = Yes - - CloudWatch Logs configured -- **Customer Managed Key** (Security Account) - - Key policy restricting access -- **S3 Bucket for CloudTrail Logs** (Log Archive Account) - - Block all public access enabled - - Versioning enabled - - Default encryption enabled - - S3 bucket policy restricting access - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/Organization-CloudTrail-Diagram.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation StackSet and Stack - -**Configuration:** - -* StackSet Names: - * CloudTrailOrgKMSKey - * CloudTrailOrgS3Bucket - * CloudTrailOrgConfig - -### 1.2 AWS Lambda Function - -**Description:** - -The custom CloudFormation Lambda resource Organization CloudTrail configuration currently not supported by -CloudFormation - -**Configuration:** - -* Lambda Function Name = cloudtrail-org-config -* Environment Variables: - * LOG_LEVEL - Default = info, Valid Values = debug, info, warning, error, critical -* Custom Resource Properties: - * AWS_PARTITION - AWS ARN partition (aws, aws-cn, aws-us-gov) - * CLOUDTRAIL_NAME - cloudtrail-org - * CLOUDWATCH_LOG_GROUP_ARN - Provided by CloudFormation after creating the resource - * CLOUDWATCH_LOG_GROUP_ROLE_ARN - Provided by CloudFormation after creating the resource - * KMS_KEY_ID - KMS Key ID ARN provided by CloudFormation from SSM parameter - * ENABLE_DATA_EVENTS_ONLY - Enables just the data events and not the management API events - * ENABLE_LAMBDA_DATA_EVENTS - Enables Lambda data events - * ENABLE_S3_DATA_EVENTS - Enables S3 data events for all buckets - * S3_BUCKET_NAME - Bucket to send logs to - * S3_KEY_PREFIX - Example: CloudTrail - * TAG_KEY1 - Tags the CloudTrail with this key - * TAG_VALUE1 - Tags the CloudTrail with this value - -**Input Validation** - -Validation of environment variables is done to make sure values exist and are the correct type - - -### 1.3 Lambda Execution IAM Role - -**Description:** - -Used by the custom CloudFormation Lambda function to create the Organization CloudTrail - -**Configuration:** - -* Role Name: cloudtrail-org-config-lambda -* Policy Name: cloudtrail-org-lambda -* Permissions: - * CloudTrail - Full: Tagging, Limited: Read, Write on TrailName like prefix - * CloudWatch Logs - Limited Write on LogGroupName like /aws/lambda/[Lambda Function Name] - * IAM - Limited Read, Write on AWSServiceRoleForCloudTrail* - * Organizations - Full: List, Read - -### 1.4 Lambda CloudWatch Log Group - -**Description:** - -Contains Lambda function execution logs - -**Configuration:** - -* Retention = 2 weeks (14 days) -* Log group name = /aws/lambda/[Lambda Function Name] -* DeletionPolicy = Retain - -### 1.5 Organization CloudTrail - -**Description:** - -CloudTrail for all AWS Organization accounts - -**Configuration:** - -* Data events only (Optional) Default = false -* Data events enabled for all S3 buckets (Optional) Default = true -* Data events enabled for all Lambda functions (Optional) Default = true -* CloudWatch Logs configured (Optional) Default = true -* Encrypt log files with SSE-KMS -* Enable log file validation = Yes - -### 1.6 Organization CloudTrail CloudWatch Log Group Role - -**Description:** - -Role used to send logs to CloudWatch - -**Configuration** - -* Role Name: [Resource Prefix]-[CloudTrail Name]-cloudwatch-logs -* Policy Name: [Resource Prefix]-[CloudTrail Name]-cloudwatch-logs -* Permissions - * CloudWatch Logs - Limited:Write to the Organization CloudTrail Log Group “CloudTrail/[CloudTrail Name]” - -### 1.7 Organization CloudTrail CloudWatch Log Group - -**Description:** - -Contains CloudTrail logs - -**Configuration:** - -* Retention = 2 weeks (14 days) -* Log group name = CloudTrail/[CloudTrail Name] - ----- - -## 2.0 Security Tooling Account - -### 2.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account StackSet - -**Configuration:** - -* Stack Name: ...-CloudTrailOrgKMSKey-... - -### 2.2 Organization CloudTrail KMS Key - -**Description:** - -Customer managed KMS key for AWS Organizations CloudTrail logs - -**Configuration:** - -* Alias: OrganizationCloudTrailKMSKey -* Permissions - * Security account (DescribeKey, Decrypt, GenerateDataKey, GenerateDataKeyWithoutPlaintext) - * Management and Logging Accounts (DescribeKey, Encrypt, Decrypt, ReEncrypt*, GenerateDataKey, - GenerateDataKeyWithoutPlaintext) - * CloudTrail Service (DescribeKey, GenerateDataKey, Decrypt, ReEncryptFrom) - ----- - -## 3.0 Security Log Archive Account - -### 3.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account StackSet - -**Configuration:** - -* Stack Name: ...-CloudTrailOrgS3Bucket-... - -### 3.2 Organization CloudTrail S3 Bucket - -**Description:** - -S3 bucket where the CloudTrail logs are sent for all the AWS Organizations accounts - -**Configuration:** - -* S3 Bucket Name: [Bucket Name Prefix]-[ACCOUNT ID]-[REGION] -* Block public access settings set to true -* Versioning Enabled -* Default encryption Enabled -* Ownership controls - Object Ownership = BucketOwnerPreferred -* S3 Bucket Policy Statements - * DenyPutObject - Only allows CloudTrail to put objects - * SecureTransport - Requires logs sent over secure transport - * AWSBucketPermissionsCheck - Allows CloudTrail to check the bucket permissions - * AWSBucketDelivery - Allows CloudTrail to PutObject and PutObjectACL with bucket owner full control - * DenyUnecryptedObjects - Requires PutObject to use KMS server side encryption (Add after initial create) - * DenyWrongKMSKey - Only allows the Organization CloudTrail KMS Key for PutObject (Add after initial create) - - ----- - -# Implementation Instructions - -### [AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets -> **Solution Deployment Order:** -> 1. security (CloudTrailOrgKMSKey) -> 2. log-archive (CloudTrailOrgS3Bucket) -> 3. management (CloudTrailOrgConfig) - -1. Create new or use an existing S3 bucket within the region owned by the Organization Management Account - * Example bucket name: lambda-zips-[Management Account ID]-[AWS Region] - * [Example CloudFormation Template](../../../extras/lambda-s3-buckets.yaml) - * The bucket must allow the s3:GetObject action to the Organization using a bucket policy like the one below to - allow the accounts within the Organization to get the Lambda files. - ``` - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AllowGetObject", - "Effect": "Allow", - "Principal": "*", - "Action": "s3:GetObject", - "Resource": "arn:[AWS::Partition]:s3:::[BUCKET NAME]/*", - "Condition": { - "StringEquals": { - "aws:PrincipalOrgID": "[ORGANIZATION ID]" - } - } - } - ] - } - ``` -2. Package the Lambda code into a zip file and upload it to the Lambda source S3 bucket - * Package and Upload the Lambda zip file to S3 - [Packaging script](../../../extras/packaging-scripts/package-lambda.sh) -3. Create CloudFormation StackSets using the following templates - - | Account | StackSet Name | Template | - | --------------- | ------------- | ---------- | - | Security | CloudTrailOrgKMSKey | templates/cloudtrail-org-kms.yaml | - | Log Archive | CloudTrailOrgS3Bucket | templates/cloudtrail-org-bucket.yaml | - | Management | CloudTrailOrg | templates/cloudtrail-org.yaml | - -4. If replacing an existing Organization Trail with this solution: - * Update any metric filters and any other resources that reference the CloudWatch Log Group - * If a CloudWatch Log Group Subscription is used for forwarding the logs, remove the Subscription from the old - group and add it to the new group - ----- - -# References -* [Creating a CloudTrail for the Organization](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/creating-trail-organization.html) -* [Allowing Cross-Account Access to a KMS Key](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-modifying-external-accounts.html) \ No newline at end of file diff --git a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/README.md b/solutions/cloudtrail/cloudtrail-org/aws-control-tower/README.md deleted file mode 100644 index 32f25993..00000000 --- a/solutions/cloudtrail/cloudtrail-org/aws-control-tower/README.md +++ /dev/null @@ -1,51 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) - 2. [parameters/cloudtrail-org-bucket.json](parameters/cloudtrail-org-bucket.json) - 3. [parameters/cloudtrail-org-kms.json](parameters/cloudtrail-org-kms.json) - 4. [parameters/cloudtrail-org.json](parameters/cloudtrail-org.json) - 5. [templates/cloudtrail-org-bucket.yaml](../templates/cloudtrail-org-bucket.yaml) - 6. [templates/cloudtrail-org-kms.yaml](../templates/cloudtrail-org-kms.yaml) - 7. [templates/cloudtrail-org.yaml](../templates/cloudtrail-org.yaml) -3. Update the parameter files with any specific values for your environment -4. Update the manifest.yaml file with your account names -5. Deploy the Customizations for AWS Control Tower configuration -6. How to verify after the pipeline completes? - 1. Log into the Primary account and navigate to the CloudTrail page - 2. Select Trails and select the "cloudtrail-org" trail - 3. Verify the correct configurations have been applied - 1. Trail log location - 2. Log file SSE-KMS encryption - 3. Log file validation - 4. CloudWatch Logs - 5. Tags - 6. Management Events - 7. Data Events - - -# Delete Instructions - -1. Within the Customizations for AWS Control Tower configuration - 1. Remove the CloudTrail configurations from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the CloudTrail solution -2. Deploy the Customizations for AWS Control Tower configuration -3. After the pipeline completes, log into the Primary account and navigate to the CloudFormation page - 1. Delete the Stack Instance from the CustomControlTower-CloudTrailOrg CloudFormation StackSet - 1. Verify that the CloudTrail created by the solution has been deleted - 2. After the Stack Instance deletes, delete the CustomControlTower-CloudTrailOrg CloudFormation StackSet - 3. Log into the Log Archive account and delete the org-trail-log S3 bucket - 4. Delete the Stack Instance from the CustomControlTower-CloudTrailOrgS3Bucket CloudFormation StackSet - 5. After the Stack Instance deletes, delete the CustomControlTower-CloudTrailOrgS3Bucket CloudFormation StackSet - 6. Delete the Stack Instance from the CustomControlTower-CloudTrailOrgKMSKey CloudFormation StackSet - 7. After the Stack Instance deletes, delete the CustomControlTower-CloudTrailOrgKMSKey CloudFormation StackSet - - - - \ No newline at end of file diff --git a/solutions/cloudtrail/cloudtrail-org/documentation/Organization-CloudTrail-Diagram.png b/solutions/cloudtrail/cloudtrail-org/documentation/Organization-CloudTrail-Diagram.png deleted file mode 100644 index 3716d000..00000000 Binary files a/solutions/cloudtrail/cloudtrail-org/documentation/Organization-CloudTrail-Diagram.png and /dev/null differ diff --git a/solutions/common/register-delegated-administrator/README.md b/solutions/common/register-delegated-administrator/README.md deleted file mode 100644 index c1d60f0a..00000000 --- a/solutions/common/register-delegated-administrator/README.md +++ /dev/null @@ -1,155 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# Register Delegated Administrator Account - -The register delegated administrator account solution is a common solution to register a delegated administrator -account (e.g. Security Tooling Account) within the AWS Organizations management account using the AWS Organizations -APIs. - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/Register-Delegated-Admin-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation StackSet and Stacks within member accounts - -**Configuration:** - -* StackSet Names: - * RegisterDelegatedAdmin - -### 1.2 AWS Lambda Function - -**Description:** - -The custom CloudFormation Lambda resource is required to delegate an administrator account because this capability -is not supported by CloudFormation. - -**Configuration:** - -* Lambda Function Name = [Prefix]-register-delegated-admin -* Environment Variables and Properties (Configurable and set via CloudFormation) - * AWS_SERVICE_PRINCIPAL_LIST - AWS service principals to delegate administration for - * DELEGATED_ADMIN_ACCOUNT_ID - Organization Member Account ID, e.g. Security Tooling Account - * LOG_LEVEL - Default = info, Valid Values = debug, info, warning, error, critical - -**Input Validation** - -Validation of environment variables and properties is done to make sure values exist and are the correct type - -### 1.3 Lambda CloudWatch Log Group - -**Description:** - -Contains Lambda function execution logs - -**Configuration:** - -* Log group name = /aws/lambda/[Lambda Function] - -### 1.4 Lambda Execution IAM Role - -**Description:** - -Used by the custom CloudFormation Lambda function to enable AWS service access for the provided service and register -an AWS account as the delegated administrator. - -**Configuration:** - -* Role Name: [Prefix]-register-delegated-admin-lambda -* Policy Name: [Prefix]-register-delegated-admin-lambda -* Permissions: - * CloudWatch Logs - Limited: Write on LogGroupName like /aws/lambda/[Lambda Function] - * Organizations - Limited: List, Read, Write - -### 1.5 AWS Organizations - -**Description:** - -AWS Organizations APIs are used to delegate the administrator account - -**Configuration:** - -* Delegated Admin Account ID -* Service Principal - - ----- - -## 2.0 Delegated Administrator Account (Security Tooling) - -### 2.1 Services Supported - -**Description:** - -The services that support a delegated administrator account can be configured and managed within this account. - -**Configuration:** - -* Service Principal Mapping - -| Service | Service Principal | -| ---------------------------- | -------------------------------------- | -| AWS IAM Access Analyzer | access-analyzer.amazonaws.com | -| AWS Audit Manager | auditmanager.amazonaws.com | -| AWS CloudFormation StackSets | stacksets.cloudformation.amazonaws.com | -| AWS Config | config.amazonaws.com | -| AWS Config Conformance Packs | config-multiaccountsetup.amazonaws.com | -| Amazon Macie | macie.amazonaws.com | -| AWS Security Hub | securityhub.amazonaws.com | -| Amazon S3 Storage Lens | storage-lens.s3.amazonaws.com | - - ----- - -# Implementation Instructions - -### [AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets - -1. Create new or use an existing S3 bucket within the deployment region owned by the Organization Management Account - * Example bucket name: lambda-zips-[Management Account ID]-[AWS region] - * [Example CloudFormation Template](../../../extras/lambda-s3-buckets.yaml) - * Each bucket must allow the s3:GetObject action to the AWS Organization using a bucket policy like the one below - to allow the accounts within the Organization to get the Lambda files. -2. Package the Lambda code into a zip file and upload it to the S3 bucket - * Package and Upload the Lambda zip file to S3 - [Packaging script](../../../extras/packaging-scripts/package-lambda.sh) - ```shell - export BUCKET=lambda-zips-CHANGE_ME_ACCOUNT_ID-CHANGE_ME_REGION - sh ~/aws-security-reference-architecture-examples/extras/packaging-scripts/package-lambda.sh \ - --file_name common-register-delegated-administrator.zip \ - --bucket $BUCKET \ - --src_dir ~/aws-security-reference-architecture-examples/solutions/common/register-delegated-admninistrator/code/src - ``` -3. Create a CloudFormation StackSet or Stack with the following template - - | Account | StackSet Name | Template | - | --------------- | ----------------- | ---------- | - | Management | RegisterDelegatedAdmin | templates/register-delegated-admin.yaml | -4. Verify configuration using the following AWS CLI shell script - ```shell - for accountId in $(aws organizations list-delegated-administrators --query 'DelegatedAdministrators[*].Id' \ - --output text); do echo -e "$accountId\n Service Principals: " \ - $(aws organizations list-delegated-services-for-account --account-id $accountId \ - --query 'DelegatedServices[*].ServicePrincipal'); done - ``` - ----- - -# References - -* [AWS services that you can use with AWS Organizations](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_integrate_services_list.html) \ No newline at end of file diff --git a/solutions/common/register-delegated-administrator/aws-control-tower/README.md b/solutions/common/register-delegated-administrator/aws-control-tower/README.md deleted file mode 100644 index 7918b8d9..00000000 --- a/solutions/common/register-delegated-administrator/aws-control-tower/README.md +++ /dev/null @@ -1,68 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Package and upload the common-register-delegated-administrator Lambda function - ```shell - export AWS_ACCESS_KEY_ID=INSERT_AWS_ACCESS_KEY_ID - export AWS_SECRET_ACCESS_KEY=INSERT_AWS_SECRET_ACCESS_KEY - export AWS_SESSION_TOKEN=INSERT_AWS_SESSION_TOKEN - - export BUCKET=lambda-zips-CHANGE_ME_ACCOUNT_ID-CHANGE_ME_REGION - sh ~/aws-security-reference-architecture-examples/extras/packaging-scripts/package-lambda.sh \ - --file_name common-register-delegated-administrator.zip \ - --bucket $BUCKET \ - --src_dir ~/aws-security-reference-architecture-examples/solutions/common/register-delegated-admninistrator/code/src - ``` -3. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) -> manifest.yaml - 2. [common/register-delegated-administrator/aws-control-tower/parameters/common-register-delegated-administrator.json](../../../common/register-delegated-administrator/aws-control-tower/parameters/common-register-delegated-administrator.json) - -> parameters/common-register-delegated-administrator.json - 3. [common/register-delegated-administrator/templates/common-register-delegated-administrator.yaml](../../../common/register-delegated-administrator/templates/common-register-delegated-administrator.yaml) - -> templates/common-register-delegated-administrator.yaml -4. Add service principals to the pServicePrincipalList parameter in the - parameters/common-register-delegated-administrator.json -5. Add the [common/register-delegated-administrator/aws-control-tower/manifest.yaml](../../../common/register-delegated-administrator/aws-control-tower) - resource configuration to your manifest.yaml file. - ```yaml - ... - cloudformation_resources: - # ----------------------------------------------------------------------------- - # Common Register Delegated Administrator - # ----------------------------------------------------------------------------- - - name: CommonRegisterDelegatedAdmin - template_file: templates/common-register-delegated-administrator.yaml - parameter_file: parameters/common-register-delegated-administrator.json - deploy_method: stack_set - deploy_to_account: - - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME - ... - ``` -6. Update the manifest.yaml file with your account names and SSM parameters -7. Deploy the Customizations for AWS Control Tower configuration -8. How to verify after the pipeline completes? - 1. Export the management account credentials in your local terminal and run the following script: - ```shell - for accountId in $(aws organizations list-delegated-administrators --query 'DelegatedAdministrators[*].Id' \ - --output text); do echo -e "$accountId\n Service Principals: " \ - $(aws organizations list-delegated-services-for-account --account-id $accountId \ - --query 'DelegatedServices[*].ServicePrincipal'); done - ``` - 2. Verify that the service principals are listed for the delegated administrator account - -# Delete Instructions - -1. Verify that all solutions related to the service principals are removed before deleting the solution -2. Within the Customizations for AWS Control Tower configuration - 1. Remove the Common Register Delegated Administrator configuration from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the Common Register Delegated Administrator solution -3. Deploy the Customizations for AWS Control Tower configuration -4. After the pipeline completes, log into the Management account and navigate to the CloudFormation StackSet page - 1. Delete the Stack Instance from the CustomControlTower-CommonRegisterDelegatedAdmin CloudFormation StackSet - 2. After the Stack Instance deletes, delete the CustomControlTower-CommonRegisterDelegatedAdmin CloudFormation - StackSet - \ No newline at end of file diff --git a/solutions/common/register-delegated-administrator/aws-control-tower/parameters/common-register-delegated-administrator.json b/solutions/common/register-delegated-administrator/aws-control-tower/parameters/common-register-delegated-administrator.json deleted file mode 100644 index 83b9b269..00000000 --- a/solutions/common/register-delegated-administrator/aws-control-tower/parameters/common-register-delegated-administrator.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "ParameterKey": "pDelegatedAdminAccountId", - "ParameterValue": "$[alfred_ssm_/org/member/Audit/account_id]" - }, - { - "ParameterKey": "pLambdaExecutionRoleName", - "ParameterValue": "cfct-common-register-delegated-admin-lambda" - }, - { - "ParameterKey": "pLambdaFunctionName", - "ParameterValue": "cfct-common-register-delegated-admin" - }, - { - "ParameterKey": "pLambdaS3BucketName", - "ParameterValue": "$[alfred_ssm_/org/primary/lambda_zips_bucket/us-east-1]" - }, - { - "ParameterKey": "pLambdaZipFileName", - "ParameterValue": "common-register-delegated-administrator.zip" - }, - { - "ParameterKey": "pLogLevel", - "ParameterValue": "debug" - }, - { - "ParameterKey": "pServicePrincipalList", - "ParameterValue": "CHANGE_ME_SERVICE_PRINCIPAL_LIST" - }, - { - "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" - }, - { - "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" - } -] \ No newline at end of file diff --git a/solutions/common/register-delegated-administrator/documentation/Register-Delegated-Admin-Architecture.png b/solutions/common/register-delegated-administrator/documentation/Register-Delegated-Admin-Architecture.png deleted file mode 100644 index ecd556b3..00000000 Binary files a/solutions/common/register-delegated-administrator/documentation/Register-Delegated-Admin-Architecture.png and /dev/null differ diff --git a/solutions/config/aggregator-acct/README.md b/solutions/config/aggregator-acct/README.md deleted file mode 100644 index 7f0f0893..00000000 --- a/solutions/config/aggregator-acct/README.md +++ /dev/null @@ -1,237 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# AWS Config Aggregator Account - -The AWS Config Aggregator Account solution enables an AWS Config Aggregator in a specified account and creates -authorizations within each member account. - -An aggregator is an AWS Config resource type that collects AWS Config configuration and compliance data -from the following: -* Multiple accounts and multiple regions. -* Single account and multiple regions. -* An organization in AWS Organizations and all the accounts in that organization. - -You can use an aggregator to view the resource configuration and compliance data recorded in AWS Config. - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/diagram/AWS-Config-Aggregator-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources are deployed via a CloudFormation StackSet and a Stack Instance within the management and each member - account - -**Configuration:** - -* StackSet Names: - * AWSConfigAggregatorLambda - * AWSConfigAggregatorRole - * AWSConfigAggregatorAuthorization - -### 1.2 EventBridge Scheduled Rule - -**Description:** - -The scheduled rule triggers the Lambda Function every day to check if a new account has been added to the AWS - Organization - -**Configuration:** - -* pEventRuleName: Name of the scheduled event rule - -### 1.3 Lambda Execution IAM Role - -**Description:** - -Used by the Lambda function to query active AWS Organization accounts and add them to the AWS Config Aggregator - within the specified account - -**Configuration:** - -* Role and Policy Name: [Prefix]-aggregator-acct-lambda -* Permissions: - * CloudWatch Logs - Limited: Write on LogGroupName like /aws/lambda/[Lambda Function Name] - * Organizations - Limited: List, Read - * STS - Limited: Write RoleName like [Prefix]-aggregator-acct - - -### 1.4 AWS Lambda Function - -**Description:** - -The Lambda Function queries for all active AWS Organizations accounts and adds them to the AWS Config Aggregator - -**Configuration:** - -* Lambda Function Name = [Prefix]-aggregator-acct -* Environment Variables (Configurable and set via CloudFormation) - * LOG_LEVEL = Valid values (info, warning, error, critical) - * ASSUME_ROLE_NAME = Role to assume in the AWS Config Aggregator Account to update the active accounts - * AWS_CONFIG_MANAGEMENT_ACCOUNT_ID = AWS Config Aggregator Account (e.g. Security Tooling Account) - * AWS_CONFIG_AGGREGATOR_NAME = [Prefix]ConfigAggregator - * AWS_PARTITION = Valid values (aws, aws-cn, aws-us-gov) - -**Input Validation** - -Validation of environment variables is done to make sure values exist and are the correct type - -### 1.5 Lambda CloudWatch Log Group - -**Description:** - -The CloudWatch Log Group containing the Lambda function execution logs - -**Configuration:** - -* Retention = Default 2 weeks (14 days) -* Log group name = /aws/lambda/[Lambda Function Name] - -### 1.6 AWS Config Authorization - -**Description:** - -Authorizes the AWS Config Aggregator account to collect AWS Config configuration and compliance data - -**Configuration:** - -* AWS Config Aggregator Name = [Prefix]ConfigAggregator -* AWS Config Aggregator Account ID = The Security Tooling Account ID -* AWS Config Aggregator Region = The aggregator region within the Security Tooling account - ----- - -## 2.0 Security Tooling Account - -### 2.1 AWS CloudFormation - -**Description:** - -Deployment of all resources is done via a CloudFormation Stack created by the Management account CloudFormation StackSet - -**Configuration:** - -* Stack Name = [Prefix]-AggregatorAcctRole-... - -### 2.2 AWS Config Aggregator Role - -**Description:** - -Creates the IAM role assumed by the Management account Lambda function to update the AWS Config Aggregator with - active accounts - -**Configuration:** - -* Role and Policy Name: [Prefix]-aggregator-acct -* Permissions: - * Config - Limited: Write - -### 2.3 AWS Config Aggregator - -**Description:** - -The AWS Config Aggregator collects AWS Config configuration and compliance data from authorized accounts and regions - -**Configuration:** - -* Provided by the Management account Lambda function which queries active AWS Organizations accounts and adds them to - the Aggregator - ----- - -## 3.0 All Existing and Future Organization Member Accounts - -### 3.1 AWS CloudFormation - -**Description:** - -Deployment of all resources is done via CloudFormation Stack created by the Management account CloudFormation StackSet - -**Configuration:** - -* Stack Name = [Prefix]-AggregatorAcctAuthorization-... - -### 3.2 AWS Config Authorization - -**Description:** - -Authorizes the AWS Config Aggregator account to collect AWS Config configuration and compliance data - -**Configuration:** - -* AWS Config Aggregator Name = [Prefix]ConfigAggregator -* AWS Config Aggregator Account ID = The Security Tooling Account ID - ----- - -# Implementation Instructions - -### CloudFormation StackSets - -> **Solution Deployment Order:** -> 1. management account (AWSConfigAggregatorLambda) -> 2. security account (AWSConfigAggregatorRole) -> 3. member accounts (AWSConfigAggregatorAuthorization) - -#### Pre-requisites -* No existing AWS Config Aggregator -* Make sure there are no SCP statements preventing the following actions: - * config:DeleteConfigurationAggregator - * config:PutConfigurationAggregator - -#### Instructions -1. Create new or use existing S3 bucket within the region owned by the Organization Management Account. The - region needs to be the same as the AWS Config Aggregator CloudFormation Stack region. The default region in the - manifest.yaml file is used. - * Example bucket name: lambda-zips-[Management Account ID]-[AWS Region] - * [Example CloudFormation Template](../../../extras/lambda-s3-buckets.yaml) - * The bucket must allow the s3:GetObject action to the Organization using a bucket policy like the one below to - allow the accounts within the Organization to get the Lambda files. - ``` - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AllowGetObject", - "Effect": "Allow", - "Principal": "*", - "Action": "s3:GetObject", - "Resource": "arn:[AWS::Partition]:s3:::[BUCKET NAME]/*", - "Condition": { - "StringEquals": { - "aws:PrincipalOrgID": "[ORGANIZATION ID]" - } - } - } - ] - } - ``` -2. Package the Lambda code into a zip file and upload it to the S3 bucket - * Package and Upload the Lambda zip file to S3 - [Packaging script](../../../extras/packaging-scripts/package-lambda.sh) -3. Copy the below folders/files to the new add-on folder excluding the lambda folder - - | Account | StackSet Name | Template | - | --------------- | ------------- | ---------- | - | Management | AWSConfigAggregatorLambda | templates/aggregator-acct-lambda.yaml | - | Security | AWSConfigAggregatorRole | templates/aggregator-acct-role.yaml | - | All Member Accounts | AWSConfigAggregatorAuthorization | templates/aggregator-acct-authorization.yaml | - -4. To trigger the initial deployment before the scheduled rule, disable then enable the scheduled event rule - ----- - -# References -* [Multi-Account Multi-Region Data Aggregation](https://docs.aws.amazon.com/config/latest/developerguide/aggregate-data.html) diff --git a/solutions/config/aggregator-acct/code/src/app.py b/solutions/config/aggregator-acct/code/src/app.py deleted file mode 100644 index 994d3754..00000000 --- a/solutions/config/aggregator-acct/code/src/app.py +++ /dev/null @@ -1,186 +0,0 @@ -######################################################################## -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: MIT-0 -######################################################################## -import logging -import os -import re -import json -import boto3 -from botocore.exceptions import ClientError -from crhelper import CfnResource - -# Setup Default Logger -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) - -""" -The purpose of this script is to setup an AWS Config Aggregator in a designated -account and adds all the AWS Organization accounts. -""" - -# Initialise the helper, all inputs are optional, this example shows the defaults -helper = CfnResource(json_logging=False, log_level="DEBUG", boto_level="CRITICAL") - -PAGE_SIZE = 20 # 20 is the max for the list_accounts paginator -STS_CLIENT = boto3.client("sts") - -try: - # Process Environment Variables - if "LOG_LEVEL" in os.environ: - LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO") - if isinstance(LOG_LEVEL, str): - log_level = logging.getLevelName(LOG_LEVEL.upper()) - logger.setLevel(log_level) - else: - raise ValueError("LOG_LEVEL parameter is not a string") - - AWS_CONFIG_MANAGEMENT_ACCOUNT_ID = os.environ.get("AWS_CONFIG_MANAGEMENT_ACCOUNT_ID", "") - if not AWS_CONFIG_MANAGEMENT_ACCOUNT_ID or not re.match("^[0-9]{12}$", AWS_CONFIG_MANAGEMENT_ACCOUNT_ID): - raise ValueError("AWS_CONFIG_MANAGEMENT_ACCOUNT_ID parameter is missing or invalid") - - ASSUME_ROLE_NAME = os.environ.get("ASSUME_ROLE_NAME", "") - if not ASSUME_ROLE_NAME or not re.match("[\\w+=,.@-]+", ASSUME_ROLE_NAME): - raise ValueError("ASSUME_ROLE_NAME parameter is missing or invalid") - - AWS_CONFIG_AGGREGATOR_NAME = os.environ.get("AWS_CONFIG_AGGREGATOR_NAME", "") - if not AWS_CONFIG_AGGREGATOR_NAME or not re.match("[\\w_-]+", AWS_CONFIG_AGGREGATOR_NAME): - raise ValueError("AWS_CONFIG_AGGREGATOR_NAME parameter is missing or invalid") - - AWS_PARTITION = os.environ.get("AWS_PARTITION", "") - if AWS_PARTITION not in ("aws", "aws-cn", "aws-us-gov"): - raise ValueError("AWS_PARTITION parameter is missing or invalid") - -except Exception as e: - helper.init_failure(e) - - -def get_all_organization_accounts() -> dict: - """ - Gets a list of Active AWS Accounts in the Organization. - - :return: AWS Account Dictionary - """ - aws_accounts_dict = dict() - - try: - session = boto3.Session() - org_client = session.client("organizations", region_name="us-east-1") - paginator = org_client.get_paginator("list_accounts") - - for page in paginator.paginate(PaginationConfig={"PageSize": PAGE_SIZE}): - for acct in page["Accounts"]: - if acct["Status"] == "ACTIVE": # Store active accounts in a dict - aws_accounts_dict.update({acct["Id"]: acct["Email"]}) - - logger.info(f"Active accounts count: {len(aws_accounts_dict.keys())}, " - f"Active accounts: {json.dumps(aws_accounts_dict)}") - except Exception as exc: - logger.error(f"Unexpected error: {str(exc)}") - raise ValueError("Error retrieving accounts") - - return aws_accounts_dict - - -def assume_role(aws_account_number, role_name): - """ - Assumes the provided role in the provided account and returns a session - :param aws_account_number: AWS Account Number - :param role_name: Role name to assume in target account - :return: session for the account and role name - """ - try: - response = STS_CLIENT.assume_role( - RoleArn=f"arn:{AWS_PARTITION}:iam::{aws_account_number}:role/{role_name}", - RoleSessionName="EnableConfigAggregator", - ) - - # Storing STS credentials - session = boto3.Session( - aws_access_key_id=response["Credentials"]["AccessKeyId"], - aws_secret_access_key=response["Credentials"]["SecretAccessKey"], - aws_session_token=response["Credentials"]["SessionToken"], - ) - - logger.debug(f"Assumed session for {aws_account_number}") - - return session - except Exception as exc: - logger.error(f"Unexpected error: {str(exc)}") - raise ValueError("Error assuming role") - - -def enable_config_aggregator(): - """ - Enables an AWS Config Aggregator in the provided account - :return: None - """ - - try: - aws_account_dict = get_all_organization_accounts() - session = assume_role(AWS_CONFIG_MANAGEMENT_ACCOUNT_ID, ASSUME_ROLE_NAME) - - config_client = session.client("config") - update_config = config_client.put_configuration_aggregator( - ConfigurationAggregatorName=AWS_CONFIG_AGGREGATOR_NAME, - AccountAggregationSources=[ - {"AccountIds": list(aws_account_dict.keys()), "AllAwsRegions": True} - ], - ) - logger.debug(update_config) - except Exception as exc: - logger.error(f"Unexpected error: {str(exc)}") - raise ValueError("Error enabling config aggregator") - - -@helper.create -@helper.update -def create(event, context): - """ - CloudFormation Create Event. - :param event: event data - :param context: runtime information - :return: Resource ID - """ - logger.info(f"Event: {event.get('RequestType')}") - enable_config_aggregator() - - return "AWSConfigAggregatorResourceId" - - -@helper.delete -def delete(event, context): - """ - CloudFormation Delete Event. - :param event: event data - :param context: runtime information - :return: CloudFormation response - """ - logger.info("Delete Event") - try: - session = assume_role(AWS_CONFIG_MANAGEMENT_ACCOUNT_ID, ASSUME_ROLE_NAME) - - config_client = session.client("config") - delete_config = config_client.delete_configuration_aggregator( - ConfigurationAggregatorName=AWS_CONFIG_AGGREGATOR_NAME - ) - logger.debug(delete_config) - logger.info("Deleted the AWS Config Aggregator") - except ClientError as exc: - logger.error(f"Unexpected error: {str(exc)}") - raise - - -def lambda_handler(event, context): - """ - Lambda Handler - :param event: event data - :param context: runtime information - :return: CloudFormation response or True - """ - logger.info("....Lambda Handler Started....") - if "detail-type" in event: - enable_config_aggregator() - return True - else: - helper(event, context) diff --git a/solutions/config/aggregator-acct/code/src/requirements.txt b/solutions/config/aggregator-acct/code/src/requirements.txt deleted file mode 100644 index 33511736..00000000 --- a/solutions/config/aggregator-acct/code/src/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -#install latest -boto3 -crhelper \ No newline at end of file diff --git a/solutions/config/aggregator-acct/documentation/diagram/AWS-Config-Aggregator-Architecture.png b/solutions/config/aggregator-acct/documentation/diagram/AWS-Config-Aggregator-Architecture.png deleted file mode 100644 index b5673ce1..00000000 Binary files a/solutions/config/aggregator-acct/documentation/diagram/AWS-Config-Aggregator-Architecture.png and /dev/null differ diff --git a/solutions/config/aggregator-acct/documentation/diagram/AWS-Config-Aggregator-Architecture.pptx b/solutions/config/aggregator-acct/documentation/diagram/AWS-Config-Aggregator-Architecture.pptx deleted file mode 100644 index 35be0f2f..00000000 Binary files a/solutions/config/aggregator-acct/documentation/diagram/AWS-Config-Aggregator-Architecture.pptx and /dev/null differ diff --git a/solutions/config/aggregator-acct/templates/aggregator-acct-authorization.yaml b/solutions/config/aggregator-acct/templates/aggregator-acct-authorization.yaml deleted file mode 100644 index d2e7c004..00000000 --- a/solutions/config/aggregator-acct/templates/aggregator-acct-authorization.yaml +++ /dev/null @@ -1,67 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09 -Description: > - Enable Config aggregation. This builds the base aggregator, and an aggregator authorization in each account, - but the accounts need to be added to the aggregator via a Lambda function that will run periodically to ensure all - accounts/regions are enabled. - -Metadata: - AWS::CloudFormation::Interface: - ParameterGroups: - - - Label: - default: Config Aggregator Attributes - Parameters: - - pAWSConfigAggregatorName - - pAWSConfigManagementAccountId - - pAggregatorRegion - - ParameterLabels: - pAWSConfigManagementAccountId: - default: AWS Config Aggregator Management Account ID - pAWSConfigAggregatorName: - default: AWS Config Aggregator Name - pAggregatorRegion: - default: AWS Config Aggregator Region - -Parameters: - - pAWSConfigManagementAccountId: - Type: String - Description: > - The AWS Config management account ID. For example, the security account ID - - pAWSConfigAggregatorName: - Type: String - Default: AWSConfigAggregator - Description: > - AWS Config Aggregator Name - - pAggregatorRegion: - Type: String - Default: us-east-1 - Description: > - AWS region where AWS Config Aggregator will consolidate data - -Conditions: - cInSecurityAccount: - !Equals - - !Sub ${AWS::AccountId} - - !Ref pAWSConfigManagementAccountId - -Resources: - rAggregatorAuth: - Type: AWS::Config::AggregationAuthorization - DeletionPolicy: Retain - Properties: - AuthorizedAccountId: !Ref pAWSConfigManagementAccountId - AuthorizedAwsRegion: !Ref pAggregatorRegion - - rAggregator: - Type: AWS::Config::ConfigurationAggregator - Condition: cInSecurityAccount - Properties: - AccountAggregationSources: - - AccountIds: - - !Ref pAWSConfigManagementAccountId - AllAwsRegions: true - ConfigurationAggregatorName: !Ref pAWSConfigAggregatorName diff --git a/solutions/config/aggregator-acct/templates/aggregator-acct-lambda.yaml b/solutions/config/aggregator-acct/templates/aggregator-acct-lambda.yaml deleted file mode 100644 index d849a731..00000000 --- a/solutions/config/aggregator-acct/templates/aggregator-acct-lambda.yaml +++ /dev/null @@ -1,273 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09 -Description: Updates Config Aggregator configuration on a scheduled basis to ensure all accounts/regions are included. - -Metadata: - AWS::CloudFormation::Interface: - ParameterGroups: - - - Label: - default: Lambda Function Attributes - Parameters: - - pLambdaFunctionName - - pLambdaS3BucketName - - pLambdaZipFileName - - pRoleToAssume - - pAWSConfigAggregatorName - - pAWSConfigManagementAccountId - - pLogLevel - - pDefaultLogGroupRetention - - - - Label: - default: Event Attributes - Parameters: - - pEventRuleName - - - - Label: - default: Lambda Role Attributes - Parameters: - - pAWSConfigAggregatorLambdaRoleName - - pTagKey1 - - pTagValue1 - - - Label: - default: Policy Attributes - Parameters: - - pRoleToAssume - - pOrganizationId - - ParameterLabels: - pLambdaFunctionName: - default: Lambda Function Name - pLambdaS3BucketName: - default: Lambda Source S3 Bucket Name - pLambdaZipFileName: - default: Lambda Zip File Name - pAWSConfigAggregatorName: - default: AWS Config Aggregator Name - pAWSConfigManagementAccountId: - default: AWS Config Aggregator Management Account ID - pLogLevel: - default: Lambda Function Log Level - pDefaultLogGroupRetention: - default: Default Log Group Retention - - pAWSConfigAggregatorLambdaRoleName: - default: Lambda Role Name - pTagKey1: - default: Lambda Role Tag Key - pTagValue1: - default: Lambda Role Tag Value - pOrganizationId: - default: Organization ID - pRoleToAssume: - default: Role to Assume in Each Account - - pEventRuleName: - default: Scheduled Event Rule Name - -Parameters: - - pAWSConfigManagementAccountId: - Type: String - Description: > - The AWS Config management account ID - - pAWSConfigAggregatorLambdaRoleName: - Type: String - Default: config-aggregator-lambda - Description: > - Lambda execution role for enabling AWS Config Aggregator in all accounts - - pRoleToAssume: - Type: String - Default: config-aggregator - Description: > - Role name to assume for enabling AWS Config Aggregator - - pAWSConfigAggregatorName: - Type: String - Default: AWSConfigAggregator - Description: > - AWS Config Aggregator Name - - pLambdaFunctionName: - Type: String - Description: Lambda function name - - pLambdaS3BucketName: - Type: String - Description: S3 bucket containing the zip file for the Lambda function - - pLambdaZipFileName: - Type: String - Description: Lambda zip file containing code - - pDefaultLogGroupRetention: - Type: String - Default: 14 - Description: Specifies the number of days you want to retain log events - AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653] - - pLogLevel: - Type: String - Default: info - Description: Lambda Function Logging Level - AllowedValues: - - info - - warning - - error - - critical - - pEventRuleName: - Type: String - Default: config-aggregator - Description: Event rule name to trigger Config Aggregator Lambda - - pOrganizationId: - Type: String - Description: AWS Organizations ID - MinLength: 12 - MaxLength: 12 - AllowedPattern: '^o-[a-z0-9]{10,32}$' - ConstraintDescription: > - The Org Id must be a 12 character string starting with o- and followed by 10 lower case alphanumeric characters - - pTagKey1: - Type: String - Description: Tag key - - pTagValue1: - Type: String - Description: Tag key value - -Resources: - - rLambdaLogGroup: - Type: AWS::Logs::LogGroup - Properties: - RetentionInDays: !Ref pDefaultLogGroupRetention - LogGroupName: !Sub "/aws/lambda/${pLambdaFunctionName}" - - AWSConfigAggregatorLambdaRole: - Type: AWS::IAM::Role - Metadata: - cfn_nag: - rules_to_suppress: - - id: W11 - reason: organizations:ListAccounts and DescribeAccount do not support resource restriction - - id: W28 - reason: Role Name required to restrict assume role in member account role - Properties: - RoleName: !Ref pAWSConfigAggregatorLambdaRoleName - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - - Effect: "Allow" - Principal: - Service: - - "lambda.amazonaws.com" - Action: - - "sts:AssumeRole" - Path: "/" - Tags: - - Key: !Ref pTagKey1 - Value: !Ref pTagValue1 - Policies: - - PolicyName: "aggregator-acct-policy-organizations" - PolicyDocument: - Version: 2012-10-17 - Statement: - - Sid: OrganizationsAccess - Effect: Allow - Action: - - organizations:ListAccounts - - organizations:DescribeAccount - Resource: '*' - Condition: - StringEquals: - "aws:PrincipalOrgId": !Ref pOrganizationId - - - PolicyName: "aggregator-acct-policy-sts" - PolicyDocument: - Version: 2012-10-17 - Statement: - - Sid: AssumeRole - Effect: Allow - Action: sts:AssumeRole - Resource: !Sub arn:${AWS::Partition}:iam::*:role/${pRoleToAssume} - Condition: - StringEquals: - "aws:PrincipalOrgId": !Ref pOrganizationId - - - PolicyName: "aggregator-acct-policy-logs" - PolicyDocument: - Version: 2012-10-17 - Statement: - - Sid: CreateLogGroup - Effect: Allow - Action: logs:CreateLogGroup - Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup} - - - Sid: CreateLogStreamAndEvents - Effect: Allow - Action: - - logs:CreateLogStream - - logs:PutLogEvents - Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup}:log-stream:* - - rAWSConfigAggregatorLambdaFunction: - Type: "AWS::Lambda::Function" - Metadata: - cfn_nag: - rules_to_suppress: - - id: W58 - reason: Lambda role provides access to CloudWatch Logs - Properties: - Description: Enable AWS Config Aggregator in all accounts and regions - FunctionName: !Ref pLambdaFunctionName - Handler: "app.lambda_handler" - Role: !GetAtt AWSConfigAggregatorLambdaRole.Arn - Code: - S3Bucket: !Ref pLambdaS3BucketName - S3Key: !Ref pLambdaZipFileName - Runtime: "python3.8" - Timeout: 300 - Environment: - Variables: - LOG_LEVEL: !Ref pLogLevel - ASSUME_ROLE_NAME: !Ref pRoleToAssume - AWS_CONFIG_MANAGEMENT_ACCOUNT_ID: !Ref pAWSConfigManagementAccountId - AWS_CONFIG_AGGREGATOR_NAME: !Ref pAWSConfigAggregatorName - AWS_PARTITION: !Sub ${AWS::Partition} - - rScheduledRule: - Type: AWS::Events::Rule - Properties: - Description: Config Aggregator Lambda Scheduler - Name: !Ref pEventRuleName - ScheduleExpression: "rate(1 day)" - State: "ENABLED" - Targets: - - - Arn: !GetAtt rAWSConfigAggregatorLambdaFunction.Arn - Id: "DailyInvite" - - rPermissionForEventsToInvokeLambda: - Type: AWS::Lambda::Permission - Properties: - FunctionName: !GetAtt rAWSConfigAggregatorLambdaFunction.Arn - Action: "lambda:InvokeFunction" - Principal: "events.amazonaws.com" - SourceArn: !GetAtt rScheduledRule.Arn - - ############################################### - ## Can be uncommented after the initial run - ############################################### - # rLambdaCustomResource: - # Type: Custom::LambdaCustomResource - # Version: "1.0" - # Properties: - # ServiceToken: !GetAtt rAWSConfigAggregatorLambdaFunction.Arn diff --git a/solutions/config/aggregator-acct/templates/aggregator-acct-role.yaml b/solutions/config/aggregator-acct/templates/aggregator-acct-role.yaml deleted file mode 100644 index c62859b1..00000000 --- a/solutions/config/aggregator-acct/templates/aggregator-acct-role.yaml +++ /dev/null @@ -1,91 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09 -Description: > - Enable Config aggregation. This builds the base aggregator, and an aggregator authorization in - each account, but the accounts need to be added to the aggregator via a Lambda function that will run periodically - to ensure all accounts/regions are enabled. - -Metadata: - AWS::CloudFormation::Interface: - ParameterGroups: - - - Label: - default: Config Aggregator Role Attributes - Parameters: - - pAWSConfigAggregatorRoleName - - pPrimaryAccountId - - pTagKey1 - - pTagValue1 - - pAWSConfigAggregatorLambdaRoleName - - ParameterLabels: - pPrimaryAccountId: - default: Organization Primary Account ID - pAWSConfigAggregatorRoleName: - default: AWS Config Aggregator Role Name - pTagKey1: - default: Lambda Role Tag Key - pTagValue1: - default: Lambda Role Tag Value - pAWSConfigAggregatorLambdaRoleName: - default: Lambda Role Name - -Parameters: - pPrimaryAccountId: - Type: String - Description: Organizations primary account ID - - pAWSConfigAggregatorRoleName: - Type: String - Description: AWS Config Aggregator Role Name - Default: config-aggregator - - pAWSConfigAggregatorLambdaRoleName: - Type: String - Description: AWS Config Aggregator Lambda Role Name - Default: config-aggregator-lambda - - pTagKey1: - Type: String - Description: Tag key - - pTagValue1: - Type: String - Description: Tag key value - -Resources: - rAWSConfigAggregatorRole: - Type: "AWS::IAM::Role" - Metadata: - cfn_nag: - rules_to_suppress: - - id: W11 - reason: "Allow put and delete configuration aggregator for all aggregators" - - id: W28 - reason: "Role Name required to restrict central account role" - Properties: - RoleName: !Ref pAWSConfigAggregatorRoleName - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: "Allow" - Principal: - AWS: - - !Sub arn:${AWS::Partition}:iam::${pPrimaryAccountId}:root - Action: sts:AssumeRole - Condition: - StringEquals: - aws:PrincipalArn: !Sub arn:${AWS::Partition}:iam::${pPrimaryAccountId}:role/${pAWSConfigAggregatorLambdaRoleName} - Path: "/" - Policies: - - PolicyName: !Ref pAWSConfigAggregatorRoleName - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: - - config:DeleteConfigurationAggregator - - config:PutConfigurationAggregator - Resource: !Sub arn:${AWS::Partition}:config:*:${AWS::AccountId}:config-aggregator/* - Tags: - - Key: !Ref pTagKey1 - Value: !Ref pTagValue1 diff --git a/solutions/config/aggregator-org/README.md b/solutions/config/aggregator-org/README.md deleted file mode 100644 index d949b7b1..00000000 --- a/solutions/config/aggregator-org/README.md +++ /dev/null @@ -1,125 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# AWS Config Aggregator - -The AWS Config Aggregator Organization solution configures an AWS Config aggregator by delegating administration -to a member account (e.g. Security Tooling) within the Organization Management account and then configuring -AWS Config Aggregator within the delegated administrator account for all the existing and future AWS Organization -accounts. - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/Aggregator-Org-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation StackSet and Stacks within member accounts - -**Configuration:** - -* StackSet Names: - * AggregatorConfiguration - -### 1.2 AWS Organizations - -**Description:** - -AWS Organizations is used to delegate an administrator account for AWS Config and to identify AWS accounts for -aggregation. - -**Configuration:** - -* Delegated Administrator Account - See [Common Register Delegated Administrator](../../common/register-delegated-administrator) - ----- - -## 2.0 Delegated Administrator Account (e.g. Security Tooling) - -### 2.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account StackSet - -**Configuration:** - -* Stack Name: StackSet-...-AggregatorConfiguration-... - -### 2.2 AWS Config Aggregator IAM Role - -**Description:** - -An IAM role is created by the solution to allow AWS Config to access AWS Organizations APIs. - -**Configuration:** - -* Role Name: [Prefix]-org-config-aggregator -* Permissions: - * Organizations - Limited: List, Read All resources - -### 2.3 AWS Config Aggregator - -**Description:** - -AWS Config Aggregator is configured for the AWS Organization and all AWS Regions. - -**Configuration:** - -* AllAwsRegions: True - ----- - -## 3.0 All Existing and Future Organization Member Accounts - -### 3.1 AWS Config Aggregator - -**Description:** - -AWS Config Aggregator within each member account has Authorizations for the Delegated Administrator Account to collect -AWS Config compliance and configuration data. - -**Configuration:** - -* N/A - ----- - -# Implementation Instructions - -### [AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets - -#### Pre-requisites -1. Register a delegated administrator using the - [Common Register Delegated Administrator](../../common/register-delegated-administrator) solution - 1. pServicePrincipalList = "config.amazonaws.com" - -#### Instructions - -> **Solution Deployment Order:** -> 1. Management Account (CommonRegisterDelegatedAdmin) -> 3. Security Account (AggregatorConfiguration) - -1. Create a CloudFormation StackSet using the following template - - | Account | StackSet Name | Template | - | --------------- | ----------------- | ---------- | - | Security | AggregatorConfiguration | templates/aggregator-org-configuration.yaml | - ----- - -# References -* [Multi-Account Multi-Region Data Aggregation](https://docs.aws.amazon.com/config/latest/developerguide/aggregate-data.html) diff --git a/solutions/config/aggregator-org/aws-control-tower/README.md b/solutions/config/aggregator-org/aws-control-tower/README.md deleted file mode 100644 index b6673b40..00000000 --- a/solutions/config/aggregator-org/aws-control-tower/README.md +++ /dev/null @@ -1,67 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Package and upload the common-register-delegated-administrator Lambda function from the - [Common Register Delegated Administrator Solution](../../../common/register-delegated-administrator) - ```shell - export AWS_ACCESS_KEY_ID=INSERT_AWS_ACCESS_KEY_ID - export AWS_SECRET_ACCESS_KEY=INSERT_AWS_SECRET_ACCESS_KEY - export AWS_SESSION_TOKEN=INSERT_AWS_SESSION_TOKEN - - export BUCKET=lambda-zips-CHANGE_ME_ACCOUNT_ID-CHANGE_ME_REGION - sh ~/aws-security-reference-architecture-examples/extras/packaging-scripts/package-lambda.sh \ - --file_name common-register-delegated-administrator.zip \ - --bucket $BUCKET \ - --src_dir ~/aws-security-reference-architecture-examples/solutions/common/register-delegated-admninistrator/code/src - ``` -3. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) -> manifest.yaml - 2. [common/register-delegated-administrator/aws-control-tower/parameters/common-register-delegated-administrator.json](../../../common/register-delegated-administrator/aws-control-tower/parameters/common-register-delegated-administrator.json) - -> parameters/common-register-delegated-administrator.json - 3. [parameters/aggregator-org-configuration.json](parameters/aggregator-org-configuration.json) - -> parameters/aggregator-org-configuration.json - 4. [common/register-delegated-administrator/templates/common-register-delegated-administrator.yaml](../../../common/register-delegated-administrator/templates/common-register-delegated-administrator.yaml) - -> templates/common-register-delegated-administrator.yaml - 5. [templates/aggregator-org-configuration.yaml](../templates/aggregator-org-configuration.yaml) - -> templates/aggregator-org-configuration.yaml - -4. Update the parameter files with any specific values for your environment -5. Add "config.amazonaws.com" to the pServicePrincipalList parameter in the parameters/common-register-delegated-administrator.json -6. Add the [common/register-delegated-administrator/aws-control-tower/manifest.yaml](../../../common/register-delegated-administrator/aws-control-tower) - resource configuration to your manifest.yaml file. - ```yaml - ... - cloudformation_resources: - # ----------------------------------------------------------------------------- - # Common Register Delegated Administrator - # ----------------------------------------------------------------------------- - - name: CommonRegisterDelegatedAdmin - template_file: templates/common-register-delegated-administrator.yaml - parameter_file: parameters/common-register-delegated-administrator.json - deploy_method: stack_set - deploy_to_account: - - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME - ... - ``` -7. Update the manifest.yaml file with your account names and SSM parameters -8. Deploy the Customizations for AWS Control Tower configuration -9. How to verify after the pipeline completes? - 1. Log into the Audit account and navigate to the AWS Config page - 1. Verify the correct AWS Config Aggregator configurations have been applied - 2. Verify all existing accounts have been enabled (This can take a few minutes to complete) - -# Delete Instructions - -1. Within the Customizations for AWS Control Tower configuration - 1. Remove the Aggregator configuration from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the Aggregator solution -2. Deploy the Customizations for AWS Control Tower configuration -3. After the pipeline completes, log into the Management account and navigate to the CloudFormation StackSet page - 1. Delete the Stack Instance from the CustomControlTower-AggregatorConfiguration CloudFormation StackSet - 2. After the Stack Instance deletes, delete the CustomControlTower-AggregatorConfiguration CloudFormation StackSet - \ No newline at end of file diff --git a/solutions/config/aggregator-org/aws-control-tower/manifest-v2.yaml b/solutions/config/aggregator-org/aws-control-tower/manifest-v2.yaml deleted file mode 100644 index 38deff96..00000000 --- a/solutions/config/aggregator-org/aws-control-tower/manifest-v2.yaml +++ /dev/null @@ -1,25 +0,0 @@ ---- -#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets -region: us-east-1 -version: 2021-03-15 - -# Control Tower Custom Resources (Service Control Policies or CloudFormation) -resources: -# ----------------------------------------------------------------------------- -# AWS Config Aggregator Solution -# ----------------------------------------------------------------------------- - - name: AggregatorConfiguration - resource_file: templates/aggregator-org-configuration.yaml - parameters: - - parameter_key: pAggregatorName - parameter_value: cfct-org-config-aggregator - - parameter_key: pAggregatorRoleName - parameter_value: cfct-org-config-aggregator - - parameter_key: pTagKey1 - parameter_value: cfct - - parameter_key: pTagValue1 - parameter_value: managed-by-cfct - deploy_method: stack_set - deployment_targets: - accounts: - - REPLACE_ME_AUDIT_OR_SECURITY_TOOLING_ACCOUNT_NAME diff --git a/solutions/config/aggregator-org/documentation/Aggregator-Org-Architecture.png b/solutions/config/aggregator-org/documentation/Aggregator-Org-Architecture.png deleted file mode 100644 index 1bb118d6..00000000 Binary files a/solutions/config/aggregator-org/documentation/Aggregator-Org-Architecture.png and /dev/null differ diff --git a/solutions/config/conformance-pack-org/README.md b/solutions/config/conformance-pack-org/README.md deleted file mode 100644 index 4448b61b..00000000 --- a/solutions/config/conformance-pack-org/README.md +++ /dev/null @@ -1,266 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# Conformance Pack Organization Rules - -The Conformance Pack Organization Rules solution deploys Organization AWS Config rules by delegating administration -to a member account within the Organization Management account and then creating an Organization Conformance Pack -within the delegated administrator account for all the existing and future AWS Organization accounts. - -[AWS Config rules](https://docs.aws.amazon.com/config/latest/developerguide/evaluate-config.html) are used to evaluate -the configuration settings of your AWS resources. - -There are three ways that you can create AWS Config rules: - 1. Directly within each AWS account/region - 2. [Conformance Packs](https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html) within the - Organization Management account and region or a delegated administrator account and region - 3. [Organization Rules](https://docs.aws.amazon.com/config/latest/developerguide/config-rule-multi-account-deployment.html) - within the Organization Management account and region or a delegated administrator account and region - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/diagram/AWS-Config-Organization-Rules-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation StackSet and Stacks within member accounts - -**Configuration:** - -* StackSet Names: - * ConformancePackDelegatedAdmin - * ConformancePackDeliveryBucket - * ConformancePackDeployment - -### 1.2 AWS Lambda Function - -**Description:** - -The custom CloudFormation Lambda resource is required to delegate an administrator account because this capability -is not supported by CloudFormation (November 2020) - -**Configuration:** - -* Lambda Function Name = [Prefix]-config-register-delegated-admin -* Environment Variables (Configurable and set via CloudFormation) - * AWS_SERVICE_PRINCIPAL - AWS service principal to delegate administration for - * DELEGATED_ADMIN_ACCOUNT_ID - Organization Member Account ID which is typically the Security account - * LOG_LEVEL - Default = info, Valid Values = debug, info, warning, error, critical - * TAG_KEY1 - Tags the IAM role and Lambda Function with this key - * TAG_VALUE1 - Tags the IAM role and Lambda Function with this value - -**Input Validation** - -Validation of environment variables is done to make sure values exist and are the correct type - -### 1.3 Lambda Execution IAM Role - -**Description:** - -Used by the custom CloudFormation Lambda function to enable AWS service access for AWS Config and register an AWS -account as the delegated administrator for AWS Config - -**Configuration:** - -* Role Name: [Prefix]-config-register-delegated-admin-lambda -* Policy Name: [Prefix]-config-register-delegated-admin-lambda -* Permissions: - * CloudWatch Logs - Limited: Write on LogGroupName like /aws/lambda/[Lambda Function] - * Organizations - Limited: List, Read, Write - -### 1.4 Lambda CloudWatch Log Group - -**Description:** - -Contains Lambda function execution logs - -**Configuration:** - -* Retention = Default 2 weeks (14 days) -* Log group name = /aws/lambda/[Lambda Function] - -### 1.5 Lambda CloudWatch Log Group - -**Description:** - -Contains Lambda function execution logs - -**Configuration:** - -* Retention = Default 2 weeks (14 days) -* Log group name = /aws/lambda/[Lambda Function] - -### 1.6 AWS Config Service-Linked Roles - -**Description:** - -AWS Config creates 2 service-linked roles within each AWS account which are used to setup and send data to the -delivery S3 bucket. - -* AWSServiceRoleForConfigMultiAccountSetup - is used for the AWS Config multi-account setup -* AWSServiceRoleForConfigConforms - is used to send data to the delivery S3 bucket - - -**Configuration:** - -* N/A - - ----- - -## 2.0 Security Log Archive Account - -### 2.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account StackSet - -**Configuration:** - -* Stack Name: ConformancePackOrgDeliveryBucket-... - -### 2.2 Conformance Pack Delivery Bucket - -**Description:** - -Organization Conformance Packs require a delivery S3 bucket with "awsconfigconforms" as the bucket name prefix. We -create this bucket within the Security Log Archive account to stay consistent with where our consolidated logs -are stored. - -**Configuration:** - -* Organization ID = AWS Organization ID -* Tag Key = Bucket Tag Key -* Tag Value = Bucket Tag Value - -### 2.3 Organization Conformance Pack - -**Description:** - -The [AWS Control Tower Detective Guardrails Conformance Pack](https://docs.aws.amazon.com/config/latest/developerguide/aws-control-tower-detective-guardrails.html) -is deployed to all regions from the Security Tooling Account. - -An [AWS Config Conformance Pack](https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html) -is a collection of AWS Config rules and remediation actions that can be easily deployed as a single entity in an -account and a Region or across an organization in AWS Organizations. - -Conformance packs are created by authoring a YAML template that contains the list of AWS Config managed or custom -rules and remediation actions. You can deploy the template by using the AWS Config console or the AWS CLI. To quickly -get started and to evaluate your AWS environment, use one of the sample conformance pack templates. - -**Configuration:** - -* N/A - ----- - -## 4.0 All Existing and Future Organization Member Accounts - -### 4.1 AWS Config Service-Linked Roles - -**Description:** - -AWS Config creates 2 service-linked roles within each AWS account which are used to setup and send data to the -delivery S3 bucket. - -* AWSServiceRoleForConfigMultiAccountSetup - is used for the AWS Config multi-account setup -* AWSServiceRoleForConfigConforms - is used to send data to the delivery S3 bucket - - -**Configuration:** - -* N/A - -### 4.2 Organization Conformance Pack - -**Description:** - -The [AWS Control Tower Detective Guardrails Conformance Pack](https://docs.aws.amazon.com/config/latest/developerguide/aws-control-tower-detective-guardrails.html) -is deployed to all regions from the Security Tooling Account. - -An [AWS Config Conformance Pack](https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html) -is a collection of AWS Config rules and remediation actions that can be easily deployed as a single entity in an -account and a Region or across an organization in AWS Organizations. - -Conformance packs are created by authoring a YAML template that contains the list of AWS Config managed or custom -rules and remediation actions. You can deploy the template by using the AWS Config console or the AWS CLI. To quickly -get started and to evaluate your AWS environment, use one of the sample conformance pack templates. - -**Configuration:** - -* N/A - ----- - -# Implementation Instructions - -### [AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets - -#### Pre-requisites -1. Create AWS Config Conformance Pack Templates S3 Bucket in the Security Tooling Account - * Create an SSM parameter in the Organization Management Account (Optional) - * [CloudFormation template](./documentation/setup/create-conformance-pack-templates-bucket.yaml) to create the S3 bucket -2. Upload [aws-control-tower-detective-guardrails.yaml](./documentation/setup/conformance-pack-templates/aws-control-tower-detective-guardrails.yaml) - or [Operational-Best-Practices-for-Encryption-and-Keys.yaml](./documentation/setup/conformance-pack-templates/Operational-Best-Practices-for-Encryption-and-Keys.yaml) - to the AWS Config Conformance Pack Templates S3 Bucket - -#### Instructions - -> **Solution Deployment Order:** -> 1. Management Account (ConformancePackDelegatedAdmin) -> 2. Log-Archive Account (ConformancePackDeliveryBucket) -> 3. Security Account (ConformancePackDeployment) - -1. Create new or use an existing S3 bucket within the deployment region owned by the Organization Management Account - * Example bucket name: lambda-zips-[Management Account ID]-[AWS region] - * [Example CloudFormation Template](../../../extras/lambda-s3-buckets.yaml) - * Each bucket must allow the s3:GetObject action to the AWS Organization using a bucket policy like the one below - to allow the accounts within the Organization to get the Lambda files. - ``` - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AllowGetObject", - "Effect": "Allow", - "Principal": "*", - "Action": "s3:GetObject", - "Resource": "arn:[AWS::Partition]:s3:::[BUCKET NAME]/*", - "Condition": { - "StringEquals": { - "aws:PrincipalOrgID": "[ORGANIZATION ID]" - } - } - } - ] - } - ``` -2. Package the Lambda code into a zip file and upload it to the S3 bucket - * Package and Upload the Lambda zip file to S3 - [Packaging script](../../../extras/packaging-scripts/package-lambda.sh) -3. Create CloudFormation StackSets using the following templates - - | Account | StackSet Name | Template | - | --------------- | ----------------- | ---------- | - | Management | ConformancePackDelegatedAdmin | templates/conformance-pack-org-register-delegated-admin.yaml | - | Log Archive | ConformancePackDeliveryBucket | templates/conformance-pack-org-delivery-bucket.yaml | - | Security | ConformancePackDeployment | templates/conformance-pack-org-deployment.yaml | - ----- - -# References -* [Enabling AWS Config Rules Across all Accounts in Your Organization](https://docs.aws.amazon.com/config/latest/developerguide/config-rule-multi-account-deployment.html) -* [Conformance Packs](https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html) diff --git a/solutions/config/conformance-pack-org/aws-control-tower/README.md b/solutions/config/conformance-pack-org/aws-control-tower/README.md deleted file mode 100644 index df456ae9..00000000 --- a/solutions/config/conformance-pack-org/aws-control-tower/README.md +++ /dev/null @@ -1,52 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Verify that all accounts in the organization have an AWS Configuration Recorder - * Run the [list-config-recorder-status.py](../../../../extras/aws-control-tower/helper-scripts/list-config-recorder-status.py) - within the Organization Management account to get the list of accounts. - * Include the Account IDs without an AWS Configuration Recorder in the pExcludedAccounts parameter -3. Create the Conformance Pack Template S3 bucket within the Security Tooling account using the - [create-conformance-pack-templates-bucket.yaml](../documentation/setup/create-conformance-pack-templates-bucket.yaml) - template -4. Upload the [Operational-Best-Practices-for-Encryption-and-Keys.yaml](../documentation/setup/conformance-pack-templates/Operational-Best-Practices-for-Encryption-and-Keys.yaml) - conformance pack template to the Conformance Pack Template S3 bucket created above. -5. Add the /org/config/conformance_pack_templates_bucket SSM Parameter in the Management account - ``` - aws ssm put-parameter \ - --name /org/config/conformance_pack_templates_bucket \ - --value conformance-pack-templates-123456789012-us-east-1 \ - --description "Conformance pack templates S3 bucket" \ - --tags Key=control-tower,Value=managed-by-control-tower - ``` -6. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) - 2. [parameters/conformance-pack-org-register-delegated-admin.json](parameters/conformance-pack-org-register-delegated-admin.json) - 3. [parameters/conformance-pack-org-delivery-bucket.json](parameters/conformance-pack-org-delivery-bucket.json) - 4. [parameters/conformance-pack-org-deployment.json](parameters/conformance-pack-org-deployment.json) - 5. [templates/conformance-pack-org-register-delegated-admin.yaml](../templates/conformance-pack-org-register-delegated-admin.yaml) - 6. [templates/conformance-pack-org-delivery-bucket.yaml](../templates/conformance-pack-org-delivery-bucket.yaml) - 7. [templates/conformance-pack-org-deployment.yaml](../templates/conformance-pack-org-deployment.yaml) -7. Update the parameter files with any specific values for your environment -8. Update the manifest.yaml file with your account names -9. Deploy the Customizations for AWS Control Tower configuration -10. How to verify after the pipeline completes? - 1. Log into the Security Tooling account and navigate to the AWS Config page - 2. Verify the correct configurations have been applied to each region - 1. Conformance packs -> OrgConformsPack-Operational-Best-Practices-for-Encryption-and-Keys-* created in each region - 2. Settings -> Delivery location set to the awsconfigconforms-[Log Archive Account ID]-[Region] - - -# Delete Instructions - -1. Within the Customizations for AWS Control Tower configuration - 1. Remove the Conformance Pack configurations from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the Conformance Pack solution -2. Deploy the Customizations for AWS Control Tower configuration -3. After the pipeline completes, log into the Management account and navigate to the CloudFormation page - 1. Delete the CustomControlTower-ConformancePack* CloudFormation StackSets - \ No newline at end of file diff --git a/solutions/config/conformance-pack-org/aws-control-tower/manifest-v2.yaml b/solutions/config/conformance-pack-org/aws-control-tower/manifest-v2.yaml deleted file mode 100644 index a71daed4..00000000 --- a/solutions/config/conformance-pack-org/aws-control-tower/manifest-v2.yaml +++ /dev/null @@ -1,78 +0,0 @@ ---- -#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets -region: us-east-1 -version: 2021-03-15 - -# Control Tower Custom Resources (Service Control Policies or CloudFormation) -resources: -# ----------------------------------------------------------------------------- -# Organization Config Conformance Pack -# ----------------------------------------------------------------------------- - - name: ConformancePackDelegatedAdmin - resource_file: templates/conformance-pack-org-register-delegated-admin.yaml - parameters: - - parameter_key: pDefaultLogGroupRetention - parameter_value: "30" - - parameter_key: pDelegatedAdminAccountId - parameter_value: $[alfred_ssm_/org/member/Audit/account_id] - - parameter_key: pLambdaExecutionRoleName - parameter_value: cfct-config-register-delegated-admin-lambda - - parameter_key: pLambdaFunctionName - parameter_value: cfct-config-register-delegated-admin - - parameter_key: pLambdaS3BucketName - parameter_value: $[alfred_ssm_/org/primary/lambda_zips_bucket/us-east-1] - - parameter_key: pLambdaZipFileName - parameter_value: organization-register-delegated-admin.zip - - parameter_key: pLogLevel - parameter_value: info - - parameter_key: pTagKey1 - parameter_value: cfct - - parameter_key: pTagValue1 - parameter_value: managed-by-cfct - deploy_method: stack_set - deployment_targets: - accounts: - - Control Tower Management - - - name: ConformancePackDeliveryBucket - resource_file: templates/conformance-pack-org-delivery-bucket.yaml - parameters: - - parameter_key: pOrganizationId - parameter_value: $[alfred_ssm_/org/primary/organization_id] - - parameter_key: pTagKey1 - parameter_value: cfct - - parameter_key: pTagValue1 - parameter_value: managed-by-cfct - deploy_method: stack_set - deployment_targets: - accounts: - - Log archive - export_outputs: - - name: /org/config/conformance_pack_delivery_bucket - value: $[output_oConformancePackDeliveryBucket] - - - name: ConformancePackDeployment - resource_file: templates/conformance-pack-org-deployment.yaml - parameters: - - parameter_key: pConformancePackName - parameter_value: Operational-Best-Practices-for-Encryption-and-Keys - - parameter_key: pDeliveryBucketName - parameter_value: $[alfred_ssm_/org/config/conformance_pack_delivery_bucket] - - parameter_key: pDeliveryS3KeyPrefix - parameter_value: Config - - parameter_key: pExcludedAccounts - parameter_value: $[alfred_ssm_/org/member/Control-Tower-Management/account_id] - - parameter_key: pTemplateBucketName - parameter_value: $[alfred_ssm_/org/config/conformance_pack_templates_bucket] - - parameter_key: pTemplatePrefix - parameter_value: Operational-Best-Practices-for-Encryption-and-Keys.yaml - deploy_method: stack_set - deployment_targets: - accounts: - - Audit - regions: - - ap-southeast-2 - - eu-west-1 - - us-east-1 - - us-east-2 - - us-west-2 diff --git a/solutions/config/conformance-pack-org/aws-control-tower/manifest.yaml b/solutions/config/conformance-pack-org/aws-control-tower/manifest.yaml deleted file mode 100644 index e78b05ef..00000000 --- a/solutions/config/conformance-pack-org/aws-control-tower/manifest.yaml +++ /dev/null @@ -1,39 +0,0 @@ ---- -#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets -region: us-east-1 -version: 2020-01-01 - -# Control Tower Custom Service Control Policies -organization_policies: [] - -# Control Tower Custom CloudFormation Resources -cloudformation_resources: - - name: ConformancePackDelegatedAdmin - template_file: templates/conformance-pack-org-register-delegated-admin.yaml - parameter_file: parameters/conformance-pack-org-register-delegated-admin.json - deploy_method: stack_set - deploy_to_account: - - Control Tower Management - - - name: ConformancePackDeliveryBucket - template_file: templates/conformance-pack-org-delivery-bucket.yaml - parameter_file: parameters/conformance-pack-org-delivery-bucket.json - deploy_method: stack_set - ssm_parameters: - - name: /org/config/conformance_pack_delivery_bucket - value: $[output_oConformancePackDeliveryBucket] - deploy_to_account: - - Log archive - - - name: ConformancePackDeployment - template_file: templates/conformance-pack-org-deployment.yaml - parameter_file: parameters/conformance-pack-org-deployment.json - deploy_method: stack_set - deploy_to_account: - - Audit - regions: - - ap-southeast-2 - - eu-west-1 - - us-east-1 - - us-east-2 - - us-west-2 \ No newline at end of file diff --git a/solutions/config/conformance-pack-org/code/src/app.py b/solutions/config/conformance-pack-org/code/src/app.py deleted file mode 100644 index b1f55efd..00000000 --- a/solutions/config/conformance-pack-org/code/src/app.py +++ /dev/null @@ -1,208 +0,0 @@ -######################################################################## -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: MIT-0 -######################################################################## -import logging -import os -import boto3 -from botocore.exceptions import ClientError -from crhelper import CfnResource - -# Setup Default Logger -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) - -""" -The purpose of this script is to enable AWS service access for AWS Config -multi-account setup and delegate an administrator account. The delete event -removes the delegated administrator account and disables the AWS service -access for AWS Config. -""" - -# Initialise the helper, all inputs are optional, this example shows the defaults -helper = CfnResource(json_logging=False, log_level="DEBUG", boto_level="CRITICAL") - -CLOUDFORMATION_PARAMETERS = ["AWS_SERVICE_PRINCIPAL", "DELEGATED_ADMIN_ACCOUNT_ID"] - -try: - # Process Environment Variables - if "LOG_LEVEL" in os.environ: - LOG_LEVEL = os.environ.get("LOG_LEVEL") - if isinstance(LOG_LEVEL, str): - log_level = logging.getLevelName(LOG_LEVEL.upper()) - logger.setLevel(log_level) - else: - raise ValueError("LOG_LEVEL parameter is not a string") -except Exception as e: - helper.init_failure(e) - - -def enable_aws_service_access(service_principal: str): - """ - Enables the AWS Service Access for the provided service principal - :param service_principal: AWS Service Principal - :return: None - """ - logger.info(f"Enable AWS Service Access for: {service_principal}") - - try: - organizations = boto3.client("organizations") - organizations.enable_aws_service_access(ServicePrincipal=service_principal) - except ClientError as ce: - logger.error(f"enable_aws_service_access error: {str(ce)}") - raise ValueError("Error enabling aws service access") - - -def disable_aws_service_access(service_principal: str): - """ - Disables aws service access for the service principal - :param service_principal: AWS Service Principal - :return: None - """ - logger.info(f"Disable AWS Service Access for: {service_principal}") - - try: - organizations = boto3.client("organizations") - organizations.disable_aws_service_access(ServicePrincipal=service_principal) - except ClientError as ce: - logger.error(f"disable_aws_service_access error: {str(ce)}") - raise ValueError("Error disabling aws service access") - - -def register_delegated_administrator(account_id: str, service_principal: str): - """ - Registers the delegated administrator account for the provided service principal - :param account_id: Delegated Administrator Account ID - :param service_principal: AWS Service Principal - :return: None - """ - logger.info(f"Register delegated administrator account for : {service_principal}") - - try: - organizations = boto3.client("organizations") - organizations.register_delegated_administrator(AccountId=account_id, ServicePrincipal=service_principal) - - delegated_administrators = organizations.list_delegated_administrators(ServicePrincipal=service_principal) - - logger.info(f"{delegated_administrators}") - - if not delegated_administrators: - logger.debug(f"Delegated administrator for the service principle {service_principal} does not exist") - - except ClientError as ce: - logger.error(f"register_delegated_administrator error: {str(ce)}") - raise ValueError("Error registering the delegated administrator account") - - -def deregister_delegated_administrator(account_id: str, service_principal: str): - """ - Deregister the delegated administrator account for the provided service principal - :param account_id: Delegated administrator account ID - :param service_principal: AWS service principal - :return: None - """ - logger.info(f"Deregister AWS Service Access for: {service_principal}") - - try: - organizations = boto3.client("organizations") - organizations.deregister_delegated_administrator(AccountId=account_id, ServicePrincipal=service_principal) - delegated_administrators = organizations.list_delegated_administrators(ServicePrincipal=service_principal) - - logger.debug(str(delegated_administrators)) - - if not delegated_administrators: - logger.debug(f"Delegated administrator for the service principle {service_principal} does not exist") - - except ClientError as ce: - logger.error(f"deregister_delegated_administrator error: {ce}") - raise ValueError("Error trying to deregister delegated administrator account") - - -def check_parameters(event: dict): - """ - Check event for required parameters in the ResourceProperties - :param event: - :return: - """ - try: - if "StackId" not in event or "ResourceProperties" not in event: - raise ValueError("Invalid CloudFormation request, missing StackId or ResourceProperties.") - - # Check CloudFormation parameters - for parameter in CLOUDFORMATION_PARAMETERS: - if parameter not in event.get("ResourceProperties", ""): - raise ValueError("Invalid CloudFormation request, missing one or more ResourceProperties.") - - logger.debug(f"Stack ID : {event.get('StackId')}") - logger.debug(f"Stack Name : {event.get('StackId').split('/')[1]}") - except Exception as error: - logger.error(f"Exception checking parameters {error}") - raise ValueError("Error checking parameters") - - -@helper.create -def create(event, _): - """ - CloudFormation Create Event. - :param event: event data - :param _: - :return: ConfigDelegatedAdminResourceId - """ - logger.info(f"Create Event: {event}") - try: - check_parameters(event) - params = event.get("ResourceProperties") - - enable_aws_service_access(params.get("AWS_SERVICE_PRINCIPAL", "")) - register_delegated_administrator(params.get("DELEGATED_ADMIN_ACCOUNT_ID", ""), - params.get("AWS_SERVICE_PRINCIPAL", "")) - except Exception as exc: - logger.error(f"Exception: {exc}") - raise ValueError("Error delegating the admin account") - - return "ConfigDelegatedAdminResourceId" - - -@helper.update -def update(event, _): - """ - CloudFormation Update Event. - :param event: event data - :param _: - :return: CloudFormation response - """ - logger.info(f"Update Event: {event}") - - -@helper.delete -def delete(event, _): - """ - CloudFormation Delete Event. - :param event: event data - :param _: - :return: CloudFormation response - """ - logger.info(f"Delete Event: {event}") - try: - check_parameters(event) - params = event.get("ResourceProperties") - - deregister_delegated_administrator( - params.get("DELEGATED_ADMIN_ACCOUNT_ID", ""), - params.get("AWS_SERVICE_PRINCIPAL", "") - ) - disable_aws_service_access(params.get("AWS_SERVICE_PRINCIPAL", "")) - except Exception as exc: - logger.error(f"Exception: {exc}") - raise ValueError("Error disabling the admin account") - - -def lambda_handler(event, context): - """ - Lambda Handler - :param event: event data - :param context: runtime information - :return: CloudFormation response - """ - logger.info("....Lambda Handler Started....") - helper(event, context) diff --git a/solutions/config/conformance-pack-org/documentation/diagram/AWS-Config-Organization-Rules-Architecture.png b/solutions/config/conformance-pack-org/documentation/diagram/AWS-Config-Organization-Rules-Architecture.png deleted file mode 100644 index 5e8090d9..00000000 Binary files a/solutions/config/conformance-pack-org/documentation/diagram/AWS-Config-Organization-Rules-Architecture.png and /dev/null differ diff --git a/solutions/config/conformance-pack-org/documentation/setup/conformance-pack-templates/aws-control-tower-detective-guardrails.yaml b/solutions/config/conformance-pack-org/documentation/setup/conformance-pack-templates/aws-control-tower-detective-guardrails.yaml deleted file mode 100644 index 6565becb..00000000 --- a/solutions/config/conformance-pack-org/documentation/setup/conformance-pack-templates/aws-control-tower-detective-guardrails.yaml +++ /dev/null @@ -1,170 +0,0 @@ -################################################################################### -# -# Conformance Pack: -# AWS Control Tower Detective Guardrails Conformance Pack -# -# The AWS Control Tower detective guardrails conformance pack contains all of the -# AWS Config Rules based guardrails from AWS Control Tower. Use this conformance -# pack to apply AWS Control Tower detective guardrails to your existing accounts -# prior to enrolling them in AWS Control Tower or to manage resources in your -# accounts in regions not currently supported by AWS Control Tower. -################################################################################### - -Resources: - CheckForEbsOptimizedInstance: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForEbsOptimizedInstance - Description: Disallow launch of EC2 instance types that are not EBS-optimized - Checks whether EBS optimization is enabled for your EC2 instances that can be EBS-optimized - Source: - Owner: AWS - SourceIdentifier: EBS_OPTIMIZED_INSTANCE - Scope: - ComplianceResourceTypes: - - AWS::EC2::Instance - CheckForEc2VolumesInUse: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForEc2VolumesInUs - Description: Disallow EBS volumes that are unattached to an EC2 instance - Checks whether EBS volumes are attached to EC2 instances - InputParameters: - deleteOnTermination: true - Source: - Owner: AWS - SourceIdentifier: EC2_VOLUME_INUSE_CHECK - Scope: - ComplianceResourceTypes: - - AWS::EC2::Volume - CheckForEncryptedVolumes: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForEncryptedVolumes - Description: Enable encryption for EBS volumes attached to EC2 instances - Checks whether EBS volumes that are in an attached state are encrypted. - Source: - Owner: AWS - SourceIdentifier: ENCRYPTED_VOLUMES - Scope: - ComplianceResourceTypes: - - AWS::EC2::Volume - CheckForIAMUserMFA: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForIAMUserMFA - Description: Disallow access to IAM users without MFA - Checks whether the AWS Identity and Access Management users have multi-factor authentication (MFA) enabled. The rule is COMPLIANT if MFA is enabled. - Source: - Owner: AWS - SourceIdentifier: IAM_USER_MFA_ENABLED - MaximumExecutionFrequency: One_Hour - CheckForIAMUserConsoleMFA: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForIAMUserConsoleMFA - Description: Disallow console access to IAM users without MFA - Checks whether AWS Multi-Factor Authentication (MFA) is enabled for all AWS Identity and Access Management (IAM) users that use a console password. The rule is COMPLIANT if MFA is enabled. - Source: - Owner: AWS - SourceIdentifier: MFA_ENABLED_FOR_IAM_CONSOLE_ACCESS - MaximumExecutionFrequency: One_Hour - CheckForRdsPublicAccess: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForRdsPublicAccess - Description: Disallow public access to RDS database instances - Checks whether the Amazon Relational Database Service (RDS) instances are not publicly accessible. The rule is non-compliant if the publiclyAccessible field is true in the instance configuration item. - Source: - Owner: AWS - SourceIdentifier: RDS_INSTANCE_PUBLIC_ACCESS_CHECK - Scope: - ComplianceResourceTypes: - - AWS::RDS::DBInstance - CheckForPublicRdsSnapshots: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForPublicRdsSnapshots - Description: Disallow public access to RDS database snapshots - Checks if Amazon Relational Database Service (Amazon RDS) snapshots are public. The rule is non-compliant if any existing and new Amazon RDS snapshots are public. - Source: - Owner: AWS - SourceIdentifier: RDS_SNAPSHOTS_PUBLIC_PROHIBITED - Scope: - ComplianceResourceTypes: - - AWS::RDS::DBSnapshot - CheckForRdsStorageEncryption: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForRdsStorageEncryption - Description: Disallow RDS database instances that are not storage encrypted - Checks whether storage encryption is enabled for your RDS DB instances. - Source: - Owner: AWS - SourceIdentifier: RDS_STORAGE_ENCRYPTED - Scope: - ComplianceResourceTypes: - - AWS::RDS::DBInstance - CheckForRestrictedCommonPortsPolicy: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForRestrictedCommonPortsPolicy - Description: Disallow internet connection through RDP - Checks whether security groups that are in use disallow unrestricted incoming TCP traffic to the specified ports. - InputParameters: - blockedPort1: 20 - blockedPort2: 21 - blockedPort3: 3389 - blockedPort4: 3306 - blockedPort5: 4333 - Scope: - ComplianceResourceTypes: - - AWS::EC2::SecurityGroup - Source: - Owner: AWS - SourceIdentifier: RESTRICTED_INCOMING_TRAFFIC - CheckForRestrictedSshPolicy: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForRestrictedSshPolicy - Description: Disallow internet connection through SSH - Checks whether security groups that are in use disallow unrestricted incoming SSH traffic. - Scope: - ComplianceResourceTypes: - - AWS::EC2::SecurityGroup - Source: - Owner: AWS - SourceIdentifier: INCOMING_SSH_DISABLED - CheckForRootMfa: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForRootMfa - Description: Enable MFA for the root user - Checks whether the root user of your AWS account requires multi-factor authentication for console sign-in. - Source: - Owner: AWS - SourceIdentifier: ROOT_ACCOUNT_MFA_ENABLED - MaximumExecutionFrequency: One_Hour - CheckForS3PublicRead: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForS3PublicRead - Description: Disallow public read access to S3 buckets - Checks that your S3 buckets do not allow public read access. If an S3 bucket policy or bucket ACL allows public read access, the bucket is noncompliant. - Source: - Owner: AWS - SourceIdentifier: S3_BUCKET_PUBLIC_READ_PROHIBITED - Scope: - ComplianceResourceTypes: - - AWS::S3::Bucket - CheckForS3PublicWrite: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForS3PublicWrite - Description: Disallow public write access to S3 buckets - Checks that your S3 buckets do not allow public write access. If an S3 bucket policy or bucket ACL allows public write access, the bucket is noncompliant. - Source: - Owner: AWS - SourceIdentifier: S3_BUCKET_PUBLIC_WRITE_PROHIBITED - Scope: - ComplianceResourceTypes: - - AWS::S3::Bucket - CheckForS3VersioningEnabled: - Type: AWS::Config::ConfigRule - Properties: - ConfigRuleName: CheckForS3VersioningEnabled - Description: Disallow S3 buckets that are not versioning enabled - Checks whether versioning is enabled for your S3 buckets. - Source: - Owner: AWS - SourceIdentifier: S3_BUCKET_VERSIONING_ENABLED - Scope: - ComplianceResourceTypes: - - AWS::S3::Bucket - \ No newline at end of file diff --git a/solutions/config/conformance-pack-org/templates/conformance-pack-org-register-delegated-admin.yaml b/solutions/config/conformance-pack-org/templates/conformance-pack-org-register-delegated-admin.yaml deleted file mode 100644 index 3254b6ee..00000000 --- a/solutions/config/conformance-pack-org/templates/conformance-pack-org-register-delegated-admin.yaml +++ /dev/null @@ -1,218 +0,0 @@ -######################################################################## -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: MIT-0 -######################################################################## -AWSTemplateFormatVersion: 2010-09-09 -Description: AWS Config register delegated administrator account - -Metadata: - AWS::CloudFormation::Interface: - ParameterGroups: - - - Label: - default: Lambda Function Attributes - Parameters: - - pDefaultLogGroupRetention - - pDelegatedAdminAccountId - - pLambdaFunctionName - - pLambdaS3BucketName - - pLambdaZipFileName - - pLogLevel - - - Label: - default: Lambda Role Attributes - Parameters: - - pLambdaExecutionRoleName - - pTagKey1 - - pTagValue1 - - ParameterLabels: - pDefaultLogGroupRetention: - default: Default Log Group Retention - pLambdaFunctionName: - default: Lambda Function Name - pLambdaS3BucketName: - default: Lambda Source S3 Bucket Name - pLambdaZipFileName: - default: Lambda Zip File Name - pDelegatedAdminAccountId: - default: AWS Config Delegated Admin Account ID - pLogLevel: - default: Lambda Function Log Level - - pLambdaExecutionRoleName: - default: Lambda Role Name - pTagKey1: - default: Tag Key - pTagValue1: - default: Tag Value - -Parameters: - pDefaultLogGroupRetention: - Type: String - Default: 14 - Description: Specifies the number of days you want to retain log events in the CloudWatch Logs - AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653] - - pDelegatedAdminAccountId: - AllowedPattern: '^\d{12}$' - ConstraintDescription: Must be 12 digits - Description: Delegated administrator account ID - Type: String - - pLambdaFunctionName: - AllowedPattern: '^[\w-]{0,64}$' - ConstraintDescription: Max 64 alphanumeric characters. Also special characters supported [_, -] - Description: Lambda function name - Type: String - - pLambdaExecutionRoleName: - AllowedPattern: '^[\w+=,.@-]{1,64}$' - ConstraintDescription: Max 64 alphanumeric characters. Also special characters supported [+, =, ., @, -] - Default: config-register-delegated-admin-lambda - Type: String - - pLambdaS3BucketName: - AllowedPattern: "^$|^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" - ConstraintDescription: - S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). - It cannot start or end with a hyphen (-). - Description: The Amazon S3 bucket name where the lambda zip file is stored - Type: String - - pLambdaZipFileName: - Description: Lambda zip file containing code - Type: String - - pLogLevel: - AllowedValues: [debug, info, warning, error, critical] - Default: info - Description: Lambda Function Logging Level - Type: String - - pTagKey1: - AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' - ConstraintDescription: - The string value can be Unicode characters and cannot be prefixed with "aws:". - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-'' - Description: Tag key - Type: String - - pTagValue1: - AllowedPattern: '^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$' - ConstraintDescription: - The string value can be Unicode characters. - The string can contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' - Description: Tag key value - Type: String - - -Mappings: - mAWSServicePrincipal: - config: - ServicePrincipal: config-multiaccountsetup.amazonaws.com - - -Resources: - rLambdaLogGroup: - Type: AWS::Logs::LogGroup - Metadata: - cfn_nag: - rules_to_suppress: - - id: W84 - reason: KMS key not provided - Properties: - RetentionInDays: !Ref pDefaultLogGroupRetention - LogGroupName: !Sub "/aws/lambda/${pLambdaFunctionName}" - - rLambdaRole: - Type: AWS::IAM::Role - Metadata: - cfn_nag: - rules_to_suppress: - - id: W11 - reason: The organizations actions do not allow resource restrictions - - id: W28 - reason: The role name is defined to identify resources - Properties: - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Service: - - lambda.amazonaws.com - Action: sts:AssumeRole - Path: "/" - Policies: - - PolicyName: conformance-pack-org-policy-logs - PolicyDocument: - Version: 2012-10-17 - Statement: - - Action: logs:CreateLogGroup - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup} - Sid: CreateLogGroup - - - Action: - - logs:CreateLogStream - - logs:PutLogEvents - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rLambdaLogGroup}:log-stream:* - Sid: CreateLogStreamAndEvents - - - PolicyName: conformance-pack-org-policy-organizations - PolicyDocument: - Version: 2012-10-17 - Statement: - - Action: - - organizations:DeregisterDelegatedAdministrator - - organizations:DescribeOrganization - - organizations:DisableAWSServiceAccess - - organizations:EnableAWSServiceAccess - - organizations:ListAWSServiceAccessForOrganization - - organizations:ListDelegatedAdministrators - - organizations:RegisterDelegatedAdministrator - Effect: Allow - Resource: "*" - Sid: Organizations - RoleName: !Ref pLambdaExecutionRoleName - Tags: - - Key: !Ref pTagKey1 - Value: !Ref pTagValue1 - - rLambdaFunction: - Type: AWS::Lambda::Function - Metadata: - cfn_nag: - rules_to_suppress: - - id: W58 - reason: CloudWatch access provided by the attached IAM role - - id: W89 - reason: Lambda is not deployed within a VPC - Properties: - Code: - S3Bucket: !Ref pLambdaS3BucketName - S3Key: !Ref pLambdaZipFileName - Description: Update the S3 account level public access block settings - Environment: - Variables: - LOG_LEVEL: !Ref pLogLevel - FunctionName: !Ref pLambdaFunctionName - Handler: app.lambda_handler - MemorySize: 128 - ReservedConcurrentExecutions: 1 - Role: !GetAtt rLambdaRole.Arn - Runtime: python3.8 - Tags: - - Key: !Ref pTagKey1 - Value: !Ref pTagValue1 - Timeout: 300 - - rLambdaCustomResource: - Type: Custom::LambdaCustomResource - Version: "1.0" - Properties: - ServiceToken: !GetAtt rLambdaFunction.Arn - AWS_SERVICE_PRINCIPAL: !FindInMap [mAWSServicePrincipal, "config", "ServicePrincipal"] - DELEGATED_ADMIN_ACCOUNT_ID: !Ref pDelegatedAdminAccountId \ No newline at end of file diff --git a/solutions/firewall-manager/firewall-manager-org/README.md b/solutions/firewall-manager/firewall-manager-org/README.md deleted file mode 100755 index ceb32126..00000000 --- a/solutions/firewall-manager/firewall-manager-org/README.md +++ /dev/null @@ -1,318 +0,0 @@ -# Firewall Manager - -The Organization Firewall Manager solution will delegate an administrator account (Security Account), deploy a maximum -allowed security group, configure a security group policy, and configure multiple WAF policies. - -AWS Firewall Manager simplifies your AWS WAF, AWS Shield Advanced, and Amazon VPC security groups administration and -maintenance tasks across multiple accounts and resources. With Firewall Manager, you set up your AWS WAF firewall rules, -Shield Advanced protections, and Amazon VPC security groups just once. Firewall Manager is particularly useful when you -want to protect your entire organization rather than a few number of specific accounts and resources, or if you -frequently add new resources that you want to protect. To use Firewall Manager, your account must be a member of an -organization in the AWS Organizations service, and you must enable AWS Config for each member account in your -AWS Organization. - - -**Resources Deployed:** - -* Delegate Administrator (Organization Management Account) - Delegate the administration of Firewall Manager to a - different account other than the Organizational Management account -* Firewall Manager Security Group Policy (Security Account) - Deploy security policies for VPC Security Groups -* Firewall Manager WAF Policy (Security Account) - Deploy security policies for AWS WAF -* Firewall Manager Disassociate IAM Role (Security Account) - Deploy an IAM role to use for disassociating the - delegated administrator account - -**Directory Structure:** -``` - firewall-manager-org - ├ control-tower/ - ├ parameters/ - ├ manifest.yaml - ├ README.md - ├ code/ - ├ src/ - ├ app.py - ├ requirements.txt - ├ templates/ - ├ firewall-manager-org-delegate-admin.yaml - ├ firewall-manager-org-waf-policy.yaml - ├ firewall-manager-org-sg-policy.yaml - ├ firewall-manager-org-disassociate-iam-role.yaml - └ README.md -``` - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/Organization-Firewall-Manager-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation StackSet and Stack - -**Configuration:** - -* StackSet Names: - * FirewallManagerOrgDelegateAdmin - * FirewallManagerOrgDisassociateRole - * FirewallManagerOrgSGPolicy - * FirewallManagerOrgWAFPolicy - -### 1.2 AWS Lambda Function - -**Description:** - -The custom CloudFormation Lambda resource is required to delegate an administrator account because this capability -is not supported by CloudFormation (September 2020) - -**Configuration:** - -* Lambda Function Name = [Prefix]-firewall-manager-org-delegate-admin -* Environment Variables (Configurable and set via CloudFormation) - * LOG_LEVEL - Default = info, Valid Values = info, warning, error, critical -* Custom Resource Properties: - * ASSUME_ROLE_NAME - Disassociate IAM role name - * AWS_PARTITION - AWS partition. Valid Values = aws, aws-cn, aws-us-gov - * DELEGATED_ADMIN_ACCOUNT_ID - AWS account to delegate administration of Firewall Manager to - -**Input Validation** - -Validation of environment variables is done to make sure values exist and are the correct type - -### 1.3 Lambda Execution IAM Role - -**Description:** - -Used by the custom CloudFormation Lambda function to enable the Firewall Delegated Administrator Account - -**Configuration:** - -* Role Name: [Prefix]-firewall-manager-org-lambda -* Policy Name: [Prefix]-firewall-manager-org-lambda -* Permissions: - * CloudWatch Logs - Limited: Write on LogGroupName like /aws/lambda/[Lambda Function Name] - * EC2 - Limited: List All resources - * Firewall Manager - Limited: Read, Write All resources - * Health - Limited: Read All resources - * IAM - Limited Write [iam:AWSServiceName like fms.amazonaws.com] - * Organizations - Limited: Read, Write All resources - * STS - Limited: Write AssumeRole [Disassociate FMS Role] - -### 1.4 Lambda CloudWatch Log Group - -**Description:** - -Contains Lambda function execution logs - -**Configuration:** - -* Retention = Default 2 weeks (14 days) -* Log group name = /aws/lambda/[Lambda Function Name] - -### 1.5 Firewall Manager - -**Description:** - -Enable a Firewall Manager delegated administrator account. - -**Configuration:** - -* Delegated administrator account ID - ----- - -## 2.0 Security Tooling Account - -### 2.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account StackSet - -**Configuration:** - -* Stack Names: - * StackSet-...-FirewallManagerOrgSGPolicy... - * StackSet-...-FirewallManagerOrgWAFPolicy... - * StackSet-...-FirewallManagerOrgDisassociateRole... - -### 2.2 VPC and Security Group - -**Description:** - -A security group is used by the Firewall Manager security group policy to define the maximum allowed rules. A VPC is -needed for creating the security group. - -**Using AWS Firewall Manager to audit VPC Security Groups:** - -AWS Firewall Manager enables the ability to audit (and remediate - if desired) security groups across the -AWS Organization Unit. This solution utilizes -[Content Audit Security Group Policies](https://docs.aws.amazon.com/waf/latest/developerguide/security-group-policies.html#security-group-policies-audit) -to verify that Security Groups created across the AWS Organization Unit adhere to the rules. A -[Usage Audit Security Group Policy](https://docs.aws.amazon.com/waf/latest/developerguide/security-group-policies.html#security-group-policies-usage) -is used to identify and remediate unused security groups to keep proper hygiene in the target accounts. - -**Configuration:** - -* Create VPC for the Security Group = true or false -* Enable auto remediation = true or false - Enables auto remediation for the security group policy non compliant resources -* Internal Network CIDR = CIDR Block for internal network traffic -* Tag Key = Tag key to apply to the security group policy -* Tag Value = Tag value to apply to the security group policy -* VPC CIDR Block = (Optional) - Defines the CIDR block for the created VPC. Default = 10.0.0.0/28 -* VPC ID = Existing VPC ID to use for the security group created by this solution - -**Security Group Policies** - -* Firewall Manager Security Group Content Audit Policy - * This Security Group Policy utilizes a provided security group to audit against 2 rules: - * The only protocol that can ever allow inbound traffic is TCP/443 (HTTPS) - * All other protocols are allowed internally to the CIDR blocks for the VPC Networks -* Firewall Manager Unused Security Group Policy - * This Security Group policy specifically targets unused Security groups. If remediation is enabled, Firewall Manager will automatically clean up security groups that are not actively being used to maintain good hygiene in the AWS environment. - -### 2.3 Firewall Manager - -**Description:** - -[Firewall Manager WAF Policies](https://docs.aws.amazon.com/waf/latest/developerguide/waf-policies.html) -allow Firewall Manager to centrally mandate the application of AWS WAF Rule sets and Web ACLs to endpoints -(ELBs, CloudFront Distributions, and API Gateway) in the environment. This solution utilizes AWS Firewall Manager -to deploy a baseline set of -[AWS Managed WAF Rules](https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html) -to monitor and remediate the configured resources within the AWS Organization. The solution enforces the policies -based on resource tags, which can be enforced using an IAM or SCP policy. - -**Configuration:** - -> All default configurations are defined within the CloudFormation template - -**WAF Policies** - -* FMS Regional WAF Default Policy - * Resource Types - * ELBv2 - * API Gateway - * AWS Managed Rule sets - * AWS Core Ruleset - * AWS SQL Database Ruleset - * AWS IP Reputation List - * Resource Tag - * Key: fms-default-policy - * Value: true -* FMS CloudFront Default Policy - * Resource Types - * Cloudfront Distribution - * AWS Managed Rule sets - * AWS Core Ruleset - * AWS SQL Database Ruleset - * AWS IP Reputation List - * Resource Tag - * Key: fms-default-policy - * Value: true -* FMS Regional WAF Windows Policy - * Resource Types - * ELBv2 - * API Gateway - * AWS Managed Rule sets - * AWS Windows Operating System Ruleset - * Resource Tag - * Key: workload-os - * Value: windows -* FMS Regional WAF Linux Policy - * Resource Types - * ELBv2 - * API Gateway - * AWS Managed Rule sets - * AWS Linux Operating System Ruleset - * Resource Tag - * Key: workload-os - * Value: linux -* FMS Regional WAF Posix Policy - * Resource Types - * ELBv2 - * API Gateway - * AWS Managed Rule sets - * AWS Posix Operating System Ruleset - * Resource Tag - * Key: workload-os - * Value: posix - -### 2.4 Firewall Manager Disassociate IAM Role - -**Description:** - -The Firewall Manager Disassociate IAM role is deployed to the delegated administrator account to disassociate the -account from Firewall Manager when the solution is deleted. Firewall Manager requires the disassociation to happen -within the delegated administrator account. The Management Account Lambda function assumes this role to disassociate -the account when the custom resource is deleted via CloudFormation. - -**Configuration:** - -* Disassociate Role Name - Needs to be the same as the 1.2 Assume Role Name -* Management Account ID - The Organization Management Account ID -* Management Account Lambda Role Name - Role name used in 1.3 -* Tag Key - IAM role tag key value -* Tag Value - IAM role tag value - ----- - -# Implementation Instructions - -### [AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets - -> **Solution Deployment Order:** -> 1. Management account (FirewallManagerOrgDelegateAdmin) -> 2. Security account (FirewallManagerOrgSGPolicy) -> 3. Security account (FirewallManagerOrgWAFPolicy) -> 4. Security account (FirewallManagerOrgDisassociateRole) - -### Prerequisites - -* Access to your AWS Organizational Management account to deploy Cloudformation templates -* Access to the AWS account that will act as the Firewall Manager Administration account to deploy - CloudFormation templates -* AWS Config must be enabled in all target accounts -* An S3 Bucket must be available to upload the Lambda zip file created in the steps below - * [Example CloudFormation Template](../../../extras/lambda-s3-buckets.yaml) to create the S3 bucket - -### Instructions - -1. Package the Lambda code into a zip file and upload it to the S3 bucket - * Package and Upload the Lambda zip file to S3 - [Packaging script](../../../extras/packaging-scripts/package-lambda.sh) - ```shell - export BUCKET=lambda-zips-CHANGE_ME_ACCOUNT_ID-CHANGE_ME_REGION - sh ~/aws-security-reference-architecture-examples/extras/packaging-scripts/package-lambda.sh \ - --file_name firewall-manager-org-delegate-admin.zip \ - --bucket $BUCKET \ - --src_dir ~/aws-security-reference-architecture-examples/solutions/firewall-manager/firewall-manager-org/code/src - ``` -2. Create a CloudFormation StackSet or Stack within the AWS account using the following templates - - | Account | StackSet Name | Template | - | --------------- | ----------------- | ---------- | - | Management | FirewallManagerOrgDelegateAdmin | templates/firewall-manager-org-delegated-admin.yaml | - | Security | FirewallManagerOrgSGPolicy | templates/firewall-manager-org-sg-policy.yaml | - | Security | FirewallManagerOrgWAFPolicy | templates/firewall-manager-org-waf-policy.yaml | - | Security | FirewallManagerOrgDisassociateRole | templates/firewall-manager-org-disassociate-iam-role.yaml | - - ----- - -# References -* [Firewall Manager Developer Guide](https://docs.aws.amazon.com/waf/latest/developerguide/fms-chapter.html) -* [Firewall Manager WAF Policies](https://docs.aws.amazon.com/waf/latest/developerguide/waf-policies.html) -* [Firewall Manager Security Group Policy Usage](https://docs.aws.amazon.com/waf/latest/developerguide/security-group-policies.html#security-group-policies-usage) - diff --git a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/README.md b/solutions/firewall-manager/firewall-manager-org/aws-control-tower/README.md deleted file mode 100644 index e9d331e8..00000000 --- a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/README.md +++ /dev/null @@ -1,41 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) - 2. [parameters/firewall-manager-org-delegate-admin.json](parameters/firewall-manager-org-delegate-admin.json) - 3. [parameters/firewall-manager-org-disassociate-iam-role.json](parameters/firewall-manager-org-disassociate-iam-role.json) - 4. [parameters/firewall-manager-org-sg-policy.json](parameters/firewall-manager-org-sg-policy.json) - 5. [templates/firewall-manager-org-delegate-admin.yaml](../templates/firewall-manager-org-delegate-admin.yaml) - 6. [templates/firewall-manager-org-disassociate-iam-role.yaml](../templates/firewall-manager-org-disassociate-iam-role.yaml) - 7. [templates/firewall-manager-org-sg-policy.yaml](../templates/firewall-manager-org-sg-policy.yaml) - 8. [templates/firewall-manager-org-waf-policy.yaml](../templates/firewall-manager-org-waf-policy.yaml) -3. Update the parameter files with any specific values for your environment -4. Update the manifest.yaml file with your account names -5. Deploy the Customizations for AWS Control Tower configuration -6. How to verify after the pipeline completes? - 1. Log into the Audit account and navigate to the AWS Firewall Manager page - 2. Verify the correct configurations have been applied - 1. Security policies - * security-group-maximum-allowed - * security-group-common-policy - * fms-regional-waf-default-policy - * fms-regional-waf-windows-policy - * fms-regional-waf-linux-policy - * fms-regional-waf-posix-policy - - -# Delete Instructions - -1. Within the Customizations for AWS Control Tower configuration - 1. Remove the Firewall Manager configurations from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the Firewall Manager solution -2. Deploy the Customizations for AWS Control Tower configuration -3. After the pipeline completes, log into the management account and navigate to the CloudFormation page - 1. Delete the CustomControlTower-FirewallManager* CloudFormation StackSets - \ No newline at end of file diff --git a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/manifest.yaml b/solutions/firewall-manager/firewall-manager-org/aws-control-tower/manifest.yaml deleted file mode 100644 index 106928dc..00000000 --- a/solutions/firewall-manager/firewall-manager-org/aws-control-tower/manifest.yaml +++ /dev/null @@ -1,39 +0,0 @@ ---- -#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets -region: us-east-1 -version: 2020-01-01 - -# Control Tower Custom Service Control Policies -organization_policies: [] - -# Control Tower Custom CloudFormation Resources -cloudformation_resources: - - name: FirewallManagerOrgDelegateAdmin - template_file: templates/firewall-manager-org-delegate-admin.yaml - parameter_file: parameters/firewall-manager-org-delegate-admin.json - deploy_method: stack_set - ssm_parameters: - - name: /org/firewall_manager/lambda_role - value: $[output_oLamdbaRole] - deploy_to_account: - - Control Tower Management - - - name: FirewallManagerOrgDisassociateRole - template_file: templates/firewall-manager-org-disassociate-iam-role.yaml - parameter_file: parameters/firewall-manager-org-disassociate-iam-role.json - deploy_method: stack_set - deploy_to_account: - - Audit - - - name: FirewallManagerOrgSGPolicy - template_file: templates/firewall-manager-org-sg-policy.yaml - parameter_file: parameters/firewall-manager-org-sg-policy.json - deploy_method: stack_set - deploy_to_account: - - Audit - - - name: FirewallManagerOrgWAFPolicy - template_file: templates/firewall-manager-org-waf-policy.yaml - deploy_method: stack_set - deploy_to_account: - - Audit \ No newline at end of file diff --git a/solutions/firewall-manager/firewall-manager-org/code/src/__init__.py b/solutions/firewall-manager/firewall-manager-org/code/src/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/solutions/firewall-manager/firewall-manager-org/documentation/Organization-Firewall-Manager-Architecture.png b/solutions/firewall-manager/firewall-manager-org/documentation/Organization-Firewall-Manager-Architecture.png deleted file mode 100644 index 3e186e8e..00000000 Binary files a/solutions/firewall-manager/firewall-manager-org/documentation/Organization-Firewall-Manager-Architecture.png and /dev/null differ diff --git a/solutions/guardduty/guardduty-org/README.md b/solutions/guardduty/guardduty-org/README.md deleted file mode 100644 index 5479f096..00000000 --- a/solutions/guardduty/guardduty-org/README.md +++ /dev/null @@ -1,298 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# GuardDuty Organization - -The GuardDuty Organization solution will enable Amazon GuardDuty by delegating administration to a member account - within the Organization management account and configuring GuardDuty within the delegated administrator account for all - the existing and future AWS Organization accounts. GuardDuty is also configured to send the findings to a central - S3 bucket encrypted with a KMS key. - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/diagram/Organization-GuardDuty-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation StackSet and Stack - -**Configuration:** - -* StackSet Names: - * GuardDutyOrgConfigurationRole - * GuardDutyOrgDeliveryKMSKey - * GuardDutyOrgDeliveryS3Bucket - * GuardDutyOrgConfiguration - * GuardDutyOrgDeleteDetectorRole - -### 1.2 AWS Lambda Function - -**Description:** - -The custom CloudFormation Lambda resource is required to delegate an administrator account because this capability -is not supported by CloudFormation (November 2020) - -**Configuration:** - -* Lambda Function Name = [Prefix]-guardduty-org-configuration -* Environment Variables (Configurable and set via CloudFormation) - * AUTO_ENABLE_S3_LOGS - default = false, Valid values = true or false - * AWS_PARTITION - aws, aws-cn, aws-us-gov - * CONFIGURATION_ROLE_NAME - Role within the delegated admin account to configure GuardDuty - * DELEGATED_ADMIN_ACCOUNT_ID - Organization Member Account ID which is typically the Security account - * DELETE_DETECTOR_ROLE_NAME - Role within each member account used to delete the GuardDuty detectors - * ENABLED_REGIONS - Comma delimited list of regions to enable Guard Duty in. Leave blank for all supported regions. - * FINDING_PUBLISHING_FREQUENCY - Default = 'FIFTEEN_MINUTES', Valid values = 'FIFTEEN_MINUTES', 'ONE_HOUR', - 'SIX_HOURS' - * KMS_KEY_ARN - KMS Key ARN to encrypt the Guard Duty findings sent to S3 - * LOG_LEVEL - Default = info, Valid Values = debug, info, warning, error, critical - * PUBLISHING_DESTINATION_BUCKET_ARN - S3 bucket ARN to send the Guard Duty findings - * TAG_KEY1 - Tags the IAM role and Lambda Function with this key - * TAG_VALUE1 - Tags the IAM role and Lambda Function with this value - -**Input Validation** - -Validation of environment variables is done to make sure values exist and are the correct type - -### 1.3 Lambda CloudWatch Log Group - -**Description:** - -Contains Lambda function execution logs - -**Configuration:** - -* Retention = Default 2 weeks (14 days) -* Log group name = /aws/lambda/[Lambda Function Name] - -### 1.4 Lambda Execution IAM Role - -**Description:** - -Used by the custom CloudFormation Lambda function to enable the GuardDuty Delegated Administrator Account within -each region provided - -**Configuration:** - -* Role Name: [Prefix]-guardduty-org-lambda -* Permissions: - * CloudWatch Logs - Limited: Write on LogGroupName like /aws/lambda/[Lambda Function Name] - * GuardDuty - Limited: List, Write - * IAM - Limited Read, Write on AWSServiceRoleForAmazonGuardDuty - * Organizations - Limited: List, Read - * STS - Assume configuration role in delegated admin account - -### 1.5 GuardDuty - -**Description:** - -Enable GuardDuty delegated administrator account within provide regions. Once enabled, a GuardDuty detector will -exist in the delegated administrator account/region. The Lambda function assumes the configuration role within the -delegated administrator account to configure GuardDuty with the below configurations. - -**Configuration:** - -* Delegated administrator account ID -* Regions to enable - Leave blank for all available regions -* GuardDuty publish destination S3 Bucket with KMS encryption -* Enable existing accounts -* Auto Enable new member accounts -* Auto Enable S3 Data Logs - Default = false - ----- - -## 2.0 Security Log Archive Account - -### 2.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the management account StackSet - -**Configuration:** - -* Stack Name: *GuardDutyOrgDeliveryS3Bucket-... - -### 2.2 GuardDuty Delivery S3 Bucket - -**Description:** - -S3 bucket where GuardDuty findings are exported for each account/region within the AWS Organization - -**Configuration:** - -* S3 bucket name prefix - the account and region are appended to the prefix - e.g. guardduty-delivery-123456789012-us-east-1 -* Encrypted with the GuardDuty delivery KMS key -* All public block settings set to true -* Versioning enabled -* S3 bucket tagged with provided key -* Bucket policy configured to limit access to the bucket -* Ownership controls - Object Ownership = BucketOwnerPreferred - -### 2.3 GuardDuty - -**Description:** - -GuardDuty is enabled for existing accounts within each member account and region during the initial setup. - -**Configuration:** - -* None - Controlled by the GuardDuty Delegated Administrator Account - ----- - -## 3.0 Security Tooling Account - -### 3.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the management account StackSet - -**Configuration:** - -* Stack Name: *GuardDutyOrgDeliveryKMSKey-... -* Stack Name: *GuardDutyOrgConfigurationRole-... - -### 3.2 GuardDuty Delivery KMS Key - -**Description:** - -Customer managed KMS key used for encrypting exported GuardDuty findings - -**Configuration:** - -* Key alias -* Organization Management Account ID -* Logging Account ID -* KMS Key Tag - -### 3.3 Configuration IAM Role - -**Description:** - -Assumed by the custom CloudFormation Lambda function within the management account to configure GuardDuty within each - region provided - -**Configuration:** - -* Role Name: [Prefix]-guardduty-org-configuration -* Permissions: - * GuardDuty - Limited: List, Write - * IAM - Limited Read, Write on AWSServiceRoleForAmazonGuardDuty - * Organizations - Limited: List - -### 3.4 GuardDuty - -**Description:** - -Configure GuardDuty to add existing member accounts and to auto enable new member accounts. - -**Configuration:** - -* See configuration details in the management account GuardDuty configuration section - ----- - -## 4.0 All Existing and Future Organization Member Accounts - -### 4.1 GuardDuty - -**Description:** - -GuardDuty is enabled for existing accounts within each member account and region during the initial setup. -GuardDuty will automatically enable new member accounts/regions when they are added to the AWS Organization. - -**Configuration:** - -* None - Controlled by the GuardDuty Delegated Administrator Account - -### 4.2 Delete Detector Role - -**Description:** - -An IAM role is created within all the accounts to clean up the GuardDuty detectors in a delete event. - -**Configuration:** - -* Role Name: [Prefix]-guardduty-org-delete-detector -* Permissions: - * GuardDuty - Limited: List, Write - ----- - -# Implementation Instructions - -### [AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets - -> **Solution Deployment Order:** -> 1. security (GuardDutyOrgConfigurationRole) -> 2. security (GuardDutyOrgDeliveryKMSKey) -> 3. logging (GuardDutyOrgDeliveryS3Bucket) -> 4. management (GuardDutyOrgConfiguration) -> 5. all accounts (GuardDutyOrgDeleteDetectorRole) - -#### Pre-requisites - -* Disable GuardDuty in all accounts/regions by removing the detector - -#### Instructions - -1. Create new or use existing S3 buckets within the us-east-1 region owned by the Organization Management Account - * Example bucket name: lambda-zips-[Management Account ID]-us-east-1 - * [Example CloudFormation Template](../../../extras/lambda-s3-buckets.yaml) - * The bucket must allow the s3:GetObject action to the Organization using a bucket policy like the one below to - allow the accounts within the Organization to get the Lambda files. - ``` - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AllowGetObject", - "Effect": "Allow", - "Principal": "*", - "Action": "s3:GetObject", - "Resource": "arn:[AWS::Partition]:s3:::[BUCKET NAME]/*", - "Condition": { - "StringEquals": { - "aws:PrincipalOrgID": "[ORGANIZATION ID]" - } - } - } - ] - } - ``` -2. Package the Lambda code into a zip file and upload it to the S3 bucket - * Package and Upload the Lambda zip file to S3 - [Packaging script](../../../extras/packaging-scripts/package-lambda.sh) -3. Copy the below folders/files to the new add-on folder excluding the lambda folder - - | Account | StackSet Name | Template | - | --------------- | ----------------- | ---------- | - | Security | GuardDutyOrgConfigurationRole | templates/guardduty-org-configuration-role.yaml | - | Security | GuardDutyOrgDeliveryKMSKey | templates/guardduty-org-delivery-kms-key.yaml | - | Log Archive | GuardDutyOrgDeliveryS3Bucket | templates/guardduty-org-delivery-s3-bucket.yaml | - | Management | GuardDutyOrgConfiguration | templates/guardduty-org-configuration.yaml | - | All | GuardDutyOrgDeleteDetectorRole | templates/guardduty-org-delete-detector-role.yaml | - -4. If the CloudFormation StackSets are removed, the solution will attempt to remove GuardDuty - > Environments containing large numbers of accounts may require additional cleanup scripts to remove the remaining - GuardDuty detectors within the enabled accounts/regions. - ----- - -# References -* [Managing GuardDuty Accounts with AWS Organizations](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_organizations.html) diff --git a/solutions/guardduty/guardduty-org/aws-control-tower/README.md b/solutions/guardduty/guardduty-org/aws-control-tower/README.md deleted file mode 100644 index 6b4727e8..00000000 --- a/solutions/guardduty/guardduty-org/aws-control-tower/README.md +++ /dev/null @@ -1,58 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) - 2. [parameters/guardduty-org-configuration.json](parameters/guardduty-org-configuration.json) - 3. [parameters/guardduty-org-configuration-role.json](parameters/guardduty-org-configuration-role.json) - 4. [parameters/guardduty-org-delete-detector-role.json](parameters/guardduty-org-delete-detector-role.json) - 5. [parameters/guardduty-org-delivery-kms-key.json](parameters/guardduty-org-delivery-kms-key.json) - 6. [parameters/guardduty-org-delivery-s3-bucket.json](parameters/guardduty-org-delivery-s3-bucket.json) - 7. [templates/guardduty-org-configuration.yaml](../templates/guardduty-org-configuration.yaml) - 8. [templates/guardduty-org-configuration-role.yaml](../templates/guardduty-org-configuration-role.yaml) - 9. [templates/guardduty-org-delete-detector-role.yaml](../templates/guardduty-org-delete-detector-role.yaml) - 10. [templates/guardduty-org-delivery-kms-key.yaml](../templates/guardduty-org-delivery-kms-key.yaml) - 11. [templates/guardduty-org-delivery-s3-bucket.yaml](../templates/guardduty-org-delivery-s3-bucket.yaml) -3. Update the parameter files with any specific values for your environment -4. Update the manifest.yaml file with your account names -5. Deploy the Customizations for AWS Control Tower configuration -6. How to verify after the pipeline completes? - 1. Log into the Management account and navigate to the GuardDuty page - 1. Validate that the delegated admin account is set for each region - 2. Log into the Audit account and navigate to the GuardDuty page - 1. Verify the correct GuardDuty configurations have been applied to each region - 2. Verify all existing accounts have been enabled - 3. Verify the findings export is configured for the S3 bucket - 4. Generate sample findings to verify S3 delivery - 3. Log into the Log archive account and navigate to the S3 page - 1. Verify the sample findings have been delivered - -# Delete Instructions - -1. Within the Customizations for AWS Control Tower configuration - 1. Remove the GuardDuty configurations from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the GuardDuty solution -2. Deploy the Customizations for AWS Control Tower configuration -3. After the pipeline completes, log into the Management account and navigate to the CloudFormation page - 1. Delete the Stack Instance from the CustomControlTower-GuardDutyOrgConfiguration CloudFormation StackSet - 1. Verify that the GuardDuty has been disabled in all accounts/regions - 2. After the Stack Instance deletes, delete the CustomControlTower-GuardDutyOrgConfiguration CloudFormation StackSet - 3. Delete the Stack Instance from the CustomControlTower-GuardDutyOrgConfigurationRole CloudFormation StackSet - 4. After the Stack Instance deletes, delete the CustomControlTower-GuardDutyOrgConfigurationRole CloudFormation - StackSet - 5. Delete the stack instances from the CustomControlTower-GuardDutyDeleteDetectorRole CloudFormation StackSet - 6. After the stack instances are deleted, delete the CustomControlTower-GuardDutyDeleteDetectorRole CloudFormation - StackSet - 7. Log into the Log Archive account and empty/delete the guardduty-delivery S3 bucket - 8. Delete the Stack Instance from the CustomControlTower-GuardDutyOrgDeliveryS3Bucket CloudFormation StackSet - 9. After the Stack Instance deletes, delete the CustomControlTower-GuardDutyOrgDeliveryS3Bucket CloudFormation - StackSet - 10. Delete the Stack Instance from the CustomControlTower-GuardDutyOrgDeliveryKMSKey CloudFormation StackSet - 11. After the Stack Instance deletes, delete the CustomControlTower-GuardDutyOrgDeliveryKMSKey CloudFormation - StackSet - 12. Verify that the CloudWatch Log Group "/aws/lambda/...guardduty-org-configuration" was deleted diff --git a/solutions/guardduty/guardduty-org/aws-control-tower/manifest.yaml b/solutions/guardduty/guardduty-org/aws-control-tower/manifest.yaml deleted file mode 100644 index 82a551e6..00000000 --- a/solutions/guardduty/guardduty-org/aws-control-tower/manifest.yaml +++ /dev/null @@ -1,52 +0,0 @@ ---- -#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets -region: us-east-1 -version: 2020-01-01 - -# Control Tower Custom Service Control Policies -organization_policies: [] - -# Control Tower Custom CloudFormation Resources -cloudformation_resources: - - name: GuardDutyOrgConfigurationRole - template_file: templates/guardduty-org-configuration-role.yaml - parameter_file: parameters/guardduty-org-configuration-role.json - deploy_method: stack_set - deploy_to_account: - - Audit - - - name: GuardDutyOrgDeliveryKMSKey - template_file: templates/guardduty-org-delivery-kms-key.yaml - parameter_file: parameters/guardduty-org-delivery-kms-key.json - deploy_method: stack_set - ssm_parameters: - - name: /org/guardduty/kms_key_arn - value: $[output_oGuardDutyDeliveryKeyArn] - deploy_to_account: - - Audit - - - name: GuardDutyOrgDeliveryS3Bucket - template_file: templates/guardduty-org-delivery-s3-bucket.yaml - parameter_file: parameters/guardduty-org-delivery-s3-bucket.json - deploy_method: stack_set - ssm_parameters: - - name: /org/guardduty/s3_bucket - value: $[output_oGuardDutyDeliveryS3Bucket] - deploy_to_account: - - Log archive - - - name: GuardDutyOrgConfiguration - template_file: templates/guardduty-org-configuration.yaml - parameter_file: parameters/guardduty-org-configuration.json - deploy_method: stack_set - deploy_to_account: - - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME - - - name: GuardDutyDeleteDetectorRole - template_file: templates/guardduty-org-delete-detector-role.yaml - parameter_file: parameters/guardduty-org-delete-detector-role.json - deploy_method: stack_set - deploy_to_ou: - - Core - - primary - - workloads \ No newline at end of file diff --git a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-configuration-role.json b/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-configuration-role.json deleted file mode 100644 index f293c1b8..00000000 --- a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-configuration-role.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "ParameterKey": "pConfigurationRoleName", - "ParameterValue": "cfct-guardduty-configuration" - }, - { - "ParameterKey": "pOrgPrimaryAccountId", - "ParameterValue": "$[alfred_ssm_/org/primary/account_id]" - }, - { - "ParameterKey": "pOrgPrimaryLambdaRoleName", - "ParameterValue": "cfct-guardduty-org-lambda" - }, - { - "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" - }, - { - "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" - } -] \ No newline at end of file diff --git a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-delete-detector-role.json b/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-delete-detector-role.json deleted file mode 100644 index 77d0a240..00000000 --- a/solutions/guardduty/guardduty-org/aws-control-tower/parameters/guardduty-org-delete-detector-role.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "ParameterKey": "pDeleteDetectorRoleName", - "ParameterValue": "cfct-guardduty-delete-detector" - }, - { - "ParameterKey": "pOrgPrimaryAccountId", - "ParameterValue": "$[alfred_ssm_/org/primary/account_id]" - }, - { - "ParameterKey": "pOrgPrimaryLambdaRoleName", - "ParameterValue": "cfct-guardduty-org-lambda" - }, - { - "ParameterKey": "pTagKey1", - "ParameterValue": "cfct" - }, - { - "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-cfct" - } -] \ No newline at end of file diff --git a/solutions/guardduty/guardduty-org/documentation/diagram/Organization-GuardDuty-Architecture.png b/solutions/guardduty/guardduty-org/documentation/diagram/Organization-GuardDuty-Architecture.png deleted file mode 100644 index 13cd1b1e..00000000 Binary files a/solutions/guardduty/guardduty-org/documentation/diagram/Organization-GuardDuty-Architecture.png and /dev/null differ diff --git a/solutions/iam/access-analyzer/README.md b/solutions/iam/access-analyzer/README.md deleted file mode 100644 index 99e3c295..00000000 --- a/solutions/iam/access-analyzer/README.md +++ /dev/null @@ -1,160 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# Access Analyzer - -The IAM Access Analyzer solution enables AWS IAM Access Analyzer by delegating administration to a member account -within the Organization management account. It then configures Access Analyzer within the delegated administrator account -for all the existing and future AWS Organization accounts. - -In addition to the organization deployment, the solution deploys AWS Access Analyzer to all the member accounts -and regions for analyzing account level permissions. - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/Access-Analyzer-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources deployed via CloudFormation StackSet and Stacks within member accounts - -**Configuration:** - -* StackSet Names: - * AccessAnalyzerOrganization - * AccessAnalyzerAccount - -### 1.2 AWS Organizations - -**Description:** - -AWS Organizations is used to delegate an administrator account for AWS Access Analyzer - -**Configuration:** - -* Delegated Administrator Account - See [Common Register Delegated Administrator](../../common/register-delegated-administrator) - - -### 1.3 Account AWS IAM Access Analyzer - -**Description:** - -AWS IAM Access Analyzer is configured to monitor supported resources for the AWS Account zone of trust. - -**Configuration:** - -* Access Analyzer Name Prefix: Default = account-access-analyzer -* Tag Key = Access Analyzer Tag Key -* Tag Value = Access Analyzer Tag Value - ----- - -## 2.0 Security Tooling Account - -### 2.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account StackSet - -**Configuration:** - -* Stack Names: - * StackSet-...-AccessAnalyzerAccount-... - * StackSet-...-AccessAnalyzerOrganization-... - -### 2.2 Account AWS IAM Access Analyzer - -**Description:** - -AWS IAM Access Analyzer is configured to monitor supported resources for the AWS Account zone of trust. - -**Configuration:** - -* Access Analyzer Name Prefix: Default = account-access-analyzer -* Tag Key = Access Analyzer Tag Key -* Tag Value = Access Analyzer Tag Value - -### 2.3 Organization AWS IAM Access Analyzer - -**Description:** - -AWS IAM Access Analyzer is configured to monitor supported resources for the AWS Organization zone of trust. - -**Configuration:** - -* Access Analyzer Name Prefix: Default = organization-access-analyzer -* Tag Key = Access Analyzer Tag Key -* Tag Value = Access Analyzer Tag Value - ----- - -## 3.0 All Existing and Future Organization Member Accounts - -### 3.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account StackSet - -**Configuration:** - -* Stack Names: - * StackSet-...-AccessAnalyzerAccount-... - -### 3.2 Account AWS IAM Access Analyzer - -**Description:** - -AWS IAM Access Analyzer is configured to monitor -[supported resources](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html) for the -AWS Account zone of trust. - -**Configuration:** - -* Access Analyzer Name Prefix: Default = account-access-analyzer -* Tag Key = Access Analyzer Tag Key -* Tag Value = Access Analyzer Tag Value - ----- - -# Implementation Instructions - -### [AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets - -#### Pre-requisites -1. Register a delegated administrator using the - [Common Register Delegated Administrator](../../common/register-delegated-administrator) solution - 1. pServicePrincipalList = "access-analyzer.amazonaws.com" - -#### Instructions - -> **Solution Deployment Order:** -> 1. All Accounts (AccessAnalyzerAccount) -> 2. Security Account (AccessAnalyzerOrganization) - - Create CloudFormation StackSets using the following templates - - | Account | StackSet Name | Template | - | --------------- | ----------------- | ---------- | - | Management | CommonRegisterDelegatedAdmin | templates/common-register-delegated-administrator.yaml | - | All Accounts | AccessAnalyzerAccount | templates/access-analyzer-acct.yaml | - | Security | AccessAnalyzerOrganization | templates/access-analyzer-org.yaml | - ----- - -# References -* [Using AWS IAM Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html) diff --git a/solutions/iam/access-analyzer/aws-control-tower/README.md b/solutions/iam/access-analyzer/aws-control-tower/README.md deleted file mode 100644 index 05187558..00000000 --- a/solutions/iam/access-analyzer/aws-control-tower/README.md +++ /dev/null @@ -1,73 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Package and upload the common-register-delegated-administrator Lambda function - ```shell - export AWS_ACCESS_KEY_ID=INSERT_AWS_ACCESS_KEY_ID - export AWS_SECRET_ACCESS_KEY=INSERT_AWS_SECRET_ACCESS_KEY - export AWS_SESSION_TOKEN=INSERT_AWS_SESSION_TOKEN - - export BUCKET=lambda-zips-CHANGE_ME_ACCOUNT_ID-CHANGE_ME_REGION - sh ~/aws-security-reference-architecture-examples/extras/packaging-scripts/package-lambda.sh \ - --file_name common-register-delegated-administrator.zip \ - --bucket $BUCKET \ - --src_dir ~/aws-security-reference-architecture-examples/solutions/common/register-delegated-admninistrator/code/src - ``` -3. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) -> manifest.yaml - 2. [common/register-delegated-administrator/aws-control-tower/parameters/common-register-delegated-administrator.json](../../../common/register-delegated-administrator/aws-control-tower/parameters/common-register-delegated-administrator.json) - -> parameters/common-register-delegated-administrator.json - 3. [parameters/access-analyzer-acct.json](parameters/access-analyzer-acct.json) - -> parameters/access-analyzer-acct.json - 4. [parameters/access-analyzer-org.json](parameters/access-analyzer-org.json) - -> parameters/access-analyzer-org.json - 5. [common/register-delegated-administrator/templates/common-register-delegated-administrator.yaml](../../../common/register-delegated-administrator/common-register-delegated-administrator.yaml) - -> templates/common-register-delegated-administrator.yaml - 6. [templates/access-analyzer-acct.yaml](../templates/access-analyzer-acct.yaml) - -> templates/access-analyzer-acct.yaml - 7. [templates/access-analyzer-org.yaml](../templates/access-analyzer-org.yaml) - -> templates/access-analyzer-org.yaml - -4. Update the parameter files with any specific values for your environment -5. Add "access-analyzer.amazonaws.com" to the pServicePrincipalList parameter in the parameters/common-register-delegated-administrator.json -6. Add the [common/register-delegated-administrator/aws-control-tower/manifest.yaml](../../../common/register-delegated-administrator/aws-control-tower) - resource configuration to your manifest.yaml file. - ```yaml - ... - cloudformation_resources: - # ----------------------------------------------------------------------------- - # Common Register Delegated Administrator - # ----------------------------------------------------------------------------- - - name: CommonRegisterDelegatedAdmin - template_file: templates/common-register-delegated-administrator.yaml - parameter_file: parameters/common-register-delegated-administrator.json - deploy_method: stack_set - deploy_to_account: - - REPLACE_ME_ORG_MANAGEMENT_ACCOUNT_NAME - ... - ``` -7. Update the manifest.yaml file with your account names and SSM parameters -8. Deploy the Customizations for AWS Control Tower configuration -9. How to verify after the pipeline completes? - 1. Log into the Audit account and navigate to the IAM Access Analyzer page - 1. Verify that there are 2 Access Analyzers (account and organization) - 2. Verify all existing accounts/regions have an account Access Analyzer - -# Delete Instructions - -1. Within the Customizations for AWS Control Tower configuration - 1. Remove the Access Analyzer configuration from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the Access Analyzer solution -2. Deploy the Customizations for AWS Control Tower configuration -3. After the pipeline completes, log into the Management account and navigate to the CloudFormation StackSet page - 1. Delete the Stack Instances from the CustomControlTower-AccessAnalyzerOrganization CloudFormation StackSet - 2. After the Stack Instance deletes, delete the CustomControlTower-AccessAnalyzerOrganization CloudFormation StackSet - 3. Delete the Stack Instances from the CustomControlTower-AccessAnalyzerAccount CloudFormation StackSet - 4. After the Stack Instance deletes, delete the CustomControlTower-AccessAnalyzerAccount CloudFormation StackSet - 5. Remove the access-analyzer.amazonaws.com service principle from the - parameters/common-register-delegated-administrator.json file diff --git a/solutions/iam/access-analyzer/documentation/Access-Analyzer-Architecture.png b/solutions/iam/access-analyzer/documentation/Access-Analyzer-Architecture.png deleted file mode 100644 index 635e7606..00000000 Binary files a/solutions/iam/access-analyzer/documentation/Access-Analyzer-Architecture.png and /dev/null differ diff --git a/solutions/iam/password-policy-acct/README.md b/solutions/iam/password-policy-acct/README.md deleted file mode 100644 index 270368d7..00000000 --- a/solutions/iam/password-policy-acct/README.md +++ /dev/null @@ -1,125 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# IAM Password Policy - -The IAM Password Policy solution updates the AWS account password policy within all accounts in an AWS Organization. - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/Password-Policy-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources deployed via CloudFormation StackSet and Stacks within member accounts - -**Configuration:** - -* StackSet Names: - * StackSet-...-PasswordPolicy-... - -### 1.2 AWS Lambda Function - -**Description:** - -The custom CloudFormation Lambda resource is required to update the existing IAM account password policy. - -**Configuration:** - -* Lambda Function Name - [Prefix]-password-policy-acct -* Lambda S3 Bucket Name - Management account S3 bucket with the Lambda zip file -* Lambda Zip File Name - Default = password-policy-acct.zip -* Log Level - Default = debug, Valid Values = debug, info, warning, error, critical -* Allow Users To Change Password - Default = true -* Hard Expiry - Default = false -* Max Password Age - Default = 90 -* Minimum Password Length - Default = 14 -* Password Reuse Prevention - Default = 24 -* Require Lowercase Characters - Default = true -* Require Numbers - Default = true -* Require Symbols - Default = true -* Require Uppercase Characters - Default = true - - -### 1.3 Amazon CloudWatch Log Group - -**Description:** - -Contains the Lambda function execution logs - -**Configuration:** - -* Log group name = /aws/lambda/[Lambda Function Name] -* Retention = Never expire - - -### 1.4 Lambda Execution IAM Role - -**Description:** - -Used by the custom CloudFormation Lambda function to update the account password policy - -**Configuration:** - -* Execution role name = [Prefix]-password-policy-lambda -* Permissions: - * CloudWatch Logs - Limited: Write on LogGroupName like /aws/lambda/[Lambda Function Name] - * IAM - Limited: Write All resources - - -### 1.5 IAM Password Policy - -**Description:** - -AWS account password policy for IAM users - -**Configuration:** - -* [Custom password policy options](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#password-policy-details) - ----- - -## 2.0 All Organization Member Accounts - -Same configuration details as 1.0 Organization Management Account - ----- - -# Implementation Instructions - -### [AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets - -#### Solution Deployment Order -1. All Accounts (PasswordPolicy) - -#### Instructions - -1. Create new or use an existing S3 bucket within the region owned by the Organization Management Account - * Example bucket name: lambda-zips-[Management Account ID]-us-east-1 - * [Example CloudFormation Template](../../../extras/lambda-s3-buckets.yaml) -2. Package the Lambda code into a zip file and upload it to the S3 bucket - * Package and Upload the Lambda zip file to S3 (Packaging script: /extras/packaging-scripts/package-lambda.sh) -3. Create CloudFormation StackSets using the following templates - - | Account | StackSet Name | Template | - | --------------- | ----------------- | ---------- | - | All Accounts | PasswordPolicy | templates/password-policy-acct.yaml | - ----- - -# References -* [Setting an account password policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html) -* [CIS AWS Foundations Benchmark controls](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html) diff --git a/solutions/iam/password-policy-acct/aws-control-tower/README.md b/solutions/iam/password-policy-acct/aws-control-tower/README.md deleted file mode 100644 index 60c2b808..00000000 --- a/solutions/iam/password-policy-acct/aws-control-tower/README.md +++ /dev/null @@ -1,44 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Package and upload the password-policy-acct Lambda function - ```shell - export AWS_ACCESS_KEY_ID=INSERT_AWS_ACCESS_KEY_ID - export AWS_SECRET_ACCESS_KEY=INSERT_AWS_SECRET_ACCESS_KEY - export AWS_SESSION_TOKEN=INSERT_AWS_SESSION_TOKEN - - export BUCKET=lambda-zips-CHANGE_ME_ACCOUNT_ID-CHANGE_ME_REGION - sh ~/aws-security-reference-architecture-examples/extras/packaging-scripts/package-lambda.sh \ - --file_name password-policy-acct.zip \ - --bucket $BUCKET \ - --src_dir ~/aws-security-reference-architecture-examples/solutions/iam/password-policy-acct/code/src - ``` -3. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) -> manifest.yaml - 2. [parameters/password-policy-acct.json](parameters/password-policy-acct.json) - -> parameters/password-policy-acct.json - 3. [templates/password-policy-acct.yaml](../templates/password-policy-acct.yaml) - -> templates/password-policy-acct.yaml - -4. Update the parameter files with any specific values for your environment -5. Update the manifest.yaml file with your account names and SSM parameters -6. Deploy the Customizations for AWS Control Tower configuration -7. How to verify after the pipeline completes? - 1. Log into any account within the AWS Organization - 1. Navigate to the IAM -> Account settings page - 2. Verify the custom password policy settings - -# Delete Instructions - -1. Within the Customizations for AWS Control Tower configuration - 1. Remove the Password Policy configuration from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the Password Policy solution -2. Deploy the Customizations for AWS Control Tower configuration -3. After the pipeline completes, log into the Management account and navigate to the CloudFormation StackSet page - 1. Delete the Stack Instances from the CustomControlTower-PasswordPolicy CloudFormation StackSet - 2. After the Stack Instance deletes, delete the CustomControlTower-PasswordPolicy CloudFormation StackSet diff --git a/solutions/iam/password-policy-acct/documentation/Password-Policy-Architecture.png b/solutions/iam/password-policy-acct/documentation/Password-Policy-Architecture.png deleted file mode 100644 index 2554315e..00000000 Binary files a/solutions/iam/password-policy-acct/documentation/Password-Policy-Architecture.png and /dev/null differ diff --git a/solutions/macie/macie-org/README.md b/solutions/macie/macie-org/README.md deleted file mode 100644 index db59c9e5..00000000 --- a/solutions/macie/macie-org/README.md +++ /dev/null @@ -1,295 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# Macie Organization - -The Macie Organization solution will enable Amazon Macie by delegating administration to a member account -within the Organization Management Account and configuring Macie within the delegated administrator account for all -the existing and future AWS Organization accounts. Macie is also configured to send the findings to a central -S3 bucket encrypted with a KMS key. - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/diagram/Macie-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation StackSet and Stack - -**Configuration:** - -* StackSet Names: - * MacieOrgConfigurationRole - * MacieOrgDeliveryKMSKey - * MacieOrgDeliveryS3Bucket - * MacieOrgConfiguration - * MacieOrgMemberDisableRole - -### 1.2 AWS Lambda Function - -**Description:** - -The custom CloudFormation Lambda resource is required to delegate an administrator account because this capability -is not supported by CloudFormation (August 2021) - -**Configuration:** - -* Lambda Function Name = [Prefix]-macie-org-configuration -* Environment Variables (Configurable and set via CloudFormation) - * AWS_PARTITION - aws, aws-cn, aws-us-gov - * CONFIGURATION_ROLE_NAME - Role within the delegated admin account to configure Macie - * CONTROL_TOWER_REGIONS_ONLY - Enable only the Control Tower regions - * DELEGATED_ADMIN_ACCOUNT_ID - Organization Member Account ID which is typically the Security account - * DISABLE_MACIE_ROLE_NAME - Role within each member account used to disable Macie - * ENABLED_REGIONS - Comma delimited list of regions to enable Macie in. Leave blank for all supported regions. - * FINDING_PUBLISHING_FREQUENCY - Specifies how often to publish updates to policy findings for the account. - Default = 'FIFTEEN_MINUTES', Valid values = 'FIFTEEN_MINUTES', 'ONE_HOUR', 'SIX_HOURS' - * KMS_KEY_ARN - KMS Key ARN to encrypt the Macie classifications sent to S3 - * S3_BUCKET_NAME - S3 bucket ARN to send the Macie classifications - -**Input Validation** - -Validation of environment variables is done to make sure values exist and are the correct type - -### 1.3 Lambda CloudWatch Log Group - -**Description:** - -Contains Lambda function execution logs - -**Configuration:** - -* Log group name = /aws/lambda/[Lambda Function Name] - -### 1.4 Lambda Execution IAM Role - -**Description:** - -Used by the custom CloudFormation Lambda function to enable the Macie Delegated Administrator Account within -each region provided - -**Configuration:** - -* Role Name: [Prefix]-macie-org-lambda -* Permissions: - * CloudWatch Logs - Limited: Write on LogGroupName like /aws/lambda/[Lambda Function Name] - * Macie - Limited: List, Write - * IAM - Limited Read, Write on AWSServiceRoleForAmazonMacie - * Organizations - Limited: List, Read - * STS - Assume configuration role in delegated admin account - -### 1.5 Macie - -**Description:** - -Enable Macie delegated administrator account within provide regions. -The Lambda function assumes the configuration role within the delegated administrator account -to configure Macie with the below configurations. - -**Configuration:** - -* Delegated administrator account ID -* Regions to enable - Leave blank for all available regions -* Macie publish destination S3 Bucket with KMS encryption -* Enable existing accounts -* Auto Enable new member accounts -* Auto Enable S3 Data Logs - Default = false - ----- - -## 2.0 Security Log Archive Account - -### 2.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account StackSet - -**Configuration:** - -* Stack Name: *MacieOrgDeliveryS3Bucket-... - -### 2.2 Macie Delivery S3 Bucket - -**Description:** - -S3 bucket where Macie classifications are exported for each account/region within the AWS Organization - -**Configuration:** - -* S3 bucket name prefix - the account and region are appended to the prefix - e.g. macie-delivery-123456789012-us-east-1 -* Encrypted with the Macie delivery KMS key -* All public block settings set to true -* Versioning enabled -* S3 bucket tagged with provided key -* Bucket policy configured to limit access to the bucket -* Bucket owner preferred object ownership - -### 2.3 Macie - -**Description:** - -Macie is enabled for existing accounts within each member account and region during the initial setup. - -**Configuration:** - -* None - Controlled by the Macie Delegated Administrator Account - ----- - -## 3.0 Security Tooling Account - -### 3.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account StackSet - -**Configuration:** - -* Stack Name: *MacieOrgDeliveryKMSKey-... -* Stack Name: *MacieOrgConfigurationRole-... - -### 3.2 Macie KMS Key - -**Description:** - -Customer managed KMS key used for encrypting exported Macie findings - -**Configuration:** - -* Key alias -* Organization Management Account ID -* Logging Account ID -* KMS Key Tag - -### 3.3 Configuration IAM Role - -**Description:** - -Assumed by the custom CloudFormation Lambda function within the management account to configure Macie within each - region provided - -**Configuration:** - -* Role Name: [Prefix]-macie-org-configuration -* Permissions: - * Macie - Limited: List, Write - * IAM - Limited Read, Write on AWSServiceRoleForAmazonMacie - * Organizations - Limited: List - -### 3.4 Macie - -**Description:** - -Configure Macie to add existing member accounts and to auto enable new member accounts. - -**Configuration:** - -* See configuration details in the management account Macie configuration section - ----- - -## 4.0 All Existing and Future Organization Member Accounts - -### 4.1 Macie - -**Description:** - -Macie is enabled for existing accounts within each member account and region during the initial setup. -Macie will automatically enable new member accounts/regions when they are added to the AWS Organization. - -**Configuration:** - -* None - Controlled by the Macie Delegated Administrator Account - -### 4.2 Disable Macie Role - -**Description:** - -An IAM role is created within all the accounts to disable Macie in a delete event. - -**Configuration:** - -* Role Name: [Prefix]-disable-macie -* Permissions: - * Macie - Limited: List, Write - ----- - -# Implementation Instructions - -### [Customizations for AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets - -#### Solution Deployment Order - -1. Security Account (MacieOrgConfigurationRole) -2. Security Account (MacieOrgDeliveryKMSKey) -3. Logging Account (MacieOrgDeliveryS3Bucket) -4. Management Account (MacieOrgConfiguration) -5. All Accounts (MacieOrgMemberDisableRole) - -### Pre-requisites - -* Disable Macie in all accounts/regions - -### Instructions - -1. Create new or use an existing S3 bucket within the region owned by the Organization Management Account - * Example bucket name: lambda-zips-[Management Account ID]-us-east-1 - * [Example CloudFormation Template](../../../extras/lambda-s3-buckets.yaml) - * The bucket must allow the s3:GetObject action to the Organization using a bucket policy like the one below to - allow the accounts within the Organization to get the Lambda files. - ``` - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AllowGetObject", - "Effect": "Allow", - "Principal": "*", - "Action": "s3:GetObject", - "Resource": "arn:[AWS::Partition]:s3:::[BUCKET NAME]/*", - "Condition": { - "StringEquals": { - "aws:PrincipalOrgID": "[ORGANIZATION ID]" - } - } - } - ] - } - ``` -2. Package the Lambda code into a zip file and upload it to the S3 bucket - * Package and Upload the Lambda zip file to S3 (Packaging script: /extras/packaging-scripts/package-lambda.sh) -3. Copy the below folders/files to the new add-on folder excluding the lambda folder - - | Account | StackSet Name | Template | - | --------------- | ----------------- | ---------- | - | Security | MacieOrgConfigurationRole | templates/macie-org-configuration-role.yaml | - | Security | MacieOrgDeliveryKMSKey | templates/macie-org-kms-key.yaml | - | Log Archive | MacieOrgDeliveryS3Bucket | templates/macie-org-s3-bucket.yaml | - | Management | MacieOrgConfiguration | templates/macie-org-configuration.yaml | - | All | MacieOrgMemberDisableRole | templates/macie-org-member-disable-role.yaml | - -4. If the CloudFormation StackSets are removed, the solution will attempt to disable Macie in all accounts - > Environments containing large numbers of accounts may require additional cleanup scripts to disable Macie in - > the remaining accounts/regions. - ----- - -# References -* [Managing multiple Amazon Macie accounts with AWS Organizations](https://docs.aws.amazon.com/macie/latest/user/macie-organizations.html) diff --git a/solutions/macie/macie-org/aws-control-tower/README.md b/solutions/macie/macie-org/aws-control-tower/README.md deleted file mode 100644 index 3d2a4de3..00000000 --- a/solutions/macie/macie-org/aws-control-tower/README.md +++ /dev/null @@ -1,56 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) - 2. [parameters/macie-org-configuration.json](parameters/macie-org-configuration.json) - 3. [parameters/macie-org-configuration-role.json](parameters/macie-org-configuration-role.json) - 4. [parameters/macie-org-member-disable-role.json](parameters/macie-org-member-disable-role.json) - 5. [parameters/macie-org-kms-key.json](parameters/macie-org-kms-key.json) - 6. [parameters/macie-org-s3-bucket.json](parameters/macie-org-s3-bucket.json) - 7. [templates/macie-org-configuration.yaml](../templates/macie-org-configuration.yaml) - 8. [templates/macie-org-configuration-role.yaml](../templates/macie-org-configuration-role.yaml) - 9. [templates/macie-org-member-disable-role.yaml](../templates/macie-org-member-disable-role.yaml) - 10. [templates/macie-org-kms-key.yaml](../templates/macie-org-kms-key.yaml) - 11. [templates/macie-org-s3-bucket.yaml](../templates/macie-org-s3-bucket.yaml) -3. Update the parameter files with any specific values for your environment -4. Update the manifest.yaml file with your account names -5. Deploy the Customizations for AWS Control Tower configuration -6. How to verify after the pipeline completes? - 1. Log into the Management account and navigate to the Macie page - 1. Validate that the delegated admin account is set for each region - 2. Log into the Audit account and navigate to the Macie page - 1. Verify the correct Macie configurations have been applied to each region - 2. Verify all existing accounts have been enabled - 3. Verify the findings export is configured for the S3 bucket - 4. Generate sample findings to verify S3 delivery - 3. Log into the Log archive account and navigate to the S3 page - 1. Verify the sample findings have been delivered - -# Delete Instructions - -1. Delete the Stack Instance from the CustomControlTower-MacieOrgConfiguration CloudFormation StackSet - 1. Verify that Macie is disabled in all accounts -2. Within the Customizations for AWS Control Tower configuration - 1. Remove the Macie configurations from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the Macie solution -3. Deploy the Customizations for AWS Control Tower configuration -4. After the pipeline completes, log into the Management account and navigate to the CloudFormation page - 1. Delete the CustomControlTower-MacieOrgDeliveryS3Bucket CloudFormation StackSet - 2. Log into the Log Archive account and delete the Macie S3 bucket - 3. Delete the Stack Instance from the CustomControlTower-MacieOrgDeliveryS3Bucket CloudFormation StackSet - 4. After the Stack Instance deletes, delete the CustomControlTower-MacieOrgDeliveryS3Bucket CloudFormation StackSet - 5. Delete the Stack Instance from the CustomControlTower-MacieOrgDeliveryKMSKey CloudFormation StackSet - 6. After the Stack Instance deletes, delete the CustomControlTower-MacieOrgDeliveryKMSKey CloudFormation StackSet - 7. Delete the Stack Instances from the CustomControlTower-MacieOrgMemberDisableRole CloudFormation StackSet - 8. After the Stack Instance deletes, delete the CustomControlTower-MacieOrgMemberDisableRole CloudFormation StackSet - 9. Delete the Lambda CloudWatch Log Group within the Management account - - - - \ No newline at end of file diff --git a/solutions/macie/macie-org/aws-control-tower/manifest.yaml b/solutions/macie/macie-org/aws-control-tower/manifest.yaml deleted file mode 100644 index 0abc4bfe..00000000 --- a/solutions/macie/macie-org/aws-control-tower/manifest.yaml +++ /dev/null @@ -1,52 +0,0 @@ ---- -#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets -region: us-east-1 -version: 2020-01-01 - -# Control Tower Custom Service Control Policies -organization_policies: [] - -# Control Tower Custom CloudFormation Resources -cloudformation_resources: - - name: MacieOrgConfigurationRole - template_file: templates/macie-org-configuration-role.yaml - parameter_file: parameters/macie-org-configuration-role.json - deploy_method: stack_set - deploy_to_account: - - Audit - - - name: MacieOrgDeliveryKMSKey - template_file: templates/macie-org-kms-key.yaml - parameter_file: parameters/macie-org-kms-key.json - deploy_method: stack_set - ssm_parameters: - - name: /org/macie/kms_key_arn - value: $[output_oMacieDeliveryKeyArn] - deploy_to_account: - - Audit - - - name: MacieOrgDeliveryS3Bucket - template_file: templates/macie-org-s3-bucket.yaml - parameter_file: parameters/macie-org-s3-bucket.json - deploy_method: stack_set - ssm_parameters: - - name: /org/macie/s3_bucket - value: $[output_oMacieDeliveryS3Bucket] - deploy_to_account: - - Log archive - - - name: MacieOrgConfiguration - template_file: templates/macie-org-configuration.yaml - parameter_file: parameters/macie-org-configuration.json - deploy_method: stack_set - deploy_to_account: - - Control Tower Management - - - name: MacieOrgMemberDisableRole - template_file: templates/macie-org-member-disable-role.yaml - parameter_file: parameters/macie-org-member-disable-role.json - deploy_method: stack_set - deploy_to_ou: - - Core - - management - - workloads diff --git a/solutions/macie/macie-org/code/src/requirements.txt b/solutions/macie/macie-org/code/src/requirements.txt deleted file mode 100644 index b9435de8..00000000 --- a/solutions/macie/macie-org/code/src/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -#install latest -crhelper \ No newline at end of file diff --git a/solutions/macie/macie-org/documentation/diagram/Macie-Architecture.png b/solutions/macie/macie-org/documentation/diagram/Macie-Architecture.png deleted file mode 100644 index 8bc6e3ca..00000000 Binary files a/solutions/macie/macie-org/documentation/diagram/Macie-Architecture.png and /dev/null differ diff --git a/solutions/securityhub/securityhub-enabler-acct/README.md b/solutions/securityhub/securityhub-enabler-acct/README.md deleted file mode 100644 index dc4848d5..00000000 --- a/solutions/securityhub/securityhub-enabler-acct/README.md +++ /dev/null @@ -1,259 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - -# SecurityHub Enabler Account - -The SecurityHub Enabler solution will enable SecurityHub within each AWS Organizations account configured with -an admin account (e.g. Security Tooling) and security standards enabled. Centralizing SecurityHub within the Security -Tooling account provides a cross-account view of security standards compliance and findings from AWS service -integrations. - -The solution implements a SecurityHub Enabler Lambda function in the Organization Management account, - which runs periodically to verify each account/region has been invited into the central SecurityHub account and that - SecurityHub is enabled. Optionally, security standards and integrations can be enabled as part of the solution - deployment. - -This solution differs from that presented [here](https://github.com/awslabs/aws-securityhub-multiaccount-scripts) -as it takes a serverless approach (vs. launching an EC2 instance) and auto enables new accounts added to the -AWS Organization. - ----- - -# Table of Contents -* [Deployed Resource Details](#deployed-resource-details) -* [Implementation Instructions](#implementation-instructions) -* [References](#references) - ----- - -# Deployed Resource Details - -![Architecture](./documentation/diagram/Centralized-SecurityHub-Architecture.png "Architecture") - -## 1.0 Organization Management Account - -### 1.1 AWS CloudFormation - -**Description:** - -All resources are deployed via a CloudFormation StackSet and a Stack Instance within each member account - -**Configuration:** - -* StackSet Names: - * SecurityHubEnablerAcctService - * SecurityHubEnablerAcctRole - -### 1.2 EventBridge Scheduled Rule - -**Description:** - -The scheduled rule triggers the Lambda Function between 1 and 3600 minutes to check organization compliance - -**Configuration:** - -* pComplianceFrequency: Frequency (in minutes between 1 and 3600, default is 60) to check for new accounts added -to the AWS Organization - -### 1.3 SNS Topic - -**Description:** - -SNS Topic triggers the Lambda Function during initial setup to handle multiple accounts. The Lambda Function will -publish all the AWS Organization accounts to the SNS Topic if it isn't triggered by SNS. - -**Configuration:** - -* SNS Topic Name: SecurityHubEnablerAcctTopic (Only configurable within the CloudFormation Template) - - -### 1.4 AWS Lambda Function - -**Description:** - -The Lambda Function enables Security Hub within all the active AWS Organizations accounts - -**Configuration:** - -* Lambda Function Name = [Prefix]-security-hub-enabler-acct -* Environment Variables (Configurable and set via CloudFormation) - * ASSUME_ROLE - AWS IAM role to assume within each account to enable Security Hub - * ENABLE_CIS_STANDARD - Default = false, enable the [CIS AWS Foundations Standard](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards-cis.html) - * CIS_STANDARD_VERSION - Default = 1.2.0 - * ENABLE_PCI_STANDARD - Default = false, enable the [Payment Card Industry Data Security Standard (PCI DSS)](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards-pcidss.html) - * PCI_STANDARD_VERSION - Default = 3.2.1 - * ENABLE_SBP_STANDARD - Default = false, enable the [AWS Foundational Security Best Practices Standard](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards-fsbp.html) - * SBP_STANDARD_VERSION - Default = 1.0.0 - * MGMT_ACCOUNT_ID - The Security Hub management account ID (e.g. Security account) - * SNS_TOPIC_ARN - SNS Topic that triggers the Lambda Function during initial setup to handle multiple accounts. The Lambda - Function publishes to the SNS Topic if it isn't triggered by SNS. - * LOG_LEVEL - Default = INFO - * REGIONS_TO_ENABLE - Comma delimited list of regions to enable. Leave blank for all enabled regions. - * CONTROL_TOWER_REGIONS_ONLY - Default = false, enables only the AWS Control Tower supported regions. - * ENABLE_PROWLER_INTEGRATION - Default = false, enables the - [Prowler](https://github.com/toniblyx/prowler#security-hub-integration) partner integration. - -**Input Validation** - -Validation of environment variables is done to make sure values exist and are the correct type - -### 1.5 Lambda CloudWatch Log Group - -**Description:** - -Contains the Lambda function execution logs - -**Configuration:** - -* Retention = Default 2 weeks (14 days) -* Log group name = /aws/lambda/[Lambda Function] - -### 1.6 Lambda Execution IAM Role - -**Description:** - -Used by the custom CloudFormation Lambda function to enable Security Hub in all accounts and regions - -**Configuration:** - -* Role Name: [Prefix]-security-hub-enabler-acct-lambda -* Policy Name: [Prefix]-security-hub-enabler-acct-lambda -* Permissions: - * CloudWatch Logs - Limited: Write on LogGroupName like /aws/lambda/[Lambda Function] - * Organizations - Limited: List, Read - * SNS - Limited: Write TopicName like SecurityHubEnablerTopic - * STS - Limited: Write RoleName like [Prefix]-security-hub-enabler-acct - -### 1.7 Security Hub - -**Description:** - -Security Hub is enabled in all the active Organization accounts and regions via the Lambda Function. Each member -account Security Hub is configured with the provided Security Hub master account. - -**Configuration:** - -* Security Hub Management Account -* Enable CIS Standard -* Enable PCI Standard -* Enable Security Best Practices Standard -* Enable Prowler integration - - ----- - -## 2.0 Security Tooling Account - -### 2.1 AWS CloudFormation - -**Description:** - -All resources are deployed via CloudFormation Stack created by the Management account CloudFormation StackSet - -**Configuration:** - -* Stack Name: SecurityHubEnablerAcctService-... - -### 2.2 Security Hub Enabler Role - -**Description:** - -IAM role assumed by the Management account Lambda function to enable Security Hub within the account and all -the active regions - -**Configuration:** - -* Role Name: [Prefix]-security-hub-enabler-acct -* Policy Name: [Prefix]-security-hub-enabler-acct -* Permissions: - * IAM - Limited: Write iam:AWSServiceName like securityhub.amazonaws.com - * SecurityHub - Full access - -### 2.3 Security Hub Master - -**Description:** - -Security Hub Master Account provides visibility of all Security Hub member results - -**Configuration:** - -* Provided by the Master account Lambda function - - ----- - -## 3.0 All Existing and Future Organization Member Accounts - -### 3.1 Security Hub Enabler Role - -**Description:** - -IAM role assumed by the Management account Lambda function to enable Security Hub within the account and all -the active regions - -**Configuration:** - -* Role Name: [Prefix]-security-hub-enabler-acct -* Policy Name: [Prefix]-security-hub-enabler-acct -* Permissions: - * IAM - Limited: Write iam:AWSServiceName like securityhub.amazonaws.com - * SecurityHub - Full access - -### 3.2 Security Hub Master - -**Description:** - -Security Hub enabled within the account and all active regions - -**Configuration:** - -* Provided by the Management account Lambda function - ----- - -# Implementation Instructions - -### [AWS Control Tower](./aws-control-tower) -### CloudFormation StackSets - -#### Pre-requisites -* Security Hub disabled in all accounts - -#### Instructions - -1. Create a new or use an existing S3 bucket within the region owned by the Organization Management Account - * Example bucket name: lambda-zips-[Management Account ID]-[AWS Region] - * [Example CloudFormation Template](../../../extras/lambda-s3-buckets.yaml) - * The bucket must allow the s3:GetObject action to the Organization using a bucket policy like the one - below to allow the accounts within the Organization to get the Lambda files. - ``` - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AllowGetObject", - "Effect": "Allow", - "Principal": "*", - "Action": "s3:GetObject", - "Resource": "arn:[AWS::Partition]:s3:::[BUCKET NAME]/*", - "Condition": { - "StringEquals": { - "aws:PrincipalOrgID": "[ORGANIZATION ID]" - } - } - } - ] - } - ``` -2. Package the Lambda code into a zip file and upload it to the S3 bucket - * Package and Upload the Lambda zip file to S3 - [Packaging script](../../../extras/packaging-scripts/package-lambda.sh) -3. Create CloudFormation StackSets using the following templates - - | Account | StackSet Name | Template | - | --------------- | ----------------- | ---------- | - | Management | SecurityHubEnablerAcctService | templates/securityhub-enabler-acct.yaml | - | All Member Accounts | SecurityHubEnablerAcctRole | templates/securityhub-enabler-acct-role.yaml | - ----- - -# References -* [Setting up AWS Security Hub](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-settingup.html) diff --git a/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/README.md b/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/README.md deleted file mode 100644 index 70cf6642..00000000 --- a/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/README.md +++ /dev/null @@ -1,38 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: CC-BY-SA-4.0 - ----- - -# Implementation Instructions - -1. Make sure the required [prerequisites](../../../../extras/aws-control-tower/prerequisites/README.md) are completed -2. Copy the files to the Customizations for AWS Control Tower configuration - 1. customizations-for-control-tower-configuration - 1. [manifest.yaml](manifest.yaml) - 2. [parameters/securityhub-enabler-acct-role.json](parameters/securityhub-enabler-acct-role.json) - 3. [parameters/securityhub-enabler-acct-role.json](parameters/securityhub-enabler-acct.json) - 4. [templates/securityhub-enabler-acct-role.yaml](../templates/securityhub-enabler-acct-role.yaml) - 5. [templates/securityhub-enabler-acct.yaml](../templates/securityhub-enabler-acct.yaml) -3. Update the parameter files with any specific values for your environment -4. Update the manifest.yaml file with your account names -5. Deploy the Customizations for AWS Control Tower configuration -6. How to verify after the pipeline completes? - 1. Log into the Audit account and navigate to the Security Hub page - 2. Verify the correct configurations have been applied to each region - 1. Security standards enabled - 2. Settings -> Accounts enabled - 3. Integrations enabled - - -# Delete Instructions - -1. Within the Customizations for AWS Control Tower configuration - 1. Remove the Security Hub configurations from the manifest.yaml file - 2. (Optional) Delete the parameter and template files for the Security Hub solution -2. Deploy the Customizations for AWS Control Tower configuration -3. After the pipeline completes, log into the Primary account and navigate to the CloudFormation page - 1. Delete the Stack Instance from the CustomControlTower-SecurityHubEnablerService CloudFormation StackSet - 2. After the Stack Instance deletes, delete the CustomControlTower-SecurityHubEnablerService CloudFormation StackSet - 3. Log into the Log Archive account and delete the 2 org-trail-logs S3 buckets - 4. Delete the Stack Instance from the CustomControlTower-SecurityHubEnablerRole CloudFormation StackSet - 5. After the Stack Instance deletes, delete the CustomControlTower-SecurityHubEnablerRole CloudFormation StackSet - \ No newline at end of file diff --git a/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/manifest.yaml b/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/manifest.yaml deleted file mode 100644 index 4e40fec8..00000000 --- a/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/manifest.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets -region: us-east-1 -version: 2020-01-01 - -# Control Tower Custom Service Control Policies -organization_policies: [] - -# Control Tower Custom CloudFormation Resources -cloudformation_resources: - - name: SecurityHubEnablerRole - template_file: templates/securityhub-enabler-acct-role.yaml - parameter_file: parameters/securityhub-enabler-acct-role.json - deploy_method: stack_set - deploy_to_ou: - - Core - - Workloads - - - name: SecurityHubEnablerService - template_file: templates/securityhub-enabler-acct.yaml - parameter_file: parameters/securityhub-enabler-acct.json - deploy_method: stack_set - deploy_to_account: - - Control Tower Primary \ No newline at end of file diff --git a/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/parameters/securityhub-enabler-acct-role.json b/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/parameters/securityhub-enabler-acct-role.json deleted file mode 100644 index 40b95f0c..00000000 --- a/solutions/securityhub/securityhub-enabler-acct/aws-control-tower/parameters/securityhub-enabler-acct-role.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "ParameterKey": "pSecurityHubEnablerRoleName", - "ParameterValue": "control-tower-security-hub-enabler" - }, - { - "ParameterKey": "pSecurityHubEnablerLambdaRoleName", - "ParameterValue": "control-tower-security-hub-enabler-lambda" - }, - { - "ParameterKey": "pOrgManagementAccountId", - "ParameterValue": "$[alfred_ssm_/org/Control-Tower-Primary/account_id]" - }, - { - "ParameterKey": "pTagKey1", - "ParameterValue": "control-tower" - }, - { - "ParameterKey": "pTagValue1", - "ParameterValue": "managed-by-control-tower" - } -] \ No newline at end of file diff --git a/solutions/securityhub/securityhub-enabler-acct/documentation/diagram/Centralized-SecurityHub-Architecture.png b/solutions/securityhub/securityhub-enabler-acct/documentation/diagram/Centralized-SecurityHub-Architecture.png deleted file mode 100644 index f82aa3de..00000000 Binary files a/solutions/securityhub/securityhub-enabler-acct/documentation/diagram/Centralized-SecurityHub-Architecture.png and /dev/null differ