Skip to content

Commit

Permalink
Add initial OUs and Accounts for shared-services, finance, and scp-te…
Browse files Browse the repository at this point in the history
…sts (#7)
  • Loading branch information
san99tiago committed Sep 24, 2023
1 parent e371918 commit 2c56104
Showing 1 changed file with 228 additions and 18 deletions.
246 changes: 228 additions & 18 deletions cdk/stacks/cdk_organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,24 @@

class OrganizationStack(Stack):
"""
Class to create the infrastructure of the AWS Organizations.
Class to create the infrastructure for AWS Organizations.
"""

def __init__(
self, scope: Construct, construct_id: str, deployment_environment: str, **kwargs
) -> None:
"""
:param scope (Construct): Parent of this stack, usually an ``App`` or a ``Stage``, but could be any construct.
:param construct_id (str): The construct ID of this stack.
:param main_resources_name (str): The main solution name being deployed.
:param deployment_environment (str): Value that represents the deployment environment. For example: "dev" or "prod".
"""
super().__init__(scope, construct_id, **kwargs)

self.construct_id = construct_id
self.deployment_environment = deployment_environment

# Organization creation, services configuration and SCPs
# AWS Organization creation, services configuration and SCPs
self.create_root_organization()
self.configure_organization_services()
self.configure_service_control_policies()
Expand All @@ -48,6 +54,19 @@ def __init__(
self.create_ou_sandbox()
self.create_accounts_inside_ou_sandbox()

# Create "infrastructure" OU with inner OUs and accounts inside
self.create_ou_infrastructure()
self.create_accounts_inside_ou_infrastructure()

# Create "workloads" OU with inner OUs and accounts inside
self.create_ou_workloads()
self.create_ou_finance()
self.create_accounts_inside_ou_finance()

# Create "policy_staging_tests" OU with inner OUs and accounts inside
self.create_ou_policy_staging_tests()
self.create_accounts_inside_ou_policy_staging_tests()

# !IMPORTANT: this is mandatory for adding CDK dependencies for each account
self.add_cdk_accounts_dependencies() # DO NOT REMOVE!

Expand All @@ -60,7 +79,7 @@ def create_root_organization(self):
"""
self.organization = Organization(
self,
id="RootOrganization",
"RootOrganization",
feature_set=FeatureSet.ALL,
)

Expand Down Expand Up @@ -107,7 +126,7 @@ def configure_service_control_policies(self):
# SCP for preventing accounts of leaving organization
self.policy_deny_leave_org = Policy(
self,
id="PolicyDenyLeave",
"PolicyDenyLeave",
content=json.dumps(scp_prevent_leaving_org),
policy_name="PreventLeavingOrganization",
policy_type=PolicyType.SERVICE_CONTROL_POLICY,
Expand All @@ -118,7 +137,7 @@ def configure_service_control_policies(self):
# SCP for only allow access to specific regions in AWS (deny others)
self.policy_allow_specific_regions = Policy(
self,
id="PolicyAllowSpecificRegions",
"PolicyAllowSpecificRegions",
content=json.dumps(scp_allow_specific_regions),
policy_name="AllowSpecificRegions",
policy_type=PolicyType.SERVICE_CONTROL_POLICY,
Expand All @@ -128,47 +147,196 @@ def configure_service_control_policies(self):

def create_ou_sandbox(self):
"""
Method that creates inner Organizational Units (OUs) inside organization.
Method that creates inner Organizational Units (OUs) inside the AWS
Organization for "Sandbox".
"""
self.top_level_ou_sandbox = OrganizationalUnit(
self,
id="SandboxOU",
"SandboxOU",
parent=self.organization.root,
organizational_unit_name="sandbox",
)

def create_accounts_inside_ou_sandbox(self):
"""
Method that creates AWS Accounts inside the required Organizational
Units (OUs).
Method that creates AWS Accounts inside the Organizational Units (OUs)
for "Sandbox".
"""
self.account_sandbox_1 = Account(
self,
id="SandboxAccount1",
"SandboxAccount1",
account_name="san99tiago-sandbox-1",
email="san99tiagodemo+san99tiago-sandbox-1@gmail.com",
parent=self.top_level_ou_sandbox,
role_name="OrganizationAccountAccessRole",
)
self.account_sandbox_2 = Account(
self,
id="SandboxAccount2",
"SandboxAccount2",
account_name="san99tiago-sandbox-2",
email="san99tiagodemo+san99tiago-sandbox-2@gmail.com",
parent=self.top_level_ou_sandbox,
role_name="OrganizationAccountAccessRole",
)

def create_ou_infrastructure(self):
"""
Method that creates inner Organizational Units (OUs) inside the AWS
Organization for "Infrastructure".
"""
self.top_level_ou_infrastructure = OrganizationalUnit(
self,
"OUInfrastructure",
parent=self.organization.root,
organizational_unit_name="infrastructure",
)
self.ou_infrastructure_non_prod = OrganizationalUnit(
self,
"OUInfrastructureNonProd",
parent=self.top_level_ou_infrastructure,
organizational_unit_name="non-prod",
)
self.ou_infrastructure_prod = OrganizationalUnit(
self,
"OUInfrastructureProd",
parent=self.top_level_ou_infrastructure,
organizational_unit_name="prod",
)

def create_accounts_inside_ou_infrastructure(self):
"""
Method that creates AWS Accounts inside the Organizational Units (OUs)
for "Infrastructure".
"""
self.account_shared_services_non_prod = Account(
self,
"AccountSharedServicesNonProd",
account_name="shared-services-non-prod",
email="san99tiagodemo+shared-services-non-prod@gmail.com",
parent=self.ou_infrastructure_non_prod,
role_name="OrganizationAccountAccessRole",
)
self.account_shared_services_prod = Account(
self,
"AccountSharedServicesProd",
account_name="shared-services-prod",
email="san99tiagodemo+shared-services-prod@gmail.com",
parent=self.ou_infrastructure_prod,
role_name="OrganizationAccountAccessRole",
)

def create_ou_workloads(self):
"""
Method that creates inner Organizational Units (OUs) inside the AWS
Organization for "Workloads".
"""
self.top_level_ou_workloads = OrganizationalUnit(
self,
"OUWorkloads",
parent=self.organization.root,
organizational_unit_name="workloads",
)

def create_ou_finance(self):
"""
Method that creates inner Organizational Units (OUs) inside the AWS
Organization for "Finance".
"""
self.ou_finance = OrganizationalUnit(
self,
"OUFinance",
parent=self.top_level_ou_workloads,
organizational_unit_name="finance",
)
self.ou_finance_non_prod = OrganizationalUnit(
self,
"OUFinanceNonProd",
parent=self.ou_finance,
organizational_unit_name="non-prod",
)
self.ou_finance_prod = OrganizationalUnit(
self,
"OUFinanceProd",
parent=self.ou_finance,
organizational_unit_name="prod",
)

def create_accounts_inside_ou_finance(self):
"""
Method that creates AWS Accounts inside the Organizational Units (OUs)
for "Finance".
"""
self.account_finance_dev = Account(
self,
"AccountFinanceDev",
account_name="finance-dev",
email="san99tiagodemo+finance-dev@gmail.com",
parent=self.ou_finance_non_prod,
role_name="OrganizationAccountAccessRole",
)
self.account_finance_qa = Account(
self,
"AccountFinanceQA",
account_name="finance-qa",
email="san99tiagodemo+finance-qa@gmail.com",
parent=self.ou_finance_non_prod,
role_name="OrganizationAccountAccessRole",
)
self.account_finance_prod = Account(
self,
"AccountFinanceProd",
account_name="finance-prod",
email="san99tiagodemo+finance-prod@gmail.com",
parent=self.ou_finance_prod,
role_name="OrganizationAccountAccessRole",
)

def create_ou_policy_staging_tests(self):
"""
Method that creates inner Organizational Units (OUs) inside the AWS
Organization for "PolicyStagingTests".
"""
self.top_level_ou_policy_staging_tests = OrganizationalUnit(
self,
"OUPolicyStagingTests",
parent=self.organization.root,
organizational_unit_name="policy-staging-tests",
)

def create_accounts_inside_ou_policy_staging_tests(self):
"""
Method that creates AWS Accounts inside the Organizational Units (OUs)
for "PolicyStagingTests".
"""
self.account_policy_staging_tests = Account(
self,
"AccountPolicyStagingTests",
account_name="policy-staging-tests",
email="san99tiagodemo+policy-staging-tests@gmail.com",
parent=self.top_level_ou_policy_staging_tests,
role_name="OrganizationAccountAccessRole",
)

def add_cdk_accounts_dependencies(self):
"""
ULTRA IMPORTANT METHOD to add CDK dependencies for the AWS Accounts that
are being created (to avoid 2 accounts creation simultaneously, which is
IMPORTANT METHOD to add CDK dependencies for the AWS Accounts that are
being created (to avoid 2 accounts creation simultaneously, which is
not supported by AWS). This is because of AWS Organizations limitation.
"""
# ! IMPORTANT: We MUST add these dependencies, as AWS Organizations only support
# ... one account creation "IN_PROGRESS". We add CDK dependency to solve issue
# ... and wait for the previous one to finish, to continue with the next...
self.account_sandbox_2.node.add_dependency(self.account_sandbox_1)
self.account_shared_services_non_prod.node.add_dependency(
self.account_sandbox_2
)
self.account_shared_services_prod.node.add_dependency(
self.account_shared_services_non_prod
)
self.account_finance_dev.node.add_dependency(self.account_shared_services_prod)
self.account_finance_qa.node.add_dependency(self.account_finance_dev)
self.account_finance_prod.node.add_dependency(self.account_finance_qa)
self.account_policy_staging_tests.node.add_dependency(self.account_finance_prod)

def generate_cloudformation_outputs(self):
"""
Expand All @@ -186,21 +354,21 @@ def generate_cloudformation_outputs(self):
self,
"OrganizationId",
value=self.organization.organization_id,
description="ID of the Organization",
description="ID of AWS Organization",
)

CfnOutput(
self,
"RootId",
value=self.organization.root.identifier(),
description="ID of the Root OU",
description="ID of AWS Organization Root OU",
)

CfnOutput(
self,
"ManagementAccountId",
value=self.organization.management_account_id,
description="ID of the Management Account",
description="ID of Management Account",
)

CfnOutput(
Expand All @@ -214,12 +382,54 @@ def generate_cloudformation_outputs(self):
self,
"AccountSandbox1Id",
value=self.account_sandbox_1.account_id,
description="ID of the SandboxAccount1",
description="ID of SandboxAccount1 Account",
)

CfnOutput(
self,
"AccountSandbox2Id",
value=self.account_sandbox_2.account_id,
description="ID of the SandboxAccount2",
description="ID of SandboxAccount2 Account",
)

CfnOutput(
self,
"AccountSharedServicesNonProdId",
value=self.account_shared_services_non_prod.account_id,
description="ID of AccountSharedServicesNonProd Account",
)

CfnOutput(
self,
"AccountSharedServicesProdId",
value=self.account_shared_services_prod.account_id,
description="ID of AccountSharedServicesProd Account",
)

CfnOutput(
self,
"AccountFinanceDevId",
value=self.account_finance_dev.account_id,
description="ID of AccountFinanceDev Account",
)

CfnOutput(
self,
"AccountFinanceQAId",
value=self.account_finance_qa.account_id,
description="ID of AccountFinanceQA Account",
)

CfnOutput(
self,
"AccountFinanceProdId",
value=self.account_finance_prod.account_id,
description="ID of AccountFinanceProd Account",
)

CfnOutput(
self,
"AccountPolicyStagingTestsId",
value=self.account_policy_staging_tests.account_id,
description="ID of AccountPolicyStagingTests Account",
)

0 comments on commit 2c56104

Please sign in to comment.