-
Notifications
You must be signed in to change notification settings - Fork 233
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]>
- Loading branch information
1 parent
6cfa5eb
commit 1ed3ea3
Showing
12 changed files
with
20,283 additions
and
0 deletions.
There are no files selected for viewing
43 changes: 43 additions & 0 deletions
43
reference-artifacts/Custom-Scripts/Region-OptIn-Script/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
## AWS SEA Multi-account Opt-In scripts | ||
|
||
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. | ||
|
||
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 | ||
|
||
## Details | ||
|
||
The logic of the script is the following: | ||
|
||
1. Intakes paramters for: Opt-In Region, Action, and ignored OUs | ||
|
||
2. Queries the Management Account's AWS Organizations API for account and OU structure | ||
|
||
3. Creates a structured list of account numbers | ||
|
||
4. Launches multiple threads and executes the enable/disable action based on the paramters passed | ||
|
||
## Instructions | ||
|
||
1. Log into the AWS console as a Full Administrator to the Organization Management account. | ||
2. Start a CloudShell session. | ||
3. Copy the files from this folder to the CloudShell session; | ||
4. Create a virtual python environment. `python3 -m venv env` | ||
5. Activate the python environment. `source env/bin/activate` | ||
6. Install the python3 required libaries (ex: `pip install -r requirements.txt`). | ||
7. Make the Python script executable (ex: `chmod +x region_optin.py`). | ||
8. Execute the script with the following parameters: | ||
`--OptInRegion` *region* | ||
`--Action` *enable / disable / status* | ||
|
||
Optional: | ||
`--IgnoreOU` *ou* | ||
|
||
Example: `python3 region_optin.py --OptInRegion ca-west-1 --Action=enable` | ||
|
||
## Requirements | ||
|
||
-boto3 | ||
-autopep8 | ||
-other | ||
|
||
|
166 changes: 166 additions & 0 deletions
166
reference-artifacts/Custom-Scripts/Region-OptIn-Script/region_optin.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
import os | ||
import boto3 | ||
from botocore.config import Config | ||
import sys | ||
import threading | ||
import argparse | ||
import time | ||
|
||
parser = argparse.ArgumentParser( | ||
description='A development script that enables opt-in regions across all accounts. Use Administrator AWS credentials in the root account when running this script.' | ||
) | ||
parser.add_argument( | ||
'--OptInRegion', | ||
help='The opt-in region to enable/disable', | ||
required=True) | ||
parser.add_argument( | ||
'--IgnoreOU', | ||
default='Ignore', | ||
help='AWS Accounts in this OU will be ignored') | ||
parser.add_argument( | ||
'--Action', | ||
default='Enable', | ||
help='AWS Accounts in this OU will be ignored', | ||
required=True) | ||
|
||
organizations_client = boto3.client('organizations') | ||
account_client = boto3.client('account') | ||
sts = boto3.client('sts') | ||
|
||
|
||
def get_all_accounts_by_ou(parentId, organizationUnits, | ||
organizationUnitsToSkip): | ||
all_accounts = [] | ||
if parentId is None: | ||
paginator = organizations_client.get_paginator('list_roots') | ||
page_iterator = paginator.paginate() | ||
for root_item in page_iterator: | ||
item = root_item['Roots'][0] | ||
if item['Name'] == 'Root' and item['Id'] and item['Arn']: | ||
parentId = item['Id'] | ||
break | ||
|
||
paginator = organizations_client.get_paginator( | ||
'list_organizational_units_for_parent') | ||
page_iterator = paginator.paginate(ParentId=parentId) | ||
for ous_paged in page_iterator: | ||
for ou in ous_paged['OrganizationalUnits']: | ||
if ou['Name'] not in organizationUnitsToSkip: | ||
all_accounts = all_accounts + \ | ||
get_accounts_by_parentId(ou['Id']) | ||
|
||
all_accounts = all_accounts + get_accounts_by_parentId(parentId) | ||
|
||
return all_accounts | ||
|
||
|
||
def get_accounts_by_parentId(parent_id): | ||
all_aws_accounts = [] | ||
paginator = organizations_client.get_paginator('list_accounts_for_parent') | ||
page_iterator = paginator.paginate(ParentId=parent_id) | ||
for accounts_paged in page_iterator: | ||
for aws_account in accounts_paged['Accounts']: | ||
all_aws_accounts.append(aws_account['Id']) | ||
return all_aws_accounts | ||
|
||
|
||
def opt_in(region, all_accounts, action): | ||
print('Opting in accounts for {}'.format(region)) | ||
|
||
aws_organziation = organizations_client.describe_organization() | ||
|
||
rootAccountId = aws_organziation['Organization']['MasterAccountId'] | ||
|
||
print('Opt-in for {} for management account {} must be done manually first'.format(region, rootAccountId)) | ||
|
||
threads = list() | ||
try: | ||
count = 0 | ||
for accountId in all_accounts: | ||
count = count + 1 | ||
if count % 15 == 0: | ||
for index, thread in enumerate(threads): | ||
thread.join() | ||
if accountId != rootAccountId: | ||
t = threading.Thread( | ||
target=thread_opt_in, args=( | ||
region, accountId,action)) | ||
threads.append(t) | ||
t.start() | ||
except BaseException: | ||
print('Error', sys.exc_info()[0], 'occurred') | ||
finally: | ||
for index, thread in enumerate(threads): | ||
thread.join() | ||
print('Done. All opt in threads finished') | ||
|
||
|
||
def thread_opt_in(region, accountId,action): | ||
print('Processing {} for {} in TID={}'.format( | ||
region, accountId, threading.get_ident())) | ||
|
||
config = Config( | ||
retries={ | ||
'max_attempts': 3, | ||
'mode': 'standard' | ||
} | ||
) | ||
|
||
account_client_tr = boto3.client('account', config=config) | ||
|
||
region_status = account_client_tr.get_region_opt_status( | ||
AccountId=accountId, RegionName=region) | ||
|
||
print( | ||
'{} is {} for {}'.format( | ||
region_status['RegionName'], | ||
region_status['RegionOptStatus'], | ||
accountId)) | ||
|
||
if action == "status": | ||
return | ||
|
||
#Enable region if disabled | ||
if region_status['RegionOptStatus'] == 'DISABLED' and action=="enable": | ||
print('Enabling {} for {}...'.format(region, accountId)) | ||
try: | ||
account_client_tr.enable_region( | ||
AccountId=accountId, RegionName=region) | ||
status = None | ||
while status != 'ENABLED': | ||
time.sleep(5) | ||
region_status = account_client_tr.get_region_opt_status( | ||
AccountId=accountId, RegionName=region) | ||
status = region_status['RegionOptStatus'] | ||
print( | ||
'Status: {} {} for {}'.format( | ||
status, region, accountId)) | ||
finally: | ||
print('Enabling {} for {}. Done'.format(region, accountId)) | ||
|
||
#Disable region if enabled | ||
|
||
if region_status['RegionOptStatus'] == 'ENABLED' and action=="disable": | ||
print('Disabling {} for {}...'.format(region, accountId)) | ||
try: | ||
account_client_tr.disable_region( | ||
AccountId=accountId, RegionName=region) | ||
status = None | ||
while status != 'DISABLED': | ||
time.sleep(5) | ||
region_status = account_client_tr.get_region_opt_status( | ||
AccountId=accountId, RegionName=region) | ||
status = region_status['RegionOptStatus'] | ||
print( | ||
'Status: {} {} for {}'.format( | ||
status, region, accountId)) | ||
finally: | ||
print('Disabling {} for {}. Done'.format(region, accountId)) | ||
|
||
|
||
if __name__ == '__main__': | ||
parser.parse_args() | ||
args = parser.parse_args() | ||
all_accounts = get_all_accounts_by_ou(None, [], args.IgnoreOU) | ||
print ("Action: " + args.Action) | ||
opt_in(args.OptInRegion, all_accounts, args.Action) |
2 changes: 2 additions & 0 deletions
2
reference-artifacts/Custom-Scripts/Region-OptIn-Script/requirements.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
boto3 | ||
autopep8 |
Oops, something went wrong.