in src/leave_organization.py [0:0]
def leave_org(event):
account = None
try:
event['Status'] = Constant.StateMachineStates.COMPLETED
account = get_account_by_id(company_name=event['CompanyName'], account_id=event['AccountId'])[0]
# INFO: If account already left the organization
if account['AccountStatus'] >= Constant.AccountStatus.INVITED:
event['Status'] = Constant.StateMachineStates.COMPLETED
return event
# INFO: Linked Account flow
if account["AccountType"] == Constant.AccountType.LINKED:
# INFO: Get target master account but don't send invitation to master until all linked accounts joins
# the AWS master account
master_record = get_master_account(company_name=event['CompanyName'])[0]
master_account_id = master_record['AccountId']
master_session = get_session(f"arn:aws:iam::{master_account_id}:role/{master_record['AdminRole']}")
organization_client = master_session.client('organizations')
account_info = organization_client.describe_account(AccountId=account['AccountId'])
arn = account_info['Account']['Arn']
account['Email'] = account_info['Account']['Email']
account['Name'] = account_info['Account']['Name']
# INFO: Double check in case user already accepted the invitation.
if arn.find(f'arn:aws:organizations::{Constant.MASTER_ACCOUNT_ID}') > 0:
account['AccountStatus'] = Constant.AccountStatus.JOINED
event['Status'] = 'JoinCH'
return event
# INFO: Check if account have already updated its account info as per AWS standards and
# ready to accept invitation from AWS organization.
if Constant.ACCOUNT_EMAIL_VALIDATION.__eq__(Constant.TRUE) and not bool(
re.search(Constant.EMAIL_PATTERN, account['Email'])):
msg = f"AccountId({account['AccountId']}): Email is not AWS's org compatible"
account['Error'] = log_error(logger=logger, account_id=account['AccountId'], company_name=account[
'CompanyName'], error_type=Constant.ErrorType.CATE, msg=msg, notify=True,
slack_handle=account['SlackHandle'])
event['Status'] = Constant.StateMachineStates.WAIT
return event
if Constant.ACCOUNT_NAME_VALIDATION.__eq__(Constant.TRUE) and not bool(
re.search(Constant.ACCOUNT_NAME_PATTERN, account['Name'])):
msg = f"AccountId({account['AccountId']}): Account name is not AWS's org compatible"
account['Error'] = log_error(logger=logger, account_id=account['AccountId'], company_name=account[
'CompanyName'], error_type=Constant.ErrorType.CATE, msg=msg, notify=True,
slack_handle=account['SlackHandle'])
event['Status'] = Constant.StateMachineStates.WAIT
organization_client.remove_account_from_organization(AccountId=account['AccountId'])
# Master account Flow
elif account["AccountType"] == Constant.AccountType.MASTER:
master_session = get_session(f"arn:aws:iam::{account['AccountId']}:role/{account['AdminRole']}")
organization_client = master_session.client('organizations')
if len(organization_client.list_accounts()["Accounts"]) > 1:
event['Status'] = Constant.StateMachineStates.WAIT
return event
else:
organization_client.delete_organization()
# Standalone account Flow
elif account["AccountType"] == Constant.AccountType.STANDALONE:
session = get_session(f"arn:aws:iam::{account['AccountId']}:role/{Constant.AWS_MASTER_ROLE}")
# Note: Double check for standalone account, if account have any organization associated with it.
try:
organization_client = session.client('organizations')
organization_client.list_accounts()["Accounts"]
raise Exception(f"Standalone account {account['AccountId']} has organization setup.")
except ClientError as ce:
# below exception occur if there is no organization attached to account.
if ce.response['Error']['Code'] == 'AWSOrganizationsNotInUseException':
pass
account['AccountStatus'] = Constant.AccountStatus.INVITED if account['Migrate'] \
else Constant.AccountStatus.LEFT
event['Status'] = Constant.StateMachineStates.COMPLETED
return event
except ClientError as ce:
# INFO: Below exception will occur when The member account have no organization or already left the
# organization
if ce.response['Error']['Code'] == 'AccountNotFoundException':
account['AccountStatus'] = Constant.AccountStatus.INVITED
event['Status'] = Constant.StateMachineStates.COMPLETED
return event
account['Error'] = log_error(logger=logger, account_id=account['AccountId'], company_name=account[
'CompanyName'], error=ce, error_type=Constant.ErrorType.LOE, notify=True,
slack_handle=account['SlackHandle'])
event['Status'] = Constant.StateMachineStates.WAIT
except Exception as ex:
log_error(logger=logger, account_id=event['AccountId'], company_name=event[
'CompanyName'], error_type=Constant.ErrorType.LOE, notify=True, error=ex)
raise ex
finally:
if account:
update_item(Constant.DB_TABLE, account)
return event