Skip to content

Commit 1ed3ea3

Browse files
rjjaegerawsColinL2021carlos
authored
ca-west-1 config sample and documentation (#1225)
* initial yyc docs * added sample multi-region config and updated network image * updates to yyc content * updated yyc docs * update yyc * Adding instructions to run automatic optin script * Files for the region enabler script * cross region peering example --------- Co-authored-by: Colin Lavallee <[email protected]> Co-authored-by: carlos <[email protected]>
1 parent 6cfa5eb commit 1ed3ea3

12 files changed

+20283
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
## AWS SEA Multi-account Opt-In scripts
2+
3+
The Opt In script is intended to assist in automatically enabling or disabling AWS Opt-In regions for already existing accounts in an ASEA deployment.
4+
5+
The region must be manually enabled for the Management Account first and and [Trusted Access] (https://docs.aws.amazon.com/accounts/latest/reference/using-orgs-trusted-access.html) also enabled
6+
7+
## Details
8+
9+
The logic of the script is the following:
10+
11+
1. Intakes paramters for: Opt-In Region, Action, and ignored OUs
12+
13+
2. Queries the Management Account's AWS Organizations API for account and OU structure
14+
15+
3. Creates a structured list of account numbers
16+
17+
4. Launches multiple threads and executes the enable/disable action based on the paramters passed
18+
19+
## Instructions
20+
21+
1. Log into the AWS console as a Full Administrator to the Organization Management account.
22+
2. Start a CloudShell session.
23+
3. Copy the files from this folder to the CloudShell session;
24+
4. Create a virtual python environment. `python3 -m venv env`
25+
5. Activate the python environment. `source env/bin/activate`
26+
6. Install the python3 required libaries (ex: `pip install -r requirements.txt`).
27+
7. Make the Python script executable (ex: `chmod +x region_optin.py`).
28+
8. Execute the script with the following parameters:
29+
`--OptInRegion` *region*
30+
`--Action` *enable / disable / status*
31+
32+
Optional:
33+
`--IgnoreOU` *ou*
34+
35+
Example: `python3 region_optin.py --OptInRegion ca-west-1 --Action=enable`
36+
37+
## Requirements
38+
39+
-boto3
40+
-autopep8
41+
-other
42+
43+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import os
2+
import boto3
3+
from botocore.config import Config
4+
import sys
5+
import threading
6+
import argparse
7+
import time
8+
9+
parser = argparse.ArgumentParser(
10+
description='A development script that enables opt-in regions across all accounts. Use Administrator AWS credentials in the root account when running this script.'
11+
)
12+
parser.add_argument(
13+
'--OptInRegion',
14+
help='The opt-in region to enable/disable',
15+
required=True)
16+
parser.add_argument(
17+
'--IgnoreOU',
18+
default='Ignore',
19+
help='AWS Accounts in this OU will be ignored')
20+
parser.add_argument(
21+
'--Action',
22+
default='Enable',
23+
help='AWS Accounts in this OU will be ignored',
24+
required=True)
25+
26+
organizations_client = boto3.client('organizations')
27+
account_client = boto3.client('account')
28+
sts = boto3.client('sts')
29+
30+
31+
def get_all_accounts_by_ou(parentId, organizationUnits,
32+
organizationUnitsToSkip):
33+
all_accounts = []
34+
if parentId is None:
35+
paginator = organizations_client.get_paginator('list_roots')
36+
page_iterator = paginator.paginate()
37+
for root_item in page_iterator:
38+
item = root_item['Roots'][0]
39+
if item['Name'] == 'Root' and item['Id'] and item['Arn']:
40+
parentId = item['Id']
41+
break
42+
43+
paginator = organizations_client.get_paginator(
44+
'list_organizational_units_for_parent')
45+
page_iterator = paginator.paginate(ParentId=parentId)
46+
for ous_paged in page_iterator:
47+
for ou in ous_paged['OrganizationalUnits']:
48+
if ou['Name'] not in organizationUnitsToSkip:
49+
all_accounts = all_accounts + \
50+
get_accounts_by_parentId(ou['Id'])
51+
52+
all_accounts = all_accounts + get_accounts_by_parentId(parentId)
53+
54+
return all_accounts
55+
56+
57+
def get_accounts_by_parentId(parent_id):
58+
all_aws_accounts = []
59+
paginator = organizations_client.get_paginator('list_accounts_for_parent')
60+
page_iterator = paginator.paginate(ParentId=parent_id)
61+
for accounts_paged in page_iterator:
62+
for aws_account in accounts_paged['Accounts']:
63+
all_aws_accounts.append(aws_account['Id'])
64+
return all_aws_accounts
65+
66+
67+
def opt_in(region, all_accounts, action):
68+
print('Opting in accounts for {}'.format(region))
69+
70+
aws_organziation = organizations_client.describe_organization()
71+
72+
rootAccountId = aws_organziation['Organization']['MasterAccountId']
73+
74+
print('Opt-in for {} for management account {} must be done manually first'.format(region, rootAccountId))
75+
76+
threads = list()
77+
try:
78+
count = 0
79+
for accountId in all_accounts:
80+
count = count + 1
81+
if count % 15 == 0:
82+
for index, thread in enumerate(threads):
83+
thread.join()
84+
if accountId != rootAccountId:
85+
t = threading.Thread(
86+
target=thread_opt_in, args=(
87+
region, accountId,action))
88+
threads.append(t)
89+
t.start()
90+
except BaseException:
91+
print('Error', sys.exc_info()[0], 'occurred')
92+
finally:
93+
for index, thread in enumerate(threads):
94+
thread.join()
95+
print('Done. All opt in threads finished')
96+
97+
98+
def thread_opt_in(region, accountId,action):
99+
print('Processing {} for {} in TID={}'.format(
100+
region, accountId, threading.get_ident()))
101+
102+
config = Config(
103+
retries={
104+
'max_attempts': 3,
105+
'mode': 'standard'
106+
}
107+
)
108+
109+
account_client_tr = boto3.client('account', config=config)
110+
111+
region_status = account_client_tr.get_region_opt_status(
112+
AccountId=accountId, RegionName=region)
113+
114+
print(
115+
'{} is {} for {}'.format(
116+
region_status['RegionName'],
117+
region_status['RegionOptStatus'],
118+
accountId))
119+
120+
if action == "status":
121+
return
122+
123+
#Enable region if disabled
124+
if region_status['RegionOptStatus'] == 'DISABLED' and action=="enable":
125+
print('Enabling {} for {}...'.format(region, accountId))
126+
try:
127+
account_client_tr.enable_region(
128+
AccountId=accountId, RegionName=region)
129+
status = None
130+
while status != 'ENABLED':
131+
time.sleep(5)
132+
region_status = account_client_tr.get_region_opt_status(
133+
AccountId=accountId, RegionName=region)
134+
status = region_status['RegionOptStatus']
135+
print(
136+
'Status: {} {} for {}'.format(
137+
status, region, accountId))
138+
finally:
139+
print('Enabling {} for {}. Done'.format(region, accountId))
140+
141+
#Disable region if enabled
142+
143+
if region_status['RegionOptStatus'] == 'ENABLED' and action=="disable":
144+
print('Disabling {} for {}...'.format(region, accountId))
145+
try:
146+
account_client_tr.disable_region(
147+
AccountId=accountId, RegionName=region)
148+
status = None
149+
while status != 'DISABLED':
150+
time.sleep(5)
151+
region_status = account_client_tr.get_region_opt_status(
152+
AccountId=accountId, RegionName=region)
153+
status = region_status['RegionOptStatus']
154+
print(
155+
'Status: {} {} for {}'.format(
156+
status, region, accountId))
157+
finally:
158+
print('Disabling {} for {}. Done'.format(region, accountId))
159+
160+
161+
if __name__ == '__main__':
162+
parser.parse_args()
163+
args = parser.parse_args()
164+
all_accounts = get_all_accounts_by_ou(None, [], args.IgnoreOU)
165+
print ("Action: " + args.Action)
166+
opt_in(args.OptInRegion, all_accounts, args.Action)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
boto3
2+
autopep8

0 commit comments

Comments
 (0)