Skip to content

Commit 3676d5c

Browse files
committed
Account provisioning customizations
0 parents  commit 3676d5c

File tree

10 files changed

+487
-0
lines changed

10 files changed

+487
-0
lines changed

.gitignore

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
### Linux ###
2+
*~
3+
4+
# temporary files which can be created if a process still has a handle open of a deleted file
5+
.fuse_hidden*
6+
7+
# KDE directory preferences
8+
.directory
9+
10+
# Linux trash folder which might appear on any partition or disk
11+
.Trash-*
12+
13+
# .nfs files are created when an open file is removed but is still being accessed
14+
.nfs*
15+
16+
### macOS ###
17+
# General
18+
.DS_Store
19+
.AppleDouble
20+
.LSOverride
21+
22+
# Icon must end with two \r
23+
Icon
24+
25+
26+
# Thumbnails
27+
._*
28+
29+
# Files that might appear in the root of a volume
30+
.DocumentRevisions-V100
31+
.fseventsd
32+
.Spotlight-V100
33+
.TemporaryItems
34+
.Trashes
35+
.VolumeIcon.icns
36+
.com.apple.timemachine.donotpresent
37+
38+
# Directories potentially created on remote AFP share
39+
.AppleDB
40+
.AppleDesktop
41+
Network Trash Folder
42+
Temporary Items
43+
.apdisk
44+
45+
### Python ###
46+
# Byte-compiled / optimized / DLL files
47+
__pycache__/
48+
*.py[cod]
49+
*$py.class
50+
51+
# C extensions
52+
*.so
53+
54+
# Distribution / packaging
55+
.Python
56+
develop-eggs/
57+
dist/
58+
downloads/
59+
eggs/
60+
.eggs/
61+
lib64/
62+
parts/
63+
sdist/
64+
var/
65+
wheels/
66+
share/python-wheels/
67+
*.egg-info/
68+
.installed.cfg
69+
*.egg
70+
MANIFEST
71+
72+
# PyInstaller
73+
# Usually these files are written by a python script from a template
74+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
75+
*.manifest
76+
*.spec
77+
78+
# Installer logs
79+
pip-log.txt
80+
pip-delete-this-directory.txt
81+
82+
# Unit test / coverage reports
83+
htmlcov/
84+
.tox/
85+
.nox/
86+
.coverage
87+
.coverage.*
88+
.cache
89+
nosetests.xml
90+
coverage.xml
91+
*.cover
92+
*.py,cover
93+
.hypothesis/
94+
.pytest_cache/
95+
cover/
96+
97+
# Translations
98+
*.mo
99+
*.pot
100+
101+
# Django stuff:
102+
*.log
103+
local_settings.py
104+
db.sqlite3
105+
db.sqlite3-journal
106+
107+
# Flask stuff:
108+
instance/
109+
.webassets-cache
110+
111+
# Scrapy stuff:
112+
.scrapy
113+
114+
# Sphinx documentation
115+
docs/_build/
116+
117+
# PyBuilder
118+
.pybuilder/
119+
target/
120+
121+
# Jupyter Notebook
122+
.ipynb_checkpoints
123+
124+
# IPython
125+
profile_default/
126+
ipython_config.py
127+
128+
# pyenv
129+
# For a library or package, you might want to ignore these files since the code is
130+
# intended to run in multiple environments; otherwise, check them in:
131+
# .python-version
132+
133+
# pipenv
134+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
135+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
136+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
137+
# install all needed dependencies.
138+
#Pipfile.lock
139+
140+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
141+
__pypackages__/
142+
143+
# Celery stuff
144+
celerybeat-schedule
145+
celerybeat.pid
146+
147+
# SageMath parsed files
148+
*.sage.py
149+
150+
# Environments
151+
.env
152+
.venv
153+
env/
154+
venv/
155+
ENV/
156+
env.bak/
157+
venv.bak/
158+
159+
# Spyder project settings
160+
.spyderproject
161+
.spyproject
162+
163+
# Rope project settings
164+
.ropeproject
165+
166+
# mkdocs documentation
167+
/site
168+
169+
# mypy
170+
.mypy_cache/
171+
.dmypy.json
172+
dmypy.json
173+
174+
# Pyre type checker
175+
.pyre/
176+
177+
# pytype static type analyzer
178+
.pytype/
179+
180+
# Cython debug symbols
181+
cython_debug/
182+
183+
### Terraform ###
184+
.terraform.lock.hcl
185+
backend.tf
186+
187+
# Local .terraform directories
188+
**/.terraform/*
189+
190+
# .tfstate files
191+
*.tfstate
192+
*.tfstate.*
193+
194+
# Crash log files
195+
crash.log
196+
197+
# Exclude all .tfvars files, which are likely to contain sentitive data, such as
198+
# password, private keys, and other secrets. These should not be part of version
199+
# control as they are data points which are potentially sensitive and subject
200+
# to change depending on the environment.
201+
#
202+
*.tfvars
203+
204+
# Ignore override files as they are usually used to override resources locally and so
205+
# are not checked in
206+
override.tf
207+
override.tf.json
208+
*_override.tf
209+
*_override.tf.json
210+
211+
# Include override files you do wish to add to version control using negated pattern
212+
# !example_override.tf
213+
214+
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
215+
# example: *tfplan*
216+
217+
# Ignore CLI configuration files
218+
.terraformrc
219+
terraform.rc
220+
221+
### Windows ###
222+
# Windows thumbnail cache files
223+
Thumbs.db
224+
Thumbs.db:encryptable
225+
ehthumbs.db
226+
ehthumbs_vista.db
227+
228+
# Dump file
229+
*.stackdump
230+
231+
# Folder config file
232+
[Dd]esktop.ini
233+
234+
# Recycle Bin used on file shares
235+
$RECYCLE.BIN/
236+
237+
# Windows Installer files
238+
*.cab
239+
*.msi
240+
*.msix
241+
*.msm
242+
*.msp
243+
244+
# Windows shortcuts
245+
*.lnk

README.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Learn Terraform - Use Control Tower Account Factory for Terraform
2+
3+
This is a companion repository for the [Provision and Manage Accounts with
4+
Control Tower Account Factory for Terraform
5+
tutorial](https://learn.hashicorp.com/tutorials/terraform/aws-control-tower-aft)
6+
tutorial on HashiCorp Learn.
7+
8+
This repository contains boilerplate configuration for defining account
9+
provisioning customizations to use with the Account Factory for Terraform
10+
module. The README below and the template files in this repository were
11+
provided by AWS.
12+
13+
To create your own state machine and step functions, replicate this repository
14+
and extend the Terraform configuration.
15+
16+
## AFT Account Provisioning Customizations Customizations
17+
18+
### Problem Statement
19+
20+
AFT provides flexibility to customize the provisioning process for new accounts and integrate with systems prior to the account customization stage.
21+
22+
While the customization stage does include integrations for pre- and post-
23+
customization steps, the Account Provisioning standard allows for further
24+
integration by using an AWS Step Functions State Machine to integrate with
25+
additional environments.
26+
27+
Using this state machine integration, customers may define Account Provisioning
28+
Customizations steps as:
29+
30+
* Lambda functions in the language of their choice
31+
* ECS or Fargate Tasks using docker containers
32+
* AWS Step Functions Activities using custom workers, hosted either in AWS or on-prem
33+
* Amazon SNS or SQS integrations to decoupled consumer-based applications
34+
35+
### Example Payload
36+
37+
```
38+
{
39+
"account_request": {
40+
"supported_regions": "",
41+
"account_tags": {
42+
"Key": "Value",
43+
},
44+
"custom_fields": "{}",
45+
"id": "Account Email",
46+
"control_tower_parameters": {
47+
"SSOUserEmail": "",
48+
"AccountEmail": "",
49+
"SSOUserFirstName": "",
50+
"SSOUserLastName": "",
51+
"ManagedOrganizationalUnit": "Sandbox",
52+
"AccountName": "sandbox03"
53+
},
54+
"customer_baselines": [],
55+
"operation": "create"
56+
},
57+
"control_tower_event": {},
58+
"validated": {
59+
"Success": true
60+
},
61+
"account_info": {
62+
"account": {
63+
"id": "",
64+
"type": "account",
65+
"email": "",
66+
"name": "sandbox03",
67+
"method": "CREATED",
68+
"joined_date": "2021-06-15 13:57:35.129000+00:00",
69+
"status": "ACTIVE",
70+
"parent_id": "",
71+
"parent_type": "ORGANIZATIONAL_UNIT",
72+
"org_name": "Sandbox",
73+
"vendor": "aws"
74+
}
75+
},
76+
"persist_metadata": {
77+
"StatusCode": 200
78+
},
79+
"role": {
80+
"Arn": "arn:aws:iam:::role/AWSAFTExecution"
81+
},
82+
"account_tags": {
83+
"StatusCode": 200
84+
}
85+
}
86+
```
87+
88+
89+
### Example Function
90+
91+
##### Validate Request:
92+
93+
Source location: `modules/account-provisioning-customizations/lambda/account-provisioning-customizations-validate-request/lambda_function.py`
94+
95+
###### Description:
96+
97+
Compares the incoming payload to the state machine against an expected
98+
jsonschema. Returns `True` if valid, raises an exception if not.
99+
100+
Demonstrates the import of `aft_common` and customers can explore the `aft_utils` module for existing AFT integrations, such as role assumption or SSM parameter retrieval.
101+
102+
```python
103+
import json
104+
import os
105+
import boto3
106+
import jsonschema
107+
import aft_common.aft_utils as utils
108+
from boto3.dynamodb.conditions import Key
109+
110+
111+
logger = utils.get_logger()
112+
113+
114+
def validate_request(payload, logger):
115+
logger.info("Function Start - validate_request")
116+
schema_path = os.path.join(os.path.dirname(__file__), "schema/request_schema.json")
117+
with open(schema_path) as schema_file:
118+
schema_object = json.load(schema_file)
119+
logger.info("Schema Loaded:" + json.dumps(schema_object))
120+
validated = jsonschema.validate(payload, schema_object)
121+
if validated is None:
122+
logger.info("Request Validated")
123+
return True
124+
else:
125+
raise Exception("Failure validating request.\n{validated}")
126+
127+
128+
def lambda_handler(event, context):
129+
logger.info("Account Provisioning Customizations Handler Start")
130+
131+
payload = event['payload']
132+
action = event['action']
133+
134+
if action == "validate":
135+
request_validated = validate_request(payload, logger)
136+
return request_validated
137+
else:
138+
raise BaseException(
139+
"Incorrect Command Passed to Lambda Function. Input: {action}. Expected: 'validate'"
140+
)
141+
142+
```
143+

0 commit comments

Comments
 (0)