Skip to content

Commit

Permalink
Release: 1.0.11
Browse files Browse the repository at this point in the history
  • Loading branch information
AWS committed Dec 30, 2021
1 parent a621bb2 commit d347c43
Show file tree
Hide file tree
Showing 60 changed files with 4,005 additions and 4,023 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ target/
profile_default/
ipython_config.py

# mypy
mypy-report.xml

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
Expand Down Expand Up @@ -334,6 +337,10 @@ modules.xml
.idea/misc.xml
*.ipr

#boto3 stub typings
build/typings/
typings/

# Sonarlint plugin
.idea/sonarlint

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.10
1.0.11
10 changes: 5 additions & 5 deletions modules/aft-account-provisioning-framework/lambda.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ resource "aws_lambda_function" "validate_request" {
function_name = "aft-account-provisioning-framework-validate-request"
description = "AFT account provisioning framework - validate_request"
role = aws_iam_role.aft_lambda_aft_account_provisioning_framework_validate_request.arn
handler = "lambda_function.lambda_handler"
handler = "aft_account_provisioning_framework_validate_request.lambda_handler"
source_code_hash = data.archive_file.validate_request.output_base64sha256
runtime = "python3.8"
timeout = 300
Expand Down Expand Up @@ -42,7 +42,7 @@ resource "aws_lambda_function" "get_account_info" {
function_name = "aft-account-provisioning-framework-get-account-info"
description = "AFT account provisioning framework - get_account_info"
role = aws_iam_role.aft_lambda_aft_account_provisioning_framework_get_account_info.arn
handler = "lambda_function.lambda_handler"
handler = "aft_account_provisioning_framework_get_account_info.lambda_handler"
source_code_hash = data.archive_file.get_account_info.output_base64sha256
runtime = "python3.8"
timeout = 300
Expand Down Expand Up @@ -72,7 +72,7 @@ resource "aws_lambda_function" "create_role" {
function_name = "aft-account-provisioning-framework-create-aft-execution-role"
description = "AFT account provisioning framework - create_role"
role = aws_iam_role.aft_lambda_aft_account_provisioning_framework_create_role.arn
handler = "lambda_function.lambda_handler"
handler = "aft_account_provisioning_framework_create_role.lambda_handler"
source_code_hash = data.archive_file.create_role.output_base64sha256
runtime = "python3.8"
timeout = 300
Expand Down Expand Up @@ -103,7 +103,7 @@ resource "aws_lambda_function" "tag_account" {
function_name = "aft-account-provisioning-framework-tag-account"
description = "AFT account provisioning framework - tag_account"
role = aws_iam_role.aft_lambda_aft_account_provisioning_framework_tag_account.arn
handler = "lambda_function.lambda_handler"
handler = "aft_account_provisioning_framework_tag_account.lambda_handler"
source_code_hash = data.archive_file.tag_account.output_base64sha256
runtime = "python3.8"
timeout = 300
Expand Down Expand Up @@ -133,7 +133,7 @@ resource "aws_lambda_function" "persist_metadata" {
function_name = "aft-account-provisioning-framework-persist-metadata"
description = "AFT account provisioning framework - persist_metadata"
role = aws_iam_role.aft_lambda_aft_account_provisioning_framework_persist_metadata.arn
handler = "lambda_function.lambda_handler"
handler = "aft_account_provisioning_framework_persist_metadata.lambda_handler"
source_code_hash = data.archive_file.persist_metadata.output_base64sha256
runtime = "python3.8"
timeout = 300
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import inspect
import json
import os
from typing import Any, Dict, Union

import boto3
import jsonschema
import aft_common.aft_utils as utils
from boto3.dynamodb.conditions import Key

import boto3
from boto3.session import Session

logger = utils.get_logger()


def get_ct_execution_session(aft_management_session, ct_management_session, account_id):
def get_ct_execution_session(
aft_management_session: Session, ct_management_session: Session, account_id: str
) -> Session:
session_name = utils.get_ssm_parameter_value(
aft_management_session, utils.SSM_PARAM_AFT_SESSION_NAME
)
Expand All @@ -25,7 +27,9 @@ def get_ct_execution_session(aft_management_session, ct_management_session, acco
return utils.get_boto_session(admin_credentials)


def persist_metadata(payload, account_info, session, logger):
def persist_metadata(
payload: Dict[str, Any], account_info: Dict[str, Any], session: Session
) -> Dict[str, Any]:
logger.info("Function Start - persist_metadata")

account_tags = payload["account_request"]["account_tags"]
Expand Down Expand Up @@ -56,8 +60,8 @@ def persist_metadata(payload, account_info, session, logger):


def create_aft_execution_role(
payload, account_info, session, ct_management_session, logger
):
account_info: Dict[str, Any], session: Session, ct_management_session: Session
) -> str:
logger.info("Function Start - create_aft_execution_role")
role_name = utils.get_ssm_parameter_value(session, utils.SSM_PARAM_AFT_EXEC_ROLE)
ct_execution_session = get_ct_execution_session(
Expand All @@ -66,17 +70,21 @@ def create_aft_execution_role(
exec_iam_client = ct_execution_session.client("iam")

try:
return_value: str
role = exec_iam_client.get_role(RoleName=role_name.split("/")[-1])
if role:
logger.info("Role Exists. Exiting")
return role["Role"]["Arn"]
logger.info("Role Exists. Exiting")
return_value = role["Role"]["Arn"]
return return_value
except exec_iam_client.exceptions.NoSuchEntityException:
logger.info("Role not found in account.")
role = create_role_in_account(session, ct_execution_session, role_name)
return role
return_value = role
return return_value


def create_role_in_account(session, ct_execution_session, role_name):
def create_role_in_account(
session: Session, ct_execution_session: Session, role_name: str
) -> str:
logger.info("Function Start - create_role_in_account")
trust_policy_template = os.path.join(
os.path.dirname(__file__), "iam/trust-policies/aftmanagement.tpl"
Expand Down Expand Up @@ -110,39 +118,56 @@ def create_role_in_account(session, ct_execution_session, role_name):
logger.info(response)
logger.info("Returning role")
logger.info(role)
return role
return_value: str = role
return return_value


def lambda_handler(event, context):
logger.info("AFT Account Provisioning Framework Create Role Handler Start")
def lambda_handler(event: Dict[str, Any], context: Union[Dict[str, Any], None]) -> str:
try:
if event["offline"]:
return True
except KeyError:
pass


payload = event["payload"]
action = event["action"]

session = boto3.session.Session()
ct_management_session = utils.get_ct_management_session(session)

if action == "create_role":
account_info = payload["account_info"]["account"]
aft_role = create_aft_execution_role(
payload, account_info, session, ct_management_session, logger
)
return aft_role
else:
raise BaseException(
"Incorrect Command Passed to Lambda Function. Input: {action}. Expected: 'create_role'"
)
logger.info("AFT Account Provisioning Framework Create Role Handler Start")

payload = event["payload"]
action = event["action"]

session = boto3.session.Session()
ct_management_session = utils.get_ct_management_session(session)

if action == "create_role":
account_info = payload["account_info"]["account"]
aft_role = create_aft_execution_role(
account_info, session, ct_management_session
)
return_value: str = aft_role
return return_value
else:
raise Exception(
"Incorrect Command Passed to Lambda Function. Input: {action}. Expected: 'create_role'"
)

except Exception as e:
message = {
"FILE": __file__.split("/")[-1],
"METHOD": inspect.stack()[0][3],
"EXCEPTION": str(e),
}
logger.exception(message)
raise


if __name__ == "__main__":
event = {}
example_file = os.path.join(os.path.dirname(__file__), "schema/example_event.json")
with open(example_file) as json_data:
event = json.load(json_data)
lambda_handler(event, None)
import json
import sys
from optparse import OptionParser

logger.info("Local Execution")
parser = OptionParser()
parser.add_option(
"-f", "--event-file", dest="event_file", help="Event file to be processed"
)
(options, args) = parser.parse_args(sys.argv)
if options.event_file is not None:
with open(options.event_file) as json_data:
event = json.load(json_data)
lambda_handler(event, None)
else:
lambda_handler({}, None)
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import inspect
from typing import Any, Dict, Union

import aft_common.aft_utils as utils
import boto3
from aft_common.account import AftAccountInfo
from boto3.session import Session

logger = utils.get_logger()


def get_ct_execution_session(
aft_management_session: Session, ct_management_session: Session, account_id: str
) -> Session:
session_name = utils.get_ssm_parameter_value(
aft_management_session, utils.SSM_PARAM_AFT_SESSION_NAME
)
admin_credentials = utils.get_assume_role_credentials(
ct_management_session,
utils.build_role_arn(
ct_management_session, "AWSControlTowerExecution", account_id
),
session_name,
)

return utils.get_boto_session(admin_credentials)


def get_account_info(
payload: Dict[str, Any], session: Session, ct_management_session: Session
) -> AftAccountInfo:
logger.info("Function Start - get_account_info")

account_id = None

# Handle a Control Tower Event
if "account" in payload["control_tower_event"]:
if (
payload["control_tower_event"]["detail"]["eventName"]
== "CreateManagedAccount"
):
account_id = payload["control_tower_event"]["detail"][
"serviceEventDetails"
]["createManagedAccountStatus"]["account"]["accountId"]
elif (
payload["control_tower_event"]["detail"]["eventName"]
== "UpdateManagedAccount"
):
account_id = payload["control_tower_event"]["detail"][
"serviceEventDetails"
]["updateManagedAccountStatus"]["account"]["accountId"]
if account_id:
logger.info(f"Account Id [{account_id}] found in control_tower_event")
return utils.get_account_info(ct_management_session, account_id)

elif "id" in payload["account_request"]:
email = payload["account_request"]["id"]
logger.info("Account Email: " + email)
account_id = utils.get_account_id_from_email(ct_management_session, email)
return utils.get_account_info(ct_management_session, account_id)

raise Exception("Account was not found")


def lambda_handler(
event: Dict[str, Any], context: Union[Dict[str, Any], None]
) -> AftAccountInfo:
try:
logger.info("AFT Account Provisioning Framework Get Account Info Handler Start")

payload = event["payload"]
action = event["action"]

session = boto3.session.Session()
ct_management_session = utils.get_ct_management_session(session)
if action == "get_account_info":
return get_account_info(payload, session, ct_management_session)
else:
raise Exception(
"Incorrect Command Passed to Lambda Function. Input: {action}. Expected: 'get_account_info'"
)

except Exception as e:
message = {
"FILE": __file__.split("/")[-1],
"METHOD": inspect.stack()[0][3],
"EXCEPTION": str(e),
}
logger.exception(message)
raise


if __name__ == "__main__":
import json
import sys
from optparse import OptionParser

logger.info("Local Execution")
parser = OptionParser()
parser.add_option(
"-f", "--event-file", dest="event_file", help="Event file to be processed"
)
(options, args) = parser.parse_args(sys.argv)
if options.event_file is not None:
with open(options.event_file) as json_data:
event = json.load(json_data)
lambda_handler(event, None)
else:
lambda_handler({}, None)
Loading

0 comments on commit d347c43

Please sign in to comment.