-
Notifications
You must be signed in to change notification settings - Fork 235
Feature: Account Management Statemachine will now opt-in to target regions when creating an account #604
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sbkok
merged 6 commits into
awslabs:master
from
StewartW:feat/enable-regions-in-account-management-pipeline
Jul 24, 2023
Merged
Feature: Account Management Statemachine will now opt-in to target regions when creating an account #604
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
f51f08f
Initial commit for enabling regions via the API
StewartW 759ca8e
Code Review Changes
StewartW 6ab3610
Update src/template.yml
StewartW 243ddb2
Merge remote-tracking branch 'upstream/master' into feat/enable-regio…
sbkok 6960eba
Fix line length - fixes lint issue
sbkok caea9a9
Merge branch 'master' into feat/enable-regions-in-account-management-…
javydekoning File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
103 changes: 103 additions & 0 deletions
103
src/lambda_codebase/account_processing/configure_account_regions.py
This file contains hidden or 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,103 @@ | ||
| # Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| # SPDX-License-Identifier: MIT-0 | ||
|
|
||
| """ | ||
| Takes regions that the account is not-opted into and opts into them. | ||
| """ | ||
| from ast import literal_eval | ||
|
|
||
|
|
||
| import boto3 | ||
| from aws_xray_sdk.core import patch_all | ||
| from logger import configure_logger | ||
|
|
||
| patch_all() | ||
| LOGGER = configure_logger(__name__) | ||
|
|
||
|
|
||
| def get_regions_from_ssm(ssm_client): | ||
| regions = ssm_client.get_parameter(Name="target_regions")["Parameter"].get("Value") | ||
| regions = literal_eval(regions) | ||
| return regions | ||
|
|
||
|
|
||
| def get_region_status(account_client, **list_region_args): | ||
| region_status_response = account_client.list_regions(**list_region_args) | ||
| region_status = { | ||
| region.get("RegionName"): region.get("RegionOptStatus") | ||
| for region in region_status_response.get("Regions") | ||
| } | ||
| # Currently no built in paginator for list_regions... | ||
| # So we have to do this manually. | ||
| next_token = region_status_response.get("NextToken") | ||
| if next_token: | ||
| while next_token: | ||
| list_region_args["NextToken"] = next_token | ||
| region_status_response = account_client.list_regions(**list_region_args) | ||
| next_token = region_status_response.get("NextToken") | ||
| region_status = region_status | { | ||
| region.get("RegionName"): region.get("RegionOptStatus") | ||
| for region in region_status_response.get("Regions") | ||
| } | ||
| return region_status | ||
|
|
||
|
|
||
| def enable_regions_for_account( | ||
| account_client, account_id, desired_regions, org_root_account_id | ||
| ): | ||
| list_region_args = {} | ||
| enable_region_args = {} | ||
| target_is_different_account = org_root_account_id != account_id | ||
| if target_is_different_account: | ||
| list_region_args["AccountId"] = account_id | ||
| enable_region_args["AccountId"] = account_id | ||
|
|
||
| region_status = get_region_status(account_client, **list_region_args) | ||
|
|
||
| regions_enabled = {} | ||
| for region in desired_regions: | ||
| regions_enabled[region] = False | ||
sbkok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| desired_region_status = region_status.get(region.lower()) | ||
| if not desired_region_status: | ||
| LOGGER.warning("Unable to obtain status of %s, not enabling") | ||
| if desired_region_status == "DISABLED": | ||
| LOGGER.info("Enabling Region %s because it is currently Disabled", region) | ||
| enable_region_args["RegionName"] = region.lower() | ||
| account_client.enable_region(**enable_region_args) | ||
| else: | ||
| LOGGER.info( | ||
| "Not enabling Region: %s because it is: %s", | ||
| region, | ||
| desired_region_status, | ||
| ) | ||
| if desired_region_status in ["ENABLED_BY_DEFAULT", "ENABLED"]: | ||
| regions_enabled[region] = True | ||
| LOGGER.info(regions_enabled) | ||
| return all(regions_enabled.values()) | ||
|
|
||
|
|
||
| def lambda_handler(event, _): | ||
| desired_regions = [] | ||
| if event.get("regions"): | ||
| LOGGER.info( | ||
| "Account Level Regions is not currently supported." | ||
| "Ignoring these values for now and using SSM only" | ||
| ) | ||
| desired_regions.extend(get_regions_from_ssm(boto3.client("ssm"))) | ||
| org_root_account_id = boto3.client("sts").get_caller_identity().get("Account") | ||
| target_account_id = event.get("account_id") | ||
| LOGGER.info( | ||
| "Target Account Id: %s - This is running in %s. These are the same: %s", | ||
| target_account_id, | ||
| org_root_account_id, | ||
| target_account_id == org_root_account_id, | ||
| ) | ||
| all_regions_enabled = enable_regions_for_account( | ||
| boto3.client("account"), | ||
| target_account_id, | ||
| desired_regions, | ||
| org_root_account_id, | ||
| ) | ||
| event["all_regions_enabled"] = all_regions_enabled | ||
|
|
||
| return event | ||
120 changes: 120 additions & 0 deletions
120
src/lambda_codebase/account_processing/tests/test_configure_account_regions.py
This file contains hidden or 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,120 @@ | ||
| """ | ||
| Tests the account alias configuration lambda | ||
| """ | ||
|
|
||
| import unittest | ||
| import boto3 | ||
| from botocore.stub import Stubber | ||
| from aws_xray_sdk import global_sdk_config | ||
| from ..configure_account_regions import get_regions_from_ssm, enable_regions_for_account | ||
|
|
||
| global_sdk_config.set_sdk_enabled(False) | ||
|
|
||
|
|
||
| class SuccessTestCase(unittest.TestCase): | ||
| def test_get_regions_from_ssm(self): | ||
| ssm_client = boto3.client("ssm", region_name="us-east-1") | ||
| ssm_stubber = Stubber(ssm_client) | ||
| ssm_stubber.add_response("get_parameter", {"Parameter": {"Value": "[1,2,3]"}}) | ||
| ssm_stubber.activate() | ||
| self.assertListEqual(get_regions_from_ssm(ssm_client), [1, 2, 3]) | ||
|
|
||
| def test_enable_regions_for_account(self): | ||
| accounts_client = boto3.client("account", region_name="us-east-1") | ||
| account_stubber = Stubber(accounts_client) | ||
| account_stubber.add_response( | ||
| "list_regions", | ||
| { | ||
| "Regions": [ | ||
| {"RegionName": "us-east-1", "RegionOptStatus": "ENABLED_BY_DEFAULT"} | ||
| ] | ||
| }, | ||
| ) | ||
| account_stubber.activate() | ||
| self.assertTrue( | ||
| enable_regions_for_account( | ||
| accounts_client, | ||
| "123456789", | ||
| desired_regions=["us-east-1"], | ||
| org_root_account_id="123456789", | ||
| ) | ||
| ) | ||
|
|
||
| def test_enable_regions_for_account_with_pagination(self): | ||
| accounts_client = boto3.client("account", region_name="us-east-1") | ||
| account_stubber = Stubber(accounts_client) | ||
| account_stubber.add_response( | ||
| "list_regions", | ||
| { | ||
| "Regions": [ | ||
| {"RegionName": "us-east-1", "RegionOptStatus": "ENABLED_BY_DEFAULT"} | ||
| ], | ||
| "NextToken": "1", | ||
| }, | ||
| ) | ||
| account_stubber.add_response( | ||
| "list_regions", | ||
| { | ||
| "Regions": [ | ||
| {"RegionName": "af-south-1", "RegionOptStatus": "DISABLED"} | ||
| ], | ||
| "NextToken": "2", | ||
| }, | ||
| ) | ||
| account_stubber.add_response( | ||
| "list_regions", | ||
| {"Regions": [{"RegionName": "sco-west-1", "RegionOptStatus": "DISABLED"}]}, | ||
| ) | ||
| account_stubber.add_response( | ||
| "enable_region", | ||
| {}, | ||
| {"RegionName": "af-south-1"}, | ||
| ) | ||
| account_stubber.add_response( | ||
| "enable_region", | ||
| {}, | ||
| {"RegionName": "sco-west-1"}, | ||
| ) | ||
| account_stubber.activate() | ||
| self.assertFalse( | ||
| enable_regions_for_account( | ||
| accounts_client, | ||
| "123456789", | ||
| desired_regions=["us-east-1", "af-south-1", "sco-west-1"], | ||
| org_root_account_id="123456789", | ||
| ) | ||
| ) | ||
| account_stubber.assert_no_pending_responses() | ||
StewartW marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| def test_enable_regions_for_account_that_is_not_current_account(self): | ||
| accounts_client = boto3.client("account", region_name="us-east-1") | ||
| account_stubber = Stubber(accounts_client) | ||
| account_stubber.add_response( | ||
| "list_regions", | ||
| { | ||
| "Regions": [ | ||
| { | ||
| "RegionName": "us-east-1", | ||
| "RegionOptStatus": "ENABLED_BY_DEFAULT", | ||
| }, | ||
| {"RegionName": "sco-west-1", "RegionOptStatus": "DISABLED"}, | ||
| ] | ||
| }, | ||
| ) | ||
| account_stubber.add_response( | ||
| "enable_region", | ||
| {}, | ||
| { | ||
| "RegionName": "sco-west-1", | ||
| "AccountId": "123456789", | ||
| }, | ||
| ) | ||
| account_stubber.activate() | ||
| self.assertFalse( | ||
| enable_regions_for_account( | ||
| accounts_client, | ||
| "123456789", | ||
| desired_regions=["us-east-1", "sco-west-1"], | ||
| org_root_account_id="987654321", | ||
| ) | ||
| ) | ||
This file contains hidden or 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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.