Showing preview only (624K chars total). Download the full file or copy to clipboard to get everything.
Repository: aws-samples/aws-account-vending-machine
Branch: master
Commit: 3d3eab302551
Files: 82
Total size: 592.0 KB
Directory structure:
gitextract_umtfd2mz/
├── .github/
│ └── PULL_REQUEST_TEMPLATE.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── govcloud/
│ ├── LICENSE
│ ├── README.md
│ ├── commercial-side-setup/
│ │ ├── CommercialAccountSetup.yaml
│ │ └── commercial-account-avm-product.yaml
│ └── govcloud-side-setup/
│ ├── Accountbaseline.yml
│ ├── GovCloudAccountSetup.yaml
│ └── govcloud-account-avm-product.yaml
└── resources/
├── AccountCreationLambdaCode/
│ ├── AccountCreationLambda.py
│ ├── cfnresponse/
│ │ └── __init__.py
│ ├── cfnresponse-1.1.2.dist-info/
│ │ ├── INSTALLER
│ │ ├── LICENSE
│ │ ├── METADATA
│ │ ├── RECORD
│ │ ├── REQUESTED
│ │ ├── WHEEL
│ │ └── top_level.txt
│ ├── crhelper/
│ │ ├── __init__.py
│ │ ├── __init__.pyi
│ │ ├── log_helper.py
│ │ ├── log_helper.pyi
│ │ ├── py.typed
│ │ ├── resource_helper.py
│ │ ├── resource_helper.pyi
│ │ ├── utils.py
│ │ └── utils.pyi
│ ├── crhelper-2.0.11-py2.7.egg-info/
│ │ ├── PKG-INFO
│ │ ├── SOURCES.txt
│ │ ├── dependency_links.txt
│ │ ├── installed-files.txt
│ │ └── top_level.txt
│ ├── urllib3/
│ │ ├── __init__.py
│ │ ├── _collections.py
│ │ ├── _version.py
│ │ ├── connection.py
│ │ ├── connectionpool.py
│ │ ├── contrib/
│ │ │ ├── __init__.py
│ │ │ ├── _appengine_environ.py
│ │ │ ├── _securetransport/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── bindings.py
│ │ │ │ └── low_level.py
│ │ │ ├── appengine.py
│ │ │ ├── ntlmpool.py
│ │ │ ├── pyopenssl.py
│ │ │ ├── securetransport.py
│ │ │ └── socks.py
│ │ ├── exceptions.py
│ │ ├── fields.py
│ │ ├── filepost.py
│ │ ├── packages/
│ │ │ ├── __init__.py
│ │ │ ├── backports/
│ │ │ │ ├── __init__.py
│ │ │ │ └── makefile.py
│ │ │ └── six.py
│ │ ├── poolmanager.py
│ │ ├── request.py
│ │ ├── response.py
│ │ └── util/
│ │ ├── __init__.py
│ │ ├── connection.py
│ │ ├── proxy.py
│ │ ├── queue.py
│ │ ├── request.py
│ │ ├── response.py
│ │ ├── retry.py
│ │ ├── ssl_.py
│ │ ├── ssl_match_hostname.py
│ │ ├── ssltransport.py
│ │ ├── timeout.py
│ │ ├── url.py
│ │ └── wait.py
│ └── urllib3-1.26.15.dist-info/
│ ├── INSTALLER
│ ├── LICENSE.txt
│ ├── METADATA
│ ├── RECORD
│ ├── WHEEL
│ └── top_level.txt
├── AccountCreationLambdaSetup-cfn.yaml
├── Accountbaseline.yml
└── accountbuilder.yml
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
*Issue #, if available:*
*Description of changes:*
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
================================================
FILE: CODE_OF_CONDUCT.md
================================================
## 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.
================================================
FILE: CONTRIBUTING.md
================================================
# 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.
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](https://github.com/aws-samples/aws-account-vending-machine/issues), or [recently closed](https://github.com/aws-samples/aws-account-vending-machine/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already
reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
* A reproducible test case or series of steps
* 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.
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.
To send us a pull request, please:
1. Fork the repository.
2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
3. Ensure local tests pass.
4. Commit to your fork using clear commit messages.
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/).
## Finding contributions to work on
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/aws-account-vending-machine/labels/help%20wanted) 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.
## 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.
## Licensing
See the [LICENSE](https://github.com/aws-samples/aws-account-vending-machine/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
================================================
FILE: LICENSE
================================================
Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
## AWS Account Vending Machine
This repository contains various versions of the account vending machine used to provision AWS accounts with custom configurations.
### Note
For **AWS GovCloud(US) account vending**, click [here](/govcloud/README.md).
## Overview
As an organization expands its use of AWS services, there is often a conversation about the need to create multiple AWS accounts to ensure separation of business processes or for security, compliance, and billing. Many of the customers we work with use separate AWS accounts for each business unit so they can meet the different needs of their organization. Although creating multiple accounts has simplified operational issues and provided benefits like security and resource isolation, a smaller blast radius, and simplified billing, it takes a lot of time to create, bootstrap and configure baseline settings. Customers want to manage account creation and bootstrapping in a scalable and efficient manner so that new accounts are created with a defined baseline and some governance guardrails are in place. Most importantly, customers want automation, to save time and resources.
The account builder is an AWS Service Catalog product that uses AWS Lambda and AWS Organizations APIs to create AWS accounts. On each invocation, the AWS Lambda function used in this sample solution does the following:
1. Creates a new AWS account.
2. If provided, creates an organization unit under the root account in AWS Organizations.
3. Moves the newly created account from the organization root to the newly created organizational unit.
4. Assumes the role OrganizationAccountAccessRole in the new account for the following:
- Creating an IAM user with the provided password.
- Adding the IAM user to a new group with least privilege permissions to access AWS Service Catalog.
- Deploying baseline templates for creating AWS Service Catalog portfolio and products.
- Deleting the default VPCs in all AWS Regions.
- Creating AWS Service Catalog products and portfolio inside the newly created account.
- Adding the provided IAM user and IAM role as principals to the created AWS Service Catalog portfolio.
This approach of bootstrapping accounts will reduce operational overhead and standardize account configurations across the provisioned AWS accounts. The following architecture outlines the process flow involved with account building :

## Step by Step walkthrough
### A) Setup the account vending machine (AVM)
As a part of creating a sample account vending machine from this repository, you will first launch a CloudFormation template to create the account vending machine set up in your account.
1. Login to your AWS account which is a **master account** in AWS Organizations. Select one the following 4 regions from the top right corner on the AWS Management Console:
- Ohio (us-east-2)
- Oregon (us-west-2)
- Ireland (eu-west-1)
- Singapore (ap-southeast-1)
_Note: You can customize this implementation to work with linked accounts as well, but for the purposes of this exercise, we will use the master account._
2. The scripts and templates needed for this exercise should be available in an S3 bucket one of the above choosen AWS regions.
- Create a new S3 bucket (or you can reuse any existing bucket as well)
- Upload all the scripts and templates available in the resources folder of this repo
- Make sure to update all these files:
- resources/AccountCreationLambdaSetup-cfn.yaml
- resources/accountbuilder.yml
- resources/Accountbaseline.yml
- resources/AccountCreationLambda.zip
3. Navigate to the CloudFormation console and launch a new template pointing it to the resources/AccountCreationLambdaSetup-cfn.yaml template and click `Next`
4. On the `Specify stack details` page, enter the following parameters:
- `AccountAdministrator` - Enter the ARN of the IAM entity (role or user or group) that will be performing account creation from AWS Service Catalog. You can go to the IAM console to find the ARN of the role/user/group. (eg. arn:aws:iam::010010011111:role/Administrator)
- `SourceBucket` - Keep the default value for the S3 bucket. _Note_: To use your own S3 bucket, you can upload all the files in the /resources folder in Github to your own S3 bucket.
- `SourceTemplate` - Keep to resources/Accountbaseline.yml. _Note_: To launch your own CloudFormation template in the new account, make sure the template parameters have a default value, and replace the `Accountbaseline.yml` template we've provided for this demo. You will also have to edit the lambda function to reflect the parameters in your custom template.
5. On the `Configure stack options` page, click `Next`.
6. On the `Review` page, check the checkbox for `I acknowledge that AWS CloudFormation might create IAM resources.`, and click `Create Stack`.
7. Once status of the stack changes to `CREATE COMPLETE`, click on the stack and open the `Outputs` tab to see the output values.
8. In the the `Outputs` section of CloudFormation, copy the key and value column contents for `AccountLambda`. You will be using this value during the execution of the account vending machine.
At this point, you have successfully set up the account vending machine in your account.
### B) Launch the AVM to create a new AWS account
In this section, you will launch the account vending machine product created in AWS Service Catalog to create a new AWS account pre-configured with custom settings defined in this lab.
1. Login to your AWS account using the IAM role/user/group that you provided in the `AccountAdministrator` in the set up phase.
2. On the Services menu, search and then choose `Service Catalog`. You will see an AWS Service Catalog product named `Account Vending Machine`.

3. In the `Products list` page, click `Account Vending Machine`, and then click `LAUNCH PRODUCT`.
6. On the `Product Version` page, configure:
a. `Name`: my-new-account-001
b. Select the available version.
7. Click `NEXT`
8. On the `Parameters` page, configure:
- `MasterLambdaArn`: **choose the value of 'AccountLambda' from the CloudFormation outputs noted in Lab Setup**
- `AccountEmail`: Enter a unique email address to be associated with the newly created account
- `OrganizationalUnitName`: Name of the organizational unit (OU) to which the account should be moved to. Keep the default value for placing the account at the root level.
- `AccountName`: Enter an account name
- `StackRegion`: Choose the region where the preconfigured settings should be applied
- `SourceBucket`: Enter the name of the source bucket where your baseline CloudFormation template is available.
- `BaselineTemplate`: Keep the default value to Accountbaseline.yml OR Enter the name of the account baseline CloudFormation template you wish to apply as a baseline.
9. Click `NEXT`.
10. On the `TagOptions` page, click `NEXT`.
11. On the Notifications page, click `NEXT`.
12. On the Review page, review the configuration information, and click `LAUNCH`. This will create a CloudFormation stack. The initial status of the product is shown as `Under change`. Wait for few minutes, then refresh the screen till the status changes to `AVAILABLE`. _Note: You can go to the CloudFormation page to monitor the stack progress, or go to CloudWatch to view the step by step execution of the account vending lambda function._
13. In the the `Outputs` section of AWS Service Catalog, you will see the account details of the newly created account as follows.

### C) Login to the newly created AWS account for end-user experience
In this section, we will log in to the newly vended account using the user created as a part of the set up and explore the account configuration.
1. Login to your AWS account using the `LoginURL` provided in the Outputs of the previous section. **Make sure you are in the same region as the `StackRegion` in the previous section.**
2. On the credentials page, enter the following information:
- Username: `service-catalog-user`
- Password: `service-catalog-2019`
_Note: You will be prompted to change your password at first log in._
3. On the Services menu, search and then choose `Service Catalog`. On the products list page, you will be to see the pre-configured AWS Service Catalog products allowed for the current user to provision.

4. As a part of the account setup, all the default VPCs from every region have been deleted for this account. You can validate this by going to the Services menu, search and then choose 'VPC'.

5. As a security best practice of least privilege, we have restricted the current user to launch AWS Service Catalog products only. You can validate this by trying to create a new VPC from the [Amazon VPC console](https://console.aws.amazon.com/vpc/home).
- Click on the `Launch VPC Wizard` button, and then click on `Select` for `VPC with a Single Public Subnet`.
- In the `VPC Name` field, enter `demo`, and click `Create VPC`.
- You will not be able to move forward from this page, due to lack of permissions.

6. Now, we will try to perform the same function using AWS Service Catalog. But first, the user will need a key pair.
- Go to the [Amazon EC2 console](https://console.aws.amazon.com/ec2/v2/home)
- In the left navigation menu, select `Key Pairs` under `Network & Security`
- Click on the `Create a key pair` button, add name as `demo`, and click `Create`.
- Now, on the Services menu, search and then choose `Service Catalog`. On the products list page, select `Amazon VPC`, and click on `Launch Product`.
- On the `Product Version` page, configure:
a. `Name`: `my-custom-vpc-001`
b. Select the available version.
7. Click `NEXT`
8. On the `Parameters` page, configure:
- `RegionAZ1Name`: Choose the availability zone for a region. eg. us-west-2a
- `RegionAZ2Name`: Choose another availability zone for the **same** region as above. eg. us-west-2b
- `VPCCIDR`: Keep the default value OR change it to a CIDR you want.
- `SubnetAPublicCIDR`: Keep the default value OR change it to a CIDR you want
- `SubnetAPublicCIDR`: Keep the default value OR change it to a CIDR you want
- `SubnetAPrivateCIDR`: Keep the default value OR change it to a CIDR you want
- `SubnetBPrivateCIDR`: Keep the default value OR change it to a CIDR you want
- `CreateBastionInstance`: Keep the default value OR change it to `true` if you want a bastion instance created.
- `BastionInstanceType`: Keep the default value OR change it to an instance type you want
- `EC2KeyPair`: Choose the key pair you created in Step 6
- `BastionSSHCIDR`: Enter any value you want eg. 0.0.0.0/0
- `LatestAmiId`: Keep the default value OR change it to an AMI ID you want
9. Click `NEXT`.
10. On the `TagOptions` page, click `NEXT`.
11. On the Notifications page, click `NEXT`.
12. On the Review page, review the configuration information, and click `LAUNCH`. This will create a CloudFormation stack. The initial status of the product is shown as `Under change`. Wait for about 5 minutes, then refresh the screen till the status changes to `AVAILABLE`.
13. Validate the Outputs section on AWS Service Catalog screen to see the details of the VPC created.

14. Finally, on the [Amazon VPC console](https://console.aws.amazon.com/vpc/home), you can verify that a VPC is now created.

In conclusion, you were able to log in as an end user in the newly vended AWS account, and create AWS resources in a compliant manner using AWS Service Catalog.
## Conclusion
This repository provides a method to enable on-demand creation of AWS accounts that can be customized to the requirements of an organization. Administrators and/or teams who are required to provision new accounts can use this approach to standardize the networking configuration and the resources that be provisioned when the new account is ready for use.
## Credits
This repository was inspired by the AWS blog post on [automation of AWS account creation](https://aws.amazon.com/blogs/mt/automate-account-creation-and-resource-provisioning-using-aws-service-catalog-aws-organizations-and-aws-lambda/).
## Clean Up
Congratulations! :tada: You have completed all the steps for setting up your own custom account vending machine using AWS Service Catalog.
**To make sure you are not charged for any unwanted services, you can clean up by deleting the stack created in the _Deployment steps_ stage and its resources.**
To delete any AWS Service Catalog products,
1. Go to the AWS Service Catalog screen and make sure you are in the same region as you selected during the launch phase
2. Go to the `Provisioned Products` screen, and terminate any products that you may have created as a part of the lab
To delete the stack and its resources
1. From the AWS CloudFormation console in the region you used in the _Lab Setup_, select the stack that you created.
2. Click `Delete Stack`.
3. In the confirmation message that appears, click `Yes`, `Delete`.
At this stage, the status for your changes to `DELETE_IN_PROGRESS`. In the same way you monitored the
creation of the stack, you can monitor its deletion by using the `Events` tab. When AWS CloudFormation completes the deletion of the stack, it removes the stack from the list.
[(Back to top)](#aws-account-vending-machine)
## Contributing
Your contributions are always welcome! Please have a look at the [contribution guidelines](CONTRIBUTING.md) first. :tada:
[(Back to top)](#aws-account-vending-machine)
## License Summary
This sample code is made available under the MIT-0 license. See the LICENSE file.
[(Back to top)](#aws-account-vending-machine)
================================================
FILE: govcloud/LICENSE
================================================
Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: govcloud/README.md
================================================
## AWS Account Vending Machine for GovCloud(US) region
AWS Organizations works differently in the AWS GovCloud(US) region, as compared to the commercial regions. For a deep dive, please refer the blog on [AWS Organizations in the AWS GovCloud (US) Regions for central governance and management of AWS accounts](https://aws.amazon.com/blogs/security/aws-organizations-available-govcloud-regions-central-governance-management-accounts/).
This guide contains a detailed description of the account vending machine used to provision AWS accounts with custom configurations in the AWS GovCloud(US) region.
## Overview
The account vending automation process for AWS GovCloud (US) will work in 2 separate steps.
1. **Creation of the AWS GovCloud Account from the commercial region's master AWS account**
*Pre-Requisities*
* Existing AWS Organization in the commercial AWS account that forms the pair for the AWS GovCloud(US) region. Refer [documentation](https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/govcloud-organizations.html)
* The account you deploy this in must meet the requirements to vend GovCloud accounts and leverage the API. Refer [documentation](https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/govcloud-organizations.html)
* Each region you want to use this solution in should have its own S3 Bucket with the CloudFormation template and lambda function zip files
We will use the commercial organization’s master account to call the CreateGovCloudAccount API, which creates a new AWS account in the commercial organization, and another AWS account in the AWS GovCloud(US) region. A role (`OrganizationAccountAccess`) is automatically created in this new commercial account that creates a trust relationship your commercial organization master account to assume it, and a role (`OrganizationAccountAccess`) is automatically created in the AWS GovCloud(US) account which allows the AWS GovCloud(US) organization master account to assume it.
In order to call the CreateGovCloudAccount API consistently, we will create an AWS Service Catalog product in the commercial organization master account, which would standardize the creation of the new account. The outputs of the AWS Service Catalog product would provide the account ID of the newly created accounts in the commercial and the GovCloud(US) regions.
For set up of the commercial region's master AWS account, we will run an AWS CloudFormation template in that account. This CloudFormation template will set up an AWS Service Catalog product that will help vend AWS GovCloud(US) accounts.

2. **Bootstrapping of the newly created AWS GovCloud account**
The newly created AWS GovCloud(US) account from the previous step will contain a role (`OrganizationAccountAccess`) is automatically created in the AWS GovCloud(US) account which allows the AWS GovCloud(US) organization master account to assume it.
We will need to perform the following steps in this newly created AWS GovCloud(US) account to get it ready for the end user:
* Invite the newly created AWS GovCloud(US) account to the AWS Organization in that region
* Accept the invite from the new account
* Bootstrap the account with baseline infrastructure
To perform all these steps, as a one time activity in the AWS GovCloud master account, we will create an AWS Service Catalog product to bootstrap the newly created GovCloud account. This product will take the newly created AWS GovCloud(US) account ID as input, and launch an automation to create an AWS Organizations invite from the master, accept the invite from the new account, and finally bootstrap the newly created account with baseline infrastructure defined by the company.
For set up of the AWS GovCloud(US) region's master AWS account, we will run an AWS CloudFormation template in that account. This CloudFormation template will set up an AWS Service Catalog product that will help bootstrap newly created AWS GovCloud(US) accounts.
We can launch the AWS Service Catalog bootstrap product once we have the account ID of the newly created GovCloud account from the previous section.

## Step by Step walkthrough
### A) In the commercial region, setup the account vending machine (AVM)
As a part of creating a sample account vending machine from this repository, you will first launch a CloudFormation template to create the account vending machine set up in your account.
1. Login to your AWS account which is a **master account** in AWS Organizations in the **commercial region**.
_Note: You can customize this implementation to work with linked accounts as well, but for the purposes of this exercise, we will use the master account._
2. Set up an S3 bucket to hold all the artifacts for this implementation
* Click on `Services`, then [Amazon S3](https://s3.console.aws.amazon.com/s3/home)
* On the Amazon S3 console, click `Create S3 bucket`
* Enter a bucket name of your choice and choose the commercial region you plan to use for this sample
* Keep the defaults, and click `Create bucket`
* Click on `Services`, then `AWS Organizations`
* On the [AWS Organizations](https://console.aws.amazon.com/organizations) page, click on the `Settings` tab
* Note the `Organization ID` on the settings page
* Go back to the `Amazon S3` console page, click on the bucket you just created, and click on the `Permissions` tab
* Click `Bucket Policy` and enter the following bucket policy: (Make sure you change the `Resource` and the `aws:PrincipalOrgId` to your Organization ID copied from AWS Organizations)
```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<REPLACE WITH YOUR AMAZON S3 BUCKET NAME>/*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "<REPLACE WITH YOUR AWS ORGANIZATION ID>"
}
}
},
{
"Sid": "AllowSSLRequestsOnly",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<REPLACE WITH YOUR AMAZON S3 BUCKET NAME>",
"arn:aws:s3:::<REPLACE WITH YOUR AMAZON S3 BUCKET NAME>/*"
],
"Condition": {
"Bool": {
aws:SecureTransport: false
}
}
}
]
}
```
3. Upload all the files from the `commercial-side-setup` folder of this repository in the Amazon S3 bucket from the previous step
4. Copy the URL of the file `CommercialAccountSetup.yaml` from your Amazon S3 bucket
5. Click on `Services`, then select `CloudFormation`
6. Click the `Create Stack` button, add the Amazon S3 URL copied in step 4, and click `Next`.
7. On the `Specify stack details` page, enter the following parameters:
- `AccountAdministrator` - Enter the ARN of the IAM entity (role or user or group) that will be performing account creation from AWS Service Catalog. You can go to the IAM console to find the ARN of the role/user/group. (eg. arn:aws:iam::010010011111:role/Administrator)
- `StackName` - Enter a stack name such as `account-vending-machine`
- `SourceBucket` - Add the name of the Amazon S3 bucket you created in the commercial region
- `AccountVendingLambdaZip` - File name of the zipped lambda function for Account Bootstrap Product.(Must be in the S3 bucket mentioned above)
- `SourceTemplate` - Add your Amazon S3 URL for the source template.
- 
8. On the `Configure stack options` page, click `Next`.
9. On the `Review` page, check the checkbox for `I acknowledge that AWS CloudFormation might create IAM resources.`, and click `Create Stack`.

10. Once status of the stack changes to `CREATE COMPLETE`, click on the stack and open the `Outputs` tab to see the output values.
11. In the the `Outputs` section of AWS CloudFormation, copy the key and value column contents for `AccountVendingLambda`. You will be using this value during the execution of the account vending machine.
At this point, you have successfully set up the account vending machine in your commercial AWS account.
### B) In the AWS GovCloud(US) region, setup the account bootstrap product
As a part of creating a sample account bootstrap product from this repository, you will first launch a CloudFormation template to create the account account bootstrap product set up in your account.
1. Login to your AWS account which is a **master account** in AWS Organizations in the **AWS GovCloud(US) region**.
_Note: You can customize this implementation to work with linked accounts as well, but for the purposes of this exercise, we will use the master account._
2. Set up an S3 bucket to hold all the artifacts for this implementation
* Click on `Services`, then [Amazon S3](https://console.amazonaws-us-gov.com/s3/)
* On the Amazon S3 console, click `Create S3 bucket`
* Enter a bucket name of your choice and choose the AWS GovCloud(US) region you plan to use for this sample
* Keep the defaults, and click `Create bucket`
* Click on `Services`, then `AWS Organizations`
* On the [AWS Organizations](https://console.amazonaws-us-gov.com/organizations/) page, click on the `Settings` tab
* Note the `Organization ID` on the settings page
* Go back to the `Amazon S3` console page, click on the bucket you just created, and click on the `Permissions` tab
* Click `Bucket Policy` and enter the following bucket policy: (Make sure you change the `Resource` and the `aws:PrincipalOrgId` to your Organization ID copied from AWS Organizations)
```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws-us-gov:s3:::<REPLACE WITH YOUR AMAZON S3 BUCKET NAME>/*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "<REPLACE WITH YOUR AWS ORGANIZATION ID>"
}
}
},
{
"Sid": "AllowSSLRequestsOnly",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws-us-gov:s3:::<REPLACE WITH YOUR AMAZON S3 BUCKET NAME>",
"arn:aws-us-gov:s3:::<REPLACE WITH YOUR AMAZON S3 BUCKET NAME>/*"
],
"Condition": {
"Bool": {
aws:SecureTransport: false
}
}
}
]
}
```
3. Upload all the files from the `govcloud-side-setup` folder of this repository in the Amazon S3 bucket from the previous step
4. Copy the URL of the file `GovCloudAccountSetup.yaml` from your Amazon S3 bucket
5. Click on `Services`, then select [AWS CloudFormation](https://console.amazonaws-us-gov.com/cloudformation/)
6. Click the `Create Stack` button, add the Amazon S3 URL copied in step 4, and click `Next`.
7. On the `Specify stack details` page, enter the following parameters:
- `AccountAdministrator` - Enter the ARN of the IAM entity (role or user or group) that will be performing account bootstrap from AWS Service Catalog. You can go to the IAM console to find the ARN of the role/user/group. (eg. arn:aws-gov-cloud:iam::010010011111:role/Administrator)
- `StackName` - Enter a stack name such as `account-bootstrap-product`
- `SourceBucket` - Add the name of the Amazon S3 bucket you created in the commercial region
- `AccountBootstrapLambdaZip` - Keep the Default Value for this solution
- `SourceTemplate` - Add your Amazon S3 URL for the source template
- 
8. On the `Configure stack options` page, click `Next`.
9. On the `Review` page, check the checkbox for `I acknowledge that AWS CloudFormation might create IAM resources.`, and click `Create Stack`.

10. Once status of the stack changes to `CREATE COMPLETE`, click on the stack and open the `Outputs` tab to see the output values.
At this point, you have successfully set up the account bootstrap product in your AWS GovCloud(US) account.
### C) In the commercial region, launch the account vending machine (AVM) to create new AWS accounts
In this section, you will launch the account vending machine product created in AWS Service Catalog to create a new AWS account pre-configured with custom settings defined in this lab.
1. Login to your AWS account using the IAM role/user/group that you provided in the `AccountAdministrator` in the set up phase.
2. On the Services menu, search and then choose `Service Catalog`. You will see an AWS Service Catalog product named `Account Vending Machine`.

3. In the `Products list` page, click `Account Vending Machine`, and then click `LAUNCH PRODUCT`.
4. On the `Product Version` page, configure:
a. `Name`: my-new-account-001
b. Select the available version.
5. Click `NEXT`
6. On the `Parameters` page, configure:
- `AccountEmail`: Enter a unique email address to be associated with the newly created account
- `OrganizationalUnitName`: Name of the organizational unit (OU) to which the account should be moved to. If the OU you provide doesn't exist, this solution will create it for you
- `AccountName`: Enter an account name
7. Click `NEXT`.
8. On the `TagOptions` page, provide your standard set of tagOptions, and/or click `NEXT`.
9. On the Notifications page, provide your standard notification Amazon SNS topic, and/or click `NEXT`.
10. On the Review page, review the configuration information, and click `LAUNCH`. This will create a CloudFormation stack. The initial status of the product is shown as `Under change`. Wait for about 5 minutes, then refresh the screen till the status changes to `AVAILABLE`. _Note: You can go to the AWS CloudFormation page to monitor the stack progress, or go to [Amazon CloudWatch](https://console.aws.amazon.com/cloudwatch/home) to view the step by step execution of the account vending lambda function._
11. In the the `Outputs` section of AWS Service Catalog, you will see the account ID details of **both** of the newly created accounts as follows. Copy the account ID `GovCloudAccountID` of the AWS GovCloud(US) account, which we will use in the next step.

### D) In the AWS GovCloud(US) region, launch the account bootstrap product to bootstrap the newly created AWS GovCloud(US) account
In this section, you will launch the account bootstrap product created in AWS Service Catalog to create a new AWS account pre-configured with custom settings defined in this lab.
1. Login to your AWS GovCloud(US) account using the IAM role/user/group that you provided in the `AccountAdministrator` in the set up phase.
2. On the Services menu, search and then choose [AWS Service Catalog](https://console.amazonaws-us-gov.com/servicecatalog/home). You will see an AWS Service Catalog product named `Account Bootstrap Product`. _Note: If you don't see this product, make sure you have logged in to this account with the role assigned to this AWS Service Catalog product. Read [documentation](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/getstarted-deploy.html) for more information_

3. In the `Products list` page, click `Account Bootstrap Product`, and then click `LAUNCH PRODUCT`.
6. On the `Product Version` page, enter the following details:
a. `Name`: my-new-account-001-bootstrap
b. Select the available version.
7. Click `NEXT`
8. On the `Parameters` page, configure:
- `AccountId`: Enter Account ID of the new account to be bootstrapped in AWS GovCloud (US). Get from Step C.
- `SourceBucket`: Enter the name of the source bucket where your baseline CloudFormation template exists.
- `AssumeRoleName`: Name of the IAM Role to be assumed in the child account. Keep the default value.
- `StackRegion`: Choose the region where the preconfigured settings should be applied
- `BaselineTemplate`: Keep the default value. OR Enter the name of the account baseline CloudFormation template.

9. Click `NEXT`.
10. On the `TagOptions` page, click `NEXT`.
11. On the Notifications page, click `NEXT`.
12. On the Review page, review the configuration information, and click `LAUNCH`. This will create a CloudFormation stack. The initial status of the product is shown as `Under change`. Wait for about 5 minutes, then refresh the screen till the status changes to `AVAILABLE`. _Note: You can go to the CloudFormation page to monitor the stack progress, or go to [Amazon CloudWatch](https://console.amazonaws-us-gov.com/cloudwatch/) to view the step by step execution of the account vending lambda function._
13. In the the `Outputs` section of AWS Service Catalog, you will see the account details of the bootstrapped account as follows.

### E) Login to the bootstrapped AWS GovCloud(US) account for end-user experience
In this section, we will log in to the newly vended account using the user created as a part of the set up and explore the account configuration.
1. Login to your AWS account using the `LoginURL` provided in the Outputs of the previous section.
2. **Make sure you change over to the same region as the `StackRegion` in the previous section.**
3. On the credentials page, enter the following information:
- Username: `service-catalog-user`
- Password: `Service-catalog-2020!`
_Note: You will be prompted to change your password at first log in._
4. On the Services menu, search and then choose [AWS Service Catalog](https://console.amazonaws-us-gov.com/servicecatalog/home). On the products list page, you will be to see the pre-configured AWS Service Catalog products allowed for the current user to provision.

4. As a part of the account setup, all the default VPCs from every region have been deleted for this account. You can validate this by going to the Services menu, search and then choose 'VPC'.
5. As a security best practice of least privilege, we have restricted the current user to launch AWS Service Catalog products only. You can validate this by trying to create a new VPC from the [Amazon VPC console](https://console.amazonaws-us-gov.com/vpc/home).
- Click on the `Launch VPC Wizard` button, and then click on `Select` for `VPC with a Single Public Subnet`.
- In the `VPC Name` field, enter `demo`, and click `Create VPC`.
- You will not be able to move forward from this page, due to lack of permissions.

6. Now, we will try to perform the same function using AWS Service Catalog. But first, the user will need a key pair.
- Go to the [Amazon EC2 console](https://console.amazonaws-us-gov.com/ec2)
- In the left navigation menu, select `Key Pairs` under `Network & Security`
- Click on the `Create a key pair` button, add name as `demo`, and click `Create`.
- Now, on the Services menu, search and then choose `Service Catalog`. On the products list page, select `Amazon VPC`, and click on `Launch Product`.
- On the `Product Version` page, configure:
a. `Name`: `my-custom-vpc-001`
b. Select the available version.
7. Click `NEXT`
8. On the `Parameters` page, configure:
- `RegionAZ1Name`: Choose the availability zone for a region. eg. us-gov-west-1
- `RegionAZ2Name`: Choose another availability zone for the **same** region as above. eg. us-gov-west-1
- `VPCCIDR`: Keep the default value OR change it to a CIDR you want.
- `SubnetAPublicCIDR`: Keep the default value OR change it to a CIDR you want
- `SubnetAPublicCIDR`: Keep the default value OR change it to a CIDR you want
- `SubnetAPrivateCIDR`: Keep the default value OR change it to a CIDR you want
- `SubnetBPrivateCIDR`: Keep the default value OR change it to a CIDR you want
- `CreateBastionInstance`: Keep the default value OR change it to `true` if you want a bastion instance created.
- `BastionInstanceType`: Keep the default value OR change it to an instance type you want
- `EC2KeyPair`: Choose the key pair you created in Step 6
- `BastionSSHCIDR`: Enter any value you want eg. 0.0.0.0/0
- `LatestAmiId`: Keep the default value OR change it to an AMI ID you want
9. Click `NEXT`.
10. On the `TagOptions` page, click `NEXT`.
11. On the Notifications page, click `NEXT`.
12. On the Review page, review the configuration information, and click `LAUNCH`. This will create a CloudFormation stack. The initial status of the product is shown as `Under change`. Wait for about 5 minutes, then refresh the screen till the status changes to `AVAILABLE`.
13. Validate the Outputs section on AWS Service Catalog screen to see the details of the VPC created.
14. Finally, on the [Amazon VPC console](https://console.amazonaws-us-gov.com/vpc/home), you can verify that a VPC is now created.
In conclusion, you were able to log in as an end user in the newly vended AWS account, and create AWS resources in a compliant manner using AWS Service Catalog.
## Conclusion
This repository provides a method to enable on-demand creation of AWS accounts that can be customized to the requirements of an organization. Administrators and/or teams who are required to provision new accounts can use this approach to standardize the networking configuration and the resources that be provisioned when the new account is ready for use.
## Credits
This repository was inspired by the AWS blog post on [automation of AWS account creation](https://aws.amazon.com/blogs/mt/automate-account-creation-and-resource-provisioning-using-aws-service-catalog-aws-organizations-and-aws-lambda/).
## Clean Up
Congratulations! :tada: You have completed all the steps for setting up your own custom account vending machine using AWS Service Catalog.
**To make sure you are not charged for any unwanted services, you can clean up by deleting the stack created in the _Deployment steps_ stage and its resources.**
To delete any AWS Service Catalog products,
1. Go to the AWS Service Catalog screen and make sure you are in the same region as you selected during the launch phase
2. Go to the `Provisioned Products` screen, and terminate any products that you may have created as a part of the lab
To delete the stack and its resources
1. From the AWS CloudFormation console in the region you used in the _Lab Setup_, select the stack that you created.
2. Click `Delete Stack`.
3. In the confirmation message that appears, click `Yes`, `Delete`.
At this stage, the status for your changes to `DELETE_IN_PROGRESS`. In the same way you monitored the
creation of the stack, you can monitor its deletion by using the `Events` tab. When AWS CloudFormation completes the deletion of the stack, it removes the stack from the list.
You will see all your AWS Service Catalog products disappear at this point.
[(Back to top)](#aws-account-vending-machine)
## Contributing
Your contributions are always welcome! Please have a look at the [contribution guidelines](CONTRIBUTING.md) first. :tada:
[(Back to top)](#aws-account-vending-machine)
## License Summary
This sample code is made available under the MIT-0 license. See the LICENSE file.
[(Back to top)](#aws-account-vending-machine)
================================================
FILE: govcloud/commercial-side-setup/CommercialAccountSetup.yaml
================================================
#Copyright 2008-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at
#http://aws.amazon.com/apache2.0/
#or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
AWSTemplateFormatVersion: 2010-09-09
Description: This template sets up the infrastructure required for an AWS Service Catalog based Account Vending Machine. (fdp-1qjtoo67i)
Parameters:
SourceBucket:
Description: "Bucket name of the S3 bucket holding all the files for the Account Vending Machine set up"
Type: String
Default: "<ENTER BUCKET NAME>"
AccountVendingLambdaZip:
Description: "File name of the zipped lambda function for account vending machine. (Must be in the S3 bucket mentioned above)"
Type: String
Default: "AccountCreationLambda.zip"
SourceTemplate:
Description: "Enter the template URL for the cloudformation template to create the account vending machine product in AWS Service Catalog"
Type: String
Default: "<URL>/commercial-account-avm-product.yaml"
AccountAdministrator:
Description: "Enter the ARN of the IAM entity (role or user or group) that will be performing account creation from AWS Service Catalog"
Type: String
AllowedPattern: ".+"
Resources:
AccountBuilderLambda:
Type: "AWS::Lambda::Function"
DependsOn: LambdaExecuteRole
Properties:
Handler: "AccountCreationLambda.lambda_handler"
Runtime: "python3.9"
Role: !GetAtt LambdaExecuteRole.Arn
Timeout: 800
TracingConfig:
Mode: "Active"
Code:
S3Bucket: !Ref SourceBucket
S3Key: !Ref AccountVendingLambdaZip
LambdaExecuteRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AdministratorAccess"
Path: "/"
AccountVendingPortfolio:
Type: "AWS::ServiceCatalog::Portfolio"
Properties:
DisplayName: "Account Vending Machine"
AcceptLanguage: "en"
ProviderName: "AWS"
AccountVendingMachineProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This product is an account vending machine builds a new account"
Distributor: "Amazon"
Name: "Account Vending Machine"
Owner: "AWS"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "April 2020"
Name: "April 2020 v1.0"
Info:
LoadTemplateFromURL : !Ref SourceTemplate
AVMAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref AccountVendingMachineProduct
PortfolioId: !Ref AccountVendingPortfolio
PortfolioPrincipalAssociation:
Type: "AWS::ServiceCatalog::PortfolioPrincipalAssociation"
Properties:
PrincipalARN: !Ref AccountAdministrator
PortfolioId: !Ref AccountVendingPortfolio
PrincipalType: IAM
ServiceCatalogLaunchRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
Effect: "Allow"
Principal:
Service:
- "servicecatalog.amazonaws.com"
Action:
- "sts:AssumeRole"
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AdministratorAccess"
Path: "/"
ServiceCatalogLaunchConstraint:
Type: "AWS::ServiceCatalog::LaunchRoleConstraint"
DependsOn: ServiceCatalogLaunchRole
Properties:
Description: This is a launch constraint created for the account vending portfolio
AcceptLanguage: en
PortfolioId: !Ref AccountVendingPortfolio
ProductId: !Ref AccountVendingMachineProduct
RoleArn: !GetAtt ServiceCatalogLaunchRole.Arn
ServiceCatalogTagOption:
Type: "AWS::ServiceCatalog::TagOption"
Properties:
Active: true
Value: "avm-reference-architecture"
Key: "Name"
ServiceCatalogTagOptionAssociation:
Type: "AWS::ServiceCatalog::TagOptionAssociation"
Properties:
TagOptionId: !Ref ServiceCatalogTagOption
ResourceId: !Ref AccountVendingPortfolio
Outputs:
AccountLambda:
Description: ARN of the account creation lambda function
Value: !GetAtt AccountBuilderLambda.Arn
Export:
Name: AccountBuilderLambda
================================================
FILE: govcloud/commercial-side-setup/commercial-account-avm-product.yaml
================================================
# /*
# * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# *
# * Permission is hereby granted, free of charge, to any person obtaining a copy of this
# * software and associated documentation files (the "Software"), to deal in the Software
# * without restriction, including without limitation the rights to use, copy, modify,
# * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# * permit persons to whom the Software is furnished to do so.
# *
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# */
AWSTemplateFormatVersion: 2010-09-09
Description: Account Builder Template. (fdp-1qjtoo67i)
Metadata:
'AWS::CloudFormation::Interface':
ParameterGroups:
- Label:
default: Parameters for the new account
Parameters:
- accountemail
- organizationunitname
- accountname
Parameters:
accountemail:
Description: "Account Email address"
Type: String
AllowedPattern: ".+"
ConstraintDescription: "Must provide a valid email address"
accountname:
Description: "Name of the new AWS Account Name"
Type: String
AllowedPattern: ".+"
ConstraintDescription: "Provide the account name"
organizationunitname:
Description: "Name of the organization unit to which the account should be moved to. If its a new OU, we will create it for you"
Type: String
Default: "destination_ou"
AllowedPattern: ".+"
Resources:
TriggerLambda:
Type: "Custom::TriggerLambda"
Properties:
ServiceToken: !ImportValue AccountBuilderLambda
'accountemail' : !Ref accountemail
'accountname' : !Ref accountname
'organizationunitname': !Ref 'organizationunitname'
Outputs:
Message:
Description: Execution Status
Value: !GetAtt 'TriggerLambda.Message'
AccountID:
Description: ID of the new account
Value: !GetAtt 'TriggerLambda.AccountID'
GovCloudAccountId:
Description: ID of the new account
Value: !GetAtt 'TriggerLambda.GovCloudAccountId'
================================================
FILE: govcloud/govcloud-side-setup/Accountbaseline.yml
================================================
# /*
# * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# *
# * Permission is hereby granted, free of charge, to any person obtaining a copy of this
# * software and associated documentation files (the "Software"), to deal in the Software
# * without restriction, including without limitation the rights to use, copy, modify,
# * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# * permit persons to whom the Software is furnished to do so.
# *
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# */
AWSTemplateFormatVersion: 2010-09-09
Description: Baseline IAM resources for new account (fdp-1qjtom7jr)
Parameters:
ServiceCatalogUserName:
Type: String
Description: Username for the IAM user for ServiceCatalog in the newly vended account
ServiceCatalogUserPassword:
Type: String
NoEcho: true
MinLength: 1
Description: Password for the IAM user for ServiceCatalog in the newly vended account
Resources:
ServiceCatalogUser:
Type: 'AWS::IAM::User'
Properties:
UserName: !Ref ServiceCatalogUserName
Path: /
LoginProfile:
Password: !Ref ServiceCatalogUserPassword
PasswordResetRequired: true
ServiceCatalogUserKey:
Type: AWS::IAM::AccessKey
Properties:
Status: 'Active'
UserName: !Ref ServiceCatalogUser
ServiceCatalogUserGroup:
Type: 'AWS::IAM::Group'
Properties:
GroupName: ServiceCatalogUserGroup
ManagedPolicyArns:
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AWSServiceCatalogEndUserFullAccess"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonEC2ReadOnlyAccess"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/IAMUserChangePassword"
Path: /
ServiceCatalogGroupPolicy:
Type: AWS::IAM::Policy
Properties:
Groups:
- !Ref ServiceCatalogUserGroup
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "cloudformation:Describe*"
- "cloudformation:List*"
- "cloudformation:Get*"
- "ec2:CreateKeyPair"
Resource: "*"
PolicyName: "KeyPairCreate"
AddUserToGroup:
Type: 'AWS::IAM::UserToGroupAddition'
DependsOn: ServiceCatalogUserGroup
Properties:
GroupName: !Ref ServiceCatalogUserGroup
Users:
- !Ref ServiceCatalogUser
SCEC2LaunchRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: SCEC2LaunchRole
ManagedPolicyArns:
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess"
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- servicecatalog.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
EC2LinuxProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This product builds one Amazon Linux EC2 instance and create a SSM patch baseline, maintenance window, and patch task to scan for and install operating system updates the EC2 instance."
Distributor: "Amazon"
Name: "Amazon Elastic Compute Cloud (EC2) Linux"
Owner: "IT Services"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "Dec 2019"
Name: "Dec 2019"
Info:
LoadTemplateFromURL : "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/ec2/sc-ec2-linux-ra.json"
EC2WindowsProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This product builds one Amazon Windows EC2 instance and create a SSM patch baseline, maintenance window, and patch task to scan for and install operating system updates the EC2 instance."
Distributor: "Amazon"
Name: "Amazon Elastic Compute Cloud (EC2) Windows"
Owner: "IT Services"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "Dec 2019"
Name: "Dec 2019"
Info:
LoadTemplateFromURL : "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/ec2/sc-ec2-windows-ra.json"
VPCProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This product builds one Amazon VPC with Public Subnets, Private Subnets, Route Tables, NAT Gateway and Internet Gateway"
Distributor: "Amazon"
Name: "Amazon VPC"
Owner: "IT Services"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "Dec 2019"
Name: "Dec 2019"
Info:
LoadTemplateFromURL : "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/vpc/sc-vpc-ra.json"
EMRProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "EMR product creates an Amazon Elastic MapReduce cluster in the VPC and Subnets selected by the end user. A remote access security group is also created to allow for a bastion host to connect to the instances used by EMR via SSH."
Distributor: "Amazon"
Name: "EMR Product"
Owner: "IT Services"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "Dec 2019"
Name: "Dec 2019"
Info:
LoadTemplateFromURL: "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/emr/sc-emr-ra.json"
SageMakerProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This template demonstrates the creation of a SageMaker NotebookInstance with encryption. You will be billed for the AWS resources used if you create a stack from this template."
Distributor: "Amazon"
Name: "SageMaker NoteBook"
Owner: "IT Services"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "Dec 2019"
Name: "Dec 2019"
Info:
LoadTemplateFromURL: "https://aws-service-catalog-reference-architectures.s3.amazonaws.com/sagemaker/sc-sagemaker.yml"
RDSMySQLProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This product allows the user to launch a RDS MySQL DB as either single instance databases or multi-availability zone databases."
Distributor: "Amazon"
Name: "RDS MySQL Product"
Owner: "IT Services"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "Dec 2019"
Name: "Dec 2019"
Info:
LoadTemplateFromURL: "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/rds/sc-rds-mssql-ra.json"
RDSMariaDBProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This product allows the user to launch a RDS Maria DB as either single instance databases or multi-availability zone databases."
Distributor: "Amazon"
Name: RDS MariaDB Product
Owner: "IT Services"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "Dec 2019"
Name: "Dec 2019"
Info:
LoadTemplateFromURL: "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/rds/sc-rds-mariadb-ra.json"
RDSPostGreSqlProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This product allows the user to launch a RDS POSTGRE SQL as either single instance databases or multi-availability zone databases."
Distributor: "Amazon"
Name: "RDS POSTGRE SQL Product"
Owner: "IT Services"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "Dec 2019"
Name: "Dec 2019"
Info:
LoadTemplateFromURL: "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/rds/sc-rds-postgresql-ra.json"
S3BucketProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This product allows the user to create an S3 Bucket locking down the access to a specific CIDR."
Distributor: "Amazon"
Name: "S3 Bucket Product"
Owner: "IT Services"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "Dec 2019"
Name: "Dec 2019"
Info:
LoadTemplateFromURL: "https://raw.githubusercontent.com/aws-samples/aws-service-catalog-reference-architectures/master/s3/sc-s3-cidr-ra.json"
BaselinePortfolio:
Type: "AWS::ServiceCatalog::Portfolio"
Properties:
DisplayName: "Baseline-Portfolio"
AcceptLanguage: "en"
ProviderName: "Amazon"
DataScientistPortfolio:
Type: "AWS::ServiceCatalog::Portfolio"
Properties:
DisplayName: "DataScientist-Portfolio"
AcceptLanguage: "en"
ProviderName: "Amazon"
LinuxAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref EC2LinuxProduct
PortfolioId: !Ref BaselinePortfolio
LinuxConstraint:
Type: AWS::ServiceCatalog::LaunchRoleConstraint
Properties:
AcceptLanguage: "en"
Description: "Launch Constraint for this AWS Service Catalog product"
PortfolioId: !Ref BaselinePortfolio
ProductId: !Ref EC2LinuxProduct
RoleArn: !GetAtt SCEC2LaunchRole.Arn
WindowsAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref EC2WindowsProduct
PortfolioId: !Ref BaselinePortfolio
WindowsConstraint:
Type: AWS::ServiceCatalog::LaunchRoleConstraint
Properties:
AcceptLanguage: "en"
Description: "Launch Constraint for this AWS Service Catalog product"
PortfolioId: !Ref BaselinePortfolio
ProductId: !Ref EC2WindowsProduct
RoleArn: !GetAtt SCEC2LaunchRole.Arn
VPCAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref VPCProduct
PortfolioId: !Ref BaselinePortfolio
VPCConstraint:
Type: AWS::ServiceCatalog::LaunchRoleConstraint
Properties:
AcceptLanguage: "en"
Description: "Launch Constraint for this AWS Service Catalog product"
PortfolioId: !Ref BaselinePortfolio
ProductId: !Ref VPCProduct
RoleArn: !GetAtt SCEC2LaunchRole.Arn
EMRAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref EMRProduct
PortfolioId: !Ref DataScientistPortfolio
EMRConstraint:
Type: AWS::ServiceCatalog::LaunchRoleConstraint
Properties:
AcceptLanguage: "en"
Description: "Launch Constraint for this AWS Service Catalog product"
PortfolioId: !Ref DataScientistPortfolio
ProductId: !Ref EMRProduct
RoleArn: !GetAtt SCEC2LaunchRole.Arn
SageMakerAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref SageMakerProduct
PortfolioId: !Ref DataScientistPortfolio
SageMakerConstraint:
Type: AWS::ServiceCatalog::LaunchRoleConstraint
DependsOn: SageMakerAssociation
Properties:
AcceptLanguage: "en"
Description: "Launch Constraint for this AWS Service Catalog product"
PortfolioId: !Ref DataScientistPortfolio
ProductId: !Ref SageMakerProduct
RoleArn: !GetAtt SCEC2LaunchRole.Arn
RDSMySQLAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref RDSMySQLProduct
PortfolioId: !Ref BaselinePortfolio
RDSConstraint:
Type: AWS::ServiceCatalog::LaunchRoleConstraint
Properties:
AcceptLanguage: "en"
Description: "Launch Constraint for this AWS Service Catalog product"
PortfolioId: !Ref BaselinePortfolio
ProductId: !Ref RDSMySQLProduct
RoleArn: !GetAtt SCEC2LaunchRole.Arn
RDSMariaDBAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref RDSMariaDBProduct
PortfolioId: !Ref BaselinePortfolio
RDSMariaDBConstraint:
Type: AWS::ServiceCatalog::LaunchRoleConstraint
Properties:
AcceptLanguage: "en"
Description: "Launch Constraint for this AWS Service Catalog product"
PortfolioId: !Ref BaselinePortfolio
ProductId: !Ref RDSMariaDBProduct
RoleArn: !GetAtt SCEC2LaunchRole.Arn
RDSPOSTGRESQLAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref RDSPostGreSqlProduct
PortfolioId: !Ref BaselinePortfolio
RDSPOSTGRESQLConstraint:
Type: AWS::ServiceCatalog::LaunchRoleConstraint
Properties:
AcceptLanguage: "en"
Description: "Launch Constraint for this AWS Service Catalog product"
PortfolioId: !Ref BaselinePortfolio
ProductId: !Ref RDSPostGreSqlProduct
RoleArn: !GetAtt SCEC2LaunchRole.Arn
S3BucketAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref S3BucketProduct
PortfolioId: !Ref BaselinePortfolio
S3BucketConstraint:
Type: AWS::ServiceCatalog::LaunchRoleConstraint
Properties:
AcceptLanguage: "en"
Description: "Launch Constraint for this AWS Service Catalog product"
PortfolioId: !Ref BaselinePortfolio
ProductId: !Ref S3BucketProduct
RoleArn: !GetAtt SCEC2LaunchRole.Arn
PortfolioPrincipalAssociationforEndUser:
Type: "AWS::ServiceCatalog::PortfolioPrincipalAssociation"
Properties:
PrincipalARN: !GetAtt ServiceCatalogUser.Arn
PortfolioId: !Ref BaselinePortfolio
PrincipalType: IAM
PortfolioPrincipalAssociationforDataScientist:
Type: "AWS::ServiceCatalog::PortfolioPrincipalAssociation"
Properties:
PrincipalARN: !GetAtt ServiceCatalogUser.Arn
PortfolioId: !Ref DataScientistPortfolio
PrincipalType: IAM
================================================
FILE: govcloud/govcloud-side-setup/GovCloudAccountSetup.yaml
================================================
# /*
# * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# *
# * Permission is hereby granted, free of charge, to any person obtaining a copy of this
# * software and associated documentation files (the "Software"), to deal in the Software
# * without restriction, including without limitation the rights to use, copy, modify,
# * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# * permit persons to whom the Software is furnished to do so.
# *
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# */
AWSTemplateFormatVersion: 2010-09-09
Description: This template sets up the infrastructure required for an AWS Service Catalog based Account Bootstrap Product. (fdp-1qjtom7jr)
Parameters:
SourceBucket:
Description: "Bucket name of the S3 bucket holding all the files for the Account Bootstrap Product set up"
Type: String
Default: "<ENTER BUCKET NAME>"
AccountBootstrapLambdaZip:
Description: "File name of the zipped lambda function for Account Bootstrap Product. (Must be in the S3 bucket mentioned above)"
Type: String
Default: "<ENTER LAMBDA ZIP NAME>"
SourceTemplate:
Description: "Enter the template URL for the cloudformation template to create the Account Bootstrap Product product in AWS Service Catalog"
Type: String
Default: "<URL>/govcloud-account-avm-product.yaml"
AccountAdministrator:
Description: "Enter the ARN of the IAM entity (role or user or group) that will be performing account creation from AWS Service Catalog"
Type: String
AllowedPattern: ".+"
Resources:
AccountBootstrapLambda:
Type: "AWS::Lambda::Function"
DependsOn: LambdaExecuteRole
Properties:
Handler: "AccountBootstrapLambda.lambda_handler"
Runtime: "python3.9"
Role: !GetAtt LambdaExecuteRole.Arn
Timeout: 800
TracingConfig:
Mode: "Active"
Code:
S3Bucket: !Ref SourceBucket
S3Key: "AccountBootstrapLambda.zip"
LambdaExecuteRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- !Sub arn:${AWS::Partition}:iam::aws:policy/AWSOrganizationsFullAccess
- !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: !Sub "LambdaAllowWriteToLogGroup"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "logs:CreateLogGroup"
Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/OrganizationsChildAccountEnrollment:*
- PolicyName: !Sub "LambdaAllowGetOrgAccountRole"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Resource: !Sub arn:${AWS::Partition}:iam::*:role/OrganizationAccountAccessRole
- Effect: Allow
Action:
- iam:GetRole
Resource: '*'
AccountBootstrapPortfolio:
Type: "AWS::ServiceCatalog::Portfolio"
Properties:
DisplayName: "Account Bootstrap Portfolio"
AcceptLanguage: "en"
ProviderName: "AWS"
AccountBootstrapProduct:
Type: "AWS::ServiceCatalog::CloudFormationProduct"
Properties:
AcceptLanguage: "en"
Description: "This product is an Account Bootstrap Product builds a new account"
Distributor: "Amazon"
Name: "Account Bootstrap Product"
Owner: "AWS"
SupportEmail: "support@yourcompany.com"
SupportUrl: "https://www.amazon.com"
SupportDescription: "Support Description"
ProvisioningArtifactParameters:
-
Description: "April 2020"
Name: "April 2020 v1.0"
Info:
LoadTemplateFromURL : !Ref SourceTemplate
AVMAssociation:
Type: "AWS::ServiceCatalog::PortfolioProductAssociation"
Properties:
ProductId: !Ref AccountBootstrapProduct
PortfolioId: !Ref AccountBootstrapPortfolio
PortfolioPrincipalAssociation:
Type: "AWS::ServiceCatalog::PortfolioPrincipalAssociation"
Properties:
PrincipalARN: !Ref AccountAdministrator
PortfolioId: !Ref AccountBootstrapPortfolio
PrincipalType: IAM
ServiceCatalogLaunchRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
Effect: "Allow"
Principal:
Service:
- "servicecatalog.amazonaws.com"
Action:
- "sts:AssumeRole"
ManagedPolicyArns:
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess"
Path: "/"
ServiceCatalogLaunchConstraint:
Type: "AWS::ServiceCatalog::LaunchRoleConstraint"
DependsOn: ServiceCatalogLaunchRole
Properties:
Description: This is a launch constraint created for the account vending portfolio
AcceptLanguage: en
PortfolioId: !Ref AccountBootstrapPortfolio
ProductId: !Ref AccountBootstrapProduct
RoleArn: !GetAtt ServiceCatalogLaunchRole.Arn
ServiceCatalogTagOption:
Type: "AWS::ServiceCatalog::TagOption"
Properties:
Active: true
Value: "avm-reference-architecture"
Key: "Name"
ServiceCatalogTagOptionAssociation:
Type: "AWS::ServiceCatalog::TagOptionAssociation"
Properties:
TagOptionId: !Ref ServiceCatalogTagOption
ResourceId: !Ref AccountBootstrapPortfolio
Outputs:
AccountLambda:
Description: ARN of the account creation lambda function
Value: !GetAtt AccountBootstrapLambda.Arn
Export:
Name: AccountBootstrapLambda
================================================
FILE: govcloud/govcloud-side-setup/govcloud-account-avm-product.yaml
================================================
# /*
# * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# *
# * Permission is hereby granted, free of charge, to any person obtaining a copy of this
# * software and associated documentation files (the "Software"), to deal in the Software
# * without restriction, including without limitation the rights to use, copy, modify,
# * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# * permit persons to whom the Software is furnished to do so.
# *
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# */
AWSTemplateFormatVersion: 2010-09-09
Description: New GovCloud Account Baseline (fdp-1qjtom7jr)
Metadata:
'AWS::CloudFormation::Interface':
ParameterGroups:
- Label:
default: Parameters for account to Onboard
Parameters:
- AccountId
Parameters:
AccountId:
Description: "Account ID of the new account to be bootstrapped"
Type: String
AllowedPattern: ".+"
ConstraintDescription: "Must be a 12 digit account number in GovCloud set up by Organizations"
StackRegion:
Description: "Region for deploying the baseline template in the vended account"
Default: "us-gov-west-1"
Type: String
AllowedPattern: ".+"
AllowedValues: ["us-gov-west-1","us-gov-east-1"]
ConstraintDescription: "Must be a valid AWS GovCloud(US) region"
SourceBucket:
Description: "Name of the S3 bucket holding the baseline template file"
Type: String
BaselineTemplate:
Description: "Baseline template to be deployed in the vended account."
Type: String
Default: "Accountbaseline.yml"
AssumeRoleName:
Description: "Rolename to be assumed in the child account."
Type: String
Default: "OrganizationAccountAccessRole"
Resources:
TriggerLambda:
Type: "Custom::TriggerLambda"
Properties:
ServiceToken: !ImportValue AccountBootstrapLambda
AccountNumber : !Ref AccountId
CentralS3Bucket: !Ref SourceBucket
StackName : 'avm-baseline-stack'
StackRegion : !Ref StackRegion
ServiceCatalogUserName : 'service-catalog-user'
ServiceCatalogUserPassword : 'Service-catalog-2020!'
ChildTemplateS3Url: !Ref BaselineTemplate
AssumeRoleName: !Ref AssumeRoleName
Outputs:
Message:
Description: Execution Status
Value: !GetAtt 'TriggerLambda.Message'
AccountID:
Description: AWS Account ID of the newly vended account
Value: !GetAtt 'TriggerLambda.AccountID'
Username:
Description: Username of IAM user created in the newly vended account
Value: !GetAtt 'TriggerLambda.Username'
LoginURL:
Description: Login URL for the newly vended account
Value: !GetAtt 'TriggerLambda.LoginURL'
================================================
FILE: resources/AccountCreationLambdaCode/AccountCreationLambda.py
================================================
#Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at
#http://aws.amazon.com/apache2.0/
#or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
#!/usr/bin/env python
#from __future__ import print_function
import boto3
import botocore
import time
import sys
import argparse
import os
import urllib
import json
from crhelper import CfnResource
import logging
logger = logging.getLogger(__name__)
# Initialise the helper, all inputs are optional, this example shows the defaults
helper = CfnResource(json_logging=False, log_level='DEBUG', boto_level='CRITICAL', sleep_on_delete=120, ssl_verify=None)
'''AWS Organizations Create Account and Provision Resources via CloudFormation
This module creates a new account using Organizations, then calls CloudFormation to deploy baseline resources within that account via a local tempalte file.
'''
__version__ = '1.1'
__author__ = '@SYK@'
__email__ = 'khasnis@'
def get_client(service):
client = boto3.client(service)
return client
def create_account(accountname,accountemail,accountrole,access_to_billing,scp,root_id):
account_id = 'None'
client = get_client('organizations')
try:
create_account_response = client.create_account(Email=accountemail, AccountName=accountname,
RoleName=accountrole,
IamUserAccessToBilling=access_to_billing)
except botocore.exceptions.ClientError as e:
logger.info(e)
return(create_account_response,account_id)
#sys.exit(1)
#time.sleep(30)
create_account_status_response = client.describe_create_account_status(CreateAccountRequestId=create_account_response.get('CreateAccountStatus').get('Id'))
account_id = create_account_status_response.get('CreateAccountStatus').get('AccountId')
while(account_id is None ):
create_account_status_response = client.describe_create_account_status(CreateAccountRequestId=create_account_response.get('CreateAccountStatus').get('Id'))
account_id = create_account_status_response.get('CreateAccountStatus').get('AccountId')
#move_response = client.move_account(AccountId=account_id,SourceParentId=root_id,DestinationParentId=organization_unit_id)
return(create_account_response,account_id)
def get_template(sourcebucket,baselinetemplate):
'''
Read a template file and return the contents
'''
#logger.info("Reading resources from " + templatefile)
s3 = boto3.resource('s3')
#obj = s3.Object('cf-to-create-lambda','5-newbaseline.yml')
obj = s3.Object(sourcebucket,baselinetemplate)
return obj.get()['Body'].read().decode('utf-8')
def delete_default_vpc(credentials,currentregion):
#logger.info("Default VPC deletion in progress in {}".format(currentregion))
ec2_client = boto3.client('ec2',
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken'],
region_name=currentregion)
vpc_response = ec2_client.describe_vpcs()
for i in range(0,len(vpc_response['Vpcs'])):
if((vpc_response['Vpcs'][i]['InstanceTenancy']) == 'default'):
default_vpcid = vpc_response['Vpcs'][0]['VpcId']
subnet_response = ec2_client.describe_subnets()
subnet_delete_response = []
default_subnets = []
for i in range(0,len(subnet_response['Subnets'])):
if(subnet_response['Subnets'][i]['VpcId'] == default_vpcid):
default_subnets.append(subnet_response['Subnets'][i]['SubnetId'])
for i in range(0,len(default_subnets)):
subnet_delete_response.append(ec2_client.delete_subnet(SubnetId=default_subnets[i],DryRun=False))
#logger.info("Default Subnets" + currentregion + "Deleted.")
igw_response = ec2_client.describe_internet_gateways()
for i in range(0,len(igw_response['InternetGateways'])):
for j in range(0,len(igw_response['InternetGateways'][i]['Attachments'])):
if(igw_response['InternetGateways'][i]['Attachments'][j]['VpcId'] == default_vpcid):
default_igw = igw_response['InternetGateways'][i]['InternetGatewayId']
#logger.info(default_igw)
detach_default_igw_response = ec2_client.detach_internet_gateway(InternetGatewayId=default_igw,VpcId=default_vpcid,DryRun=False)
delete_internet_gateway_response = ec2_client.delete_internet_gateway(InternetGatewayId=default_igw)
#logger.info("Default IGW " + currentregion + "Deleted.")
time.sleep(10)
delete_vpc_response = ec2_client.delete_vpc(VpcId=default_vpcid,DryRun=False)
logger.info("Deleted Default VPC in {}".format(currentregion))
return delete_vpc_response
def deploy_resources(credentials, template, stackname, stackregion, ServiceCatalogUserName, ServiceCatalogUserPassword,account_id):
'''
Create a CloudFormation stack of resources within the new account
'''
datestamp = time.strftime("%d/%m/%Y %H:%M:%S")
client = boto3.client('cloudformation',
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken'],
region_name=stackregion)
#time.sleep(120)
logger.info("Deploying stack - " + stackname + " in " + account_id + " started at " + time.strftime("%d/%m/%Y %H:%M:%S"))
creating_stack = True
while creating_stack is True:
try:
creating_stack = False
create_stack_response = client.create_stack(
StackName=stackname,
TemplateBody=template,
Parameters=[
{
'ParameterKey' : 'ServiceCatalogUserName',
'ParameterValue' : ServiceCatalogUserName
},
{
'ParameterKey' : 'ServiceCatalogUserPassword',
'ParameterValue' : ServiceCatalogUserPassword
}
],
NotificationARNs=[],
Capabilities=[
'CAPABILITY_NAMED_IAM',
],
OnFailure='ROLLBACK',
Tags=[
{
'Key': 'ManagedResource',
'Value': 'True'
},
{
'Key': 'DeployDate',
'Value': datestamp
}
]
)
except botocore.exceptions.ClientError as e:
creating_stack = True
logger.info(e)
logger.info("Retrying...")
time.sleep(10)
stack_building = True
logger.info("Stack creation in process...")
logger.info(create_stack_response)
while stack_building is True:
event_list = client.describe_stack_events(StackName=stackname).get("StackEvents")
stack_event = event_list[0]
if (stack_event.get('ResourceType') == 'AWS::CloudFormation::Stack' and
stack_event.get('ResourceStatus') == 'CREATE_COMPLETE'):
stack_building = False
logger.info("Stack construction complete.")
elif (stack_event.get('ResourceType') == 'AWS::CloudFormation::Stack' and
stack_event.get('ResourceStatus') == 'ROLLBACK_COMPLETE'):
stack_building = False
logger.info("Stack construction failed.")
#sys.exit(1)
else:
logger.info(stack_event)
logger.info("Stack building . . .")
time.sleep(10)
stack = client.describe_stacks(StackName=stackname)
return stack
def assume_role(account_id, account_role):
sts_client = boto3.client('sts')
role_arn = 'arn:aws:iam::' + account_id + ':role/' + account_role
assuming_role = True
while assuming_role is True:
try:
assuming_role = False
assumedRoleObject = sts_client.assume_role(
RoleArn=role_arn,
RoleSessionName="NewAccountRole"
)
except botocore.exceptions.ClientError as e:
assuming_role = True
logger.info(e)
logger.info("Retrying...")
time.sleep(10)
# From the response that contains the assumed role, get the temporary
# credentials that can be used to make subsequent API calls
return assumedRoleObject['Credentials']
def get_ou_name_id(event, root_id,organization_unit_name):
ou_client = get_client('organizations')
list_of_OU_ids = []
list_of_OU_names = []
ou_name_to_id = {}
list_of_OUs_response = ou_client.list_organizational_units_for_parent(ParentId=root_id)
for i in list_of_OUs_response['OrganizationalUnits']:
list_of_OU_ids.append(i['Id'])
list_of_OU_names.append(i['Name'])
if(organization_unit_name not in list_of_OU_names):
logger.info("The provided Organization Unit Name doesnt exist. Creating an OU named: {}".format(organization_unit_name))
try:
ou_creation_response = ou_client.create_organizational_unit(ParentId=root_id,Name=organization_unit_name)
for k,v in ou_creation_response.items():
for k1,v1 in v.items():
if(k1 == 'Name'):
organization_unit_name = v1
if(k1 == 'Id'):
organization_unit_id = v1
except botocore.exceptions.ClientError as e:
logger.info("Error in creating the OU: {}".format(e))
else:
for i in range(len(list_of_OU_names)):
ou_name_to_id[list_of_OU_names[i]] = list_of_OU_ids[i]
organization_unit_id = ou_name_to_id[organization_unit_name]
return(organization_unit_name,organization_unit_id)
def build_accounts_list(org_client,list_accounts_response,account_details):
for account in range(0,len(list_accounts_response['Accounts'])):
if(list_accounts_response['Accounts'][account]['Status'] == 'ACTIVE' or list_accounts_response['Accounts'][account]['Status'] == 'SUSPENDED' or list_accounts_response['Accounts'][account]['Status'] == 'PENDING_CLOSURE'):
account_details[list_accounts_response['Accounts'][account]['Email']] = list_accounts_response['Accounts'][account]['Id']
return account_details
@helper.create
def create(event,context):
logger.info("Got Create")
logger.info(event)
client = get_client('organizations')
ec2_client = get_client('ec2')
accountname = event['ResourceProperties']['AccountName']
accountemail = event['ResourceProperties']['AccountEmail']
organization_unit_name = event['ResourceProperties']['OrganizationalUnitName']
accountrole = 'OrganizationAccountAccessRole'
stackname = event['ResourceProperties']['StackName']
stackregion = event['ResourceProperties']['StackRegion']
ServiceCatalogUserName = event['ResourceProperties']['ServiceCatalogUserName']
ServiceCatalogUserPassword = event['ResourceProperties']['ServiceCatalogUserPassword']
sourcebucket = event['ResourceProperties']['SourceBucket']
baselinetemplate = event['ResourceProperties']['BaselineTemplate']
access_to_billing = "DENY"
scp = None
try:
top_level_account = event['ServiceToken'].split(':')[4]
logger.info("The top level account is "+top_level_account)
org_client = get_client('organizations')
list_roots_response = org_client.list_roots()
root_id = list_roots_response['Roots'][0]['Id']
account_details = {}
inputtogetconfigurationdetails = {}
allaccounts = []
list_accounts_response = org_client.list_accounts()
while 'NextToken' in list_accounts_response:
accounts_ids = build_accounts_list(org_client,list_accounts_response,account_details)
list_accounts_response = org_client.list_accounts(NextToken=list_accounts_response['NextToken'])
accounts_ids = build_accounts_list(org_client,list_accounts_response,account_details)
logger.info(f"List of all AWS accounts created under the Organization Root : {accounts_ids}")
if root_id != "Error" and accountemail not in accounts_ids and accountname not in accounts_ids.values():
#Create new account
logger.info("Creating new account: " + accountname + " (" + accountemail + ")")
create_account_response,account_id = create_account(accountname,accountemail,accountrole,access_to_billing,scp,root_id)
logger.info(create_account_response)
else:
logger.error(f"Account creation failed. This may be due to an AWS account with the same provided name or email already exists in this Organization")
raise ValueError("Account creation failed. This may be due to an AWS account with the same provided name or email already exists in this Organization")
while org_client.describe_account(AccountId=account_id)['Account']['Status'] != 'ACTIVE':
logger.info(f"Account Creation Status: {org_client.describe_account(AccountId=account_id)['Account']['Status']}")
time.sleep(5)
logger.info(f"Account Status: {org_client.describe_account(AccountId=account_id)['Account']['Status']}")
logger.info("Created account:{} at {} UTC \n".format(account_id,time.strftime("%d/%m/%Y %H:%M:%S")))
#Move account to OU provided
if(organization_unit_name!='None'):
try:
(organization_unit_name,organization_unit_id) = get_ou_name_id(event, root_id,organization_unit_name)
move_response = org_client.move_account(AccountId=account_id,SourceParentId=root_id,DestinationParentId=organization_unit_id)
except botocore.exceptions.ClientError as e:
logger.info("An error occured. Org account move response: {} . Error Stack: {}".format(move_response, e))
#sys.exit(0)
credentials = assume_role(account_id, accountrole)
template = get_template(sourcebucket,baselinetemplate)
#delete default vpc in every region
regions = []
regions_response = ec2_client.describe_regions()
for i in range(0,len(regions_response['Regions'])):
regions.append(regions_response['Regions'][i]['RegionName'])
time.sleep(60)
datestamp = time.strftime("%d/%m/%Y %H:%M:%S")
logger.info(f"Deleting Default VPCs. Started at {datestamp} ")
for r in regions:
try:
logger.info(f"Deleting VPCs in [{regions.index(r)+1}/{len(regions)}] aws-regions")
delete_vpc_response = delete_default_vpc(credentials,r)
except botocore.exceptions.ClientError as e:
logger.info("An error occured while deleting Default VPC in {}. Error: {}".format(r,e))
i+=1
#deploy cloudformation template (AccountBaseline.yml)
stack = deploy_resources(credentials, template, stackname, stackregion, ServiceCatalogUserName, ServiceCatalogUserPassword,account_id)
logger.info(stack)
logger.info("Baseline setup deployment for account " + account_id + " (" + accountemail + ") complete!")
response_data = {
"Message": "Account created successfully",
"AccountID" : account_id,
"LoginURL" : "https://" +account_id+".signin.aws.amazon.com/console",
"Username" : ServiceCatalogUserName
}
helper.Data.update(response_data)
except ValueError as e:
response_data = {
"Log_Group_Name" : context.log_group_name,
"Error" : str(e)
}
helper.Data.update(response_data)
raise
def main(event,context):
helper(event,context)
================================================
FILE: resources/AccountCreationLambdaCode/cfnresponse/__init__.py
================================================
# Copyright 2016 Amazon Web Services, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
import urllib3
import json
http = urllib3.PoolManager()
SUCCESS = "SUCCESS"
FAILED = "FAILED"
def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False):
responseUrl = event['ResponseURL']
print(responseUrl)
responseBody = {}
responseBody['Status'] = responseStatus
responseBody['Reason'] = 'See the details in CloudWatch Log Stream: ' + context.log_stream_name
responseBody['PhysicalResourceId'] = physicalResourceId or context.log_stream_name
responseBody['StackId'] = event['StackId']
responseBody['RequestId'] = event['RequestId']
responseBody['LogicalResourceId'] = event['LogicalResourceId']
responseBody['NoEcho'] = noEcho
responseBody['Data'] = responseData
json_responseBody = json.dumps(responseBody)
print("Response body:\n" + json_responseBody)
headers = {
'content-type' : '',
'content-length' : str(len(json_responseBody))
}
try:
response = http.request('PUT',responseUrl,body=json_responseBody.encode('utf-8'),headers=headers)
print("Status code: " + response.reason)
except Exception as e:
print("send(..) failed executing requests.put(..): " + str(e))
================================================
FILE: resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/INSTALLER
================================================
pip
================================================
FILE: resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/METADATA
================================================
Metadata-Version: 2.1
Name: cfnresponse
Version: 1.1.2
Summary: Send a response object to a custom resource by way of an Amazon S3 presigned URL
Home-page: https://github.com/gene1wood/cfnresponse
Author: Amazon Web Services
License: UNKNOWN
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 2
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: urllib3
# cfnresponse
This package contains the Amazon Web Services (AWS) cfnresponse module which is
available in Python AWS Lambda environments.
The code for this module can be found [in the Lambda Function Code documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html#cfn-lambda-function-code-cfnresponsemodule)
and in the [awslabs GitHub repo](https://github.com/awslabs/aws-cloudformation-templates/blob/master/aws/services/CloudFormation/MacrosExamples/StackMetrics/lambda/cfnresponse.py)
You can compare the code in `awslabs` with this pypi package with this command
```
if [ "$(curl -s https://raw.githubusercontent.com/awslabs/aws-cloudformation-templates/master/aws/services/CloudFormation/MacrosExamples/StackMetrics/lambda/cfnresponse.py | sha256sum)" = "$(curl -s https://raw.githubusercontent.com/gene1wood/cfnresponse/master/cfnresponse/__init__.py | sha256sum)" ]; then echo "GitHub matches AWS"; fi
if [ "$(curl -s https://raw.githubusercontent.com/awslabs/aws-cloudformation-templates/master/aws/services/CloudFormation/MacrosExamples/StackMetrics/lambda/cfnresponse.py | sha256sum)" = "$(wget --quiet https://files.pythonhosted.org/packages/91/1c/99d3119ee59205ef321e48ecaf3a3bb92fe6de6d3d5ec296e9025975061c/cfnresponse-1.1.1-py2.py3-none-any.whl && unzip -p cfnresponse-1.1.1-py2.py3-none-any.whl cfnresponse/__init__.py | sha256sum && rm cfnresponse-1.1.1-py2.py3-none-any.whl)" ]; then echo "Pypi matches AWS"; fi
```
This module [used to use the vendored version of `requests`](https://github.com/awslabs/aws-cloudformation-templates/blob/dd484dd32680fcbfc52b34de45923f78b5626e39/aws/services/CloudFormation/MacrosExamples/StackMetrics/lambda/cfnresponse.py)
provided by `botocore` but this changed in
[April 2020](https://github.com/awslabs/aws-cloudformation-templates/commit/44b76a1f694f82eeee14fe804bf9dc973fdc2230#diff-f6c57142d56d8704aaf1d429ff1a06a6dd3f2ee6d80f0572ada8af010ff17124)
to instead use `urllib3` as
[`botocore.vendored.requests` was removed](https://github.com/boto/botocore/pull/1829).
================================================
FILE: resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/RECORD
================================================
cfnresponse-1.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
cfnresponse-1.1.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
cfnresponse-1.1.2.dist-info/METADATA,sha256=zucBfHb5yfdlQapGxyVKyPh4Tn3ARe3V2XOFH0hzq4s,2724
cfnresponse-1.1.2.dist-info/RECORD,,
cfnresponse-1.1.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
cfnresponse-1.1.2.dist-info/WHEEL,sha256=WzZ8cwjh8l0jtULNjYq1Hpr-WCqCRgPr--TX4P5I1Wo,110
cfnresponse-1.1.2.dist-info/top_level.txt,sha256=j9Zq5oZ_a04PdpNkYtZ_QZxzTSGGO7cH3MKnJPdL_EE,12
cfnresponse/__init__.py,sha256=r1W9LnE38no9gV97Sj0_iDrjv6Mj93esERJ9mEoOPKo,1352
cfnresponse/__init__.pyc,,
================================================
FILE: resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/REQUESTED
================================================
================================================
FILE: resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/WHEEL
================================================
Wheel-Version: 1.0
Generator: bdist_wheel (0.37.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any
================================================
FILE: resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/top_level.txt
================================================
cfnresponse
================================================
FILE: resources/AccountCreationLambdaCode/crhelper/__init__.py
================================================
from crhelper.resource_helper import CfnResource, SUCCESS, FAILED
================================================
FILE: resources/AccountCreationLambdaCode/crhelper/__init__.pyi
================================================
"""
*.pyi files are auto-generated with the following commands:
$> pip install mypy
$> stubgen ./crhelper -o .
"""
from crhelper.resource_helper import CfnResource as CfnResource, FAILED as FAILED, SUCCESS as SUCCESS
================================================
FILE: resources/AccountCreationLambdaCode/crhelper/log_helper.py
================================================
from __future__ import print_function
import json
import logging
def _json_formatter(obj):
"""Formatter for unserialisable values."""
return str(obj)
class JsonFormatter(logging.Formatter):
"""AWS Lambda Logging formatter.
Formats the log message as a JSON encoded string. If the message is a
dict it will be used directly. If the message can be parsed as JSON, then
the parse d value is used in the output record.
"""
def __init__(self, **kwargs):
super(JsonFormatter, self).__init__()
self.format_dict = {
'timestamp': '%(asctime)s',
'level': '%(levelname)s',
'location': '%(name)s.%(funcName)s:%(lineno)d',
}
self.format_dict.update(kwargs)
self.default_json_formatter = kwargs.pop(
'json_default', _json_formatter)
def format(self, record):
record_dict = record.__dict__.copy()
record_dict['asctime'] = self.formatTime(record)
log_dict = {
k: v % record_dict
for k, v in self.format_dict.items()
if v
}
if isinstance(record_dict['msg'], dict):
log_dict['message'] = record_dict['msg']
else:
log_dict['message'] = record.getMessage()
# Attempt to decode the message as JSON, if so, merge it with the
# overall message for clarity.
try:
log_dict['message'] = json.loads(log_dict['message'])
except (TypeError, ValueError):
pass
if record.exc_info:
# Cache the traceback text to avoid converting it multiple times
# (it's constant anyway)
# from logging.Formatter:format
if not record.exc_text:
record.exc_text = self.formatException(record.exc_info)
if record.exc_text:
log_dict['exception'] = record.exc_text
json_record = json.dumps(log_dict, default=self.default_json_formatter)
if hasattr(json_record, 'decode'): # pragma: no cover
json_record = json_record.decode('utf-8')
return json_record
def setup(level='DEBUG', formatter_cls=JsonFormatter, boto_level=None, **kwargs):
if formatter_cls:
for handler in logging.root.handlers:
handler.setFormatter(formatter_cls(**kwargs))
logging.root.setLevel(level)
if not boto_level:
boto_level = level
logging.getLogger('boto').setLevel(boto_level)
logging.getLogger('boto3').setLevel(boto_level)
logging.getLogger('botocore').setLevel(boto_level)
logging.getLogger('urllib3').setLevel(boto_level)
================================================
FILE: resources/AccountCreationLambdaCode/crhelper/log_helper.pyi
================================================
import logging
from typing import Any, Optional
class JsonFormatter(logging.Formatter):
format_dict: Any = ...
default_json_formatter: Any = ...
def __init__(self, **kwargs: Any) -> None: ...
def format(self, record: Any): ...
def setup(level: str = ..., formatter_cls: Any = ..., boto_level: Optional[Any] = ..., **kwargs: Any) -> None: ...
================================================
FILE: resources/AccountCreationLambdaCode/crhelper/py.typed
================================================
================================================
FILE: resources/AccountCreationLambdaCode/crhelper/resource_helper.py
================================================
# -*- coding: utf-8 -*-
"""
TODO:
* Async mode – take a wait condition handle as an input, increases max timeout to 12 hours
* Idempotency – If a duplicate request comes in (say there was a network error in signaling back to cfn) the subsequent
request should return the already created response, will need a persistent store of some kind...
* Functional tests
"""
from __future__ import print_function
import threading
from crhelper.utils import _send_response
from crhelper import log_helper
import logging
import random
import boto3
import string
import json
import os
from time import sleep
logger = logging.getLogger(__name__)
SUCCESS = 'SUCCESS'
FAILED = 'FAILED'
class CfnResource(object):
def __init__(self, json_logging=False, log_level='DEBUG', boto_level='ERROR', polling_interval=2, sleep_on_delete=120, ssl_verify=None):
self._sleep_on_delete = sleep_on_delete
self._create_func = None
self._update_func = None
self._delete_func = None
self._poll_create_func = None
self._poll_update_func = None
self._poll_delete_func = None
self._timer = None
self._init_failed = None
self._json_logging = json_logging
self._log_level = log_level
self._boto_level = boto_level
self._send_response = False
self._polling_interval = polling_interval
self.Status = ""
self.Reason = ""
self.PhysicalResourceId = ""
self.StackId = ""
self.RequestId = ""
self.LogicalResourceId = ""
self.Data = {}
self.NoEcho = False
self._event = {}
self._context = None
self._response_url = ""
self._sam_local = os.getenv('AWS_SAM_LOCAL')
self._region = os.getenv('AWS_REGION')
self._ssl_verify = ssl_verify
try:
if not self._sam_local:
self._lambda_client = boto3.client('lambda', region_name=self._region, verify=self._ssl_verify)
self._events_client = boto3.client('events', region_name=self._region, verify=self._ssl_verify)
self._logs_client = boto3.client('logs', region_name=self._region, verify=self._ssl_verify)
if json_logging:
log_helper.setup(log_level, boto_level=boto_level, RequestType='ContainerInit')
else:
log_helper.setup(log_level, formatter_cls=None, boto_level=boto_level)
except Exception as e:
logger.error(e, exc_info=True)
self.init_failure(e)
def __call__(self, event, context):
try:
self._log_setup(event, context)
logger.debug(event)
if not self._crhelper_init(event, context):
return
# Check for polling functions
if self._poll_enabled() and self._sam_local:
logger.info("Skipping poller functionality, as this is a local invocation")
elif self._poll_enabled():
self._polling_init(event)
# If polling is not enabled, then we should respond
else:
logger.debug("enabling send_response")
self._send_response = True
logger.debug("_send_response: %s" % self._send_response)
if self._send_response:
if self.RequestType == 'Delete':
self._wait_for_cwlogs()
self._cfn_response(event)
except Exception as e:
logger.error(e, exc_info=True)
self._send(FAILED, str(e))
finally:
if self._timer:
self._timer.cancel()
def _wait_for_cwlogs(self, sleep=sleep):
time_left = int(self._context.get_remaining_time_in_millis() / 1000) - 15
sleep_time = 0
if time_left > self._sleep_on_delete:
sleep_time = self._sleep_on_delete
if sleep_time > 1:
sleep(sleep_time)
def _log_setup(self, event, context):
if self._json_logging:
log_helper.setup(self._log_level, boto_level=self._boto_level, RequestType=event['RequestType'],
StackId=event['StackId'], RequestId=event['RequestId'],
LogicalResourceId=event['LogicalResourceId'], aws_request_id=context.aws_request_id)
else:
log_helper.setup(self._log_level, boto_level=self._boto_level, formatter_cls=None)
def _crhelper_init(self, event, context):
self._send_response = False
self.Status = SUCCESS
self.Reason = ""
self.PhysicalResourceId = ""
self.StackId = event["StackId"]
self.RequestId = event["RequestId"]
self.LogicalResourceId = event["LogicalResourceId"]
self.Data = {}
if "CrHelperData" in event.keys():
self.Data = event["CrHelperData"]
self.RequestType = event["RequestType"]
self._event = event
self._context = context
self._response_url = event['ResponseURL']
if self._timer:
self._timer.cancel()
if self._init_failed:
self._send(FAILED, str(self._init_failed))
return False
self._set_timeout()
self._wrap_function(self._get_func())
return True
def _polling_init(self, event):
# Setup polling on initial request
logger.debug("pid1: %s" % self.PhysicalResourceId)
if 'CrHelperPoll' not in event.keys() and self.Status != FAILED:
logger.info("Setting up polling")
self.Data["PhysicalResourceId"] = self.PhysicalResourceId
self._setup_polling()
self.PhysicalResourceId = None
logger.debug("pid2: %s" % self.PhysicalResourceId)
# if physical id is set, or there was a failure then we're done
logger.debug("pid3: %s" % self.PhysicalResourceId)
if self.PhysicalResourceId or self.Status == FAILED:
logger.info("Polling complete, removing cwe schedule")
self._remove_polling()
self._send_response = True
def generate_physical_id(self, event):
return '_'.join([
event['StackId'].split('/')[1],
event['LogicalResourceId'],
self._rand_string(8)
])
def _cfn_response(self, event):
# Use existing PhysicalResourceId if it's in the event and no ID was set
if not self.PhysicalResourceId and "PhysicalResourceId" in event.keys():
logger.info("PhysicalResourceId present in event, Using that for response")
self.PhysicalResourceId = event['PhysicalResourceId']
# Generate a physical id if none is provided
elif not self.PhysicalResourceId or self.PhysicalResourceId is True:
logger.info("No physical resource id returned, generating one...")
self.PhysicalResourceId = self.generate_physical_id(event)
self._send()
def _poll_enabled(self):
return getattr(self, "_poll_{}_func".format(self._event['RequestType'].lower()))
def create(self, func):
self._create_func = func
return func
def update(self, func):
self._update_func = func
return func
def delete(self, func):
self._delete_func = func
return func
def poll_create(self, func):
self._poll_create_func = func
return func
def poll_update(self, func):
self._poll_update_func = func
return func
def poll_delete(self, func):
self._poll_delete_func = func
return func
def _wrap_function(self, func):
try:
self.PhysicalResourceId = func(self._event, self._context) if func else ''
except Exception as e:
logger.error(str(e), exc_info=True)
self.Reason = str(e)
self.Status = FAILED
def _timeout(self):
logger.error("Execution is about to time out, sending failure message")
self._send(FAILED, "Execution timed out")
def _set_timeout(self):
self._timer = threading.Timer((self._context.get_remaining_time_in_millis() / 1000.00) - 0.5,
self._timeout)
self._timer.start()
def _get_func(self):
request_type = "_{}_func"
if "CrHelperPoll" in self._event.keys():
request_type = "_poll" + request_type
return getattr(self, request_type.format(self._event['RequestType'].lower()))
def _send(self, status=None, reason="", send_response=_send_response):
if len(str(str(self.Reason))) > 256:
self.Reason = "ERROR: (truncated) " + str(self.Reason)[len(str(self.Reason)) - 240:]
if len(str(reason)) > 256:
reason = "ERROR: (truncated) " + str(reason)[len(str(reason)) - 240:]
response_body = {
'Status': self.Status,
'PhysicalResourceId': str(self.PhysicalResourceId),
'StackId': self.StackId,
'RequestId': self.RequestId,
'LogicalResourceId': self.LogicalResourceId,
'Reason': str(self.Reason),
'Data': self.Data,
'NoEcho': self.NoEcho,
}
if status:
response_body.update({'Status': status, 'Reason': reason})
send_response(self._response_url, response_body, self._ssl_verify)
def init_failure(self, error):
self._init_failed = error
logger.error(str(error), exc_info=True)
def _cleanup_response(self):
for k in ["CrHelperPoll", "CrHelperPermission", "CrHelperRule"]:
if k in self.Data.keys():
del self.Data[k]
@staticmethod
def _rand_string(l):
return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(l))
def _add_permission(self, rule_arn):
sid = self._event['LogicalResourceId'] + self._rand_string(8)
self._lambda_client.add_permission(
FunctionName=self._context.function_name,
StatementId=sid,
Action='lambda:InvokeFunction',
Principal='events.amazonaws.com',
SourceArn=rule_arn
)
return sid
def _put_rule(self):
schedule_unit = 'minutes' if self._polling_interval != 1 else 'minute'
response = self._events_client.put_rule(
Name=self._event['LogicalResourceId'] + self._rand_string(8),
ScheduleExpression='rate({} {})'.format(self._polling_interval, schedule_unit),
State='ENABLED',
)
return response["RuleArn"]
def _put_targets(self, func_name):
region = self._event['CrHelperRule'].split(":")[3]
account_id = self._event['CrHelperRule'].split(":")[4]
partition = self._event['CrHelperRule'].split(":")[1]
rule_name = self._event['CrHelperRule'].split("/")[1]
logger.debug(self._event)
self._events_client.put_targets(
Rule=rule_name,
Targets=[
{
'Id': '1',
'Arn': 'arn:%s:lambda:%s:%s:function:%s' % (partition, region, account_id, func_name),
'Input': json.dumps(self._event)
}
]
)
def _remove_targets(self, rule_arn):
self._events_client.remove_targets(
Rule=rule_arn.split("/")[1],
Ids=['1']
)
def _remove_permission(self, sid):
self._lambda_client.remove_permission(
FunctionName=self._context.function_name,
StatementId=sid
)
def _delete_rule(self, rule_arn):
self._events_client.delete_rule(
Name=rule_arn.split("/")[1]
)
def _setup_polling(self):
self._event['CrHelperData'] = self.Data
self._event['CrHelperPoll'] = True
self._event['CrHelperRule'] = self._put_rule()
self._event['CrHelperPermission'] = self._add_permission(self._event['CrHelperRule'])
self._put_targets(self._context.function_name)
def _remove_polling(self):
if 'CrHelperData' in self._event.keys():
self._event.pop('CrHelperData')
if "PhysicalResourceId" in self.Data.keys():
self.Data.pop("PhysicalResourceId")
if 'CrHelperRule' in self._event.keys():
self._remove_targets(self._event['CrHelperRule'])
else:
logger.error("Cannot remove CloudWatch events rule, Rule arn not available in event")
if 'CrHelperPermission' in self._event.keys():
self._remove_permission(self._event['CrHelperPermission'])
else:
logger.error("Cannot remove lambda events permission, permission id not available in event")
if 'CrHelperRule' in self._event.keys():
self._delete_rule(self._event['CrHelperRule'])
else:
logger.error("Cannot remove CloudWatch events target, Rule arn not available in event")
================================================
FILE: resources/AccountCreationLambdaCode/crhelper/resource_helper.pyi
================================================
from crhelper import log_helper as log_helper
from typing import Any, Callable, Optional, Union
logger: Any
SUCCESS: str
FAILED: str
_DecoratorTypeDef = Callable[[Any, Any], Union[bool, str, None]]
class CfnResource:
Status: str = ...
Reason: str = ...
PhysicalResourceId: str = ...
StackId: str = ...
RequestId: str = ...
LogicalResourceId: str = ...
Data: Any = ...
NoEcho: bool = ...
def __init__(self, json_logging: bool = ..., log_level: str = ..., boto_level: str = ..., polling_interval: int = ..., sleep_on_delete: int = ..., ssl_verify: Optional[bool] = ...) -> None: ...
def __call__(self, event: Any, context: Any) -> None: ...
def generate_physical_id(self, event: Any): ...
def create(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
def update(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
def delete(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
def poll_create(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
def poll_update(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
def poll_delete(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
def init_failure(self, error: Any) -> None: ...
================================================
FILE: resources/AccountCreationLambdaCode/crhelper/utils.py
================================================
from __future__ import print_function
import json
import logging as logging
import ssl
import time
from http.client import HTTPSConnection
from os import path
from typing import Union, AnyStr
from urllib.parse import urlsplit, urlunsplit
logger = logging.getLogger(__name__)
def _send_response(response_url: AnyStr, response_body: AnyStr, ssl_verify: Union[bool, AnyStr] = None):
try:
json_response_body = json.dumps(response_body)
except Exception as e:
msg = "Failed to convert response to json: {}".format(str(e))
logger.error(msg, exc_info=True)
response_body = {'Status': 'FAILED', 'Data': {}, 'Reason': msg}
json_response_body = json.dumps(response_body)
logger.debug("CFN response URL: {}".format(response_url))
logger.debug(json_response_body)
headers = {'content-type': '', 'content-length': str(len(json_response_body))}
split_url = urlsplit(response_url)
host = split_url.netloc
url = urlunsplit(("", "", *split_url[2:]))
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
if isinstance(ssl_verify, str):
if path.exists(ssl_verify):
ctx.load_verify_locations(cafile=ssl_verify)
else:
logger.warning("Cert path {0} does not exist!. Falling back to using system cafile.".format(ssl_verify))
if ssl_verify is False:
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
# If ssl_verify is True or None dont modify the context in any way.
while True:
try:
connection = HTTPSConnection(host, context=ctx)
connection.request(method="PUT", url=url, body=json_response_body, headers=headers)
response = connection.getresponse()
logger.info("CloudFormation returned status code: {}".format(response.reason))
break
except Exception as e:
logger.error("Unexpected failure sending response to CloudFormation {}".format(e), exc_info=True)
time.sleep(5)
================================================
FILE: resources/AccountCreationLambdaCode/crhelper/utils.pyi
================================================
from typing import Any
logger: Any
================================================
FILE: resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/PKG-INFO
================================================
Metadata-Version: 2.1
Name: crhelper
Version: 2.0.11
Summary: crhelper simplifies authoring CloudFormation Custom Resources
Home-page: https://github.com/aws-cloudformation/custom-resource-helper
Author: Jay McConnell
Author-email: jmmccon@amazon.com
License: Apache2
Description: ## Custom Resource Helper
Simplify best practice Custom Resource creation, sending responses to CloudFormation and providing exception, timeout
trapping, and detailed configurable logging.
[](https://pypi.org/project/crhelper/)

[](https://travis-ci.com/aws-cloudformation/custom-resource-helper)
[](https://codecov.io/gh/aws-cloudformation/custom-resource-helper)
## Features
* Dead simple to use, reduces the complexity of writing a CloudFormation custom resource
* Guarantees that CloudFormation will get a response even if an exception is raised
* Returns meaningful errors to CloudFormation Stack events in the case of a failure
* Polling enables run times longer than the lambda 15 minute limit
* JSON logging that includes request id's, stack id's and request type to assist in tracing logs relevant to a
particular CloudFormation event
* Catches function timeouts and sends CloudFormation a failure response
* Static typing (mypy) compatible
## Installation
Install into the root folder of your lambda function
```shell
cd my-lambda-function/
pip install crhelper -t .
```
## Example Usage
[This blog](https://aws.amazon.com/blogs/infrastructure-and-automation/aws-cloudformation-custom-resource-creation-with-python-aws-lambda-and-crhelper/) covers usage in more detail.
```python
from __future__ import print_function
from crhelper import CfnResource
import logging
logger = logging.getLogger(__name__)
# Initialise the helper, all inputs are optional, this example shows the defaults
helper = CfnResource(json_logging=False, log_level='DEBUG', boto_level='CRITICAL', sleep_on_delete=120, ssl_verify=None)
try:
## Init code goes here
pass
except Exception as e:
helper.init_failure(e)
@helper.create
def create(event, context):
logger.info("Got Create")
# Optionally return an ID that will be used for the resource PhysicalResourceId,
# if None is returned an ID will be generated. If a poll_create function is defined
# return value is placed into the poll event as event['CrHelperData']['PhysicalResourceId']
#
# To add response data update the helper.Data dict
# If poll is enabled data is placed into poll event as event['CrHelperData']
helper.Data.update({"test": "testdata"})
# To return an error to cloudformation you raise an exception:
if not helper.Data.get("test"):
raise ValueError("this error will show in the cloudformation events log and console.")
return "MyResourceId"
@helper.update
def update(event, context):
logger.info("Got Update")
# If the update resulted in a new resource being created, return an id for the new resource.
# CloudFormation will send a delete event with the old id when stack update completes
@helper.delete
def delete(event, context):
logger.info("Got Delete")
# Delete never returns anything. Should not fail if the underlying resources are already deleted.
# Desired state.
@helper.poll_create
def poll_create(event, context):
logger.info("Got create poll")
# Return a resource id or True to indicate that creation is complete. if True is returned an id
# will be generated
return True
def handler(event, context):
helper(event, context)
```
### Polling
If you need longer than the max runtime of 15 minutes, you can enable polling by adding additional decorators for
`poll_create`, `poll_update` or `poll_delete`. When a poll function is defined for `create`/`update`/`delete` the
function will not send a response to CloudFormation and instead a CloudWatch Events schedule will be created to
re-invoke the lambda function every 2 minutes. When the function is invoked the matching `@helper.poll_` function will
be called, logic to check for completion should go here, if the function returns `None` then the schedule will run again
in 2 minutes. Once complete either return a PhysicalResourceID or `True` to have one generated. The schedule will be
deleted and a response sent back to CloudFormation. If you use polling the following additional IAM policy must be
attached to the function's IAM role:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:AddPermission",
"lambda:RemovePermission",
"events:PutRule",
"events:DeleteRule",
"events:PutTargets",
"events:RemoveTargets"
],
"Resource": "*"
}
]
}
```
### Certificate Verification
To turn off certification verification, or to use a custom CA bundle path for the underlying boto3 clients used by this library, override the `ssl_verify` argument with the appropriate values. These can be either:
* `False` - do not validate SSL certificates. SSL will still be used, but SSL certificates will not be verified.
* `path/to/cert/bundle.pem` - A filename of the CA cert bundle to uses. You can specify this argument if you want to use a different CA cert bundle than the one used by botocore.
## Credits
Decorator implementation inspired by https://github.com/ryansb/cfn-wrapper-python
Log implementation inspired by https://gitlab.com/hadrien/aws_lambda_logging
## License
This library is licensed under the Apache 2.0 License.
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Description-Content-Type: text/markdown
================================================
FILE: resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/SOURCES.txt
================================================
LICENSE
NOTICE
README.md
setup.cfg
setup.py
crhelper/__init__.py
crhelper/__init__.pyi
crhelper/log_helper.py
crhelper/log_helper.pyi
crhelper/py.typed
crhelper/resource_helper.py
crhelper/resource_helper.pyi
crhelper/utils.py
crhelper/utils.pyi
crhelper.egg-info/PKG-INFO
crhelper.egg-info/SOURCES.txt
crhelper.egg-info/dependency_links.txt
crhelper.egg-info/top_level.txt
================================================
FILE: resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/dependency_links.txt
================================================
================================================
FILE: resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/installed-files.txt
================================================
../crhelper/__init__.py
../crhelper/__init__.pyc
../crhelper/__init__.pyi
../crhelper/log_helper.py
../crhelper/log_helper.pyc
../crhelper/log_helper.pyi
../crhelper/py.typed
../crhelper/resource_helper.py
../crhelper/resource_helper.pyc
../crhelper/resource_helper.pyi
../crhelper/utils.py
../crhelper/utils.pyc
../crhelper/utils.pyi
PKG-INFO
SOURCES.txt
dependency_links.txt
top_level.txt
================================================
FILE: resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/top_level.txt
================================================
crhelper
================================================
FILE: resources/AccountCreationLambdaCode/urllib3/__init__.py
================================================
"""
Python HTTP library with thread-safe connection pooling, file post support, user friendly, and more
"""
from __future__ import absolute_import
# Set default logging handler to avoid "No handler found" warnings.
import logging
import warnings
from logging import NullHandler
from . import exceptions
from ._version import __version__
from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url
from .filepost import encode_multipart_formdata
from .poolmanager import PoolManager, ProxyManager, proxy_from_url
from .response import HTTPResponse
from .util.request import make_headers
from .util.retry import Retry
from .util.timeout import Timeout
from .util.url import get_host
# === NOTE TO REPACKAGERS AND VENDORS ===
# Please delete this block, this logic is only
# for urllib3 being distributed via PyPI.
# See: https://github.com/urllib3/urllib3/issues/2680
try:
import urllib3_secure_extra # type: ignore # noqa: F401
except ImportError:
pass
else:
warnings.warn(
"'urllib3[secure]' extra is deprecated and will be removed "
"in a future release of urllib3 2.x. Read more in this issue: "
"https://github.com/urllib3/urllib3/issues/2680",
category=DeprecationWarning,
stacklevel=2,
)
__author__ = "Andrey Petrov (andrey.petrov@shazow.net)"
__license__ = "MIT"
__version__ = __version__
__all__ = (
"HTTPConnectionPool",
"HTTPSConnectionPool",
"PoolManager",
"ProxyManager",
"HTTPResponse",
"Retry",
"Timeout",
"add_stderr_logger",
"connection_from_url",
"disable_warnings",
"encode_multipart_formdata",
"get_host",
"make_headers",
"proxy_from_url",
)
logging.getLogger(__name__).addHandler(NullHandler())
def add_stderr_logger(level=logging.DEBUG):
"""
Helper for quickly adding a StreamHandler to the logger. Useful for
debugging.
Returns the handler after adding it.
"""
# This method needs to be in this __init__.py to get the __name__ correct
# even if urllib3 is vendored within another package.
logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s"))
logger.addHandler(handler)
logger.setLevel(level)
logger.debug("Added a stderr logging handler to logger: %s", __name__)
return handler
# ... Clean up.
del NullHandler
# All warning filters *must* be appended unless you're really certain that they
# shouldn't be: otherwise, it's very hard for users to use most Python
# mechanisms to silence them.
# SecurityWarning's always go off by default.
warnings.simplefilter("always", exceptions.SecurityWarning, append=True)
# SubjectAltNameWarning's should go off once per host
warnings.simplefilter("default", exceptions.SubjectAltNameWarning, append=True)
# InsecurePlatformWarning's don't vary between requests, so we keep it default.
warnings.simplefilter("default", exceptions.InsecurePlatformWarning, append=True)
# SNIMissingWarnings should go off only once.
warnings.simplefilter("default", exceptions.SNIMissingWarning, append=True)
def disable_warnings(category=exceptions.HTTPWarning):
"""
Helper for quickly disabling all urllib3 warnings.
"""
warnings.simplefilter("ignore", category)
================================================
FILE: resources/AccountCreationLambdaCode/urllib3/_collections.py
================================================
from __future__ import absolute_import
try:
from collections.abc import Mapping, MutableMapping
except ImportError:
from collections import Mapping, MutableMapping
try:
from threading import RLock
except ImportError: # Platform-specific: No threads available
class RLock:
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
pass
from collections import OrderedDict
from .exceptions import InvalidHeader
from .packages import six
from .packages.six import iterkeys, itervalues
__all__ = ["RecentlyUsedContainer", "HTTPHeaderDict"]
_Null = object()
class RecentlyUsedContainer(MutableMapping):
"""
Provides a thread-safe dict-like container which maintains up to
``maxsize`` keys while throwing away the least-recently-used keys beyond
``maxsize``.
:param maxsize:
Maximum number of recent elements to retain.
:param dispose_func:
Every time an item is evicted from the container,
``dispose_func(value)`` is called. Callback which will get called
"""
ContainerCls = OrderedDict
def __init__(self, maxsize=10, dispose_func=None):
self._maxsize = maxsize
self.dispose_func = dispose_func
self._container = self.ContainerCls()
self.lock = RLock()
def __getitem__(self, key):
# Re-insert the item, moving it to the end of the eviction line.
with self.lock:
item = self._container.pop(key)
self._container[key] = item
return item
def __setitem__(self, key, value):
evicted_value = _Null
with self.lock:
# Possibly evict the existing value of 'key'
evicted_value = self._container.get(key, _Null)
self._container[key] = value
# If we didn't evict an existing value, we might have to evict the
# least recently used item from the beginning of the container.
if len(self._container) > self._maxsize:
_key, evicted_value = self._container.popitem(last=False)
if self.dispose_func and evicted_value is not _Null:
self.dispose_func(evicted_value)
def __delitem__(self, key):
with self.lock:
value = self._container.pop(key)
if self.dispose_func:
self.dispose_func(value)
def __len__(self):
with self.lock:
return len(self._container)
def __iter__(self):
raise NotImplementedError(
"Iteration over this class is unlikely to be threadsafe."
)
def clear(self):
with self.lock:
# Copy pointers to all values, then wipe the mapping
values = list(itervalues(self._container))
self._container.clear()
if self.dispose_func:
for value in values:
self.dispose_func(value)
def keys(self):
with self.lock:
return list(iterkeys(self._container))
class HTTPHeaderDict(MutableMapping):
"""
:param headers:
An iterable of field-value pairs. Must not contain multiple field names
when compared case-insensitively.
:param kwargs:
Additional field-value pairs to pass in to ``dict.update``.
A ``dict`` like container for storing HTTP Headers.
Field names are stored and compared case-insensitively in compliance with
RFC 7230. Iteration provides the first case-sensitive key seen for each
case-insensitive pair.
Using ``__setitem__`` syntax overwrites fields that compare equal
case-insensitively in order to maintain ``dict``'s api. For fields that
compare equal, instead create a new ``HTTPHeaderDict`` and use ``.add``
in a loop.
If multiple fields that are equal case-insensitively are passed to the
constructor or ``.update``, the behavior is undefined and some will be
lost.
>>> headers = HTTPHeaderDict()
>>> headers.add('Set-Cookie', 'foo=bar')
>>> headers.add('set-cookie', 'baz=quxx')
>>> headers['content-length'] = '7'
>>> headers['SET-cookie']
'foo=bar, baz=quxx'
>>> headers['Content-Length']
'7'
"""
def __init__(self, headers=None, **kwargs):
super(HTTPHeaderDict, self).__init__()
self._container = OrderedDict()
if headers is not None:
if isinstance(headers, HTTPHeaderDict):
self._copy_from(headers)
else:
self.extend(headers)
if kwargs:
self.extend(kwargs)
def __setitem__(self, key, val):
self._container[key.lower()] = [key, val]
return self._container[key.lower()]
def __getitem__(self, key):
val = self._container[key.lower()]
return ", ".join(val[1:])
def __delitem__(self, key):
del self._container[key.lower()]
def __contains__(self, key):
return key.lower() in self._container
def __eq__(self, other):
if not isinstance(other, Mapping) and not hasattr(other, "keys"):
return False
if not isinstance(other, type(self)):
other = type(self)(other)
return dict((k.lower(), v) for k, v in self.itermerged()) == dict(
(k.lower(), v) for k, v in other.itermerged()
)
def __ne__(self, other):
return not self.__eq__(other)
if six.PY2: # Python 2
iterkeys = MutableMapping.iterkeys
itervalues = MutableMapping.itervalues
__marker = object()
def __len__(self):
return len(self._container)
def __iter__(self):
# Only provide the originally cased names
for vals in self._container.values():
yield vals[0]
def pop(self, key, default=__marker):
"""D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
If key is not found, d is returned if given, otherwise KeyError is raised.
"""
# Using the MutableMapping function directly fails due to the private marker.
# Using ordinary dict.pop would expose the internal structures.
# So let's reinvent the wheel.
try:
value = self[key]
except KeyError:
if default is self.__marker:
raise
return default
else:
del self[key]
return value
def discard(self, key):
try:
del self[key]
except KeyError:
pass
def add(self, key, val):
"""Adds a (name, value) pair, doesn't overwrite the value if it already
exists.
>>> headers = HTTPHeaderDict(foo='bar')
>>> headers.add('Foo', 'baz')
>>> headers['foo']
'bar, baz'
"""
key_lower = key.lower()
new_vals = [key, val]
# Keep the common case aka no item present as fast as possible
vals = self._container.setdefault(key_lower, new_vals)
if new_vals is not vals:
vals.append(val)
def extend(self, *args, **kwargs):
"""Generic import function for any type of header-like object.
Adapted version of MutableMapping.update in order to insert items
with self.add instead of self.__setitem__
"""
if len(args) > 1:
raise TypeError(
"extend() takes at most 1 positional "
"arguments ({0} given)".format(len(args))
)
other = args[0] if len(args) >= 1 else ()
if isinstance(other, HTTPHeaderDict):
for key, val in other.iteritems():
self.add(key, val)
elif isinstance(other, Mapping):
for key in other:
self.add(key, other[key])
elif hasattr(other, "keys"):
for key in other.keys():
self.add(key, other[key])
else:
for key, value in other:
self.add(key, value)
for key, value in kwargs.items():
self.add(key, value)
def getlist(self, key, default=__marker):
"""Returns a list of all the values for the named field. Returns an
empty list if the key doesn't exist."""
try:
vals = self._container[key.lower()]
except KeyError:
if default is self.__marker:
return []
return default
else:
return vals[1:]
# Backwards compatibility for httplib
getheaders = getlist
getallmatchingheaders = getlist
iget = getlist
# Backwards compatibility for http.cookiejar
get_all = getlist
def __repr__(self):
return "%s(%s)" % (type(self).__name__, dict(self.itermerged()))
def _copy_from(self, other):
for key in other:
val = other.getlist(key)
if isinstance(val, list):
# Don't need to convert tuples
val = list(val)
self._container[key.lower()] = [key] + val
def copy(self):
clone = type(self)()
clone._copy_from(self)
return clone
def iteritems(self):
"""Iterate over all header lines, including duplicate ones."""
for key in self:
vals = self._container[key.lower()]
for val in vals[1:]:
yield vals[0], val
def itermerged(self):
"""Iterate over all headers, merging duplicate ones together."""
for key in self:
val = self._container[key.lower()]
yield val[0], ", ".join(val[1:])
def items(self):
return list(self.iteritems())
@classmethod
def from_httplib(cls, message): # Python 2
"""Read headers from a Python 2 httplib message object."""
# python2.7 does not expose a proper API for exporting multiheaders
# efficiently. This function re-reads raw lines from the message
# object and extracts the multiheaders properly.
obs_fold_continued_leaders = (" ", "\t")
headers = []
for line in message.headers:
if line.startswith(obs_fold_continued_leaders):
if not headers:
# We received a header line that starts with OWS as described
# in RFC-7230 S3.2.4. This indicates a multiline header, but
# there exists no previous header to which we can attach it.
raise InvalidHeader(
"Header continuation with no previous header: %s" % line
)
else:
key, value = headers[-1]
headers[-1] = (key, value + " " + line.strip())
continue
key, value = line.split(":", 1)
headers.append((key, value.strip()))
return cls(headers)
================================================
FILE: resources/AccountCreationLambdaCode/urllib3/_version.py
================================================
# This file is protected via CODEOWNERS
__version__ = "1.26.15"
================================================
FILE: resources/AccountCreationLambdaCode/urllib3/connection.py
================================================
from __future__ import absolute_import
import datetime
import logging
import os
import re
import socket
import warnings
from socket import error as SocketError
from socket import timeout as SocketTimeout
from .packages import six
from .packages.six.moves.http_client import HTTPConnection as _HTTPConnection
from .packages.six.moves.http_client import HTTPException # noqa: F401
from .util.proxy import create_proxy_ssl_context
try: # Compiled with SSL?
import ssl
BaseSSLError = ssl.SSLError
except (ImportError, AttributeError): # Platform-specific: No SSL.
ssl = None
class BaseSSLError(BaseException):
pass
try:
# Python 3: not a no-op, we're adding this to the namespace so it can be imported.
ConnectionError = ConnectionError
except NameError:
# Python 2
class ConnectionError(Exception):
pass
try: # Python 3:
# Not a no-op, we're adding this to the namespace so it can be imported.
BrokenPipeError = BrokenPipeError
except NameError: # Python 2:
class BrokenPipeError(Exception):
pass
from ._collections import HTTPHeaderDict # noqa (historical, removed in v2)
from ._version import __version__
from .exceptions import (
ConnectTimeoutError,
NewConnectionError,
SubjectAltNameWarning,
SystemTimeWarning,
)
from .util import SKIP_HEADER, SKIPPABLE_HEADERS, connection
from .util.ssl_ import (
assert_fingerprint,
create_urllib3_context,
is_ipaddress,
resolve_cert_reqs,
resolve_ssl_version,
ssl_wrap_socket,
)
from .util.ssl_match_hostname import CertificateError, match_hostname
log = logging.getLogger(__name__)
port_by_scheme = {"http": 80, "https": 443}
# When it comes time to update this value as a part of regular maintenance
# (ie test_recent_date is failing) update it to ~6 months before the current date.
RECENT_DATE = datetime.date(2022, 1, 1)
_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]")
class HTTPConnection(_HTTPConnection, object):
"""
Based on :class:`http.client.HTTPConnection` but provides an extra constructor
backwards-compatibility layer between older and newer Pythons.
Additional keyword parameters are used to configure attributes of the connection.
Accepted parameters include:
- ``strict``: See the documentation on :class:`urllib3.connectionpool.HTTPConnectionPool`
- ``source_address``: Set the source address for the current connection.
- ``socket_options``: Set specific options on the underlying socket. If not specified, then
defaults are loaded from ``HTTPConnection.default_socket_options`` which includes disabling
Nagle's algorithm (sets TCP_NODELAY to 1) unless the connection is behind a proxy.
For example, if you wish to enable TCP Keep Alive in addition to the defaults,
you might pass:
.. code-block:: python
HTTPConnection.default_socket_options + [
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
]
Or you may want to disable the defaults by passing an empty list (e.g., ``[]``).
"""
default_port = port_by_scheme["http"]
#: Disable Nagle's algorithm by default.
#: ``[(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]``
default_socket_options = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]
#: Whether this connection verifies the host's certificate.
is_verified = False
#: Whether this proxy connection (if used) verifies the proxy host's
#: certificate.
proxy_is_verified = None
def __init__(self, *args, **kw):
if not six.PY2:
kw.pop("strict", None)
# Pre-set source_address.
self.source_address = kw.get("source_address")
#: The socket options provided by the user. If no options are
#: provided, we use the default options.
self.socket_options = kw.pop("socket_options", self.default_socket_options)
# Proxy options provided by the user.
self.proxy = kw.pop("proxy", None)
self.proxy_config = kw.pop("proxy_config", None)
_HTTPConnection.__init__(self, *args, **kw)
@property
def host(self):
"""
Getter method to remove any trailing dots that indicate the hostname is an FQDN.
In general, SSL certificates don't include the trailing dot indicating a
fully-qualified domain name, and thus, they don't validate properly when
checked against a domain name that includes the dot. In addition, some
servers may not expect to receive the trailing dot when provided.
However, the hostname with trailing dot is critical to DNS resolution; doing a
lookup with the trailing dot will properly only resolve the appropriate FQDN,
whereas a lookup without a trailing dot will search the system's search domain
list. Thus, it's important to keep the original host around for use only in
those cases where it's appropriate (i.e., when doing DNS lookup to establish the
actual TCP connection across which we're going to send HTTP requests).
"""
return self._dns_host.rstrip(".")
@host.setter
def host(self, value):
"""
Setter for the `host` property.
We assume that only urllib3 uses the _dns_host attribute; httplib itself
only uses `host`, and it seems reasonable that other libraries follow suit.
"""
self._dns_host = value
def _new_conn(self):
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
extra_kw = {}
if self.source_address:
extra_kw["source_address"] = self.source_address
if self.socket_options:
extra_kw["socket_options"] = self.socket_options
try:
conn = connection.create_connection(
(self._dns_host, self.port), self.timeout, **extra_kw
)
except SocketTimeout:
raise ConnectTimeoutError(
self,
"Connection to %s timed out. (connect timeout=%s)"
% (self.host, self.timeout),
)
except SocketError as e:
raise NewConnectionError(
self, "Failed to establish a new connection: %s" % e
)
return conn
def _is_using_tunnel(self):
# Google App Engine's httplib does not define _tunnel_host
return getattr(self, "_tunnel_host", None)
def _prepare_conn(self, conn):
self.sock = conn
if self._is_using_tunnel():
# TODO: Fix tunnel so it doesn't depend on self.sock state.
self._tunnel()
# Mark this connection as not reusable
self.auto_open = 0
def connect(self):
conn = self._new_conn()
self._prepare_conn(conn)
def putrequest(self, method, url, *args, **kwargs):
""" """
# Empty docstring because the indentation of CPython's implementation
# is broken but we don't want this method in our documentation.
match = _CONTAINS_CONTROL_CHAR_RE.search(method)
if match:
raise ValueError(
"Method cannot contain non-token characters %r (found at least %r)"
% (method, match.group())
)
return _HTTPConnection.putrequest(self, method, url, *args, **kwargs)
def putheader(self, header, *values):
""" """
if not any(isinstance(v, str) and v == SKIP_HEADER for v in values):
_HTTPConnection.putheader(self, header, *values)
elif six.ensure_str(header.lower()) not in SKIPPABLE_HEADERS:
raise ValueError(
"urllib3.util.SKIP_HEADER only supports '%s'"
% ("', '".join(map(str.title, sorted(SKIPPABLE_HEADERS))),)
)
def request(self, method, url, body=None, headers=None):
# Update the inner socket's timeout value to send the request.
# This only triggers if the connection is re-used.
if getattr(self, "sock", None) is not None:
self.sock.settimeout(self.timeout)
if headers is None:
headers = {}
else:
# Avoid modifying the headers passed into .request()
headers = headers.copy()
if "user-agent" not in (six.ensure_str(k.lower()) for k in headers):
headers["User-Agent"] = _get_default_user_agent()
super(HTTPConnection, self).request(method, url, body=body, headers=headers)
def request_chunked(self, method, url, body=None, headers=None):
"""
Alternative to the common request method, which sends the
body with chunked encoding and not as one block
"""
headers = headers or {}
header_keys = set([six.ensure_str(k.lower()) for k in headers])
skip_accept_encoding = "accept-encoding" in header_keys
skip_host = "host" in header_keys
self.putrequest(
method, url, skip_accept_encoding=skip_accept_encoding, skip_host=skip_host
)
if "user-agent" not in header_keys:
self.putheader("User-Agent", _get_default_user_agent())
for header, value in headers.items():
self.putheader(header, value)
if "transfer-encoding" not in header_keys:
self.putheader("Transfer-Encoding", "chunked")
self.endheaders()
if body is not None:
stringish_types = six.string_types + (bytes,)
if isinstance(body, stringish_types):
body = (body,)
for chunk in body:
if not chunk:
continue
if not isinstance(chunk, bytes):
chunk = chunk.encode("utf8")
len_str = hex(len(chunk))[2:]
to_send = bytearray(len_str.encode())
to_send += b"\r\n"
to_send += chunk
to_send += b"\r\n"
self.send(to_send)
# After the if clause, to always have a closed body
self.send(b"0\r\n\r\n")
class HTTPSConnection(HTTPConnection):
"""
Many of the parameters to this constructor are passed to the underlying SSL
socket by means of :py:func:`urllib3.util.ssl_wrap_socket`.
"""
default_port = port_by_scheme["https"]
cert_reqs = None
ca_certs = None
ca_cert_dir = None
ca_cert_data = None
ssl_version = None
assert_fingerprint = None
tls_in_tls_required = False
def __init__(
self,
host,
port=None,
key_file=None,
cert_file=None,
key_password=None,
strict=None,
timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
ssl_context=None,
server_hostname=None,
**kw
):
HTTPConnection.__init__(self, host, port, strict=strict, timeout=timeout, **kw)
self.key_file = key_file
self.cert_file = cert_file
self.key_password = key_password
self.ssl_context = ssl_context
self.server_hostname = server_hostname
# Required property for Google AppEngine 1.9.0 which otherwise causes
# HTTPS requests to go out as HTTP. (See Issue #356)
self._protocol = "https"
def set_cert(
self,
key_file=None,
cert_file=None,
cert_reqs=None,
key_password=None,
ca_certs=None,
assert_hostname=None,
assert_fingerprint=None,
ca_cert_dir=None,
ca_cert_data=None,
):
"""
This method should only be called once, before the connection is used.
"""
# If cert_reqs is not provided we'll assume CERT_REQUIRED unless we also
# have an SSLContext object in which case we'll use its verify_mode.
if cert_reqs is None:
if self.ssl_context is not None:
cert_reqs = self.ssl_context.verify_mode
else:
cert_reqs = resolve_cert_reqs(None)
self.key_file = key_file
self.cert_file = cert_file
self.cert_reqs = cert_reqs
self.key_password = key_password
self.assert_hostname = assert_hostname
self.assert_fingerprint = assert_fingerprint
self.ca_certs = ca_certs and os.path.expanduser(ca_certs)
self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir)
self.ca_cert_data = ca_cert_data
def connect(self):
# Add certificate verification
self.sock = conn = self._new_conn()
hostname = self.host
tls_in_tls = False
if self._is_using_tunnel():
if self.tls_in_tls_required:
self.sock = conn = self._connect_tls_proxy(hostname, conn)
tls_in_tls = True
# Calls self._set_hostport(), so self.host is
# self._tunnel_host below.
self._tunnel()
# Mark this connection as not reusable
self.auto_open = 0
# Override the host with the one we're requesting data from.
hostname = self._tunnel_host
server_hostname = hostname
if self.server_hostname is not None:
server_hostname = self.server_hostname
is_time_off = datetime.date.today() < RECENT_DATE
if is_time_off:
warnings.warn(
(
"System time is way off (before {0}). This will probably "
"lead to SSL verification errors"
).format(RECENT_DATE),
SystemTimeWarning,
)
# Wrap socket using verification with the root certs in
# trusted_root_certs
default_ssl_context = False
if self.ssl_context is None:
default_ssl_context = True
self.ssl_context = create_urllib3_context(
ssl_version=resolve_ssl_version(self.ssl_version),
cert_reqs=resolve_cert_reqs(self.cert_reqs),
)
context = self.ssl_context
context.verify_mode = resolve_cert_reqs(self.cert_reqs)
# Try to load OS default certs if none are given.
# Works well on Windows (requires Python3.4+)
if (
not self.ca_certs
and not self.ca_cert_dir
and not self.ca_cert_data
and default_ssl_context
and hasattr(context, "load_default_certs")
):
context.load_default_certs()
self.sock = ssl_wrap_socket(
sock=conn,
keyfile=self.key_file,
certfile=self.cert_file,
key_password=self.key_password,
ca_certs=self.ca_certs,
ca_cert_dir=self.ca_cert_dir,
ca_cert_data=self.ca_cert_data,
server_hostname=server_hostname,
ssl_context=context,
tls_in_tls=tls_in_tls,
)
# If we're using all defaults and the connection
# is TLSv1 or TLSv1.1 we throw a DeprecationWarning
# for the host.
if (
default_ssl_context
and self.ssl_version is None
and hasattr(self.sock, "version")
and self.sock.version() in {"TLSv1", "TLSv1.1"}
):
warnings.warn(
"Negotiating TLSv1/TLSv1.1 by default is deprecated "
"and will be disabled in urllib3 v2.0.0. Connecting to "
"'%s' with '%s' can be enabled by explicitly opting-in "
"with 'ssl_version'" % (self.host, self.sock.version()),
DeprecationWarning,
)
if self.assert_fingerprint:
assert_fingerprint(
self.sock.getpeercert(binary_form=True), self.assert_fingerprint
)
elif (
context.verify_mode != ssl.CERT_NONE
and not getattr(context, "check_hostname", False)
and self.assert_hostname is not False
):
# While urllib3 attempts to always turn off hostname matching from
# the TLS library, this cannot always be done. So we check whether
# the TLS Library still thinks it's matching hostnames.
cert = self.sock.getpeercert()
if not cert.get("subjectAltName", ()):
warnings.warn(
(
"Certificate for {0} has no `subjectAltName`, falling back to check for a "
"`commonName` for now. This feature is being removed by major browsers and "
"deprecated by RFC 2818. (See https://github.com/urllib3/urllib3/issues/497 "
"for details.)".format(hostname)
),
SubjectAltNameWarning,
)
_match_hostname(cert, self.assert_hostname or server_hostname)
self.is_verified = (
context.verify_mode == ssl.CERT_REQUIRED
or self.assert_fingerprint is not None
)
def _connect_tls_proxy(self, hostname, conn):
"""
Establish a TLS connection to the proxy using the provided SSL context.
"""
proxy_config = self.proxy_config
ssl_context = proxy_config.ssl_context
if ssl_context:
# If the user provided a proxy context, we assume CA and client
# certificates have already been set
return ssl_wrap_socket(
sock=conn,
server_hostname=hostname,
ssl_context=ssl_context,
)
ssl_context = create_proxy_ssl_context(
self.ssl_version,
self.cert_reqs,
self.ca_certs,
self.ca_cert_dir,
self.ca_cert_data,
)
# If no cert was provided, use only the default options for server
# certificate validation
socket = ssl_wrap_socket(
sock=conn,
ca_certs=self.ca_certs,
ca_cert_dir=self.ca_cert_dir,
ca_cert_data=self.ca_cert_data,
server_hostname=hostname,
ssl_context=ssl_context,
)
if ssl_context.verify_mode != ssl.CERT_NONE and not getattr(
ssl_context, "check_hostname", False
):
# While urllib3 attempts to always turn off hostname matching from
# the TLS library, this cannot always be done. So we check whether
# the TLS Library still thinks it's matching hostnames.
cert = socket.getpeercert()
if not cert.get("subjectAltName", ()):
warnings.warn(
(
"Certificate for {0} has no `subjectAltName`, falling back to check for a "
"`commonName` for now. This feature is being removed by major browsers and "
"deprecated by RFC 2818. (See https://github.com/urllib3/urllib3/issues/497 "
"for details.)".format(hostname)
),
SubjectAltNameWarning,
)
_match_hostname(cert, hostname)
self.proxy_is_verified = ssl_context.verify_mode == ssl.CERT_REQUIRED
return socket
def _match_hostname(cert, asserted_hostname):
# Our upstream implementation of ssl.match_hostname()
# only applies this normalization to IP addresses so it doesn't
# match DNS SANs so we do the same thing!
stripped_hostname = asserted_hostname.strip("u[]")
if is_ipaddress(stripped_hostname):
asserted_hostname = stripped_hostname
try:
match_hostname(cert, asserted_hostname)
except CertificateError as e:
log.warning(
"Certificate did not match expected hostname: %s. Certificate: %s",
asserted_hostname,
cert,
)
# Add cert to exception and reraise so client code can inspect
# the cert when catching the exception, if they want to
e._peer_cert = cert
raise
def _get_default_user_agent():
return "python-urllib3/%s" % __version__
class DummyConnection(object):
"""Used to detect a failed ConnectionCls import."""
pass
if not ssl:
HTTPSConnection = DummyConnection # noqa: F811
VerifiedHTTPSConnection = HTTPSConnection
================================================
FILE: resources/AccountCreationLambdaCode/urllib3/connectionpool.py
================================================
from __future__ import absolute_import
import errno
import logging
import re
import socket
import sys
import warnings
from socket import error as SocketError
from socket import timeout as SocketTimeout
from .connection import (
BaseSSLError,
BrokenPipeError,
DummyConnection,
HTTPConnection,
HTTPException,
HTTPSConnection,
VerifiedHTTPSConnection,
port_by_scheme,
)
from .exceptions import (
ClosedPoolError,
EmptyPoolError,
HeaderParsingError,
HostChangedError,
InsecureRequestWarning,
LocationValueError,
MaxRetryError,
NewConnectionError,
ProtocolError,
ProxyError,
ReadTimeoutError,
SSLError,
TimeoutError,
)
from .packages import six
from .packages.six.moves import queue
from .request import RequestMethods
from .response import HTTPResponse
from .util.connection import is_connection_dropped
from .util.proxy import connection_requires_http_tunnel
from .util.queue import LifoQueue
from .util.request import set_file_position
from .util.response import assert_header_parsing
from .util.retry import Retry
from .util.ssl_match_hostname import CertificateError
from .util.timeout import Timeout
from .util.url import Url, _encode_target
from .util.url import _normalize_host as normalize_host
from .util.url import get_host, parse_url
xrange = six.moves.xrange
log = logging.getLogger(__name__)
_Default = object()
# Pool objects
class ConnectionPool(object):
"""
Base class for all connection pools, such as
:class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`.
.. note::
ConnectionPool.urlopen() does not normalize or percent-encode target URIs
which is useful if your target server doesn't support percent-encoded
target URIs.
"""
scheme = None
QueueCls = LifoQueue
def __init__(self, host, port=None):
if not host:
raise LocationValueError("No host specified.")
self.host = _normalize_host(host, scheme=self.scheme)
self._proxy_host = host.lower()
self.port = port
def __str__(self):
return "%s(host=%r, port=%r)" % (type(self).__name__, self.host, self.port)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
# Return False to re-raise any potential exceptions
return False
def close(self):
"""
Close all pooled connections and disable the pool.
"""
pass
# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252
_blocking_errnos = {errno.EAGAIN, errno.EWOULDBLOCK}
class HTTPConnectionPool(ConnectionPool, RequestMethods):
"""
Thread-safe connection pool for one host.
:param host:
Host used for this HTTP Connection (e.g. "localhost"), passed into
:class:`http.client.HTTPConnection`.
:param port:
Port used for this HTTP Connection (None is equivalent to 80), passed
into :class:`http.client.HTTPConnection`.
:param strict:
Causes BadStatusLine to be raised if the status line can't be parsed
as a valid HTTP/1.0 or 1.1 status line, passed into
:class:`http.client.HTTPConnection`.
.. note::
Only works in Python 2. This parameter is ignored in Python 3.
:param timeout:
Socket timeout in seconds for each individual connection. This can
be a float or integer, which sets the timeout for the HTTP request,
or an instance of :class:`urllib3.util.Timeout` which gives you more
fine-grained control over request timeouts. After the constructor has
been parsed, this is always a `urllib3.util.Timeout` object.
:param maxsize:
Number of connections to save that can be reused. More than 1 is useful
in multithreaded situations. If ``block`` is set to False, more
connections will be created but they will not be saved once they've
been used.
:param block:
If set to True, no more than ``maxsize`` connections will be used at
a time. When no free connections are available, the call will block
until a connection has been released. This is a useful side effect for
particular multithreaded situations where one does not want to use more
than maxsize connections per host to prevent flooding.
:param headers:
Headers to include with all requests, unless other headers are given
explicitly.
:param retries:
Retry configuration to use by default with requests in this pool.
:param _proxy:
Parsed proxy URL, should not be used directly, instead, see
:class:`urllib3.ProxyManager`
:param _proxy_headers:
A dictionary with proxy headers, should not be used directly,
instead, see :class:`urllib3.ProxyManager`
:param \\**conn_kw:
Additional parameters are used to create fresh :class:`urllib3.connection.HTTPConnection`,
:class:`urllib3.connection.HTTPSConnection` instances.
"""
scheme = "http"
ConnectionCls = HTTPConnection
ResponseCls = HTTPResponse
def __init__(
self,
host,
port=None,
strict=False,
timeout=Timeout.DEFAULT_TIMEOUT,
maxsize=1,
block=False,
headers=None,
retries=None,
_proxy=None,
_proxy_headers=None,
_proxy_config=None,
**conn_kw
):
ConnectionPool.__init__(self, host, port)
RequestMethods.__init__(self, headers)
self.strict = strict
if not isinstance(timeout, Timeout):
timeout = Timeout.from_float(timeout)
if retries is None:
retries = Retry.DEFAULT
self.timeout = timeout
self.retries = retries
self.pool = self.QueueCls(maxsize)
self.block = block
self.proxy = _proxy
self.proxy_headers = _proxy_headers or {}
self.proxy_config = _proxy_config
# Fill the queue up so that doing get() on it will block properly
for _ in xrange(maxsize):
self.pool.put(None)
# These are mostly for testing and debugging purposes.
self.num_connections = 0
self.num_requests = 0
self.conn_kw = conn_kw
if self.proxy:
# Enable Nagle's algorithm for proxies, to avoid packet fragmentation.
# We cannot know if the user has added default socket options, so we cannot replace the
# list.
self.conn_kw.setdefault("socket_options", [])
self.conn_kw["proxy"] = self.proxy
self.conn_kw["proxy_config"] = self.proxy_config
def _new_conn(self):
"""
Return a fresh :class:`HTTPConnection`.
"""
self.num_connections += 1
log.debug(
"Starting new HTTP connection (%d): %s:%s",
self.num_connections,
self.host,
self.port or "80",
)
conn = self.ConnectionCls(
host=self.host,
port=self.port,
timeout=self.timeout.connect_timeout,
strict=self.strict,
**self.conn_kw
)
return conn
def _get_conn(self, timeout=None):
"""
Get a connection. Will return a pooled connection if one is available.
If no connections are available and :prop:`.block` is ``False``, then a
fresh connection is returned.
:param timeout:
Seconds to wait before giving up and raising
:class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and
:prop:`.block` is ``True``.
"""
conn = None
try:
conn = self.pool.get(block=self.block, timeout=timeout)
except AttributeError: # self.pool is None
raise ClosedPoolError(self, "Pool is closed.")
except queue.Empty:
if self.block:
raise EmptyPoolError(
self,
"Pool reached maximum size and no more connections are allowed.",
)
pass # Oh well, we'll create a new connection then
# If this is a persistent connection, check if it got disconnected
if conn and is_connection_dropped(conn):
log.debug("Resetting dropped connection: %s", self.host)
conn.close()
if getattr(conn, "auto_open", 1) == 0:
# This is a proxied connection that has been mutated by
# http.client._tunnel() and cannot be reused (since it would
# attempt to bypass the proxy)
conn = None
return conn or self._new_conn()
def _put_conn(self, conn):
"""
Put a connection back into the pool.
:param conn:
Connection object for the current host and port as returned by
:meth:`._new_conn` or :meth:`._get_conn`.
If the pool is already full, the connection is closed and discarded
because we exceeded maxsize. If connections are discarded frequently,
then maxsize should be increased.
If the pool is closed, then the connection will be closed and discarded.
"""
try:
self.pool.put(conn, block=False)
return # Everything is dandy, done.
except AttributeError:
# self.pool is None.
pass
except queue.Full:
# This should never happen if self.block == True
log.warning(
"Connection pool is full, discarding connection: %s. Connection pool size: %s",
self.host,
self.pool.qsize(),
)
# Connection never got put back into the pool, close it.
if conn:
conn.close()
def _validate_conn(self, conn):
"""
Called right before a request is made, after the socket is created.
"""
pass
def _prepare_proxy(self, conn):
# Nothing to do for HTTP connections.
pass
def _get_timeout(self, timeout):
"""Helper that always returns a :class:`urllib3.util.Timeout`"""
if timeout is _Default:
return self.timeout.clone()
if isinstance(timeout, Timeout):
return timeout.clone()
else:
# User passed us an int/float. This is for backwards compatibility,
# can be removed later
return Timeout.from_float(timeout)
def _raise_timeout(self, err, url, timeout_value):
"""Is the error actually a timeout? Will raise a ReadTimeout or pass"""
if isinstance(err, SocketTimeout):
raise ReadTimeoutError(
self, url, "Read timed out. (read timeout=%s)" % timeout_value
)
# See the above comment about EAGAIN in Python 3. In Python 2 we have
# to specifically catch it and throw the timeout error
if hasattr(err, "errno") and err.errno in _blocking_errnos:
raise ReadTimeoutError(
self, url, "Read timed out. (read timeout=%s)" % timeout_value
)
# Catch possible read timeouts thrown as SSL errors. If not the
# case, rethrow the original. We need to do this because of:
# http://bugs.python.org/issue10272
if "timed out" in str(err) or "did not complete (read)" in str(
err
): # Python < 2.7.4
raise ReadTimeoutError(
self, url, "Read timed out. (read timeout=%s)" % timeout_value
)
def _make_request(
self, conn, method, url, timeout=_Default, chunked=False, **httplib_request_kw
):
"""
Perform a request on a given urllib connection object taken from our
pool.
:param conn:
a connection from one of our connection pools
:param timeout:
Socket timeout in seconds for the request. This can be a
float or integer, which will set the same timeout value for
the socket connect and the socket read, or an instance of
:class:`urllib3.util.Timeout`, which gives you more fine-grained
control over your timeouts.
"""
self.num_requests += 1
timeout_obj = self._get_timeout(timeout)
timeout_obj.start_connect()
conn.timeout = Timeout.resolve_default_timeout(timeout_obj.connect_timeout)
# Trigger any extra validation we need to do.
try:
self._validate_conn(conn)
except (SocketTimeout, BaseSSLError) as e:
# Py2 raises this as a BaseSSLError, Py3 raises it as socket timeout.
self._raise_timeout(err=e, url=url, timeout_value=conn.timeout)
raise
# conn.request() calls http.client.*.request, not the method in
# urllib3.request. It also calls makefile (recv) on the socket.
try:
if chunked:
conn.request_chunked(method, url, **httplib_request_kw)
else:
conn.request(method, url, **httplib_request_kw)
# We are swallowing BrokenPipeError (errno.EPIPE) since the server is
# legitimately able to close the connection after sending a valid response.
# With this behaviour, the received response is still readable.
except BrokenPipeError:
# Python 3
pass
except IOError as e:
# Python 2 and macOS/Linux
# EPIPE and ESHUTDOWN are BrokenPipeError on Python 2, and EPROTOTYPE is needed on macOS
# https://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/
if e.errno not in {
errno.EPIPE,
errno.ESHUTDOWN,
errno.EPROTOTYPE,
}:
raise
# Reset the timeout for the recv() on the socket
read_timeout = timeout_obj.read_timeout
# App Engine doesn't have a sock attr
if getattr(conn, "sock", None):
# In Python 3 socket.py will catch EAGAIN and return None when you
# try and read into the file pointer created by http.client, which
# instead raises a BadStatusLine exception. Instead of catching
# the exception and assuming all BadStatusLine exceptions are read
# timeouts, check for a zero timeout before making the request.
if read_timeout == 0:
raise ReadTimeoutError(
self, url, "Read timed out. (read timeout=%s)" % read_timeout
)
if read_timeout is Timeout.DEFAULT_TIMEOUT:
conn.sock.settimeout(socket.getdefaulttimeout())
else: # None or a value
conn.sock.settimeout(read_timeout)
# Receive the response from the server
try:
try:
# Python 2.7, use buffering of HTTP responses
httplib_response = conn.getresponse(buffering=True)
except TypeError:
# Python 3
try:
httplib_response = conn.getresponse()
except BaseException as e:
# Remove the TypeError from the exception chain in
# Python 3 (including for exceptions like SystemExit).
# Otherwise it looks like a bug in the code.
six.raise_from(e, None)
except (SocketTimeout, BaseSSLError, SocketError) as e:
self._raise_timeout(err=e, url=url, timeout_value=read_timeout)
raise
# AppEngine doesn't have a version attr.
http_version = getattr(conn, "_http_vsn_str", "HTTP/?")
log.debug(
'%s://%s:%s "%s %s %s" %s %s',
self.scheme,
self.host,
self.port,
method,
url,
http_version,
httplib_response.status,
httplib_response.length,
)
try:
assert_header_parsing(httplib_response.msg)
except (HeaderParsingError, TypeError) as hpe: # Platform-specific: Python 3
log.warning(
"Failed to parse headers (url=%s): %s",
self._absolute_url(url),
hpe,
exc_info=True,
)
return httplib_response
def _absolute_url(self, path):
return Url(scheme=self.scheme, host=self.host, port=self.port, path=path).url
def close(self):
"""
Close all pooled connections and disable the pool.
"""
if self.pool is None:
return
# Disable access to the pool
old_pool, self.pool = self.pool, None
try:
while True:
conn = old_pool.get(block=False)
if conn:
conn.close()
except queue.Empty:
pass # Done.
def is_same_host(self, url):
"""
Check if the given ``url`` is a member of the same host as this
connection pool.
"""
if url.startswith("/"):
return True
# TODO: Add optional support for socket.gethostbyname checking.
scheme, host, port = get_host(url)
if host is not None:
host = _normalize_host(host, scheme=scheme)
# Use explicit default port for comparison when none is given
if self.port and not port:
port = port_by_scheme.get(scheme)
elif not self.port and port == port_by_scheme.get(scheme):
port = None
return (scheme, host, port) == (self.scheme, self.host, self.port)
def urlopen(
self,
method,
url,
body=None,
headers=None,
retries=None,
redirect=True,
assert_same_host=True,
timeout=_Default,
pool_timeout=None,
release_conn=None,
chunked=False,
body_pos=None,
**response_kw
):
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method provided
by :class:`.RequestMethods`, such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
Pass ``None`` to retry until you receive a response. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of
``response_kw.get('preload_content', True)``.
:param chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto
gitextract_umtfd2mz/
├── .github/
│ └── PULL_REQUEST_TEMPLATE.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── govcloud/
│ ├── LICENSE
│ ├── README.md
│ ├── commercial-side-setup/
│ │ ├── CommercialAccountSetup.yaml
│ │ └── commercial-account-avm-product.yaml
│ └── govcloud-side-setup/
│ ├── Accountbaseline.yml
│ ├── GovCloudAccountSetup.yaml
│ └── govcloud-account-avm-product.yaml
└── resources/
├── AccountCreationLambdaCode/
│ ├── AccountCreationLambda.py
│ ├── cfnresponse/
│ │ └── __init__.py
│ ├── cfnresponse-1.1.2.dist-info/
│ │ ├── INSTALLER
│ │ ├── LICENSE
│ │ ├── METADATA
│ │ ├── RECORD
│ │ ├── REQUESTED
│ │ ├── WHEEL
│ │ └── top_level.txt
│ ├── crhelper/
│ │ ├── __init__.py
│ │ ├── __init__.pyi
│ │ ├── log_helper.py
│ │ ├── log_helper.pyi
│ │ ├── py.typed
│ │ ├── resource_helper.py
│ │ ├── resource_helper.pyi
│ │ ├── utils.py
│ │ └── utils.pyi
│ ├── crhelper-2.0.11-py2.7.egg-info/
│ │ ├── PKG-INFO
│ │ ├── SOURCES.txt
│ │ ├── dependency_links.txt
│ │ ├── installed-files.txt
│ │ └── top_level.txt
│ ├── urllib3/
│ │ ├── __init__.py
│ │ ├── _collections.py
│ │ ├── _version.py
│ │ ├── connection.py
│ │ ├── connectionpool.py
│ │ ├── contrib/
│ │ │ ├── __init__.py
│ │ │ ├── _appengine_environ.py
│ │ │ ├── _securetransport/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── bindings.py
│ │ │ │ └── low_level.py
│ │ │ ├── appengine.py
│ │ │ ├── ntlmpool.py
│ │ │ ├── pyopenssl.py
│ │ │ ├── securetransport.py
│ │ │ └── socks.py
│ │ ├── exceptions.py
│ │ ├── fields.py
│ │ ├── filepost.py
│ │ ├── packages/
│ │ │ ├── __init__.py
│ │ │ ├── backports/
│ │ │ │ ├── __init__.py
│ │ │ │ └── makefile.py
│ │ │ └── six.py
│ │ ├── poolmanager.py
│ │ ├── request.py
│ │ ├── response.py
│ │ └── util/
│ │ ├── __init__.py
│ │ ├── connection.py
│ │ ├── proxy.py
│ │ ├── queue.py
│ │ ├── request.py
│ │ ├── response.py
│ │ ├── retry.py
│ │ ├── ssl_.py
│ │ ├── ssl_match_hostname.py
│ │ ├── ssltransport.py
│ │ ├── timeout.py
│ │ ├── url.py
│ │ └── wait.py
│ └── urllib3-1.26.15.dist-info/
│ ├── INSTALLER
│ ├── LICENSE.txt
│ ├── METADATA
│ ├── RECORD
│ ├── WHEEL
│ └── top_level.txt
├── AccountCreationLambdaSetup-cfn.yaml
├── Accountbaseline.yml
└── accountbuilder.yml
SYMBOL INDEX (621 symbols across 39 files)
FILE: resources/AccountCreationLambdaCode/AccountCreationLambda.py
function get_client (line 37) | def get_client(service):
function create_account (line 41) | def create_account(accountname,accountemail,accountrole,access_to_billin...
function get_template (line 61) | def get_template(sourcebucket,baselinetemplate):
function delete_default_vpc (line 71) | def delete_default_vpc(credentials,currentregion):
function deploy_resources (line 111) | def deploy_resources(credentials, template, stackname, stackregion, Serv...
function assume_role (line 189) | def assume_role(account_id, account_role):
function get_ou_name_id (line 210) | def get_ou_name_id(event, root_id,organization_unit_name):
function build_accounts_list (line 243) | def build_accounts_list(org_client,list_accounts_response,account_details):
function create (line 250) | def create(event,context):
function main (line 354) | def main(event,context):
FILE: resources/AccountCreationLambdaCode/cfnresponse/__init__.py
function send (line 10) | def send(event, context, responseStatus, responseData, physicalResourceI...
FILE: resources/AccountCreationLambdaCode/crhelper/log_helper.py
function _json_formatter (line 6) | def _json_formatter(obj):
class JsonFormatter (line 11) | class JsonFormatter(logging.Formatter):
method __init__ (line 19) | def __init__(self, **kwargs):
method format (line 30) | def format(self, record):
function setup (line 70) | def setup(level='DEBUG', formatter_cls=JsonFormatter, boto_level=None, *...
FILE: resources/AccountCreationLambdaCode/crhelper/log_helper.pyi
class JsonFormatter (line 4) | class JsonFormatter(logging.Formatter):
method __init__ (line 7) | def __init__(self, **kwargs: Any) -> None: ...
method format (line 8) | def format(self, record: Any): ...
function setup (line 10) | def setup(level: str = ..., formatter_cls: Any = ..., boto_level: Option...
FILE: resources/AccountCreationLambdaCode/crhelper/resource_helper.py
class CfnResource (line 28) | class CfnResource(object):
method __init__ (line 30) | def __init__(self, json_logging=False, log_level='DEBUG', boto_level='...
method __call__ (line 72) | def __call__(self, event, context):
method _wait_for_cwlogs (line 99) | def _wait_for_cwlogs(self, sleep=sleep):
method _log_setup (line 109) | def _log_setup(self, event, context):
method _crhelper_init (line 117) | def _crhelper_init(self, event, context):
method _polling_init (line 141) | def _polling_init(self, event):
method generate_physical_id (line 157) | def generate_physical_id(self, event):
method _cfn_response (line 164) | def _cfn_response(self, event):
method _poll_enabled (line 175) | def _poll_enabled(self):
method create (line 178) | def create(self, func):
method update (line 182) | def update(self, func):
method delete (line 186) | def delete(self, func):
method poll_create (line 190) | def poll_create(self, func):
method poll_update (line 194) | def poll_update(self, func):
method poll_delete (line 198) | def poll_delete(self, func):
method _wrap_function (line 202) | def _wrap_function(self, func):
method _timeout (line 210) | def _timeout(self):
method _set_timeout (line 214) | def _set_timeout(self):
method _get_func (line 219) | def _get_func(self):
method _send (line 225) | def _send(self, status=None, reason="", send_response=_send_response):
method init_failure (line 244) | def init_failure(self, error):
method _cleanup_response (line 248) | def _cleanup_response(self):
method _rand_string (line 254) | def _rand_string(l):
method _add_permission (line 257) | def _add_permission(self, rule_arn):
method _put_rule (line 268) | def _put_rule(self):
method _put_targets (line 277) | def _put_targets(self, func_name):
method _remove_targets (line 294) | def _remove_targets(self, rule_arn):
method _remove_permission (line 300) | def _remove_permission(self, sid):
method _delete_rule (line 306) | def _delete_rule(self, rule_arn):
method _setup_polling (line 311) | def _setup_polling(self):
method _remove_polling (line 318) | def _remove_polling(self):
FILE: resources/AccountCreationLambdaCode/crhelper/resource_helper.pyi
class CfnResource (line 10) | class CfnResource:
method __init__ (line 19) | def __init__(self, json_logging: bool = ..., log_level: str = ..., bot...
method __call__ (line 20) | def __call__(self, event: Any, context: Any) -> None: ...
method generate_physical_id (line 21) | def generate_physical_id(self, event: Any): ...
method create (line 22) | def create(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
method update (line 23) | def update(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
method delete (line 24) | def delete(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
method poll_create (line 25) | def poll_create(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
method poll_update (line 26) | def poll_update(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
method poll_delete (line 27) | def poll_delete(self, func: _DecoratorTypeDef) -> _DecoratorTypeDef: ...
method init_failure (line 28) | def init_failure(self, error: Any) -> None: ...
FILE: resources/AccountCreationLambdaCode/crhelper/utils.py
function _send_response (line 15) | def _send_response(response_url: AnyStr, response_body: AnyStr, ssl_veri...
FILE: resources/AccountCreationLambdaCode/urllib3/__init__.py
function add_stderr_logger (line 63) | def add_stderr_logger(level=logging.DEBUG):
function disable_warnings (line 98) | def disable_warnings(category=exceptions.HTTPWarning):
FILE: resources/AccountCreationLambdaCode/urllib3/_collections.py
class RLock (line 11) | class RLock:
method __enter__ (line 12) | def __enter__(self):
method __exit__ (line 15) | def __exit__(self, exc_type, exc_value, traceback):
class RecentlyUsedContainer (line 31) | class RecentlyUsedContainer(MutableMapping):
method __init__ (line 47) | def __init__(self, maxsize=10, dispose_func=None):
method __getitem__ (line 54) | def __getitem__(self, key):
method __setitem__ (line 61) | def __setitem__(self, key, value):
method __delitem__ (line 76) | def __delitem__(self, key):
method __len__ (line 83) | def __len__(self):
method __iter__ (line 87) | def __iter__(self):
method clear (line 92) | def clear(self):
method keys (line 102) | def keys(self):
class HTTPHeaderDict (line 107) | class HTTPHeaderDict(MutableMapping):
method __init__ (line 141) | def __init__(self, headers=None, **kwargs):
method __setitem__ (line 152) | def __setitem__(self, key, val):
method __getitem__ (line 156) | def __getitem__(self, key):
method __delitem__ (line 160) | def __delitem__(self, key):
method __contains__ (line 163) | def __contains__(self, key):
method __eq__ (line 166) | def __eq__(self, other):
method __ne__ (line 175) | def __ne__(self, other):
method __len__ (line 184) | def __len__(self):
method __iter__ (line 187) | def __iter__(self):
method pop (line 192) | def pop(self, key, default=__marker):
method discard (line 209) | def discard(self, key):
method add (line 215) | def add(self, key, val):
method extend (line 231) | def extend(self, *args, **kwargs):
method getlist (line 259) | def getlist(self, key, default=__marker):
method __repr__ (line 279) | def __repr__(self):
method _copy_from (line 282) | def _copy_from(self, other):
method copy (line 290) | def copy(self):
method iteritems (line 295) | def iteritems(self):
method itermerged (line 302) | def itermerged(self):
method items (line 308) | def items(self):
method from_httplib (line 312) | def from_httplib(cls, message): # Python 2
FILE: resources/AccountCreationLambdaCode/urllib3/connection.py
class BaseSSLError (line 24) | class BaseSSLError(BaseException):
class ConnectionError (line 33) | class ConnectionError(Exception):
class BrokenPipeError (line 42) | class BrokenPipeError(Exception):
class HTTPConnection (line 76) | class HTTPConnection(_HTTPConnection, object):
method __init__ (line 115) | def __init__(self, *args, **kw):
method host (line 133) | def host(self):
method host (line 152) | def host(self, value):
method _new_conn (line 161) | def _new_conn(self):
method _is_using_tunnel (line 192) | def _is_using_tunnel(self):
method _prepare_conn (line 196) | def _prepare_conn(self, conn):
method connect (line 204) | def connect(self):
method putrequest (line 208) | def putrequest(self, method, url, *args, **kwargs):
method putheader (line 221) | def putheader(self, header, *values):
method request (line 231) | def request(self, method, url, body=None, headers=None):
method request_chunked (line 246) | def request_chunked(self, method, url, body=None, headers=None):
class HTTPSConnection (line 286) | class HTTPSConnection(HTTPConnection):
method __init__ (line 302) | def __init__(
method set_cert (line 328) | def set_cert(
method connect (line 361) | def connect(self):
method _connect_tls_proxy (line 479) | def _connect_tls_proxy(self, hostname, conn):
function _match_hostname (line 536) | def _match_hostname(cert, asserted_hostname):
function _get_default_user_agent (line 558) | def _get_default_user_agent():
class DummyConnection (line 562) | class DummyConnection(object):
FILE: resources/AccountCreationLambdaCode/urllib3/connectionpool.py
class ConnectionPool (line 61) | class ConnectionPool(object):
method __init__ (line 75) | def __init__(self, host, port=None):
method __str__ (line 83) | def __str__(self):
method __enter__ (line 86) | def __enter__(self):
method __exit__ (line 89) | def __exit__(self, exc_type, exc_val, exc_tb):
method close (line 94) | def close(self):
class HTTPConnectionPool (line 105) | class HTTPConnectionPool(ConnectionPool, RequestMethods):
method __init__ (line 169) | def __init__(
method _new_conn (line 223) | def _new_conn(self):
method _get_conn (line 244) | def _get_conn(self, timeout=None):
method _put_conn (line 283) | def _put_conn(self, conn):
method _validate_conn (line 314) | def _validate_conn(self, conn):
method _prepare_proxy (line 320) | def _prepare_proxy(self, conn):
method _get_timeout (line 324) | def _get_timeout(self, timeout):
method _raise_timeout (line 336) | def _raise_timeout(self, err, url, timeout_value):
method _make_request (line 361) | def _make_request(
method _absolute_url (line 480) | def _absolute_url(self, path):
method close (line 483) | def close(self):
method is_same_host (line 501) | def is_same_host(self, url):
method urlopen (line 522) | def urlopen(
class HTTPSConnectionPool (line 897) | class HTTPSConnectionPool(HTTPConnectionPool):
method __init__ (line 914) | def __init__(
method _prepare_conn (line 963) | def _prepare_conn(self, conn):
method _prepare_proxy (line 983) | def _prepare_proxy(self, conn):
method _new_conn (line 998) | def _new_conn(self):
method _validate_conn (line 1034) | def _validate_conn(self, conn):
function connection_from_url (line 1067) | def connection_from_url(url, **kw):
function _normalize_host (line 1095) | def _normalize_host(host, scheme):
FILE: resources/AccountCreationLambdaCode/urllib3/contrib/_appengine_environ.py
function is_appengine (line 8) | def is_appengine():
function is_appengine_sandbox (line 12) | def is_appengine_sandbox():
function is_local_appengine (line 22) | def is_local_appengine():
function is_prod_appengine (line 28) | def is_prod_appengine():
function is_prod_appengine_mvms (line 34) | def is_prod_appengine_mvms():
FILE: resources/AccountCreationLambdaCode/urllib3/contrib/_securetransport/bindings.py
function load_cdll (line 65) | def load_cdll(name, macos10_16_path):
class CFConst (line 423) | class CFConst(object):
class SecurityConst (line 432) | class SecurityConst(object):
FILE: resources/AccountCreationLambdaCode/urllib3/contrib/_securetransport/low_level.py
function _cf_data_from_bytes (line 27) | def _cf_data_from_bytes(bytestring):
function _cf_dictionary_from_tuples (line 37) | def _cf_dictionary_from_tuples(tuples):
function _cfstr (line 59) | def _cfstr(py_bstr):
function _create_cfstring_array (line 73) | def _create_cfstring_array(lst):
function _cf_string_to_unicode (line 104) | def _cf_string_to_unicode(value):
function _assert_no_error (line 129) | def _assert_no_error(error, exception_class=None):
function _cert_array_from_pem (line 150) | def _cert_array_from_pem(pem_bundle):
function _is_cert (line 196) | def _is_cert(item):
function _is_identity (line 204) | def _is_identity(item):
function _temporary_keychain (line 212) | def _temporary_keychain():
function _load_items_from_file (line 247) | def _load_items_from_file(keychain, path):
function _load_client_cert_chain (line 302) | def _load_client_cert_chain(keychain, *paths):
function _build_tls_unknown_ca_alert (line 386) | def _build_tls_unknown_ca_alert(version):
FILE: resources/AccountCreationLambdaCode/urllib3/contrib/appengine.py
class AppEnginePlatformWarning (line 71) | class AppEnginePlatformWarning(HTTPWarning):
class AppEnginePlatformError (line 75) | class AppEnginePlatformError(HTTPError):
class AppEngineManager (line 79) | class AppEngineManager(RequestMethods):
method __init__ (line 99) | def __init__(
method __enter__ (line 124) | def __enter__(self):
method __exit__ (line 127) | def __exit__(self, exc_type, exc_val, exc_tb):
method urlopen (line 131) | def urlopen(
method _urlfetch_response_to_http_response (line 245) | def _urlfetch_response_to_http_response(self, urlfetch_resp, **respons...
method _get_absolute_timeout (line 281) | def _get_absolute_timeout(self, timeout):
method _get_retries (line 294) | def _get_retries(self, retries, redirect):
FILE: resources/AccountCreationLambdaCode/urllib3/contrib/ntlmpool.py
class NTLMConnectionPool (line 27) | class NTLMConnectionPool(HTTPSConnectionPool):
method __init__ (line 34) | def __init__(self, user, pw, authurl, *args, **kwargs):
method _new_conn (line 48) | def _new_conn(self):
method urlopen (line 115) | def urlopen(
FILE: resources/AccountCreationLambdaCode/urllib3/contrib/pyopenssl.py
class UnsupportedExtension (line 59) | class UnsupportedExtension(Exception):
function inject_into_urllib3 (line 130) | def inject_into_urllib3():
function extract_from_urllib3 (line 143) | def extract_from_urllib3():
function _validate_dependencies_met (line 154) | def _validate_dependencies_met():
function _dnsname_to_stdlib (line 180) | def _dnsname_to_stdlib(name):
function get_subj_alt_name (line 223) | def get_subj_alt_name(peer_cert):
class WrappedSocket (line 276) | class WrappedSocket(object):
method __init__ (line 283) | def __init__(self, connection, socket, suppress_ragged_eofs=True):
method fileno (line 290) | def fileno(self):
method _decref_socketios (line 294) | def _decref_socketios(self):
method recv (line 300) | def recv(self, *args, **kwargs):
method recv_into (line 325) | def recv_into(self, *args, **kwargs):
method settimeout (line 348) | def settimeout(self, timeout):
method _send_until_done (line 351) | def _send_until_done(self, data):
method sendall (line 362) | def sendall(self, data):
method shutdown (line 370) | def shutdown(self):
method close (line 374) | def close(self):
method getpeercert (line 384) | def getpeercert(self, binary_form=False):
method version (line 398) | def version(self):
method _reuse (line 401) | def _reuse(self):
method _drop (line 404) | def _drop(self):
function makefile (line 413) | def makefile(self, mode, bufsize=-1):
class PyOpenSSLContext (line 423) | class PyOpenSSLContext(object):
method __init__ (line 430) | def __init__(self, protocol):
method options (line 437) | def options(self):
method options (line 441) | def options(self, value):
method verify_mode (line 446) | def verify_mode(self):
method verify_mode (line 450) | def verify_mode(self, value):
method set_default_verify_paths (line 453) | def set_default_verify_paths(self):
method set_ciphers (line 456) | def set_ciphers(self, ciphers):
method load_verify_locations (line 461) | def load_verify_locations(self, cafile=None, capath=None, cadata=None):
method load_cert_chain (line 473) | def load_cert_chain(self, certfile, keyfile=None, password=None):
method set_alpn_protocols (line 481) | def set_alpn_protocols(self, protocols):
method wrap_socket (line 485) | def wrap_socket(
function _verify_callback (line 517) | def _verify_callback(cnx, x509, err_no, err_depth, return_code):
FILE: resources/AccountCreationLambdaCode/urllib3/contrib/securetransport.py
function inject_into_urllib3 (line 189) | def inject_into_urllib3():
function extract_from_urllib3 (line 201) | def extract_from_urllib3():
function _read_callback (line 213) | def _read_callback(connection_id, data_buffer, data_length_pointer):
function _write_callback (line 268) | def _write_callback(connection_id, data_buffer, data_length_pointer):
class WrappedSocket (line 326) | class WrappedSocket(object):
method __init__ (line 334) | def __init__(self, socket):
method _raise_on_error (line 353) | def _raise_on_error(self):
method _set_ciphers (line 373) | def _set_ciphers(self):
method _set_alpn_protocols (line 386) | def _set_alpn_protocols(self, protocols):
method _custom_validate (line 399) | def _custom_validate(self, verify, trust_bundle):
method _evaluate_trust (line 434) | def _evaluate_trust(self, trust_bundle):
method handshake (line 474) | def handshake(
method fileno (line 567) | def fileno(self):
method _decref_socketios (line 571) | def _decref_socketios(self):
method recv (line 577) | def recv(self, bufsiz):
method recv_into (line 583) | def recv_into(self, buffer, nbytes=None):
method settimeout (line 626) | def settimeout(self, timeout):
method gettimeout (line 629) | def gettimeout(self):
method send (line 632) | def send(self, data):
method sendall (line 649) | def sendall(self, data):
method shutdown (line 655) | def shutdown(self):
method close (line 659) | def close(self):
method getpeercert (line 678) | def getpeercert(self, binary_form=False):
method version (line 736) | def version(self):
method _reuse (line 757) | def _reuse(self):
method _drop (line 760) | def _drop(self):
function makefile (line 769) | def makefile(self, mode, bufsize=-1):
function makefile (line 775) | def makefile(self, mode="r", buffering=None, *args, **kwargs):
class SecureTransportContext (line 785) | class SecureTransportContext(object):
method __init__ (line 792) | def __init__(self, protocol):
method check_hostname (line 803) | def check_hostname(self):
method check_hostname (line 811) | def check_hostname(self, value):
method options (line 819) | def options(self):
method options (line 829) | def options(self, value):
method verify_mode (line 834) | def verify_mode(self):
method verify_mode (line 838) | def verify_mode(self, value):
method set_default_verify_paths (line 841) | def set_default_verify_paths(self):
method load_default_certs (line 853) | def load_default_certs(self):
method set_ciphers (line 856) | def set_ciphers(self, ciphers):
method load_verify_locations (line 861) | def load_verify_locations(self, cafile=None, capath=None, cadata=None):
method load_cert_chain (line 873) | def load_cert_chain(self, certfile, keyfile=None, password=None):
method set_alpn_protocols (line 878) | def set_alpn_protocols(self, protocols):
method wrap_socket (line 890) | def wrap_socket(
FILE: resources/AccountCreationLambdaCode/urllib3/contrib/socks.py
class SOCKSConnection (line 75) | class SOCKSConnection(HTTPConnection):
method __init__ (line 80) | def __init__(self, *args, **kwargs):
method _new_conn (line 84) | def _new_conn(self):
class SOCKSHTTPSConnection (line 147) | class SOCKSHTTPSConnection(SOCKSConnection, HTTPSConnection):
class SOCKSHTTPConnectionPool (line 151) | class SOCKSHTTPConnectionPool(HTTPConnectionPool):
class SOCKSHTTPSConnectionPool (line 155) | class SOCKSHTTPSConnectionPool(HTTPSConnectionPool):
class SOCKSProxyManager (line 159) | class SOCKSProxyManager(PoolManager):
method __init__ (line 170) | def __init__(
FILE: resources/AccountCreationLambdaCode/urllib3/exceptions.py
class HTTPError (line 8) | class HTTPError(Exception):
class HTTPWarning (line 14) | class HTTPWarning(Warning):
class PoolError (line 20) | class PoolError(HTTPError):
method __init__ (line 23) | def __init__(self, pool, message):
method __reduce__ (line 27) | def __reduce__(self):
class RequestError (line 32) | class RequestError(PoolError):
method __init__ (line 35) | def __init__(self, pool, url, message):
method __reduce__ (line 39) | def __reduce__(self):
class SSLError (line 44) | class SSLError(HTTPError):
class ProxyError (line 50) | class ProxyError(HTTPError):
method __init__ (line 53) | def __init__(self, message, error, *args):
class DecodeError (line 58) | class DecodeError(HTTPError):
class ProtocolError (line 64) | class ProtocolError(HTTPError):
class MaxRetryError (line 77) | class MaxRetryError(RequestError):
method __init__ (line 87) | def __init__(self, pool, url, reason=None):
class HostChangedError (line 95) | class HostChangedError(RequestError):
method __init__ (line 98) | def __init__(self, pool, url, retries=3):
class TimeoutStateError (line 104) | class TimeoutStateError(HTTPError):
class TimeoutError (line 110) | class TimeoutError(HTTPError):
class ReadTimeoutError (line 120) | class ReadTimeoutError(TimeoutError, RequestError):
class ConnectTimeoutError (line 128) | class ConnectTimeoutError(TimeoutError):
class NewConnectionError (line 134) | class NewConnectionError(ConnectTimeoutError, PoolError):
class EmptyPoolError (line 140) | class EmptyPoolError(PoolError):
class ClosedPoolError (line 146) | class ClosedPoolError(PoolError):
class LocationValueError (line 152) | class LocationValueError(ValueError, HTTPError):
class LocationParseError (line 158) | class LocationParseError(LocationValueError):
method __init__ (line 161) | def __init__(self, location):
class URLSchemeUnknown (line 168) | class URLSchemeUnknown(LocationValueError):
method __init__ (line 171) | def __init__(self, scheme):
class ResponseError (line 178) | class ResponseError(HTTPError):
class SecurityWarning (line 185) | class SecurityWarning(HTTPWarning):
class SubjectAltNameWarning (line 191) | class SubjectAltNameWarning(SecurityWarning):
class InsecureRequestWarning (line 197) | class InsecureRequestWarning(SecurityWarning):
class SystemTimeWarning (line 203) | class SystemTimeWarning(SecurityWarning):
class InsecurePlatformWarning (line 209) | class InsecurePlatformWarning(SecurityWarning):
class SNIMissingWarning (line 215) | class SNIMissingWarning(HTTPWarning):
class DependencyWarning (line 221) | class DependencyWarning(HTTPWarning):
class ResponseNotChunked (line 230) | class ResponseNotChunked(ProtocolError, ValueError):
class BodyNotHttplibCompatible (line 236) | class BodyNotHttplibCompatible(HTTPError):
class IncompleteRead (line 245) | class IncompleteRead(HTTPError, httplib_IncompleteRead):
method __init__ (line 253) | def __init__(self, partial, expected):
method __repr__ (line 256) | def __repr__(self):
class InvalidChunkLength (line 263) | class InvalidChunkLength(HTTPError, httplib_IncompleteRead):
method __init__ (line 266) | def __init__(self, response, length):
method __repr__ (line 273) | def __repr__(self):
class InvalidHeader (line 280) | class InvalidHeader(HTTPError):
class ProxySchemeUnknown (line 286) | class ProxySchemeUnknown(AssertionError, URLSchemeUnknown):
method __init__ (line 291) | def __init__(self, scheme):
class ProxySchemeUnsupported (line 306) | class ProxySchemeUnsupported(ValueError):
class HeaderParsingError (line 312) | class HeaderParsingError(HTTPError):
method __init__ (line 315) | def __init__(self, defects, unparsed_data):
class UnrewindableBodyError (line 320) | class UnrewindableBodyError(HTTPError):
FILE: resources/AccountCreationLambdaCode/urllib3/fields.py
function guess_content_type (line 10) | def guess_content_type(filename, default="application/octet-stream"):
function format_header_param_rfc2231 (line 24) | def format_header_param_rfc2231(name, value):
function _replace_multiple (line 82) | def _replace_multiple(value, needles_and_replacements):
function format_header_param_html5 (line 95) | def format_header_param_html5(name, value):
class RequestField (line 126) | class RequestField(object):
method __init__ (line 143) | def __init__(
method from_tuples (line 160) | def from_tuples(cls, fieldname, value, header_formatter=format_header_...
method _render_part (line 195) | def _render_part(self, name, value):
method _render_parts (line 208) | def _render_parts(self, header_parts):
method render_headers (line 230) | def render_headers(self):
method make_multipart (line 249) | def make_multipart(
FILE: resources/AccountCreationLambdaCode/urllib3/filepost.py
function choose_boundary (line 15) | def choose_boundary():
function iter_field_objects (line 25) | def iter_field_objects(fields):
function iter_fields (line 45) | def iter_fields(fields):
function encode_multipart_formdata (line 63) | def encode_multipart_formdata(fields, boundary=None):
FILE: resources/AccountCreationLambdaCode/urllib3/packages/backports/makefile.py
function backport_makefile (line 13) | def backport_makefile(
FILE: resources/AccountCreationLambdaCode/urllib3/packages/six.py
class X (line 60) | class X(object):
method __len__ (line 61) | def __len__(self):
function _add_doc (line 80) | def _add_doc(func, doc):
function _import_module (line 85) | def _import_module(name):
class _LazyDescr (line 91) | class _LazyDescr(object):
method __init__ (line 92) | def __init__(self, name):
method __get__ (line 95) | def __get__(self, obj, tp):
class MovedModule (line 107) | class MovedModule(_LazyDescr):
method __init__ (line 108) | def __init__(self, name, old, new=None):
method _resolve (line 117) | def _resolve(self):
method __getattr__ (line 120) | def __getattr__(self, attr):
class _LazyModule (line 127) | class _LazyModule(types.ModuleType):
method __init__ (line 128) | def __init__(self, name):
method __dir__ (line 132) | def __dir__(self):
class MovedAttribute (line 141) | class MovedAttribute(_LazyDescr):
method __init__ (line 142) | def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
method _resolve (line 160) | def _resolve(self):
class _SixMetaPathImporter (line 165) | class _SixMetaPathImporter(object):
method __init__ (line 174) | def __init__(self, six_module_name):
method _add_module (line 178) | def _add_module(self, mod, *fullnames):
method _get_module (line 182) | def _get_module(self, fullname):
method find_module (line 185) | def find_module(self, fullname, path=None):
method find_spec (line 190) | def find_spec(self, fullname, path, target=None):
method __get_module (line 195) | def __get_module(self, fullname):
method load_module (line 201) | def load_module(self, fullname):
method is_package (line 215) | def is_package(self, fullname):
method get_code (line 224) | def get_code(self, fullname):
method create_module (line 233) | def create_module(self, spec):
method exec_module (line 236) | def exec_module(self, module):
class _MovedItems (line 243) | class _MovedItems(_LazyModule):
class Module_six_moves_urllib_parse (line 352) | class Module_six_moves_urllib_parse(_LazyModule):
class Module_six_moves_urllib_error (line 399) | class Module_six_moves_urllib_error(_LazyModule):
class Module_six_moves_urllib_request (line 422) | class Module_six_moves_urllib_request(_LazyModule):
class Module_six_moves_urllib_response (line 477) | class Module_six_moves_urllib_response(_LazyModule):
class Module_six_moves_urllib_robotparser (line 501) | class Module_six_moves_urllib_robotparser(_LazyModule):
class Module_six_moves_urllib (line 524) | class Module_six_moves_urllib(types.ModuleType):
method __dir__ (line 535) | def __dir__(self):
function add_move (line 544) | def add_move(move):
function remove_move (line 549) | def remove_move(name):
function advance_iterator (line 582) | def advance_iterator(it):
function callable (line 593) | def callable(obj):
function get_unbound_function (line 599) | def get_unbound_function(unbound):
function create_unbound_method (line 604) | def create_unbound_method(func, cls):
function get_unbound_function (line 610) | def get_unbound_function(unbound):
function create_bound_method (line 613) | def create_bound_method(func, obj):
function create_unbound_method (line 616) | def create_unbound_method(func, cls):
class Iterator (line 619) | class Iterator(object):
method next (line 620) | def next(self):
function iterkeys (line 639) | def iterkeys(d, **kw):
function itervalues (line 642) | def itervalues(d, **kw):
function iteritems (line 645) | def iteritems(d, **kw):
function iterlists (line 648) | def iterlists(d, **kw):
function iterkeys (line 658) | def iterkeys(d, **kw):
function itervalues (line 661) | def itervalues(d, **kw):
function iteritems (line 664) | def iteritems(d, **kw):
function iterlists (line 667) | def iterlists(d, **kw):
function b (line 686) | def b(s):
function u (line 689) | def u(s):
function b (line 716) | def b(s):
function u (line 721) | def u(s):
function byte2int (line 727) | def byte2int(bs):
function indexbytes (line 730) | def indexbytes(buf, i):
function assertCountEqual (line 745) | def assertCountEqual(self, *args, **kwargs):
function assertRaisesRegex (line 749) | def assertRaisesRegex(self, *args, **kwargs):
function assertRegex (line 753) | def assertRegex(self, *args, **kwargs):
function assertNotRegex (line 757) | def assertNotRegex(self, *args, **kwargs):
function reraise (line 764) | def reraise(tp, value, tb=None):
function exec_ (line 777) | def exec_(_code_, _globs_=None, _locs_=None):
function raise_from (line 810) | def raise_from(value, from_value):
function print_ (line 817) | def print_(*args, **kwargs):
function print_ (line 878) | def print_(*args, **kwargs):
function _update_wrapper (line 894) | def _update_wrapper(
function wraps (line 914) | def wraps(
function with_metaclass (line 929) | def with_metaclass(meta, *bases):
function add_metaclass (line 953) | def add_metaclass(metaclass):
function ensure_binary (line 973) | def ensure_binary(s, encoding="utf-8", errors="strict"):
function ensure_str (line 991) | def ensure_str(s, encoding="utf-8", errors="strict"):
function ensure_text (line 1014) | def ensure_text(s, encoding="utf-8", errors="strict"):
function python_2_unicode_compatible (line 1033) | def python_2_unicode_compatible(klass):
FILE: resources/AccountCreationLambdaCode/urllib3/poolmanager.py
function _default_key_normalizer (line 79) | def _default_key_normalizer(key_class, request_context):
class PoolManager (line 140) | class PoolManager(RequestMethods):
method __init__ (line 171) | def __init__(self, num_pools=10, headers=None, **connection_pool_kw):
method __enter__ (line 181) | def __enter__(self):
method __exit__ (line 184) | def __exit__(self, exc_type, exc_val, exc_tb):
method _new_pool (line 189) | def _new_pool(self, scheme, host, port, request_context=None):
method clear (line 216) | def clear(self):
method connection_from_host (line 225) | def connection_from_host(self, host, port=None, scheme="http", pool_kw...
method connection_from_context (line 248) | def connection_from_context(self, request_context):
method connection_from_pool_key (line 263) | def connection_from_pool_key(self, pool_key, request_context=None):
method connection_from_url (line 287) | def connection_from_url(self, url, pool_kwargs=None):
method _merge_pool_kwargs (line 303) | def _merge_pool_kwargs(self, override):
method _proxy_requires_url_absolute_form (line 323) | def _proxy_requires_url_absolute_form(self, parsed_url):
method _validate_proxy_scheme_url_selection (line 336) | def _validate_proxy_scheme_url_selection(self, url_scheme):
method urlopen (line 353) | def urlopen(self, method, url, redirect=True, **kw):
class ProxyManager (line 421) | class ProxyManager(PoolManager):
method __init__ (line 461) | def __init__(
method connection_from_host (line 498) | def connection_from_host(self, host, port=None, scheme="http", pool_kw...
method _set_proxy_headers (line 508) | def _set_proxy_headers(self, url, headers=None):
method urlopen (line 523) | def urlopen(self, method, url, redirect=True, **kw):
function proxy_from_url (line 536) | def proxy_from_url(url, **kw):
FILE: resources/AccountCreationLambdaCode/urllib3/request.py
class RequestMethods (line 9) | class RequestMethods(object):
method __init__ (line 40) | def __init__(self, headers=None):
method urlopen (line 43) | def urlopen(
method request (line 58) | def request(self, method, url, fields=None, headers=None, **urlopen_kw):
method request_encode_url (line 82) | def request_encode_url(self, method, url, fields=None, headers=None, *...
method request_encode_body (line 98) | def request_encode_body(
FILE: resources/AccountCreationLambdaCode/urllib3/response.py
class DeflateDecoder (line 41) | class DeflateDecoder(object):
method __init__ (line 42) | def __init__(self):
method __getattr__ (line 47) | def __getattr__(self, name):
method decompress (line 50) | def decompress(self, data):
class GzipDecoderState (line 73) | class GzipDecoderState(object):
class GzipDecoder (line 80) | class GzipDecoder(object):
method __init__ (line 81) | def __init__(self):
method __getattr__ (line 85) | def __getattr__(self, name):
method decompress (line 88) | def decompress(self, data):
class BrotliDecoder (line 112) | class BrotliDecoder(object):
method __init__ (line 116) | def __init__(self):
method flush (line 123) | def flush(self):
class MultiDecoder (line 129) | class MultiDecoder(object):
method __init__ (line 138) | def __init__(self, modes):
method flush (line 141) | def flush(self):
method decompress (line 144) | def decompress(self, data):
function _get_decoder (line 150) | def _get_decoder(mode):
class HTTPResponse (line 163) | class HTTPResponse(io.IOBase):
method __init__ (line 201) | def __init__(
method get_redirect_location (line 268) | def get_redirect_location(self):
method release_conn (line 281) | def release_conn(self):
method drain_conn (line 288) | def drain_conn(self):
method data (line 300) | def data(self):
method connection (line 309) | def connection(self):
method isclosed (line 312) | def isclosed(self):
method tell (line 315) | def tell(self):
method _init_length (line 323) | def _init_length(self, request_method):
method _init_decoder (line 375) | def _init_decoder(self):
method _decode (line 398) | def _decode(self, data, decode_content, flush_decoder):
method _flush_decoder (line 420) | def _flush_decoder(self):
method _error_catcher (line 432) | def _error_catcher(self):
method _fp_read (line 487) | def _fp_read(self, amt):
method read (line 535) | def read(self, amt=None, decode_content=None, cache_content=False):
method stream (line 607) | def stream(self, amt=2 ** 16, decode_content=None):
method from_httplib (line 634) | def from_httplib(ResponseCls, r, **response_kw):
method getheaders (line 666) | def getheaders(self):
method getheader (line 675) | def getheader(self, name, default=None):
method info (line 685) | def info(self):
method close (line 689) | def close(self):
method closed (line 700) | def closed(self):
method fileno (line 712) | def fileno(self):
method flush (line 723) | def flush(self):
method readable (line 731) | def readable(self):
method readinto (line 735) | def readinto(self, b):
method supports_chunked_reads (line 744) | def supports_chunked_reads(self):
method _update_chunk_length (line 753) | def _update_chunk_length(self):
method _handle_chunk (line 767) | def _handle_chunk(self, amt):
method read_chunked (line 789) | def read_chunked(self, amt=None, decode_content=None):
method geturl (line 859) | def geturl(self):
method __iter__ (line 870) | def __iter__(self):
FILE: resources/AccountCreationLambdaCode/urllib3/util/connection.py
function is_connection_dropped (line 11) | def is_connection_dropped(conn): # Platform-specific
function create_connection (line 37) | def create_connection(
function _set_socket_options (line 100) | def _set_socket_options(sock, options):
function allowed_gai_family (line 108) | def allowed_gai_family():
function _has_ipv6 (line 119) | def _has_ipv6(host):
FILE: resources/AccountCreationLambdaCode/urllib3/util/proxy.py
function connection_requires_http_tunnel (line 4) | def connection_requires_http_tunnel(
function create_proxy_ssl_context (line 37) | def create_proxy_ssl_context(
FILE: resources/AccountCreationLambdaCode/urllib3/util/queue.py
class LifoQueue (line 11) | class LifoQueue(queue.Queue):
method _init (line 12) | def _init(self, _):
method _qsize (line 15) | def _qsize(self, len=len):
method _put (line 18) | def _put(self, item):
method _get (line 21) | def _get(self):
FILE: resources/AccountCreationLambdaCode/urllib3/util/request.py
function make_headers (line 29) | def make_headers(
function set_file_position (line 101) | def set_file_position(body, pos):
function rewind_body (line 119) | def rewind_body(body, body_pos):
FILE: resources/AccountCreationLambdaCode/urllib3/util/response.py
function is_fp_closed (line 9) | def is_fp_closed(obj):
function assert_header_parsing (line 40) | def assert_header_parsing(headers):
function is_response_to_head (line 94) | def is_response_to_head(response):
FILE: resources/AccountCreationLambdaCode/urllib3/util/retry.py
class _RetryMeta (line 35) | class _RetryMeta(type):
method DEFAULT_METHOD_WHITELIST (line 37) | def DEFAULT_METHOD_WHITELIST(cls):
method DEFAULT_METHOD_WHITELIST (line 46) | def DEFAULT_METHOD_WHITELIST(cls, value):
method DEFAULT_REDIRECT_HEADERS_BLACKLIST (line 55) | def DEFAULT_REDIRECT_HEADERS_BLACKLIST(cls):
method DEFAULT_REDIRECT_HEADERS_BLACKLIST (line 64) | def DEFAULT_REDIRECT_HEADERS_BLACKLIST(cls, value):
method BACKOFF_MAX (line 73) | def BACKOFF_MAX(cls):
method BACKOFF_MAX (line 82) | def BACKOFF_MAX(cls, value):
class Retry (line 92) | class Retry(object):
method __init__ (line 243) | def __init__(
method new (line 304) | def new(self, **kw):
method from_int (line 341) | def from_int(cls, retries, redirect=True, default=None):
method get_backoff_time (line 354) | def get_backoff_time(self):
method parse_retry_after (line 371) | def parse_retry_after(self, retry_after):
method get_retry_after (line 394) | def get_retry_after(self, response):
method sleep_for_retry (line 404) | def sleep_for_retry(self, response=None):
method _sleep_backoff (line 412) | def _sleep_backoff(self):
method sleep (line 418) | def sleep(self, response=None):
method _is_connection_error (line 434) | def _is_connection_error(self, err):
method _is_read_error (line 442) | def _is_read_error(self, err):
method _is_method_retryable (line 448) | def _is_method_retryable(self, method):
method is_retry (line 468) | def is_retry(self, method, status_code, has_retry_after=False):
method is_exhausted (line 488) | def is_exhausted(self):
method increment (line 504) | def increment(
method __repr__ (line 598) | def __repr__(self):
method __getattr__ (line 604) | def __getattr__(self, item):
FILE: resources/AccountCreationLambdaCode/urllib3/util/ssl_.py
function _const_compare_digest_backport (line 30) | def _const_compare_digest_backport(a, b):
class SSLContext (line 133) | class SSLContext(object): # Platform-specific: Python 2
method __init__ (line 134) | def __init__(self, protocol_version):
method load_cert_chain (line 145) | def load_cert_chain(self, certfile, keyfile):
method load_verify_locations (line 149) | def load_verify_locations(self, cafile=None, capath=None, cadata=None):
method set_ciphers (line 158) | def set_ciphers(self, cipher_suite):
method wrap_socket (line 161) | def wrap_socket(self, socket, server_hostname=None, server_side=False):
function assert_fingerprint (line 182) | def assert_fingerprint(cert, fingerprint):
function resolve_cert_reqs (line 211) | def resolve_cert_reqs(candidate):
function resolve_ssl_version (line 234) | def resolve_ssl_version(candidate):
function create_urllib3_context (line 250) | def create_urllib3_context(
function ssl_wrap_socket (line 355) | def ssl_wrap_socket(
function is_ipaddress (line 457) | def is_ipaddress(hostname):
function _is_key_file_encrypted (line 470) | def _is_key_file_encrypted(key_file):
function _ssl_wrap_socket_impl (line 481) | def _ssl_wrap_socket_impl(sock, ssl_context, tls_in_tls, server_hostname...
FILE: resources/AccountCreationLambdaCode/urllib3/util/ssl_match_hostname.py
class CertificateError (line 21) | class CertificateError(ValueError):
function _dnsname_match (line 25) | def _dnsname_match(dn, hostname, max_wildcards=1):
function _to_unicode (line 79) | def _to_unicode(obj):
function _ipaddress_match (line 86) | def _ipaddress_match(ipname, host_ip):
function match_hostname (line 98) | def match_hostname(cert, hostname):
FILE: resources/AccountCreationLambdaCode/urllib3/util/ssltransport.py
class SSLTransport (line 11) | class SSLTransport:
method _validate_ssl_context_for_tls_in_tls (line 23) | def _validate_ssl_context_for_tls_in_tls(ssl_context):
method __init__ (line 44) | def __init__(
method __enter__ (line 63) | def __enter__(self):
method __exit__ (line 66) | def __exit__(self, *_):
method fileno (line 69) | def fileno(self):
method read (line 72) | def read(self, len=1024, buffer=None):
method recv (line 75) | def recv(self, len=1024, flags=0):
method recv_into (line 80) | def recv_into(self, buffer, nbytes=None, flags=0):
method sendall (line 89) | def sendall(self, data, flags=0):
method send (line 99) | def send(self, data, flags=0):
method makefile (line 105) | def makefile(
method unwrap (line 150) | def unwrap(self):
method close (line 153) | def close(self):
method getpeercert (line 156) | def getpeercert(self, binary_form=False):
method version (line 159) | def version(self):
method cipher (line 162) | def cipher(self):
method selected_alpn_protocol (line 165) | def selected_alpn_protocol(self):
method selected_npn_protocol (line 168) | def selected_npn_protocol(self):
method shared_ciphers (line 171) | def shared_ciphers(self):
method compression (line 174) | def compression(self):
method settimeout (line 177) | def settimeout(self, value):
method gettimeout (line 180) | def gettimeout(self):
method _decref_socketios (line 183) | def _decref_socketios(self):
method _wrap_ssl_read (line 186) | def _wrap_ssl_read(self, len, buffer=None):
method _ssl_io_loop (line 195) | def _ssl_io_loop(self, func, *args):
FILE: resources/AccountCreationLambdaCode/urllib3/util/timeout.py
class Timeout (line 19) | class Timeout(object):
method __init__ (line 101) | def __init__(self, total=None, connect=_Default, read=_Default):
method __repr__ (line 107) | def __repr__(self):
method resolve_default_timeout (line 119) | def resolve_default_timeout(cls, timeout):
method _validate_timeout (line 123) | def _validate_timeout(cls, value, name):
method from_float (line 169) | def from_float(cls, timeout):
method clone (line 184) | def clone(self):
method start_connect (line 198) | def start_connect(self):
method get_connect_duration (line 209) | def get_connect_duration(self):
method connect_timeout (line 224) | def connect_timeout(self):
method read_timeout (line 242) | def read_timeout(self):
FILE: resources/AccountCreationLambdaCode/urllib3/util/url.py
class Url (line 82) | class Url(namedtuple("Url", url_attrs)):
method __new__ (line 91) | def __new__(
method hostname (line 110) | def hostname(self):
method request_uri (line 115) | def request_uri(self):
method netloc (line 125) | def netloc(self):
method url (line 132) | def url(self):
method __str__ (line 171) | def __str__(self):
function split_first (line 175) | def split_first(s, delims):
function _encode_invalid_chars (line 210) | def _encode_invalid_chars(component, allowed_chars, encoding="utf-8"):
function _remove_path_dot_segments (line 244) | def _remove_path_dot_segments(path):
function _normalize_host (line 274) | def _normalize_host(host, scheme):
function _idna_encode (line 305) | def _idna_encode(name):
function _encode_target (line 323) | def _encode_target(target):
function parse_url (line 333) | def parse_url(url):
function get_host (line 430) | def get_host(url):
FILE: resources/AccountCreationLambdaCode/urllib3/util/wait.py
class NoWayToWaitForSocketError (line 14) | class NoWayToWaitForSocketError(Exception):
function _retry_on_intr (line 42) | def _retry_on_intr(fn, timeout):
function _retry_on_intr (line 47) | def _retry_on_intr(fn, timeout):
function select_wait_for_socket (line 70) | def select_wait_for_socket(sock, read=False, write=False, timeout=None):
function poll_wait_for_socket (line 89) | def poll_wait_for_socket(sock, read=False, write=False, timeout=None):
function null_wait_for_socket (line 109) | def null_wait_for_socket(*args, **kwargs):
function _have_working_poll (line 113) | def _have_working_poll():
function wait_for_socket (line 126) | def wait_for_socket(*args, **kwargs):
function wait_for_read (line 141) | def wait_for_read(sock, timeout=None):
function wait_for_write (line 148) | def wait_for_write(sock, timeout=None):
Condensed preview — 82 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (637K chars).
[
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 197,
"preview": "*Issue #, if available:*\n\n*Description of changes:*\n\n\nBy submitting this pull request, I confirm that you can use, modif"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 309,
"preview": "## Code of Conduct\nThis project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-condu"
},
{
"path": "CONTRIBUTING.md",
"chars": 3643,
"preview": "# Contributing Guidelines\n\nThank you for your interest in contributing to our project. Whether it's a bug report, new fe"
},
{
"path": "LICENSE",
"chars": 931,
"preview": "Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n\nPermission is hereby granted, free of charge, t"
},
{
"path": "README.md",
"chars": 13992,
"preview": "## AWS Account Vending Machine\n\nThis repository contains various versions of the account vending machine used to provisi"
},
{
"path": "govcloud/LICENSE",
"chars": 931,
"preview": "Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n\nPermission is hereby granted, free of charge, t"
},
{
"path": "govcloud/README.md",
"chars": 23265,
"preview": "## AWS Account Vending Machine for GovCloud(US) region\nAWS Organizations works differently in the AWS GovCloud(US) regio"
},
{
"path": "govcloud/commercial-side-setup/CommercialAccountSetup.yaml",
"chars": 4996,
"preview": "#Copyright 2008-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n\n#Licensed under the Apache License, Versi"
},
{
"path": "govcloud/commercial-side-setup/commercial-account-avm-product.yaml",
"chars": 2566,
"preview": "# /*\r\n# * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r\n# *\r\n# * Permission is hereby gran"
},
{
"path": "govcloud/govcloud-side-setup/Accountbaseline.yml",
"chars": 15944,
"preview": "# /*\n# * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n# *\n# * Permission is hereby granted"
},
{
"path": "govcloud/govcloud-side-setup/GovCloudAccountSetup.yaml",
"chars": 6661,
"preview": "# /*\n# * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n# *\n# * Permission is hereby granted"
},
{
"path": "govcloud/govcloud-side-setup/govcloud-account-avm-product.yaml",
"chars": 3255,
"preview": "# /*\r\n# * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r\n# *\r\n# * Permission is hereby gran"
},
{
"path": "resources/AccountCreationLambdaCode/AccountCreationLambda.py",
"chars": 16476,
"preview": "\n#Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n\n#Licensed under the Apache License, Version 2"
},
{
"path": "resources/AccountCreationLambdaCode/cfnresponse/__init__.py",
"chars": 1352,
"preview": "# Copyright 2016 Amazon Web Services, Inc. or its affiliates. All Rights Reserved.\n# SPDX-License-Identifier: Apache-2"
},
{
"path": "resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/INSTALLER",
"chars": 4,
"preview": "pip\n"
},
{
"path": "resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/METADATA",
"chars": 2724,
"preview": "Metadata-Version: 2.1\nName: cfnresponse\nVersion: 1.1.2\nSummary: Send a response object to a custom resource by way of an"
},
{
"path": "resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/RECORD",
"chars": 706,
"preview": "cfnresponse-1.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4\r\ncfnresponse-1.1.2.dist-info/"
},
{
"path": "resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/REQUESTED",
"chars": 0,
"preview": ""
},
{
"path": "resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/WHEEL",
"chars": 110,
"preview": "Wheel-Version: 1.0\nGenerator: bdist_wheel (0.37.0)\nRoot-Is-Purelib: true\nTag: py2-none-any\nTag: py3-none-any\n\n"
},
{
"path": "resources/AccountCreationLambdaCode/cfnresponse-1.1.2.dist-info/top_level.txt",
"chars": 12,
"preview": "cfnresponse\n"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper/__init__.py",
"chars": 66,
"preview": "from crhelper.resource_helper import CfnResource, SUCCESS, FAILED\n"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper/__init__.pyi",
"chars": 218,
"preview": "\"\"\"\n*.pyi files are auto-generated with the following commands:\n\n$> pip install mypy\n$> stubgen ./crhelper -o .\n\"\"\"\nfrom"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper/log_helper.py",
"chars": 2665,
"preview": "from __future__ import print_function\nimport json\nimport logging\n\n\ndef _json_formatter(obj):\n \"\"\"Formatter for unseri"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper/log_helper.pyi",
"chars": 360,
"preview": "import logging\nfrom typing import Any, Optional\n\nclass JsonFormatter(logging.Formatter):\n format_dict: Any = ...\n "
},
{
"path": "resources/AccountCreationLambdaCode/crhelper/py.typed",
"chars": 0,
"preview": ""
},
{
"path": "resources/AccountCreationLambdaCode/crhelper/resource_helper.py",
"chars": 12934,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\nTODO:\n* Async mode – take a wait condition handle as an input, increases max timeout to 12 h"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper/resource_helper.pyi",
"chars": 1233,
"preview": "from crhelper import log_helper as log_helper\nfrom typing import Any, Callable, Optional, Union\n\nlogger: Any\nSUCCESS: st"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper/utils.py",
"chars": 2016,
"preview": "from __future__ import print_function\n\nimport json\nimport logging as logging\nimport ssl\nimport time\nfrom http.client imp"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper/utils.pyi",
"chars": 36,
"preview": "from typing import Any\n\nlogger: Any\n"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/PKG-INFO",
"chars": 7208,
"preview": "Metadata-Version: 2.1\nName: crhelper\nVersion: 2.0.11\nSummary: crhelper simplifies authoring CloudFormation Custom Resour"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/SOURCES.txt",
"chars": 373,
"preview": "LICENSE\nNOTICE\nREADME.md\nsetup.cfg\nsetup.py\ncrhelper/__init__.py\ncrhelper/__init__.pyi\ncrhelper/log_helper.py\ncrhelper/l"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/dependency_links.txt",
"chars": 1,
"preview": "\n"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/installed-files.txt",
"chars": 391,
"preview": "../crhelper/__init__.py\n../crhelper/__init__.pyc\n../crhelper/__init__.pyi\n../crhelper/log_helper.py\n../crhelper/log_help"
},
{
"path": "resources/AccountCreationLambdaCode/crhelper-2.0.11-py2.7.egg-info/top_level.txt",
"chars": 9,
"preview": "crhelper\n"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/__init__.py",
"chars": 3333,
"preview": "\"\"\"\nPython HTTP library with thread-safe connection pooling, file post support, user friendly, and more\n\"\"\"\nfrom __futur"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/_collections.py",
"chars": 10811,
"preview": "from __future__ import absolute_import\n\ntry:\n from collections.abc import Mapping, MutableMapping\nexcept ImportError:"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/_version.py",
"chars": 64,
"preview": "# This file is protected via CODEOWNERS\n__version__ = \"1.26.15\"\n"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/connection.py",
"chars": 20300,
"preview": "from __future__ import absolute_import\n\nimport datetime\nimport logging\nimport os\nimport re\nimport socket\nimport warnings"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/connectionpool.py",
"chars": 39128,
"preview": "from __future__ import absolute_import\n\nimport errno\nimport logging\nimport re\nimport socket\nimport sys\nimport warnings\nf"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/_appengine_environ.py",
"chars": 957,
"preview": "\"\"\"\nThis module provides means to detect the App Engine environment.\n\"\"\"\n\nimport os\n\n\ndef is_appengine():\n return is_"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/_securetransport/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/_securetransport/bindings.py",
"chars": 17632,
"preview": "\"\"\"\nThis module uses ctypes to bind a whole bunch of functions and constants from\nSecureTransport. The goal here is to p"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/_securetransport/low_level.py",
"chars": 13922,
"preview": "\"\"\"\nLow-level helpers for the SecureTransport bindings.\n\nThese are Python functions that are not directly related to the"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/appengine.py",
"chars": 11012,
"preview": "\"\"\"\nThis module provides a pool manager that uses Google App Engine's\n`URLFetch Service <https://cloud.google.com/appeng"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/ntlmpool.py",
"chars": 4528,
"preview": "\"\"\"\nNTLM authenticating pool, contributed by erikcederstran\n\nIssue #10, see: http://code.google.com/p/urllib3/issues/det"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/pyopenssl.py",
"chars": 17055,
"preview": "\"\"\"\nTLS with SNI_-support for Python 2. Follow these instructions if you would\nlike to verify TLS certificates in Python"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/securetransport.py",
"chars": 34416,
"preview": "\"\"\"\nSecureTranport support for urllib3 via ctypes.\n\nThis makes platform-native TLS available to urllib3 users on macOS w"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/contrib/socks.py",
"chars": 7097,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\nThis module contains provisional support for SOCKS proxies from within\nurllib3. This module "
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/exceptions.py",
"chars": 8217,
"preview": "from __future__ import absolute_import\n\nfrom .packages.six.moves.http_client import IncompleteRead as httplib_Incomplete"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/fields.py",
"chars": 8579,
"preview": "from __future__ import absolute_import\n\nimport email.utils\nimport mimetypes\nimport re\n\nfrom .packages import six\n\n\ndef g"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/filepost.py",
"chars": 2440,
"preview": "from __future__ import absolute_import\n\nimport binascii\nimport codecs\nimport os\nfrom io import BytesIO\n\nfrom .fields imp"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/packages/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/packages/backports/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/packages/backports/makefile.py",
"chars": 1417,
"preview": "# -*- coding: utf-8 -*-\n\"\"\"\nbackports.makefile\n~~~~~~~~~~~~~~~~~~\n\nBackports the Python 3 ``socket.makefile`` method for"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/packages/six.py",
"chars": 34665,
"preview": "# Copyright (c) 2010-2020 Benjamin Peterson\n#\n# Permission is hereby granted, free of charge, to any person obtaining a "
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/poolmanager.py",
"chars": 19786,
"preview": "from __future__ import absolute_import\n\nimport collections\nimport functools\nimport logging\n\nfrom ._collections import Re"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/request.py",
"chars": 5985,
"preview": "from __future__ import absolute_import\n\nfrom .filepost import encode_multipart_formdata\nfrom .packages.six.moves.urllib."
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/response.py",
"chars": 30761,
"preview": "from __future__ import absolute_import\n\nimport io\nimport logging\nimport sys\nimport warnings\nimport zlib\nfrom contextlib "
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/__init__.py",
"chars": 1155,
"preview": "from __future__ import absolute_import\n\n# For backwards compatibility, provide imports that used to be here.\nfrom .conne"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/connection.py",
"chars": 4901,
"preview": "from __future__ import absolute_import\n\nimport socket\n\nfrom ..contrib import _appengine_environ\nfrom ..exceptions import"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/proxy.py",
"chars": 1605,
"preview": "from .ssl_ import create_urllib3_context, resolve_cert_reqs, resolve_ssl_version\n\n\ndef connection_requires_http_tunnel(\n"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/queue.py",
"chars": 498,
"preview": "import collections\n\nfrom ..packages import six\nfrom ..packages.six.moves import queue\n\nif six.PY2:\n # Queue is import"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/request.py",
"chars": 4225,
"preview": "from __future__ import absolute_import\n\nfrom base64 import b64encode\n\nfrom ..exceptions import UnrewindableBodyError\nfro"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/response.py",
"chars": 3510,
"preview": "from __future__ import absolute_import\n\nfrom email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoun"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/retry.py",
"chars": 22003,
"preview": "from __future__ import absolute_import\n\nimport email\nimport logging\nimport re\nimport time\nimport warnings\nfrom collectio"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/ssl_.py",
"chars": 17165,
"preview": "from __future__ import absolute_import\n\nimport hmac\nimport os\nimport sys\nimport warnings\nfrom binascii import hexlify, u"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/ssl_match_hostname.py",
"chars": 5758,
"preview": "\"\"\"The match_hostname() function from Python 3.3.3, essential when using SSL.\"\"\"\n\n# Note: This file is under the PSF lic"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/ssltransport.py",
"chars": 6895,
"preview": "import io\nimport socket\nimport ssl\n\nfrom ..exceptions import ProxySchemeUnsupported\nfrom ..packages import six\n\nSSL_BLOC"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/timeout.py",
"chars": 10168,
"preview": "from __future__ import absolute_import\n\nimport time\n\n# The default socket timeout, used by httplib to indicate that no t"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/url.py",
"chars": 14279,
"preview": "from __future__ import absolute_import\n\nimport re\nfrom collections import namedtuple\n\nfrom ..exceptions import LocationP"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3/util/wait.py",
"chars": 5403,
"preview": "import errno\nimport select\nimport sys\nfrom functools import partial\n\ntry:\n from time import monotonic\nexcept ImportEr"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3-1.26.15.dist-info/INSTALLER",
"chars": 4,
"preview": "pip\n"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3-1.26.15.dist-info/LICENSE.txt",
"chars": 1115,
"preview": "MIT License\n\nCopyright (c) 2008-2020 Andrey Petrov and contributors (see CONTRIBUTORS.txt)\n\nPermission is hereby granted"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3-1.26.15.dist-info/METADATA",
"chars": 48122,
"preview": "Metadata-Version: 2.1\nName: urllib3\nVersion: 1.26.15\nSummary: HTTP library with thread-safe connection pooling, file pos"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3-1.26.15.dist-info/RECORD",
"chars": 4873,
"preview": "urllib3-1.26.15.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4\r\nurllib3-1.26.15.dist-info/LICE"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3-1.26.15.dist-info/WHEEL",
"chars": 110,
"preview": "Wheel-Version: 1.0\nGenerator: bdist_wheel (0.38.4)\nRoot-Is-Purelib: true\nTag: py2-none-any\nTag: py3-none-any\n\n"
},
{
"path": "resources/AccountCreationLambdaCode/urllib3-1.26.15.dist-info/top_level.txt",
"chars": 8,
"preview": "urllib3\n"
},
{
"path": "resources/AccountCreationLambdaSetup-cfn.yaml",
"chars": 5969,
"preview": "#Copyright 2008-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n\n#Licensed under the Apache License, Versi"
},
{
"path": "resources/Accountbaseline.yml",
"chars": 15257,
"preview": "#This is the baseline template that will be launched in the newly vended account\n#version1- creates a new IAM user with "
},
{
"path": "resources/accountbuilder.yml",
"chars": 4112,
"preview": "#Cloud Formation for vending a new account.\n#Copyright 2008-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved"
}
]
About this extraction
This page contains the full source code of the aws-samples/aws-account-vending-machine GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 82 files (592.0 KB), approximately 143.0k tokens, and a symbol index with 621 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.