From 00fa111e90fcfccc78d6b655e8a35defd92964ce Mon Sep 17 00:00:00 2001 From: Alex Evans Date: Wed, 18 Oct 2023 09:42:24 +0200 Subject: [PATCH 01/51] Feat: Adf Multi-Org support --- docs/admin-guide.md | 4 + docs/multi-org-guide.md | 152 ++++++++++++++++++ .../deployment/example-global-iam.yml | 22 +++ .../adf-bootstrap/example-global-iam.yml | 20 +++ .../bootstrap_repository/adf-build/config.py | 17 +- .../bootstrap_repository/adf-build/main.py | 9 ++ .../example-adfconfig.yml | 9 +- 7 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 docs/multi-org-guide.md diff --git a/docs/admin-guide.md b/docs/admin-guide.md index 808105460..19338602a 100644 --- a/docs/admin-guide.md +++ b/docs/admin-guide.md @@ -100,6 +100,8 @@ config: scm: # Source Control Management auto-create-repositories: enabled # Optional default-scm-branch: main # Optional + org: + stage: dev # Optional ``` In the above example the properties are categorized into `roles`, `regions`, @@ -225,6 +227,8 @@ Config has five components in `main-notification-endpoint`, `scp`, `scm`, org-specific deployments; without hardcoding the AWS Organization stage in your buildspec. If this variable is not set, the SSM parameter `/adf/org/stage` defaults to "none". + More information about Multi-Org ADF setup can be found in the + [Multi-Org Guide](#multi-Org-Guide) ## Accounts diff --git a/docs/multi-org-guide.md b/docs/multi-org-guide.md new file mode 100644 index 000000000..0b6342bdb --- /dev/null +++ b/docs/multi-org-guide.md @@ -0,0 +1,152 @@ +# Multi-Org-Guide + +- [Multi Org Guide](#multi-org-guide) + - [What is A Multi-Org AWS-Deployment-Framework Setup](#what-is-a-multi-org-aws-deployment-framework-setup) + - [Coordinating Changes Between ADF Installations](#Coordinating-Changes-Between-ADF-Installations) + - [Customizing ADF Config Per AWS Organization](#customizing-adfconfig-per-aws-organization) + - [Customizing Base IAM Roles Per Organization](#customizing-base-iam-roles-per-organization) + - [Customizing Codepipeline BuildSpecs Per Organization](#customizing-codepipeline-buildspecs-per-organization) + - [Considerations for Multi-Org Deployment Maps](#considerations-for-multi-org-deployment-maps) + + +# What is A Multi-Org AWS-Deployment-Framework Setup +A Multi-Org AWS-Deployment-Framework (ADF) setup describes a scenario where an +Enterprise maintains more than one AWS Organizations and each with it's own +dedicated ADF installation. + +The benefits of such a configuration is that in Enteprise organizations +hosting with many production cloud workloads and applications which are deployed +and governed by ADF, can apply the same common `Software Development Lifecycle` +approachs to configuration changes in the deployment and governance tooling as +they do with the workloads they run. + +With a dedicated AWS Organization and ADF install setup with Dev, Int and Prod +Organizations, it enables an Enterprises 'Cloud Center of Excellence' an +controlled process to validate changes to wide reaching mission-critical +services, including but not limited to: + +- Service Control Policies Updates +- Identity Center and IAM based Access Management Configuration changes +- Deployment Framework Updates +- Control Tower and Account Provisioning Configurations +- Centralized Security Hub and Cost Management Configurations +- Networking Architectural changes. + +# Coordinating Changes Between ADF Installations +With Multiple ADF configurations within a single organization there comes a +new challenge to maintain ADF-Bootstrap repository configurations across multiple +environments. Typically in an ADF Installation for any given Organization you +would define a customized configuration, and bootstrapped Global Roles and or +resources. + +As the requirements of the bootstrapped resources and adf configuration evolve +they need to be updated over time, and these changes ideally propogated from one + Installation to the next in a coordinated, controlled fashion. + +One approach to promoting validated changes in an `ADF Installation` from +a Dev to Int to Prod Organization could be to mirror specific branches of +a Source ADF Repository to a Target ADF Repository, Consider the Following table + +Org | Repository | Branch | Commit Trigger +--|--|--|-- +Dev | AWS-deployment-framework-Bootstrap | Dev Branch | Trigger State Machine Dev Org +Dev | AWS-deployment-framework-Bootstrap | Int Branch | Mirror to Int Org +Int | AWS-deployment-framework-Bootstrap | Int Branch | Trigger State Machine Int Org +Int | AWS-deployment-framework-Bootstrap | Prod Branch | Mirror to Prod Org +Prod | AWS-deployment-framework-Bootstrap | Prod Branch | Trigger State Machine Int Org + +Here with an `Environment Branching` approach it's possible to build a 'hands-off' +automated mechanism to Promote from a Dev ADF Installation to a Prod Installation. + +# Customizing adfconfig.yml Per AWS Organization +One challenge with syncronising the aws-deployment-framework-bootstrap repository +across AWS Organizations is that the contents of the `adfconfig.yml` configuration +file is typically tailored to the ADF installation. The can be solved by adding a +custom adfconfig file for the given organization. + +Adding a configuration file with the name pattern `adfconfig.{organization id}.yml` +in the root of the `aws-deployment-framework-bootstrap` repository will take +precedence over the default `adfconfig.yml` settings file for that organization. + +For each AWS organization used with the ADF Framework setup an additional adfconfig +file can be defined. + +# Customizing Base IAM Roles Per Organization +ADF Supports Bootstrapping Baseline Cloudformation Stacks to all accounts +when they first join an AWS Organization and centrally governing the subsequent +Lifecycle of those Stacks. [See Here]("admin-guide.md#bootstrapping-accounts) + +These Baseline Templates are typically used for Setting up Default IAM Roles and +Policies necessary for the foundations of an ADF Based Enteprise Landing Zone. + +In guidance with AWS Security Guidelines and `Least Privilege Access Principles`, +it it recommended to reduce the scope of any IAM Policy to the minimum required +Actions, Principals and Resource Scope necessary. + +To customize the scope of which resources or Principals are permitted within the +IAM Policies of the Baseline templates CFN Mapping fields can be utilized based +on the `Org Stage` SSM Parameter. As shown below: + +``` +Parameters: + OrgStage: + Type: "AWS::SSM::Parameter::Value" + Description: Org Stage + Default: /adf/org/stage +# At the time this Stack is deployed, the FinOps Account ID SSM Parameter doesnt exist, so we derived it from mapping it to +# the org stage +Mappings: + # Usage:!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId] + OrgStageBasedPropertyMap: + dev: + FinOpsAccountId: 1234567891012 # Dev Org + int: + FinOpsAccountId: 1234567891013 # Int Org + prod: + FinOpsAccountId: 1234567891014 # Prod Org +``` +In the above usage example you can see how the Cloudformation function FindInMap +`!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId]` can be +utilized to dynamically reference a custom 'AccountId' within the Template, +enabling the construction account specific granular Resource/Principal ARNS. + +# Customizing Codepipeline BuildSpecs Per Organization +A simple pattern to customize the buildspec is to load the `adf/org/stage` parameter +from ssm parameter from the parameter store via codebuild native mechanism. + +``` +env: + parameter-store: + ADF_ORG_STAGE: "/adf/org/stage" +``` + +This environment variable can then be used to drive decision/deployment logic +within any of the subsequent build commands/actions. +Some scenarios which could require Org specific context: +- Deriving the default log level based on the org stage for +a specific CDK application +- Appending the Stage name to AWS resource names having a requirement to be +both deterministic as well as globally unique +(whilst being deployed into multiple organizatinos) + +# Considerations for Multi-Org Deployment Maps +Whilst the Deployment Maps for ADF exist within a simarly named +`aws-deployment-framwork-pipelines` codecommit repository within the deployment +account. + +Some additional Multi-Org challenges exist when defining Targets for Deployments. + +The following considerations should be observed: +- Avoid utlizing Account Ids for Deplyment Map Targets unless the deployment + is destined for a single organization. + - As an alternative Deploy via `Account Names`, `Account Tags` or `OU Paths` + which ADF will then use to dynamically genrate the respective Account IDs + Target List when updating the Pipelines. +- Consider in a Large Enteprise Setup the number of targets that a Production +stage generates may be much greater than in predecessing Stages and design accordingly + - Review the Codepipeline action limitations. + - ADF handles best efforts to distribute Targets across Stages with a Pipeline, however + Deployments may need to be distributed across Multiple Pipelines when upper limits are reached. +- The source branch for the application code may be different per Organization + - The above described custom `adfconfig` configuration allows a different default +branch to be specified in the path `config.scm.default-scm-branch` per Organization \ No newline at end of file diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml index 02a88d85f..f5acaf100 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml @@ -4,6 +4,28 @@ AWSTemplateFormatVersion: "2010-09-09" Description: ADF CloudFormation Template (Global) for IAM in the Deployment Account +Parameters: + # OrgStage can be set in the respective adfconfig file using the + # path config.org.stage + OrgStage: + Type: "AWS::SSM::Parameter::Value" + Description: A stage used to differentiate Multi-Org ADF environments + Default: /adf/org/stage + +# Org StageCustom Mappings allows you to dynamically build different IAM +# Conditions / Principals ARN / Resource ARN per Organization applying Least +# Privilege Principals whilst retaining a Single Stack Definition for all +# environments. +# Usage: !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] +Mappings: + OrgStageMap: + Dev: + ExampleCustomProperty: 1234 + Int: + ExampleCustomProperty: 5678 + Prod: + ExampleCustomProperty: 9102 + Resources: CloudFormationDeploymentPolicy: # This is the policy that will be used to deploy CloudFormation resources from diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml index be971baec..1bb9806a9 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml @@ -9,6 +9,26 @@ Parameters: Type: "AWS::SSM::Parameter::Value" Description: Deployment Account ID Default: deployment_account_id + # OrgStage can be set in the respective adfconfig file using the + # path config.org.stage + OrgStage: + Type: "AWS::SSM::Parameter::Value" + Description: A stage used to differentiate Multi-Org ADF environments + Default: /adf/org/stage + +# Org StageCustom Mappings allows you to dynamically build different IAM +# Conditions / Principals ARN / Resource ARN per Organization applying Least +# Privilege Principals whilst retaining a Single Stack Definition for all +# environments. +# usage !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] +Mappings: + OrgStageMap: + Dev: + ExampleCustomProperty: 1234 + Int: + ExampleCustomProperty: 5678 + Prod: + ExampleCustomProperty: 9102 Resources: CloudFormationDeploymentPolicy: diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py index 0a72ecafc..c60e5a78c 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py @@ -90,11 +90,20 @@ def _validate(self): def _load_config_file(self): """ - Loads the adfconfig.yml file and executes _parse_config + Checks for an Org Specific adfconfig.yml (adfconfig.{ORG_ID}.yml) + and uses that if it exists. Otherwise it uses the default adfconfig.yml + and executes _parse_config """ - with open(self.config_path, encoding="utf-8") as config: - self.config_contents = yaml.load(config, Loader=yaml.FullLoader) - self._parse_config() + org_config_path = self.config_path.replace(".yml", f".{self.organization_id}.yml") + if os.exists(org_config_path): + with open(org_config_path, encoding="utf-8") as org_config_file: + LOGGER.info("Using custom org config") + self.config_contents = yaml.load(org_config_file, Loader=yaml.FullLoader) + else: + LOGGER.info("Using default org config") + with open(self.config_path, encoding="utf-8") as config: + self.config_contents = yaml.load(config, Loader=yaml.FullLoader) + self._parse_config() def _parse_config(self): """ diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py index fd268ebc7..307fb6d19 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py @@ -253,6 +253,15 @@ def worker_thread( 'bucket_name', updated_kms_bucket_dict[region]['s3_regional_bucket'], ) + + # Ensuring the stage parameter on the target account is up-to-date + parameter_store.put_parameter( + '/adf/org/stage', + config.config.get('org', {}).get( + 'stage', + ADF_DEFAULT_ORG_STAGE, + ) + ) cloudformation = CloudFormation( region=region, deployment_account_region=config.deployment_account_region, diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml index 0b48e654b..f58d2d0c7 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml @@ -28,7 +28,14 @@ config: default-scm-branch: master # ^ The default branch is used when the pipeline does not specify a specific branch. # If this parameter is not specified, it defaults to the "master" branch. - + org: + stage: prod + # ^ This value will be set as an SSM Parameter named /adf/org/stage + # in both the deployment account and and all + # Target member accounts as part of the Bootstrap Statemachine. + # It is useful as a flag to drive Organization specific logic within + # IAM Role definitions/conditions aswell as Build spec behavior. + extensions: terraform: enabled: false # If true resources needed to run Terraform template will be deployed From 51ce2417f9dc6722e5bf9ec4fec4294787afeced Mon Sep 17 00:00:00 2001 From: Alex Evans Date: Wed, 18 Oct 2023 09:45:33 +0200 Subject: [PATCH 02/51] fix: Broken links --- docs/multi-org-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/multi-org-guide.md b/docs/multi-org-guide.md index 0b6342bdb..c33a94555 100644 --- a/docs/multi-org-guide.md +++ b/docs/multi-org-guide.md @@ -3,7 +3,7 @@ - [Multi Org Guide](#multi-org-guide) - [What is A Multi-Org AWS-Deployment-Framework Setup](#what-is-a-multi-org-aws-deployment-framework-setup) - [Coordinating Changes Between ADF Installations](#Coordinating-Changes-Between-ADF-Installations) - - [Customizing ADF Config Per AWS Organization](#customizing-adfconfig-per-aws-organization) + - [Customizing ADF Config Per AWS Organization](#customizing-adfconfig.yml-per-aws-organization) - [Customizing Base IAM Roles Per Organization](#customizing-base-iam-roles-per-organization) - [Customizing Codepipeline BuildSpecs Per Organization](#customizing-codepipeline-buildspecs-per-organization) - [Considerations for Multi-Org Deployment Maps](#considerations-for-multi-org-deployment-maps) @@ -74,7 +74,7 @@ file can be defined. # Customizing Base IAM Roles Per Organization ADF Supports Bootstrapping Baseline Cloudformation Stacks to all accounts when they first join an AWS Organization and centrally governing the subsequent -Lifecycle of those Stacks. [See Here]("admin-guide.md#bootstrapping-accounts) +Lifecycle of those Stacks. [See Here](admin-guide.md#bootstrapping-accounts) These Baseline Templates are typically used for Setting up Default IAM Roles and Policies necessary for the foundations of an ADF Based Enteprise Landing Zone. From 2ad95db660d616099485835453a82362d6ad81cc Mon Sep 17 00:00:00 2001 From: Alex Evans Date: Wed, 18 Oct 2023 09:48:19 +0200 Subject: [PATCH 03/51] fix: Updated link --- docs/admin-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin-guide.md b/docs/admin-guide.md index 19338602a..946041438 100644 --- a/docs/admin-guide.md +++ b/docs/admin-guide.md @@ -228,7 +228,7 @@ Config has five components in `main-notification-endpoint`, `scp`, `scm`, your buildspec. If this variable is not set, the SSM parameter `/adf/org/stage` defaults to "none". More information about Multi-Org ADF setup can be found in the - [Multi-Org Guide](#multi-Org-Guide) + [Multi-Org Guide](multi-org-guide) ## Accounts From fd4f6585d4df7bb0d6042d73fff6b25e0bd66a8e Mon Sep 17 00:00:00 2001 From: Alex Evans Date: Wed, 18 Oct 2023 09:51:34 +0200 Subject: [PATCH 04/51] docs: update wording --- docs/admin-guide.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/admin-guide.md b/docs/admin-guide.md index 946041438..187008094 100644 --- a/docs/admin-guide.md +++ b/docs/admin-guide.md @@ -223,12 +223,13 @@ Config has five components in `main-notification-endpoint`, `scp`, `scm`, and prod AWS Organization with its own ADF instance per AWS organization. This approach allows for well-tested and stable prod AWS Organization deployments. If set, a matching SSM parameter `/adf/org/stage` gets - created that you can reference in your buildspec files to allow for + created in deployment aswell as all target accounts. + You can reference it within your buildspec files to allow for org-specific deployments; without hardcoding the AWS Organization stage in your buildspec. If this variable is not set, the SSM parameter `/adf/org/stage` defaults to "none". More information about Multi-Org ADF setup can be found in the - [Multi-Org Guide](multi-org-guide) + [Multi-Org Guide](multi-org-guide.md) ## Accounts From 0c35eecf525700a6ca53a86833ee828bb990979f Mon Sep 17 00:00:00 2001 From: Alex Evans Date: Wed, 18 Oct 2023 11:13:19 +0200 Subject: [PATCH 05/51] fix: codespell fixes --- docs/multi-org-guide.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/multi-org-guide.md b/docs/multi-org-guide.md index c33a94555..b8aab86d9 100644 --- a/docs/multi-org-guide.md +++ b/docs/multi-org-guide.md @@ -17,7 +17,7 @@ dedicated ADF installation. The benefits of such a configuration is that in Enteprise organizations hosting with many production cloud workloads and applications which are deployed and governed by ADF, can apply the same common `Software Development Lifecycle` -approachs to configuration changes in the deployment and governance tooling as +approaches to configuration changes in the deployment and governance tooling as they do with the workloads they run. With a dedicated AWS Organization and ADF install setup with Dev, Int and Prod @@ -40,7 +40,7 @@ would define a customized configuration, and bootstrapped Global Roles and or resources. As the requirements of the bootstrapped resources and adf configuration evolve -they need to be updated over time, and these changes ideally propogated from one +they need to be updated over time, and these changes ideally propagated from one Installation to the next in a coordinated, controlled fashion. One approach to promoting validated changes in an `ADF Installation` from @@ -59,7 +59,7 @@ Here with an `Environment Branching` approach it's possible to build a 'hands-of automated mechanism to Promote from a Dev ADF Installation to a Prod Installation. # Customizing adfconfig.yml Per AWS Organization -One challenge with syncronising the aws-deployment-framework-bootstrap repository +One challenge with synchronising the aws-deployment-framework-bootstrap repository across AWS Organizations is that the contents of the `adfconfig.yml` configuration file is typically tailored to the ADF installation. The can be solved by adding a custom adfconfig file for the given organization. @@ -93,8 +93,8 @@ Parameters: Type: "AWS::SSM::Parameter::Value" Description: Org Stage Default: /adf/org/stage -# At the time this Stack is deployed, the FinOps Account ID SSM Parameter doesnt exist, so we derived it from mapping it to -# the org stage +# At the time this Stack is deployed, the FinOps Account ID SSM Parameter doesn't +# exist, so we derive it from mapping it to the org stage Mappings: # Usage:!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId] OrgStageBasedPropertyMap: @@ -137,10 +137,10 @@ account. Some additional Multi-Org challenges exist when defining Targets for Deployments. The following considerations should be observed: -- Avoid utlizing Account Ids for Deplyment Map Targets unless the deployment +- Avoid utilizing Account Ids for Deployment Map Targets unless the deployment is destined for a single organization. - As an alternative Deploy via `Account Names`, `Account Tags` or `OU Paths` - which ADF will then use to dynamically genrate the respective Account IDs + which ADF will then use to dynamically generate the respective Account IDs Target List when updating the Pipelines. - Consider in a Large Enteprise Setup the number of targets that a Production stage generates may be much greater than in predecessing Stages and design accordingly From 182d02a774fd09b350093ec1aeec3565415d01e5 Mon Sep 17 00:00:00 2001 From: Alex Evans Date: Wed, 18 Oct 2023 16:11:39 +0200 Subject: [PATCH 06/51] fix: Added propagation of org/stage parameter --- src/lambda_codebase/account_bootstrap.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lambda_codebase/account_bootstrap.py b/src/lambda_codebase/account_bootstrap.py index d59cef9f2..80357e5b8 100644 --- a/src/lambda_codebase/account_bootstrap.py +++ b/src/lambda_codebase/account_bootstrap.py @@ -65,6 +65,9 @@ def configure_generic_account(sts, event, region, role): bucket_name = parameter_store_deployment_account.fetch_parameter( f'/cross_region/s3_regional_bucket/{region}', ) + org_stage = parameter_store_deployment_account.fetch_parameter( + '/adf/org/stage' + ) except (ClientError, ParameterNotFoundError): raise GenericAccountConfigureError( f'Account {event["account_id"]} cannot yet be bootstrapped ' @@ -77,6 +80,7 @@ def configure_generic_account(sts, event, region, role): 'deployment_account_id', event['deployment_account_id'], ) + parameter_store_target_account.put_parameter('/adf/org/stage', org_stage) def configure_master_account_parameters(event): From 677cddb1443ca0c632309578937c2dd91ddc3a9c Mon Sep 17 00:00:00 2001 From: Alex Evans Date: Wed, 18 Oct 2023 17:18:57 +0200 Subject: [PATCH 07/51] fix path part missing for os.path.exists --- .../initial_commit/bootstrap_repository/adf-build/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py index c60e5a78c..2ac9414d3 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py @@ -95,10 +95,10 @@ def _load_config_file(self): and executes _parse_config """ org_config_path = self.config_path.replace(".yml", f".{self.organization_id}.yml") - if os.exists(org_config_path): + if os.path.exists(org_config_path): with open(org_config_path, encoding="utf-8") as org_config_file: LOGGER.info("Using custom org config") - self.config_contents = yaml.load(org_config_file, Loader=yaml.FullLoader) + self.config_contents = yaml.load(org_config_file, Loader=yaml.FullLoader) else: LOGGER.info("Using default org config") with open(self.config_path, encoding="utf-8") as config: From 7c5f647054d826eefec2108042df7c14a8ed5c36 Mon Sep 17 00:00:00 2001 From: Andreas Falkenberg Date: Tue, 31 Oct 2023 16:51:40 +0100 Subject: [PATCH 08/51] feat: extended Multi-Org Docs --- README.md | 1 + docs/admin-guide.md | 4 +- docs/images/aws-multi-org-1.png | Bin 0 -> 66395 bytes docs/images/aws-multi-org-2.png | Bin 0 -> 173387 bytes docs/multi-org-guide.md | 152 -------------------------- docs/multi-organization-guide.md | 182 +++++++++++++++++++++++++++++++ 6 files changed, 185 insertions(+), 154 deletions(-) create mode 100644 docs/images/aws-multi-org-1.png create mode 100644 docs/images/aws-multi-org-2.png delete mode 100644 docs/multi-org-guide.md create mode 100644 docs/multi-organization-guide.md diff --git a/README.md b/README.md index 64fcba76f..40fb335d6 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,4 @@ within the AWS Console. - Refer to the [User Guide](docs/user-guide.md) for using ADF once it is setup. - Refer to the [Samples Guide](docs/samples-guide.md) for a detailed walk through of the provided samples. +- Refer to the [Multi-Orgaization ADF Setup](docs/multi-organization-guide.md) for using ADF in an enterprise-grade setup. \ No newline at end of file diff --git a/docs/admin-guide.md b/docs/admin-guide.md index 187008094..0b42f2d07 100644 --- a/docs/admin-guide.md +++ b/docs/admin-guide.md @@ -228,8 +228,8 @@ Config has five components in `main-notification-endpoint`, `scp`, `scm`, org-specific deployments; without hardcoding the AWS Organization stage in your buildspec. If this variable is not set, the SSM parameter `/adf/org/stage` defaults to "none". - More information about Multi-Org ADF setup can be found in the - [Multi-Org Guide](multi-org-guide.md) + More information about Multi-AWS Organization ADF setup can be found in the + [Multi-Organization Guide](multi-org-guide.md) ## Accounts diff --git a/docs/images/aws-multi-org-1.png b/docs/images/aws-multi-org-1.png new file mode 100644 index 0000000000000000000000000000000000000000..3fc4fcde5f749288657c2273ab398a5d9d38c843 GIT binary patch literal 66395 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 W$=8x%a~RHii;2M@{R)Cd" - Description: Org Stage - Default: /adf/org/stage -# At the time this Stack is deployed, the FinOps Account ID SSM Parameter doesn't -# exist, so we derive it from mapping it to the org stage -Mappings: - # Usage:!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId] - OrgStageBasedPropertyMap: - dev: - FinOpsAccountId: 1234567891012 # Dev Org - int: - FinOpsAccountId: 1234567891013 # Int Org - prod: - FinOpsAccountId: 1234567891014 # Prod Org -``` -In the above usage example you can see how the Cloudformation function FindInMap -`!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId]` can be -utilized to dynamically reference a custom 'AccountId' within the Template, -enabling the construction account specific granular Resource/Principal ARNS. - -# Customizing Codepipeline BuildSpecs Per Organization -A simple pattern to customize the buildspec is to load the `adf/org/stage` parameter -from ssm parameter from the parameter store via codebuild native mechanism. - -``` -env: - parameter-store: - ADF_ORG_STAGE: "/adf/org/stage" -``` - -This environment variable can then be used to drive decision/deployment logic -within any of the subsequent build commands/actions. -Some scenarios which could require Org specific context: -- Deriving the default log level based on the org stage for -a specific CDK application -- Appending the Stage name to AWS resource names having a requirement to be -both deterministic as well as globally unique -(whilst being deployed into multiple organizatinos) - -# Considerations for Multi-Org Deployment Maps -Whilst the Deployment Maps for ADF exist within a simarly named -`aws-deployment-framwork-pipelines` codecommit repository within the deployment -account. - -Some additional Multi-Org challenges exist when defining Targets for Deployments. - -The following considerations should be observed: -- Avoid utilizing Account Ids for Deployment Map Targets unless the deployment - is destined for a single organization. - - As an alternative Deploy via `Account Names`, `Account Tags` or `OU Paths` - which ADF will then use to dynamically generate the respective Account IDs - Target List when updating the Pipelines. -- Consider in a Large Enteprise Setup the number of targets that a Production -stage generates may be much greater than in predecessing Stages and design accordingly - - Review the Codepipeline action limitations. - - ADF handles best efforts to distribute Targets across Stages with a Pipeline, however - Deployments may need to be distributed across Multiple Pipelines when upper limits are reached. -- The source branch for the application code may be different per Organization - - The above described custom `adfconfig` configuration allows a different default -branch to be specified in the path `config.scm.default-scm-branch` per Organization \ No newline at end of file diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md new file mode 100644 index 000000000..9dc35a629 --- /dev/null +++ b/docs/multi-organization-guide.md @@ -0,0 +1,182 @@ +# Multi-Organization ADF Setup Guide + +This document describes how ADF can be run and managed in a multi AWS organization setup. + +- [Intended Audience](#intended-audience) +- [Defintion of a Multi-Organization ADF Setup](#defintion-of-a-multi-organization-adf-setup) +- [Common Use Case for a Multi-Organization ADF Setup - A Multi-Stage Landing Zone](#common-use-case-for-a-multi-organization-adf-setup---a-multi-stage-landing-zone) +- [Propagating Code Changes Between ADF Installations](#propagating-code-changes-between-adf-installations) +- [Customizing ADF Config Per AWS Organization](#customizing-adfconfig.yml-per-aws-organization) +- [Best Practices for Multi-Organization ADF setups](#best-practices-for-multi-organization-adf-setups) + - [1. Create a dedicated adfconfig.yml Per AWS Organization](#customizing-base-iam-roles-per-organization) + - [2. Design Multi-Organization ADF Deployment Maps](#customizing-codepipeline-buildspecs-per-organization) + - [3. Make the AWS Organization Stage Context Available in Codepipeline Build jobs](#3.-make-the-aws-organization-stage-context-available-in-codepipeline-build-jobs) + - [4. Customize the Base IAM Roles Per Organization](4.-customize-the-base-iam-roles-per-organization) + +## Intended Audience +This guide is intended for users that run a large scale AWS Organization with complex ADF application deployments and large numbers of ADF deployment pipelines. +Enterprises usually best meet the criteria for a multi AWS organization setup. We therefore refer to "Enterprises" as the target audience in the section below. +However, the approach described here should be applied to smaller organizations as well; assuming that sufficient engineering staff is available to support a multi AWS organization setup. + +## Defintion of a Multi-Organization ADF Setup +A multi-organization AWS-Deployment-Framework (ADF) setup describes a scenario where an +enterprise (or any user) maintains more than one AWS Organizations and each with it's own +dedicated ADF installation. + +The following diagram shows such a setup in the most generic level: + +![Multi Org Intro](images/aws-multi-org-1.png) + +## Common Use Case for a Multi-Organization ADF Setup - A Multi-Stage Landing Zone +The most common use case for a multi-organization ADF setup is a multi-stage (and multi-organization) [landing zone](https://docs.aws.amazon.com/prescriptive-guidance/latest/migration-aws-environment/understanding-landing-zones.html). Such a setup enables stable landing zone feature development that is otherwise not possible in a single AWS Organization. + +Let's assume that "Enterprise A" has a dedicated "prod" AWS Organization. This "prod" AWS Organization is used by it's end users to run all their workloads. In a single AWS Organization setup, the "prod" AWS Organization is be the only AWS Organization that exists. As part of the multi-organization ADF setup, we now add a separate "dev" and "int" AWS Organization. The following diagram shows such an architecture: +![Multi Org Intro](images/aws-multi-org-2.png) + +The development flow is as follows: +1. Development work for any landing zone feature always starts in the "dev" AWS Organization. The ADF repository `aws-deployment-framework-bootstrap` and `aws-deployment-framework-pipelines` are also considered a landing zone feature. The "dev" AWS Organization is exclusivly reserved for the landing zone development team. No end-user has access to the "dev" AWS Organization. +2. Once the code under development is stable and underwent successful unit and basic integration tests, it is moved from the "dev" AWS Organization to the "int" AWS Organization. The process of propagating code form one AWS Organization to another is described here [Propagating Code Changes Between ADF Installations](#Propagating-Code-Changes-Between-ADF-Installations). +3. The "int" AWS Organization is used for final integration testing and verification. The "dev" AWS Organization is exclusivly reserved for the landing zone development team. No end-user has access to the dev org. +4. Once all tests passed successfully, the code is moved from the "int" AWS Organization to the "prod" AWS Organization. +5. Assuming that the propagation and the deploymemt in the "prod" AWS Organization was successful, the code is now fully deployed in the "prod" AWS Organization and is available to the end-users. + +The benefits of such a setup is that an Enteprise can apply the same common `Software Development Lifecycle` to typical "one-off" landing zone services that are hard to test in a single-orgaization setup. It enables an Enterprises 'Cloud Center of Excellence' (landing zone team) a +controlled process to develop, test and validate changes to wide reaching mission-critical +services, including but not limited to: +- Service Control Policies changes. +- Identity Center and IAM based Access Management Configuration changes. +- Deployment Framework changes. +- AWS Organization changes; including OU structure. +- Control Tower and Account Provisioning configurations changes. +- Centralized security service configuration changes. +- Centralized cost management configuration changes. +- Centralized networking changes. + +The following sections are written in the context of this "". + +## Propagating Code Changes Between ADF Installations +With multiple ADF configurations across multiple AWS organization there comes a new challenge to maintain repositories and its configurations across multiple environments. +This applies to the following repositories: +- aws-deployment-framework-bootstrap +- aws-deployment-framework-pipelines +- any other landing zone repository + +As the requirements of the bootstrapped resources and adf configuration evolve they need to be updated over time, and these changes ideally propagated from one Installation to the next in a coordinated, controlled fashion. + +With an `Environment Branching` approach it's possible to build a 'hands-off' +automated mechanism to Promote from a "dev" AWS Organization installation to a "prod" AWS Organization installation. +This means that for example merging code from the "dev" branch of a repository to the "int" branch of a repository, will trigger the deployment process in the "int" AWS Organization. + +Implementing such an approach is out of scope of this guide and it heavily depends on the specific source code & CICD tool in use. + + +## Best Practices for Multi-Organization ADF setups +If you want to run ADF in a multi-organization setup, there are various best practices that should be followed. +When following these recommendations, the content of the repository `aws-deployment-framework-bootstrap` and `aws-deployment-framework-pipelines` should be stage agnostic. +This means that you can copy and paste the content of any of those two repositories into any AWS Organization stage ("dev", "int", "prod") and ADF will behave exactly + +### 1. Create a dedicated adfconfig.yml Per AWS Organization +One challenge with synchronising the aws-deployment-framework-bootstrap repository +across AWS Organizations is that the contents of the `adfconfig.yml` configuration +file is typically tailored to the ADF installation. The can be solved by adding a +custom adfconfig file for the given organization. + +Adding a configuration file with the name pattern `adfconfig.{organization id}.yml` +in the root of the `aws-deployment-framework-bootstrap` repository will take +precedence over the default `adfconfig.yml` settings file for that organization. + +For each AWS organization used with the ADF Framework setup an additional adfconfig +file can be defined. + + +### 2. Design Multi-Organization ADF Deployment Maps +The Deployment Maps for ADF exist in the codecommit repository +`aws-deployment-framwork-pipelines` within the deployment +account. Some additional Multi-Org challenges exist when defining targets for Deployments. As a high-level goal, a deployment map should be setup in such a way, that it can be copied over from one ADF instance to another without breaking / requiring any change. + +The following considerations should be observed when creating Deployment Maps for an multi-organization ADF setup: +1. Create Organization-agnostic deployment maps + - As a best-practice, deployment maps should be free of any hardocded AWS Account Ids for Deployment Map Targets, unless the deployment is destined for a single AWS Organization. + - Instead, target AWS accounts via `Account Names`, `Account Tags` or `OU Paths` + which ADF will then use to dynamically generate the respective Account IDs + Target List when updating the Pipelines. +2. Consider AWS service limits for AWS CodePipeline + - In a large enteprise setup the number of targets in a "prod" AWS Organizations AWS CodePipeline + stage may be much greater than in predecessing stages of the "int" and "prod" AWS Organizations. + - Review the Codepipeline action limitations. + - ADF distributes targets across AWS CodePipeline stages within a AWS CodePipeline on a best efforts basis, however + deployments may need to be distributed across multiple AWS CodePipeline when upper limits are reached. + - The current limits are ([AWS CodePipeline Limits](https://docs.aws.amazon.com/codepipeline/latest/userguide/limits.html)) + - 1000 AWS CodePipeline per AWS Account per region + - 500 Actions per AWS CodePipeline + - 50 Actions per AWS CodePipeline Stage + - This implies that a single ADF pipeline can target 500 AWS accounts max. At this point latest, the ADF pipeline needs to be manually rebalanced into smaller individual ADF pipelines. +3. Allow for empty deployment map targets + - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), ADF can be instructed to ignore any target that is not resolvable or empty (because no AWS Accounts exists in it). It is suggested to set this setting to `True`. Eventhough the OU structure and general setup across the different AWS Organization stages is usually identical, the number of created AWS Accounts might not. With this setting to `True`, temporary empty OUs are just ignored and do not lead to an error. + + 4. The source branch for the application code may be different per AWS Organization + - The above described custom `adfconfig` configuration allows a different default + branch to be specified in the path `config.scm.default-scm-branch` per AWS Organization + +### 3. Make the AWS Organization Stage Context Available in Codepipeline Build jobs +ADF applications often contain environment / AWS Organization stage specific configuration files. +In order to allow AWS Codebuild to select the proper configuration context for an application, the environment / AWS Organization stage context needs to be made available. +A simple pattern to solve this problem is the introduction of the SSM parameter `adf/org/stage` in the buildspec file of the application. +The following snippet shows the header of such a `codebuild.yaml` file. +``` +env: + parameter-store: + ADF_ORG_STAGE: "/adf/org/stage" +[...] +``` +This environment variable can then be used to drive decision/deployment logic +within any of the subsequent build commands/actions. +Some scenarios which could require Org specific context: +- Deriving the default log level based on the org stage for +a specific CDK application +- Appending the Stage name to AWS resource names having a requirement to be +both deterministic as well as globally unique +(whilst being deployed into multiple organizatinos) +- Selection a config file from a config folder with the following files: + - `config-dev.yaml` + - `config-int.yaml` + - `config-prod.yaml` + +### 4. Customize the Base IAM Roles Per Organization +ADF Supports Bootstrapping Baseline Cloudformation Stacks to all accounts +when they first join an AWS Organization and centrally governing the subsequent +Lifecycle of those Stacks. [See Here](admin-guide.md#bootstrapping-accounts) + +These Baseline Templates are typically used for Setting up Default IAM Roles and +Policies necessary for the foundations of an ADF Based Enteprise Landing Zone. + +In guidance with AWS Security Guidelines and `Least Privilege Access Principles`, +it it recommended to reduce the scope of any IAM Policy to the minimum required +Actions, Principals and Resource Scope necessary. + +To customize the scope of which resources or Principals are permitted within the +IAM Policies of the Baseline templates CFN Mapping fields can be utilized based +on the `Org Stage` SSM Parameter. As shown below: + +``` +Parameters: + OrgStage: + Type: "AWS::SSM::Parameter::Value" + Description: Org Stage + Default: /adf/org/stage +# At the time this Stack is deployed, the FinOps Account ID SSM Parameter doesn't +# exist, so we derive it from mapping it to the org stage +Mappings: + # Usage:!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId] + OrgStageBasedPropertyMap: + dev: + FinOpsAccountId: 1234567891012 # Dev Org + int: + FinOpsAccountId: 1234567891013 # Int Org + prod: + FinOpsAccountId: 1234567891014 # Prod Org +``` +In the above usage example you can see how the Cloudformation function FindInMap +`!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId]` can be +utilized to dynamically reference a custom 'AccountId' within the Template, +enabling the construction account specific granular Resource/Principal ARNS. \ No newline at end of file From 1e88aa79590154e5d0f4365d0d1c3b11421b54cc Mon Sep 17 00:00:00 2001 From: Andreas Falkenberg Date: Tue, 31 Oct 2023 17:52:55 +0100 Subject: [PATCH 09/51] feat: extended Multi-Org Docs --- docs/multi-organization-guide.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 9dc35a629..ba4ec140b 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -8,10 +8,10 @@ This document describes how ADF can be run and managed in a multi AWS organizati - [Propagating Code Changes Between ADF Installations](#propagating-code-changes-between-adf-installations) - [Customizing ADF Config Per AWS Organization](#customizing-adfconfig.yml-per-aws-organization) - [Best Practices for Multi-Organization ADF setups](#best-practices-for-multi-organization-adf-setups) - - [1. Create a dedicated adfconfig.yml Per AWS Organization](#customizing-base-iam-roles-per-organization) - - [2. Design Multi-Organization ADF Deployment Maps](#customizing-codepipeline-buildspecs-per-organization) - - [3. Make the AWS Organization Stage Context Available in Codepipeline Build jobs](#3.-make-the-aws-organization-stage-context-available-in-codepipeline-build-jobs) - - [4. Customize the Base IAM Roles Per Organization](4.-customize-the-base-iam-roles-per-organization) + - [1. Create a dedicated adfconfig.yml Per AWS Organization](#1-create-a-dedicated-adfconfigyml-per-aws-organization) + - [2. Design Multi-Organization ADF Deployment Maps](#2-design-multi-organization-adf-deployment-maps) + - [3. Make the AWS Organization Stage Context Available in Codepipeline Build jobs](#3-make-the-aws-organization-stage-context-available-in-codepipeline-build-jobs) + - [4. Customize the Base IAM Roles Per Organization](#4-customize-the-base-iam-roles-per-organization) ## Intended Audience This guide is intended for users that run a large scale AWS Organization with complex ADF application deployments and large numbers of ADF deployment pipelines. From dfb540c763a7d8b915b91cb0e60f42807f070d98 Mon Sep 17 00:00:00 2001 From: Andreas Falkenberg Date: Tue, 31 Oct 2023 17:57:04 +0100 Subject: [PATCH 10/51] feat: extended Multi-Org Docs - fix typo --- docs/multi-organization-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index ba4ec140b..800c9c4b1 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -3,7 +3,7 @@ This document describes how ADF can be run and managed in a multi AWS organization setup. - [Intended Audience](#intended-audience) -- [Defintion of a Multi-Organization ADF Setup](#defintion-of-a-multi-organization-adf-setup) +- [Definition of a Multi-Organization ADF Setup](#definition-of-a-multi-organization-adf-setup) - [Common Use Case for a Multi-Organization ADF Setup - A Multi-Stage Landing Zone](#common-use-case-for-a-multi-organization-adf-setup---a-multi-stage-landing-zone) - [Propagating Code Changes Between ADF Installations](#propagating-code-changes-between-adf-installations) - [Customizing ADF Config Per AWS Organization](#customizing-adfconfig.yml-per-aws-organization) @@ -18,7 +18,7 @@ This guide is intended for users that run a large scale AWS Organization with co Enterprises usually best meet the criteria for a multi AWS organization setup. We therefore refer to "Enterprises" as the target audience in the section below. However, the approach described here should be applied to smaller organizations as well; assuming that sufficient engineering staff is available to support a multi AWS organization setup. -## Defintion of a Multi-Organization ADF Setup +## Definition of a Multi-Organization ADF Setup A multi-organization AWS-Deployment-Framework (ADF) setup describes a scenario where an enterprise (or any user) maintains more than one AWS Organizations and each with it's own dedicated ADF installation. From 24e6ec97cfcef0c9995d69eb466becfeab77966d Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 12:49:03 +0100 Subject: [PATCH 11/51] Update README.md Co-authored-by: Simon Kok --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 40fb335d6..ac2230e53 100644 --- a/README.md +++ b/README.md @@ -36,4 +36,5 @@ within the AWS Console. - Refer to the [User Guide](docs/user-guide.md) for using ADF once it is setup. - Refer to the [Samples Guide](docs/samples-guide.md) for a detailed walk through of the provided samples. -- Refer to the [Multi-Orgaization ADF Setup](docs/multi-organization-guide.md) for using ADF in an enterprise-grade setup. \ No newline at end of file +- Refer to the [Multi-Organization ADF Setup](docs/multi-organization-guide.md) + to use ADF in an enterprise-grade setup. \ No newline at end of file From ae42efb8a1b04f0b8d15900808058c9fd8c96267 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 12:50:13 +0100 Subject: [PATCH 12/51] Update docs/admin-guide.md Co-authored-by: Simon Kok --- docs/admin-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/admin-guide.md b/docs/admin-guide.md index 3aa878494..f175cc923 100644 --- a/docs/admin-guide.md +++ b/docs/admin-guide.md @@ -239,8 +239,8 @@ Config has five components in `main-notification-endpoint`, `scp`, `scm`, org-specific deployments; without hardcoding the AWS Organization stage in your buildspec. If this variable is not set, the SSM parameter `/adf/org/stage` defaults to "none". - More information about Multi-AWS Organization ADF setup can be found in the - [Multi-Organization Guide](multi-org-guide.md) + More information about setting up ADF with multiple AWS Organizations can + be found in the [Multi-Organization Guide](multi-organization-guide.md) ## Accounts From 5ee01ba8b1d27e5a17009d7843f452d260ca5bab Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 12:50:55 +0100 Subject: [PATCH 13/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 800c9c4b1..8dccd991d 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -10,7 +10,7 @@ This document describes how ADF can be run and managed in a multi AWS organizati - [Best Practices for Multi-Organization ADF setups](#best-practices-for-multi-organization-adf-setups) - [1. Create a dedicated adfconfig.yml Per AWS Organization](#1-create-a-dedicated-adfconfigyml-per-aws-organization) - [2. Design Multi-Organization ADF Deployment Maps](#2-design-multi-organization-adf-deployment-maps) - - [3. Make the AWS Organization Stage Context Available in Codepipeline Build jobs](#3-make-the-aws-organization-stage-context-available-in-codepipeline-build-jobs) + - [3. Make the AWS Organization Stage Context Available in CodePipeline Build jobs](#3-make-the-aws-organization-stage-context-available-in-codepipeline-build-jobs) - [4. Customize the Base IAM Roles Per Organization](#4-customize-the-base-iam-roles-per-organization) ## Intended Audience From 058b393dfacc4a3a3acd229821e97da9631284b0 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 12:51:15 +0100 Subject: [PATCH 14/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 8dccd991d..934701e04 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -178,5 +178,5 @@ Mappings: ``` In the above usage example you can see how the Cloudformation function FindInMap `!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId]` can be -utilized to dynamically reference a custom 'AccountId' within the Template, +utilized to dynamically reference a custom 'AccountId' within the template, enabling the construction account specific granular Resource/Principal ARNS. \ No newline at end of file From e0ca1376525afe1604917e0f33bb946a779d6142 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 12:58:48 +0100 Subject: [PATCH 15/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 934701e04..6c605ae78 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -179,4 +179,4 @@ Mappings: In the above usage example you can see how the Cloudformation function FindInMap `!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId]` can be utilized to dynamically reference a custom 'AccountId' within the template, -enabling the construction account specific granular Resource/Principal ARNS. \ No newline at end of file +enabling the construction of account specific granular Resource and Principal ARNs. \ No newline at end of file From 851bcd331afe02d807aaf1771121cd64a077e954 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 12:59:01 +0100 Subject: [PATCH 16/51] Update src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml Co-authored-by: Simon Kok --- .../initial_commit/bootstrap_repository/example-adfconfig.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml index f58d2d0c7..4deb5b821 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml @@ -34,7 +34,7 @@ config: # in both the deployment account and and all # Target member accounts as part of the Bootstrap Statemachine. # It is useful as a flag to drive Organization specific logic within - # IAM Role definitions/conditions aswell as Build spec behavior. + # IAM Role definitions/conditions as well as Build spec behavior. extensions: terraform: From d9677a1e0278cbee79976474f08c4db41c4347b8 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 12:59:50 +0100 Subject: [PATCH 17/51] Update src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml Co-authored-by: Simon Kok --- .../bootstrap_repository/adf-bootstrap/example-global-iam.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml index 1bb9806a9..5c530590c 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml @@ -17,8 +17,8 @@ Parameters: Default: /adf/org/stage # Org StageCustom Mappings allows you to dynamically build different IAM -# Conditions / Principals ARN / Resource ARN per Organization applying Least -# Privilege Principals whilst retaining a Single Stack Definition for all +# Conditions / Principals ARN / Resource ARN per Organization applying +# least-privilege principles whilst retaining a Single Stack Definition for all # environments. # usage !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] Mappings: From 0512cd56afd932fb51859ad7b78ef31fb7defda9 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 13:00:16 +0100 Subject: [PATCH 18/51] Update src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml Co-authored-by: Simon Kok --- .../adf-bootstrap/deployment/example-global-iam.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml index f5acaf100..bbf619bf6 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml @@ -9,7 +9,7 @@ Parameters: # path config.org.stage OrgStage: Type: "AWS::SSM::Parameter::Value" - Description: A stage used to differentiate Multi-Org ADF environments + Description: A stage used to differentiate Multi-Organization ADF environments Default: /adf/org/stage # Org StageCustom Mappings allows you to dynamically build different IAM From caa4afbad1a347820b3e9fe33efcc05f75b4ab58 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 13:02:19 +0100 Subject: [PATCH 19/51] Update docs/admin-guide.md Co-authored-by: Simon Kok --- docs/admin-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin-guide.md b/docs/admin-guide.md index f175cc923..e695092c5 100644 --- a/docs/admin-guide.md +++ b/docs/admin-guide.md @@ -234,7 +234,7 @@ Config has five components in `main-notification-endpoint`, `scp`, `scm`, and prod AWS Organization with its own ADF instance per AWS organization. This approach allows for well-tested and stable prod AWS Organization deployments. If set, a matching SSM parameter `/adf/org/stage` gets - created in deployment aswell as all target accounts. + created in the deployment and all target accounts. You can reference it within your buildspec files to allow for org-specific deployments; without hardcoding the AWS Organization stage in your buildspec. If this variable is not set, the SSM parameter From 2569f21c4f29fe7ec6f33230733e991afe62bfb6 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 13:03:34 +0100 Subject: [PATCH 20/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 6c605ae78..00b85fa10 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -11,7 +11,7 @@ This document describes how ADF can be run and managed in a multi AWS organizati - [1. Create a dedicated adfconfig.yml Per AWS Organization](#1-create-a-dedicated-adfconfigyml-per-aws-organization) - [2. Design Multi-Organization ADF Deployment Maps](#2-design-multi-organization-adf-deployment-maps) - [3. Make the AWS Organization Stage Context Available in CodePipeline Build jobs](#3-make-the-aws-organization-stage-context-available-in-codepipeline-build-jobs) - - [4. Customize the Base IAM Roles Per Organization](#4-customize-the-base-iam-roles-per-organization) + - [4. Customize the Base IAM Roles Per AWS Organization](#4-customize-the-base-iam-roles-per-aws-organization) ## Intended Audience This guide is intended for users that run a large scale AWS Organization with complex ADF application deployments and large numbers of ADF deployment pipelines. From 0e382e25897e4b223bfdf4ef02747cd2d4736285 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 13:04:21 +0100 Subject: [PATCH 21/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 00b85fa10..7ee8c69fb 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -20,8 +20,8 @@ However, the approach described here should be applied to smaller organizations ## Definition of a Multi-Organization ADF Setup A multi-organization AWS-Deployment-Framework (ADF) setup describes a scenario where an -enterprise (or any user) maintains more than one AWS Organizations and each with it's own -dedicated ADF installation. +enterprise (or any user) maintains more than one AWS Organizations. +Where each AWS Organization holds its own dedicated ADF installation. The following diagram shows such a setup in the most generic level: From cf4206004db7ee05db81cdc7f74d9c008a1be99b Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 13:05:02 +0100 Subject: [PATCH 22/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 7ee8c69fb..886c2e6ce 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -45,7 +45,7 @@ controlled process to develop, test and validate changes to wide reaching missio services, including but not limited to: - Service Control Policies changes. - Identity Center and IAM based Access Management Configuration changes. -- Deployment Framework changes. +- AWS Deployment Framework changes. - AWS Organization changes; including OU structure. - Control Tower and Account Provisioning configurations changes. - Centralized security service configuration changes. From 3d25aeb6e876ab40a60c4812c543690fd763d69e Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 13:05:39 +0100 Subject: [PATCH 23/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 886c2e6ce..b7531b6d5 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -40,7 +40,7 @@ The development flow is as follows: 4. Once all tests passed successfully, the code is moved from the "int" AWS Organization to the "prod" AWS Organization. 5. Assuming that the propagation and the deploymemt in the "prod" AWS Organization was successful, the code is now fully deployed in the "prod" AWS Organization and is available to the end-users. -The benefits of such a setup is that an Enteprise can apply the same common `Software Development Lifecycle` to typical "one-off" landing zone services that are hard to test in a single-orgaization setup. It enables an Enterprises 'Cloud Center of Excellence' (landing zone team) a +The benefits of such a setup is that an Enterprise can apply the same common `Software Development Lifecycle` to typical "one-off" landing zone services that are hard to test in a single-organization setup. It provides the enterprise's 'Cloud Center of Excellence' (landing zone team) a controlled process to develop, test and validate changes to wide reaching mission-critical services, including but not limited to: - Service Control Policies changes. From 815bc1902a2ee9927d25595558e09aafc804aa63 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 13:43:37 +0100 Subject: [PATCH 24/51] Apply suggestions from code review Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 92 +++++++++++++++++--------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index b7531b6d5..582d2d8c8 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -30,15 +30,20 @@ The following diagram shows such a setup in the most generic level: ## Common Use Case for a Multi-Organization ADF Setup - A Multi-Stage Landing Zone The most common use case for a multi-organization ADF setup is a multi-stage (and multi-organization) [landing zone](https://docs.aws.amazon.com/prescriptive-guidance/latest/migration-aws-environment/understanding-landing-zones.html). Such a setup enables stable landing zone feature development that is otherwise not possible in a single AWS Organization. -Let's assume that "Enterprise A" has a dedicated "prod" AWS Organization. This "prod" AWS Organization is used by it's end users to run all their workloads. In a single AWS Organization setup, the "prod" AWS Organization is be the only AWS Organization that exists. As part of the multi-organization ADF setup, we now add a separate "dev" and "int" AWS Organization. The following diagram shows such an architecture: +Let's assume that "Enterprise A" has a dedicated production (referenced as "prod" hereafter) AWS Organization. This "prod" AWS Organization is used by it's end users to run all their workloads. +In a single AWS Organization setup, the "prod" AWS Organization is the only AWS Organization that exists. +Applying changes to this single organization, for example updating ADF, changing SCPs or applying enforcing controls via AWS Config, introduces the risk or disrupting your production workloads. +To mitigate this risk, it is recommended to apply the mutl-organization ADF setup as described in this document. + +As part of the multi-organization ADF setup, one or more AWS Organizations are added. In the instructions below, a separate development ("dev") and integration ("int") AWS Organization are added. The following diagram shows such an architecture: ![Multi Org Intro](images/aws-multi-org-2.png) The development flow is as follows: -1. Development work for any landing zone feature always starts in the "dev" AWS Organization. The ADF repository `aws-deployment-framework-bootstrap` and `aws-deployment-framework-pipelines` are also considered a landing zone feature. The "dev" AWS Organization is exclusivly reserved for the landing zone development team. No end-user has access to the "dev" AWS Organization. -2. Once the code under development is stable and underwent successful unit and basic integration tests, it is moved from the "dev" AWS Organization to the "int" AWS Organization. The process of propagating code form one AWS Organization to another is described here [Propagating Code Changes Between ADF Installations](#Propagating-Code-Changes-Between-ADF-Installations). -3. The "int" AWS Organization is used for final integration testing and verification. The "dev" AWS Organization is exclusivly reserved for the landing zone development team. No end-user has access to the dev org. +1. Development work for any landing zone feature always starts in the "dev" AWS Organization. The ADF repository `aws-deployment-framework-bootstrap` and `aws-deployment-framework-pipelines` are also considered a landing zone feature. The "dev" AWS Organization is exclusively reserved for the landing zone development team. End-users do not have access to the "dev" AWS Organization. +2. Once the code under development is stable and underwent successful unit and basic integration tests, it is moved from the "dev" AWS Organization to the "int" AWS Organization. The process of propagating code from one AWS Organization to another is described in the [Propagating Code Changes Between ADF Installations section](#Propagating-Code-Changes-Between-ADF-Installations). +3. The "int" AWS Organization is used for final integration testing and verification. The "int" AWS Organization is exclusively reserved for the landing zone development team. No end-user has access to the "int" AWS Organization. 4. Once all tests passed successfully, the code is moved from the "int" AWS Organization to the "prod" AWS Organization. -5. Assuming that the propagation and the deploymemt in the "prod" AWS Organization was successful, the code is now fully deployed in the "prod" AWS Organization and is available to the end-users. +5. Assuming that the propagation and the deployment in the "prod" AWS Organization was successful, the code is now fully deployed in the "prod" AWS Organization and is available to the end-users. The benefits of such a setup is that an Enterprise can apply the same common `Software Development Lifecycle` to typical "one-off" landing zone services that are hard to test in a single-organization setup. It provides the enterprise's 'Cloud Center of Excellence' (landing zone team) a controlled process to develop, test and validate changes to wide reaching mission-critical @@ -55,28 +60,28 @@ services, including but not limited to: The following sections are written in the context of this "". ## Propagating Code Changes Between ADF Installations -With multiple ADF configurations across multiple AWS organization there comes a new challenge to maintain repositories and its configurations across multiple environments. +With multiple ADF configurations across multiple AWS Organization there comes a new challenge to maintain repositories and its configurations across multiple environments. This applies to the following repositories: - aws-deployment-framework-bootstrap - aws-deployment-framework-pipelines - any other landing zone repository -As the requirements of the bootstrapped resources and adf configuration evolve they need to be updated over time, and these changes ideally propagated from one Installation to the next in a coordinated, controlled fashion. +As the requirements of the bootstrapped resources and ADF configuration evolves they need to be updated over time. These changes must propagate from one environment to the next in a coordinated, controlled fashion. -With an `Environment Branching` approach it's possible to build a 'hands-off' -automated mechanism to Promote from a "dev" AWS Organization installation to a "prod" AWS Organization installation. -This means that for example merging code from the "dev" branch of a repository to the "int" branch of a repository, will trigger the deployment process in the "int" AWS Organization. +With an `Environment Branching` approach it is possible to build a 'hands-off' +automated mechanism to promote from a "dev" AWS Organization environment to a "prod" AWS Organization environment. +This means that, for example merging code from the "dev" branch of a repository to the "int" branch of a repository, it will trigger the deployment process in the "int" AWS Organization. -Implementing such an approach is out of scope of this guide and it heavily depends on the specific source code & CICD tool in use. +Implementing such an approach is out of scope for this guide as it heavily depends on the specific source code and CI/CD tool in use. ## Best Practices for Multi-Organization ADF setups If you want to run ADF in a multi-organization setup, there are various best practices that should be followed. When following these recommendations, the content of the repository `aws-deployment-framework-bootstrap` and `aws-deployment-framework-pipelines` should be stage agnostic. -This means that you can copy and paste the content of any of those two repositories into any AWS Organization stage ("dev", "int", "prod") and ADF will behave exactly +This means that you can copy and paste the content of any of those two repositories into any AWS Organization stage ("dev", "int", "prod") and ADF will behave exactly the same. ### 1. Create a dedicated adfconfig.yml Per AWS Organization -One challenge with synchronising the aws-deployment-framework-bootstrap repository +One challenge with synchronizing the `aws-deployment-framework-bootstrap` repository across AWS Organizations is that the contents of the `adfconfig.yml` configuration file is typically tailored to the ADF installation. The can be solved by adding a custom adfconfig file for the given organization. @@ -90,38 +95,38 @@ file can be defined. ### 2. Design Multi-Organization ADF Deployment Maps -The Deployment Maps for ADF exist in the codecommit repository +The Deployment Maps for ADF exist in the CodeCommit repository `aws-deployment-framwork-pipelines` within the deployment -account. Some additional Multi-Org challenges exist when defining targets for Deployments. As a high-level goal, a deployment map should be setup in such a way, that it can be copied over from one ADF instance to another without breaking / requiring any change. +account. Some additional multi-organization challenges exist when defining targets for deployments. As a high-level goal, a deployment map should be setup in such a way, that it can be copied over from one ADF instance to another without breaking / requiring any change. -The following considerations should be observed when creating Deployment Maps for an multi-organization ADF setup: +The following considerations should be observed when creating deployment maps for a multi-organization ADF setup: 1. Create Organization-agnostic deployment maps - - As a best-practice, deployment maps should be free of any hardocded AWS Account Ids for Deployment Map Targets, unless the deployment is destined for a single AWS Organization. - - Instead, target AWS accounts via `Account Names`, `Account Tags` or `OU Paths` - which ADF will then use to dynamically generate the respective Account IDs - Target List when updating the Pipelines. + - As a best-practice, deployment maps should be free of any hard-coded AWS Account IDs for deployment map targets, unless the deployment is destined for a single AWS Organization only. + - Instead, target AWS accounts via `Account Names`, `Account Tags` or `OU Paths`. + This will allow ADF to dynamically generate the respective AWS Account IDs + for the target list when updating the pipelines. 2. Consider AWS service limits for AWS CodePipeline - - In a large enteprise setup the number of targets in a "prod" AWS Organizations AWS CodePipeline - stage may be much greater than in predecessing stages of the "int" and "prod" AWS Organizations. - - Review the Codepipeline action limitations. - - ADF distributes targets across AWS CodePipeline stages within a AWS CodePipeline on a best efforts basis, however + - In a large enterprise setup, the number of targets in a "prod" AWS Organizations for an AWS CodePipeline + stage may be much larger than its preceding stages in the "dev" and "int" AWS Organizations. + - Review the CodePipeline action limitations. + - ADF distributes targets across AWS CodePipeline stages within a deployment pipeline, spreading the accounts across multiple stages to workaround the AWS CodePipeline actions-per-stage limitation. deployments may need to be distributed across multiple AWS CodePipeline when upper limits are reached. - The current limits are ([AWS CodePipeline Limits](https://docs.aws.amazon.com/codepipeline/latest/userguide/limits.html)) - 1000 AWS CodePipeline per AWS Account per region - 500 Actions per AWS CodePipeline - 50 Actions per AWS CodePipeline Stage - - This implies that a single ADF pipeline can target 500 AWS accounts max. At this point latest, the ADF pipeline needs to be manually rebalanced into smaller individual ADF pipelines. + - This implies that a single ADF pipeline can target 500 AWS Accounts max. This may require you to manually balance the targets across multiple deployment pipelines. 3. Allow for empty deployment map targets - - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), ADF can be instructed to ignore any target that is not resolvable or empty (because no AWS Accounts exists in it). It is suggested to set this setting to `True`. Eventhough the OU structure and general setup across the different AWS Organization stages is usually identical, the number of created AWS Accounts might not. With this setting to `True`, temporary empty OUs are just ignored and do not lead to an error. + - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), ADF can be instructed to ignore any target that is not resolvable or empty (because no AWS Accounts exists in it). It is suggested to set this setting to `True`. Even though the OU structure and general setup across the different AWS Organization stages is usually identical, the number of created AWS Accounts might not be. With this setting is set to `True`, temporary empty OUs are just ignored and do not lead to an error. 4. The source branch for the application code may be different per AWS Organization - The above described custom `adfconfig` configuration allows a different default - branch to be specified in the path `config.scm.default-scm-branch` per AWS Organization + branch to be specified in the path `config.scm.default-scm-branch` per AWS Organization. -### 3. Make the AWS Organization Stage Context Available in Codepipeline Build jobs +### 3. Make the AWS Organization Stage Context Available in CodePipeline Build jobs ADF applications often contain environment / AWS Organization stage specific configuration files. -In order to allow AWS Codebuild to select the proper configuration context for an application, the environment / AWS Organization stage context needs to be made available. -A simple pattern to solve this problem is the introduction of the SSM parameter `adf/org/stage` in the buildspec file of the application. +In order to allow AWS CodeBuild to select the proper configuration context for an application, the environment / AWS Organization stage context needs to be made available. +A simple pattern to solve this problem is the introduction of the SSM parameter `adf/org/stage` in the buildspec file of the application. The following snippet shows the header of such a `codebuild.yaml` file. ``` env: @@ -131,31 +136,32 @@ env: ``` This environment variable can then be used to drive decision/deployment logic within any of the subsequent build commands/actions. -Some scenarios which could require Org specific context: -- Deriving the default log level based on the org stage for + +Some scenarios which could require organization specific context include: +- Deriving the default log level based on the organization stage for a specific CDK application - Appending the Stage name to AWS resource names having a requirement to be -both deterministic as well as globally unique -(whilst being deployed into multiple organizatinos) + both deterministic as well as globally unique +(whilst being deployed into multiple organizations). - Selection a config file from a config folder with the following files: - `config-dev.yaml` - `config-int.yaml` - `config-prod.yaml` -### 4. Customize the Base IAM Roles Per Organization -ADF Supports Bootstrapping Baseline Cloudformation Stacks to all accounts +### 4. Customize the Base IAM Roles Per AWS Organization +ADF Supports Bootstrapping Baseline CloudFormation Stacks to all AWS Accounts when they first join an AWS Organization and centrally governing the subsequent -Lifecycle of those Stacks. [See Here](admin-guide.md#bootstrapping-accounts) +lifecycle of those stacks. [More information on bootstrapping accounts can be found in the admin guide](admin-guide.md#bootstrapping-accounts). -These Baseline Templates are typically used for Setting up Default IAM Roles and -Policies necessary for the foundations of an ADF Based Enteprise Landing Zone. +These Baseline Templates are typically used for setting up the default IAM roles and +Policies necessary for the foundations of an ADF Based Enterprise Landing Zone. In guidance with AWS Security Guidelines and `Least Privilege Access Principles`, -it it recommended to reduce the scope of any IAM Policy to the minimum required +it is recommended to reduce the scope of any IAM Policy to the minimum required Actions, Principals and Resource Scope necessary. -To customize the scope of which resources or Principals are permitted within the -IAM Policies of the Baseline templates CFN Mapping fields can be utilized based +To customize the scope of which resources or principals are permitted within the +IAM Policies of the baseline templates CFN Mapping fields can be utilized based on the `Org Stage` SSM Parameter. As shown below: ``` @@ -176,7 +182,7 @@ Mappings: prod: FinOpsAccountId: 1234567891014 # Prod Org ``` -In the above usage example you can see how the Cloudformation function FindInMap +In the above usage example you can see how the CloudFormation function FindInMap `!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId]` can be utilized to dynamically reference a custom 'AccountId' within the template, enabling the construction of account specific granular Resource and Principal ARNs. \ No newline at end of file From 09a8d89632ba7db0a92a7945bfcd2a8d35880ea6 Mon Sep 17 00:00:00 2001 From: Andreas Falkenberg Date: Sat, 11 Nov 2023 16:06:04 +0100 Subject: [PATCH 25/51] fix: make doc changes based on review --- ...ulti-org-adf-config-multi-organization.png | Bin 0 -> 81389 bytes docs/multi-organization-guide.md | 110 +++++++++++++----- 2 files changed, 81 insertions(+), 29 deletions(-) create mode 100644 docs/images/aws-multi-org-adf-config-multi-organization.png diff --git a/docs/images/aws-multi-org-adf-config-multi-organization.png b/docs/images/aws-multi-org-adf-config-multi-organization.png new file mode 100644 index 0000000000000000000000000000000000000000..1cedc1f2d5b4c08bd45032a736862f5fdac8b720 GIT binary patch literal 81389 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 literal 0 HcmV?d00001 diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 582d2d8c8..7917e2446 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -9,9 +9,10 @@ This document describes how ADF can be run and managed in a multi AWS organizati - [Customizing ADF Config Per AWS Organization](#customizing-adfconfig.yml-per-aws-organization) - [Best Practices for Multi-Organization ADF setups](#best-practices-for-multi-organization-adf-setups) - [1. Create a dedicated adfconfig.yml Per AWS Organization](#1-create-a-dedicated-adfconfigyml-per-aws-organization) - - [2. Design Multi-Organization ADF Deployment Maps](#2-design-multi-organization-adf-deployment-maps) - - [3. Make the AWS Organization Stage Context Available in CodePipeline Build jobs](#3-make-the-aws-organization-stage-context-available-in-codepipeline-build-jobs) - - [4. Customize the Base IAM Roles Per AWS Organization](#4-customize-the-base-iam-roles-per-aws-organization) + - [2. Customize the ADF Config File Per AWS Organization](#2-customize-the-adf-config-file-per-aws-organization) + - [3. Design Multi-Organization ADF Deployment Maps](#2-design-multi-organization-adf-deployment-maps) + - [4. Make the AWS Organization Stage Context Available in AWS CodePipeline Build jobs](#3-make-the-aws-organization-stage-context-available-in-aws-codepipeline-build-jobs) + - [5. Customize the Base IAM Roles Per AWS Organization](#4-customize-the-base-iam-roles-per-aws-organization) ## Intended Audience This guide is intended for users that run a large scale AWS Organization with complex ADF application deployments and large numbers of ADF deployment pipelines. @@ -33,7 +34,7 @@ The most common use case for a multi-organization ADF setup is a multi-stage (an Let's assume that "Enterprise A" has a dedicated production (referenced as "prod" hereafter) AWS Organization. This "prod" AWS Organization is used by it's end users to run all their workloads. In a single AWS Organization setup, the "prod" AWS Organization is the only AWS Organization that exists. Applying changes to this single organization, for example updating ADF, changing SCPs or applying enforcing controls via AWS Config, introduces the risk or disrupting your production workloads. -To mitigate this risk, it is recommended to apply the mutl-organization ADF setup as described in this document. +To mitigate this risk, it is recommended to apply the multi-organization ADF setup as described in this document. As part of the multi-organization ADF setup, one or more AWS Organizations are added. In the instructions below, a separate development ("dev") and integration ("int") AWS Organization are added. The following diagram shows such an architecture: ![Multi Org Intro](images/aws-multi-org-2.png) @@ -41,12 +42,12 @@ As part of the multi-organization ADF setup, one or more AWS Organizations are a The development flow is as follows: 1. Development work for any landing zone feature always starts in the "dev" AWS Organization. The ADF repository `aws-deployment-framework-bootstrap` and `aws-deployment-framework-pipelines` are also considered a landing zone feature. The "dev" AWS Organization is exclusively reserved for the landing zone development team. End-users do not have access to the "dev" AWS Organization. 2. Once the code under development is stable and underwent successful unit and basic integration tests, it is moved from the "dev" AWS Organization to the "int" AWS Organization. The process of propagating code from one AWS Organization to another is described in the [Propagating Code Changes Between ADF Installations section](#Propagating-Code-Changes-Between-ADF-Installations). -3. The "int" AWS Organization is used for final integration testing and verification. The "int" AWS Organization is exclusively reserved for the landing zone development team. No end-user has access to the "int" AWS Organization. +3. The "int" AWS Organization is used for final integration testing and verification. The "int" AWS Organization is exclusively reserved for the landing zone development team. End-users do not have access to the "int" AWS Organization. 4. Once all tests passed successfully, the code is moved from the "int" AWS Organization to the "prod" AWS Organization. 5. Assuming that the propagation and the deployment in the "prod" AWS Organization was successful, the code is now fully deployed in the "prod" AWS Organization and is available to the end-users. The benefits of such a setup is that an Enterprise can apply the same common `Software Development Lifecycle` to typical "one-off" landing zone services that are hard to test in a single-organization setup. It provides the enterprise's 'Cloud Center of Excellence' (landing zone team) a -controlled process to develop, test and validate changes to wide reaching mission-critical +controlled process to develop, test, and validate changes to wide reaching mission-critical services, including but not limited to: - Service Control Policies changes. - Identity Center and IAM based Access Management Configuration changes. @@ -57,10 +58,10 @@ services, including but not limited to: - Centralized cost management configuration changes. - Centralized networking changes. -The following sections are written in the context of this "". +The following sections are written in the context of the above described use case; a multi-stage landing zone. ## Propagating Code Changes Between ADF Installations -With multiple ADF configurations across multiple AWS Organization there comes a new challenge to maintain repositories and its configurations across multiple environments. +With multiple ADF configurations across multiple AWS Organizations there comes a new challenge to maintain repositories and its configurations across multiple environments. This applies to the following repositories: - aws-deployment-framework-bootstrap - aws-deployment-framework-pipelines @@ -91,49 +92,99 @@ in the root of the `aws-deployment-framework-bootstrap` repository will take precedence over the default `adfconfig.yml` settings file for that organization. For each AWS organization used with the ADF Framework setup an additional adfconfig -file can be defined. +file can be defined. + +The following screenshot shows the ADF root directory of a multi-organisation ADF setup with three stages ("dev", "int", "prod"). +Each AWS Organization has its own ADF config file with environment-specific values. +![adf-multi-org-root-directory-screenshot](images/aws-multi-org-adf-config-multi-organization.png) + +## 2. Customize the ADF Config File Per AWS Organization +Once a dedicated ADF config file per tenant is setup, it needs to be customized for each AWS Organizations context. It is recommended to make use of the following ADF configuration options in a multi-organization context: + +```yaml + scm: + default-scm-branch: prod # This setting ensures, that the "prod" branch is selected as the source branch for any ADF deployment pipeline. + default-scm-codecommit-account-id: "123456789012" # This setting ensure that the AWS Account 123456789012 is selected as the default AWS account to + org: + stage: prod # This setting will create the SSM parameter "/adf/org/stage" in the ADF deployment AWS Account. This parameter then can be referenced as an environement variable in application buildspec files to establish the AWS organization context. + deployment-maps: + allow-empty: "True" # It is recommened to set this setting to "True". When this setting is set to `True`, temporary empty OUs are just ignored and do not lead to an error. +``` +The following sample ADF config file `adfconfig.o-a123456789.yml` shows a complete example for a "prod" AWS organization. + +```yaml +# The following configuration is only loaded for int Organization: o-a123456789 +roles: + cross-account-access: AWSControlTowerExecution + # ^ The role by ADF to assume cross account access + +regions: + deployment-account: eu-central-1 + # ^ The region you define as your main deployment region + targets: # A list of regions you wish to bootstrap and also deploy into via pipelines + - us-east-1 +config: + main-notification-endpoint: + - type: email + target: john.doe@example.com + # ^ Email/Slack channel who receives notifications for the main bootstrapping pipeline + protected: + - ou-1234-abcdefgh # OU Lockdown + moves: + - name: to-root + action: safe # Can be safe or remove-base + scp: + keep-default-scp: enabled + # ^ Determines if the default AWSFullAccess SCP stays attached to all OU's + scm: + auto-create-repositories: enabled + default-scm-branch: prod + default-scm-codecommit-account-id: "123456789012" + org: + stage: prod + deployment-maps: + allow-empty: "True" # Defaults to "False". Needs to be "True" or "False" +``` -### 2. Design Multi-Organization ADF Deployment Maps -The Deployment Maps for ADF exist in the CodeCommit repository +### 3. Design Multi-Organization ADF Deployment Maps +The Deployment Maps for ADF exist in the AWS CodeCommit repository `aws-deployment-framwork-pipelines` within the deployment account. Some additional multi-organization challenges exist when defining targets for deployments. As a high-level goal, a deployment map should be setup in such a way, that it can be copied over from one ADF instance to another without breaking / requiring any change. The following considerations should be observed when creating deployment maps for a multi-organization ADF setup: 1. Create Organization-agnostic deployment maps - As a best-practice, deployment maps should be free of any hard-coded AWS Account IDs for deployment map targets, unless the deployment is destined for a single AWS Organization only. - - Instead, target AWS accounts via `Account Names`, `Account Tags` or `OU Paths`. - This will allow ADF to dynamically generate the respective AWS Account IDs - for the target list when updating the pipelines. + - Instead, target AWS Accounts via `Account Names`, `Account Tags` or `OU Paths`. + This will allow ADF to dynamically generate the respective AWS Account IDs for the target list when updating the pipelines. 2. Consider AWS service limits for AWS CodePipeline - - In a large enterprise setup, the number of targets in a "prod" AWS Organizations for an AWS CodePipeline - stage may be much larger than its preceding stages in the "dev" and "int" AWS Organizations. - - Review the CodePipeline action limitations. - - ADF distributes targets across AWS CodePipeline stages within a deployment pipeline, spreading the accounts across multiple stages to workaround the AWS CodePipeline actions-per-stage limitation. - deployments may need to be distributed across multiple AWS CodePipeline when upper limits are reached. - - The current limits are ([AWS CodePipeline Limits](https://docs.aws.amazon.com/codepipeline/latest/userguide/limits.html)) + - Review the AWS CodePipeline action limitations. The current limits are ([AWS CodePipeline Limits](https://docs.aws.amazon.com/codepipeline/latest/userguide/limits.html)) - 1000 AWS CodePipeline per AWS Account per region - 500 Actions per AWS CodePipeline - 50 Actions per AWS CodePipeline Stage - - This implies that a single ADF pipeline can target 500 AWS Accounts max. This may require you to manually balance the targets across multiple deployment pipelines. + - Those limits imply that a single ADF pipeline can target 500 AWS Accounts max. This may require you to manually balance the targets across multiple deployment pipelines. + - ADF distributes targets across AWS CodePipeline stages within a deployment pipeline, spreading the accounts across multiple stages to workaround the AWS CodePipeline actions-per-stage limitation. Deployments may need to be manually distributed across multiple deployment pipelines if they target hundreds of accounts in an AWS Organization. + - In a large enterprise setup, the number of targets in a "prod" AWS Organization for an AWS CodePipeline + stage may be much larger than its preceding stages in the "dev" and "int" AWS Organizations. 3. Allow for empty deployment map targets - - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), ADF can be instructed to ignore any target that is not resolvable or empty (because no AWS Accounts exists in it). It is suggested to set this setting to `True`. Even though the OU structure and general setup across the different AWS Organization stages is usually identical, the number of created AWS Accounts might not be. With this setting is set to `True`, temporary empty OUs are just ignored and do not lead to an error. + - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), ADF can be instructed to ignore any target that is not resolvable or empty (because no AWS Accounts exists in it). It is suggested to set this setting to `True`. Even though the OU structure and general setup across the different AWS Organization stages is usually identical, the number of created AWS Accounts might not be. When this setting is set to `True`, temporary empty OUs are just ignored and do not lead to an error. 4. The source branch for the application code may be different per AWS Organization - - The above described custom `adfconfig` configuration allows a different default - branch to be specified in the path `config.scm.default-scm-branch` per AWS Organization. + - The above described custom `adfconfig` configuration allows a different default branch to be specified in the path `config.scm.default-scm-branch` per AWS Organization. -### 3. Make the AWS Organization Stage Context Available in CodePipeline Build jobs +### 4. Make the AWS Organization Stage Context Available in AWS CodePipeline Build jobs ADF applications often contain environment / AWS Organization stage specific configuration files. In order to allow AWS CodeBuild to select the proper configuration context for an application, the environment / AWS Organization stage context needs to be made available. -A simple pattern to solve this problem is the introduction of the SSM parameter `adf/org/stage` in the buildspec file of the application. +A simple pattern to solve this problem is the introduction of the SSM parameter `adf/org/stage` in the buildspec file of the application. This SSM parameter will be auto-created by ADF, if the The following snippet shows the header of such a `codebuild.yaml` file. -``` + +```yaml env: parameter-store: ADF_ORG_STAGE: "/adf/org/stage" [...] ``` + This environment variable can then be used to drive decision/deployment logic within any of the subsequent build commands/actions. @@ -148,7 +199,7 @@ a specific CDK application - `config-int.yaml` - `config-prod.yaml` -### 4. Customize the Base IAM Roles Per AWS Organization +### 5. Customize the Base IAM Roles Per AWS Organization ADF Supports Bootstrapping Baseline CloudFormation Stacks to all AWS Accounts when they first join an AWS Organization and centrally governing the subsequent lifecycle of those stacks. [More information on bootstrapping accounts can be found in the admin guide](admin-guide.md#bootstrapping-accounts). @@ -164,7 +215,7 @@ To customize the scope of which resources or principals are permitted within the IAM Policies of the baseline templates CFN Mapping fields can be utilized based on the `Org Stage` SSM Parameter. As shown below: -``` +```yaml Parameters: OrgStage: Type: "AWS::SSM::Parameter::Value" @@ -182,6 +233,7 @@ Mappings: prod: FinOpsAccountId: 1234567891014 # Prod Org ``` + In the above usage example you can see how the CloudFormation function FindInMap `!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId]` can be utilized to dynamically reference a custom 'AccountId' within the template, From aabc72f0e53ec6743d30c8557d7acbc00e62ad22 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:02:07 +0100 Subject: [PATCH 26/51] Update docs/multi-organization-guide.md Correct suggestion Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 7917e2446..7332212bc 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -6,7 +6,6 @@ This document describes how ADF can be run and managed in a multi AWS organizati - [Definition of a Multi-Organization ADF Setup](#definition-of-a-multi-organization-adf-setup) - [Common Use Case for a Multi-Organization ADF Setup - A Multi-Stage Landing Zone](#common-use-case-for-a-multi-organization-adf-setup---a-multi-stage-landing-zone) - [Propagating Code Changes Between ADF Installations](#propagating-code-changes-between-adf-installations) -- [Customizing ADF Config Per AWS Organization](#customizing-adfconfig.yml-per-aws-organization) - [Best Practices for Multi-Organization ADF setups](#best-practices-for-multi-organization-adf-setups) - [1. Create a dedicated adfconfig.yml Per AWS Organization](#1-create-a-dedicated-adfconfigyml-per-aws-organization) - [2. Customize the ADF Config File Per AWS Organization](#2-customize-the-adf-config-file-per-aws-organization) From c7d39f9c24600278dae4029fe2853e52c54abda9 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:02:54 +0100 Subject: [PATCH 27/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 7332212bc..a9089463e 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -9,9 +9,9 @@ This document describes how ADF can be run and managed in a multi AWS organizati - [Best Practices for Multi-Organization ADF setups](#best-practices-for-multi-organization-adf-setups) - [1. Create a dedicated adfconfig.yml Per AWS Organization](#1-create-a-dedicated-adfconfigyml-per-aws-organization) - [2. Customize the ADF Config File Per AWS Organization](#2-customize-the-adf-config-file-per-aws-organization) - - [3. Design Multi-Organization ADF Deployment Maps](#2-design-multi-organization-adf-deployment-maps) - - [4. Make the AWS Organization Stage Context Available in AWS CodePipeline Build jobs](#3-make-the-aws-organization-stage-context-available-in-aws-codepipeline-build-jobs) - - [5. Customize the Base IAM Roles Per AWS Organization](#4-customize-the-base-iam-roles-per-aws-organization) + - [3. Design Multi-Organization ADF Deployment Maps](#3-design-multi-organization-adf-deployment-maps) + - [4. Make the AWS Organization Stage Context Available in AWS CodePipeline Build jobs](#4-make-the-aws-organization-stage-context-available-in-aws-codepipeline-build-jobs) + - [5. Customize the Base IAM Roles Per AWS Organization](#5-customize-the-base-iam-roles-per-aws-organization) ## Intended Audience This guide is intended for users that run a large scale AWS Organization with complex ADF application deployments and large numbers of ADF deployment pipelines. From c50db6c92deefcc7cf8949580125c188ff911732 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:03:18 +0100 Subject: [PATCH 28/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index a9089463e..e4e0b2377 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -193,7 +193,7 @@ a specific CDK application - Appending the Stage name to AWS resource names having a requirement to be both deterministic as well as globally unique (whilst being deployed into multiple organizations). -- Selection a config file from a config folder with the following files: +- Selecting a config file from a config folder with the following files: - `config-dev.yaml` - `config-int.yaml` - `config-prod.yaml` From aa68074d1228c4cedcbea8a84c3f44bf031a9e25 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:03:30 +0100 Subject: [PATCH 29/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index e4e0b2377..c757a9b58 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -167,7 +167,6 @@ The following considerations should be observed when creating deployment maps fo stage may be much larger than its preceding stages in the "dev" and "int" AWS Organizations. 3. Allow for empty deployment map targets - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), ADF can be instructed to ignore any target that is not resolvable or empty (because no AWS Accounts exists in it). It is suggested to set this setting to `True`. Even though the OU structure and general setup across the different AWS Organization stages is usually identical, the number of created AWS Accounts might not be. When this setting is set to `True`, temporary empty OUs are just ignored and do not lead to an error. - 4. The source branch for the application code may be different per AWS Organization - The above described custom `adfconfig` configuration allows a different default branch to be specified in the path `config.scm.default-scm-branch` per AWS Organization. From 8a25e905fa28bacc8f5f02daf5b5d07ae7fb0919 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:03:42 +0100 Subject: [PATCH 30/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index c757a9b58..fb18c4cd3 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -107,7 +107,7 @@ Once a dedicated ADF config file per tenant is setup, it needs to be customized org: stage: prod # This setting will create the SSM parameter "/adf/org/stage" in the ADF deployment AWS Account. This parameter then can be referenced as an environement variable in application buildspec files to establish the AWS organization context. deployment-maps: - allow-empty: "True" # It is recommened to set this setting to "True". When this setting is set to `True`, temporary empty OUs are just ignored and do not lead to an error. + allow-empty: "True" # It is recommended to set this setting to "True". When this setting is set to "True", temporary empty OUs are just ignored and do not lead to an error. ``` The following sample ADF config file `adfconfig.o-a123456789.yml` shows a complete example for a "prod" AWS organization. From 47893ab1ed03f4507444c14c7a7a8c274cfae136 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:03:52 +0100 Subject: [PATCH 31/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index fb18c4cd3..51cc265a0 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -98,7 +98,7 @@ Each AWS Organization has its own ADF config file with environment-specific valu ![adf-multi-org-root-directory-screenshot](images/aws-multi-org-adf-config-multi-organization.png) ## 2. Customize the ADF Config File Per AWS Organization -Once a dedicated ADF config file per tenant is setup, it needs to be customized for each AWS Organizations context. It is recommended to make use of the following ADF configuration options in a multi-organization context: +Once a dedicated ADF config file per tenant is setup, it needs to be customized for each AWS Organizations context. It is recommended to make use of the following ADF configuration options in a multi-organization context: ```yaml scm: From 3b2e789ab0ae2170cd5db74838b75f2da2c9b6e8 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:04:10 +0100 Subject: [PATCH 32/51] Update src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py Co-authored-by: Simon Kok --- .../initial_commit/bootstrap_repository/adf-build/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py index 2ac9414d3..d4c718fbf 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py @@ -101,7 +101,7 @@ def _load_config_file(self): self.config_contents = yaml.load(org_config_file, Loader=yaml.FullLoader) else: LOGGER.info("Using default org config") - with open(self.config_path, encoding="utf-8") as config: + with open(self.config_path, encoding="utf-8") as config: self.config_contents = yaml.load(config, Loader=yaml.FullLoader) self._parse_config() From c593135f9452b449bef89f5497455f3338ee044a Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:04:24 +0100 Subject: [PATCH 33/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 51cc265a0..0439ae929 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -93,7 +93,7 @@ precedence over the default `adfconfig.yml` settings file for that organization. For each AWS organization used with the ADF Framework setup an additional adfconfig file can be defined. -The following screenshot shows the ADF root directory of a multi-organisation ADF setup with three stages ("dev", "int", "prod"). +The following screenshot shows the ADF root directory of a multi-organization ADF setup with three stages ("dev", "int", "prod"). Each AWS Organization has its own ADF config file with environment-specific values. ![adf-multi-org-root-directory-screenshot](images/aws-multi-org-adf-config-multi-organization.png) From 94bd04120dd306f028449dbf71ff8f5b412ab3eb Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:07:49 +0100 Subject: [PATCH 34/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 0439ae929..3dfc8c77f 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -196,6 +196,8 @@ a specific CDK application - `config-dev.yaml` - `config-int.yaml` - `config-prod.yaml` +- Copy a specific `params` folder to use for the given organization context, before `generate_params.py` is invoked: + `cp -r ./org_specific/${ADF_ORG_STAGE}/params ./params` ### 5. Customize the Base IAM Roles Per AWS Organization ADF Supports Bootstrapping Baseline CloudFormation Stacks to all AWS Accounts From 665772996ccf72ff388d423432e344d409aecf7b Mon Sep 17 00:00:00 2001 From: Andreas Falkenberg Date: Sat, 20 Jan 2024 16:19:16 +0100 Subject: [PATCH 35/51] fix: linter issues --- .../adf-bootstrap/deployment/example-global-iam.yml | 6 +++--- .../adf-bootstrap/example-global-iam.yml | 4 ++-- .../bootstrap_repository/example-adfconfig.yml | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml index bbf619bf6..218a16fa6 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml @@ -5,15 +5,15 @@ AWSTemplateFormatVersion: "2010-09-09" Description: ADF CloudFormation Template (Global) for IAM in the Deployment Account Parameters: - # OrgStage can be set in the respective adfconfig file using the + # OrgStage can be set in the respective adfconfig file using the # path config.org.stage OrgStage: Type: "AWS::SSM::Parameter::Value" Description: A stage used to differentiate Multi-Organization ADF environments Default: /adf/org/stage -# Org StageCustom Mappings allows you to dynamically build different IAM -# Conditions / Principals ARN / Resource ARN per Organization applying Least +# Org StageCustom Mappings allows you to dynamically build different IAM +# Conditions / Principals ARN / Resource ARN per Organization applying Least # Privilege Principals whilst retaining a Single Stack Definition for all # environments. # Usage: !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml index 5c530590c..9ce04c087 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml @@ -9,14 +9,14 @@ Parameters: Type: "AWS::SSM::Parameter::Value" Description: Deployment Account ID Default: deployment_account_id - # OrgStage can be set in the respective adfconfig file using the + # OrgStage can be set in the respective adfconfig file using the # path config.org.stage OrgStage: Type: "AWS::SSM::Parameter::Value" Description: A stage used to differentiate Multi-Org ADF environments Default: /adf/org/stage -# Org StageCustom Mappings allows you to dynamically build different IAM +# Org StageCustom Mappings allows you to dynamically build different IAM # Conditions / Principals ARN / Resource ARN per Organization applying # least-privilege principles whilst retaining a Single Stack Definition for all # environments. diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml index 4deb5b821..e84ff8ed4 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/example-adfconfig.yml @@ -28,14 +28,14 @@ config: default-scm-branch: master # ^ The default branch is used when the pipeline does not specify a specific branch. # If this parameter is not specified, it defaults to the "master" branch. - org: + org: stage: prod - # ^ This value will be set as an SSM Parameter named /adf/org/stage + # ^ This value will be set as an SSM Parameter named /adf/org/stage # in both the deployment account and and all # Target member accounts as part of the Bootstrap Statemachine. # It is useful as a flag to drive Organization specific logic within - # IAM Role definitions/conditions as well as Build spec behavior. - + # IAM Role definitions/conditions as well as Build spec behavior. + extensions: terraform: enabled: false # If true resources needed to run Terraform template will be deployed From e58d35edb51c16ea2dadb5a50a1b51d93fd268cd Mon Sep 17 00:00:00 2001 From: Andreas Falkenberg Date: Sat, 20 Jan 2024 16:49:05 +0100 Subject: [PATCH 36/51] fix: linter issues --- .../deployment/example-global-iam.yml | 30 +++++++++---------- .../adf-bootstrap/example-global-iam.yml | 28 ++++++++--------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml index 218a16fa6..1d331dbce 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml @@ -4,27 +4,27 @@ AWSTemplateFormatVersion: "2010-09-09" Description: ADF CloudFormation Template (Global) for IAM in the Deployment Account -Parameters: - # OrgStage can be set in the respective adfconfig file using the - # path config.org.stage - OrgStage: - Type: "AWS::SSM::Parameter::Value" - Description: A stage used to differentiate Multi-Organization ADF environments - Default: /adf/org/stage +# Parameters: +# OrgStage can be set in the respective adfconfig file using the +# path config.org.stage +# OrgStage: +# Type: "AWS::SSM::Parameter::Value" +# Description: A stage used to differentiate Multi-Organization ADF environments +# Default: /adf/org/stage # Org StageCustom Mappings allows you to dynamically build different IAM # Conditions / Principals ARN / Resource ARN per Organization applying Least # Privilege Principals whilst retaining a Single Stack Definition for all # environments. # Usage: !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] -Mappings: - OrgStageMap: - Dev: - ExampleCustomProperty: 1234 - Int: - ExampleCustomProperty: 5678 - Prod: - ExampleCustomProperty: 9102 +# Mappings: +# OrgStageMap: +# Dev: +# ExampleCustomProperty: 1234 +# Int: +# ExampleCustomProperty: 5678 +# Prod: +# ExampleCustomProperty: 9102 Resources: CloudFormationDeploymentPolicy: diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml index 9ce04c087..29f2f362e 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml @@ -9,26 +9,26 @@ Parameters: Type: "AWS::SSM::Parameter::Value" Description: Deployment Account ID Default: deployment_account_id - # OrgStage can be set in the respective adfconfig file using the - # path config.org.stage - OrgStage: - Type: "AWS::SSM::Parameter::Value" - Description: A stage used to differentiate Multi-Org ADF environments - Default: /adf/org/stage + # OrgStage can be set in the respective adfconfig file using the + # path config.org.stage + # OrgStage: + # Type: "AWS::SSM::Parameter::Value" + # Description: A stage used to differentiate Multi-Org ADF environments + # Default: /adf/org/stage # Org StageCustom Mappings allows you to dynamically build different IAM # Conditions / Principals ARN / Resource ARN per Organization applying # least-privilege principles whilst retaining a Single Stack Definition for all # environments. # usage !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] -Mappings: - OrgStageMap: - Dev: - ExampleCustomProperty: 1234 - Int: - ExampleCustomProperty: 5678 - Prod: - ExampleCustomProperty: 9102 +# Mappings: +# OrgStageMap: +# Dev: +# ExampleCustomProperty: 1234 +# Int: +# ExampleCustomProperty: 5678 +# Prod: +# ExampleCustomProperty: 9102 Resources: CloudFormationDeploymentPolicy: From 06502913273dfa885cfbc8c4a71d9a64aceacbee Mon Sep 17 00:00:00 2001 From: Andreas Falkenberg Date: Sat, 20 Jan 2024 17:37:32 +0100 Subject: [PATCH 37/51] fix: linter issues --- docs/multi-organization-guide.md | 268 +++++++++++++++++++++---------- 1 file changed, 183 insertions(+), 85 deletions(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 3dfc8c77f..81ca8b5f0 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -1,6 +1,7 @@ # Multi-Organization ADF Setup Guide -This document describes how ADF can be run and managed in a multi AWS organization setup. +This document describes how ADF can be run and managed in a multi AWS organization +setup. - [Intended Audience](#intended-audience) - [Definition of a Multi-Organization ADF Setup](#definition-of-a-multi-organization-adf-setup) @@ -10,44 +11,78 @@ This document describes how ADF can be run and managed in a multi AWS organizati - [1. Create a dedicated adfconfig.yml Per AWS Organization](#1-create-a-dedicated-adfconfigyml-per-aws-organization) - [2. Customize the ADF Config File Per AWS Organization](#2-customize-the-adf-config-file-per-aws-organization) - [3. Design Multi-Organization ADF Deployment Maps](#3-design-multi-organization-adf-deployment-maps) - - [4. Make the AWS Organization Stage Context Available in AWS CodePipeline Build jobs](#4-make-the-aws-organization-stage-context-available-in-aws-codepipeline-build-jobs) + - [4. Make AWS Organization Stage Context Available in AWS CodePipeline Build jobs](#4-make-aws-organization-stage-context-available-in-aws-codepipeline-build-jobs) - [5. Customize the Base IAM Roles Per AWS Organization](#5-customize-the-base-iam-roles-per-aws-organization) ## Intended Audience -This guide is intended for users that run a large scale AWS Organization with complex ADF application deployments and large numbers of ADF deployment pipelines. -Enterprises usually best meet the criteria for a multi AWS organization setup. We therefore refer to "Enterprises" as the target audience in the section below. -However, the approach described here should be applied to smaller organizations as well; assuming that sufficient engineering staff is available to support a multi AWS organization setup. -## Definition of a Multi-Organization ADF Setup -A multi-organization AWS-Deployment-Framework (ADF) setup describes a scenario where an -enterprise (or any user) maintains more than one AWS Organizations. -Where each AWS Organization holds its own dedicated ADF installation. +This guide is intended for users that run a large scale AWS Organization with +complex ADF application deployments and large numbers of ADF deployment pipelines. +Enterprises usually best meet the criteria for a multi AWS organization setup. +We therefore refer to "Enterprises" as the target audience in the section below. +However, the approach described here should be applied to smaller organizations +as well; assuming that sufficient engineering staff is available to support a +multi AWS organization setup. + +## Definition of a Multi-Organization ADF Setup + +A multi-organization AWS-Deployment-Framework (ADF) setup describes a scenario +where an enterprise (or any user) maintains more than one AWS Organizations. Where +each AWS Organization holds its own dedicated ADF installation. The following diagram shows such a setup in the most generic level: ![Multi Org Intro](images/aws-multi-org-1.png) ## Common Use Case for a Multi-Organization ADF Setup - A Multi-Stage Landing Zone -The most common use case for a multi-organization ADF setup is a multi-stage (and multi-organization) [landing zone](https://docs.aws.amazon.com/prescriptive-guidance/latest/migration-aws-environment/understanding-landing-zones.html). Such a setup enables stable landing zone feature development that is otherwise not possible in a single AWS Organization. - -Let's assume that "Enterprise A" has a dedicated production (referenced as "prod" hereafter) AWS Organization. This "prod" AWS Organization is used by it's end users to run all their workloads. -In a single AWS Organization setup, the "prod" AWS Organization is the only AWS Organization that exists. -Applying changes to this single organization, for example updating ADF, changing SCPs or applying enforcing controls via AWS Config, introduces the risk or disrupting your production workloads. -To mitigate this risk, it is recommended to apply the multi-organization ADF setup as described in this document. -As part of the multi-organization ADF setup, one or more AWS Organizations are added. In the instructions below, a separate development ("dev") and integration ("int") AWS Organization are added. The following diagram shows such an architecture: +The most common use case for a multi-organization ADF setup is a multi-stage +(and multi-organization) [landing zone](https://docs.aws.amazon.com/prescriptive-guidance/latest/migration-aws-environment/understanding-landing-zones.html). +Such a setup enables stable landing zone feature development that is otherwise +not possible in a single AWS Organization. + +Let's assume that "Enterprise A" has a dedicated production (referenced as "prod" +hereafter) AWS Organization. This "prod" AWS Organization is used by it's end users +to run all their workloads. In a single AWS Organization setup, the "prod" AWS +Organization is the only AWS Organization that exists. Applying changes to this +single organization, for example updating ADF, changing SCPs or applying enforcing +controls via AWS Config, introduces the risk or disrupting your production workloads. +To mitigate this risk, it is recommended to apply the multi-organization ADF setup +as described in this document. + +As part of the multi-organization ADF setup, one or more AWS Organizations are added. +In the instructions below, a separate development ("dev") and integration ("int") +AWS Organization are added. The following diagram shows such an architecture: ![Multi Org Intro](images/aws-multi-org-2.png) -The development flow is as follows: -1. Development work for any landing zone feature always starts in the "dev" AWS Organization. The ADF repository `aws-deployment-framework-bootstrap` and `aws-deployment-framework-pipelines` are also considered a landing zone feature. The "dev" AWS Organization is exclusively reserved for the landing zone development team. End-users do not have access to the "dev" AWS Organization. -2. Once the code under development is stable and underwent successful unit and basic integration tests, it is moved from the "dev" AWS Organization to the "int" AWS Organization. The process of propagating code from one AWS Organization to another is described in the [Propagating Code Changes Between ADF Installations section](#Propagating-Code-Changes-Between-ADF-Installations). -3. The "int" AWS Organization is used for final integration testing and verification. The "int" AWS Organization is exclusively reserved for the landing zone development team. End-users do not have access to the "int" AWS Organization. -4. Once all tests passed successfully, the code is moved from the "int" AWS Organization to the "prod" AWS Organization. -5. Assuming that the propagation and the deployment in the "prod" AWS Organization was successful, the code is now fully deployed in the "prod" AWS Organization and is available to the end-users. - -The benefits of such a setup is that an Enterprise can apply the same common `Software Development Lifecycle` to typical "one-off" landing zone services that are hard to test in a single-organization setup. It provides the enterprise's 'Cloud Center of Excellence' (landing zone team) a -controlled process to develop, test, and validate changes to wide reaching mission-critical +The development flow is as follows: + +1. Development work for any landing zone feature always starts in the "dev" +AWS Organization. The ADF repository `aws-deployment-framework-bootstrap` and +`aws-deployment-framework-pipelines` are also considered a landing zone feature. +The "dev" AWS Organization is exclusively reserved for the landing zone +development team. End-users do not have access to the "dev" AWS Organization. +2. Once the code under development is stable and underwent successful unit and +basic integration tests, it is moved from the "dev" AWS Organization to the +"int" AWS Organization. The process of propagating code from one AWS Organization +to another is described in the +[Propagating Code Changes Between ADF Installations section](#propagating-code-changes-between-adf-installations). +3. The "int" AWS Organization is used for final integration testing and +verification. The "int" AWS Organization is exclusively reserved for the landing + zone development team. End-users do not have access to the "int" AWS Organization. +4. Once all tests passed successfully, the code is moved from the "int" AWS +Organization to the "prod" AWS Organization. +5. Assuming that the propagation and the deployment in the "prod" +AWS Organization was successful, the code is now fully deployed in the +"prod" AWS Organization and is available to the end-users. + +The benefits of such a setup is that an Enterprise can apply the same common +`Software Development Lifecycle` to typical "one-off" landing zone services that +are hard to test in a single-organization setup. It provides the enterprise's +'Cloud Center of Excellence' (landing zone team) a controlled process to +develop, test, and validate changes to wide reaching mission-critical services, including but not limited to: + - Service Control Policies changes. - Identity Center and IAM based Access Management Configuration changes. - AWS Deployment Framework changes. @@ -57,60 +92,88 @@ services, including but not limited to: - Centralized cost management configuration changes. - Centralized networking changes. -The following sections are written in the context of the above described use case; a multi-stage landing zone. +The following sections are written in the context of the above described use +case; a multi-stage landing zone. + +## Propagating Code Changes Between ADF Installations + +With multiple ADF configurations across multiple AWS Organizations there comes a +new challenge to maintain repositories and its configurations across multiple environments. +This applies to the following repositories: -## Propagating Code Changes Between ADF Installations -With multiple ADF configurations across multiple AWS Organizations there comes a new challenge to maintain repositories and its configurations across multiple environments. -This applies to the following repositories: - aws-deployment-framework-bootstrap - aws-deployment-framework-pipelines - any other landing zone repository -As the requirements of the bootstrapped resources and ADF configuration evolves they need to be updated over time. These changes must propagate from one environment to the next in a coordinated, controlled fashion. - -With an `Environment Branching` approach it is possible to build a 'hands-off' -automated mechanism to promote from a "dev" AWS Organization environment to a "prod" AWS Organization environment. -This means that, for example merging code from the "dev" branch of a repository to the "int" branch of a repository, it will trigger the deployment process in the "int" AWS Organization. +As the requirements of the bootstrapped resources and ADF configuration evolves +they need to be updated over time. These changes must propagate from one environment +to the next in a coordinated, controlled fashion. -Implementing such an approach is out of scope for this guide as it heavily depends on the specific source code and CI/CD tool in use. +With an `Environment Branching` approach it is possible to build a 'hands-off' +automated mechanism to promote from a "dev" AWS Organization environment to a +"prod" AWS Organization environment. This means that, for example merging code +from the "dev" branch of a repository to the "int" branch of a repository, it +will trigger the deployment process in the "int" AWS Organization. +Implementing such an approach is out of scope for this guide as it heavily +depends on the specific source code and CI/CD tool in use. ## Best Practices for Multi-Organization ADF setups -If you want to run ADF in a multi-organization setup, there are various best practices that should be followed. -When following these recommendations, the content of the repository `aws-deployment-framework-bootstrap` and `aws-deployment-framework-pipelines` should be stage agnostic. -This means that you can copy and paste the content of any of those two repositories into any AWS Organization stage ("dev", "int", "prod") and ADF will behave exactly the same. + +If you want to run ADF in a multi-organization setup, there are various best +practices that should be followed. When following these recommendations, the +content of the repository `aws-deployment-framework-bootstrap` and +`aws-deployment-framework-pipelines` should be stage agnostic. This means that +you can copy and paste the content of any of those two repositories into any +AWS Organization stage ("dev", "int", "prod") and ADF will behave exactly the same. ### 1. Create a dedicated adfconfig.yml Per AWS Organization + One challenge with synchronizing the `aws-deployment-framework-bootstrap` repository across AWS Organizations is that the contents of the `adfconfig.yml` configuration -file is typically tailored to the ADF installation. The can be solved by adding a +file is typically tailored to the ADF installation. The can be solved by adding a custom adfconfig file for the given organization. -Adding a configuration file with the name pattern `adfconfig.{organization id}.yml` -in the root of the `aws-deployment-framework-bootstrap` repository will take +Adding a configuration file with the name pattern `adfconfig.{organization id}.yml`` +in the root of the`aws-deployment-framework-bootstrap` repository will take precedence over the default `adfconfig.yml` settings file for that organization. For each AWS organization used with the ADF Framework setup an additional adfconfig -file can be defined. +file can be defined. -The following screenshot shows the ADF root directory of a multi-organization ADF setup with three stages ("dev", "int", "prod"). -Each AWS Organization has its own ADF config file with environment-specific values. +The following screenshot shows the ADF root directory of a multi-organization ADF +setup with three stages ("dev", "int", "prod"). Each AWS Organization has its own +ADF config file with environment-specific values. d ![adf-multi-org-root-directory-screenshot](images/aws-multi-org-adf-config-multi-organization.png) ## 2. Customize the ADF Config File Per AWS Organization -Once a dedicated ADF config file per tenant is setup, it needs to be customized for each AWS Organizations context. It is recommended to make use of the following ADF configuration options in a multi-organization context: + +Once a dedicated ADF config file per tenant is setup, it needs to be customized +for each AWS Organizations context. It is recommended to make use of the following + ADF configuration options in a multi-organization context: ```yaml scm: - default-scm-branch: prod # This setting ensures, that the "prod" branch is selected as the source branch for any ADF deployment pipeline. - default-scm-codecommit-account-id: "123456789012" # This setting ensure that the AWS Account 123456789012 is selected as the default AWS account to + # This setting ensures, that the "prod" branch is selected as the source + # branch for any ADF deployment pipeline. + default-scm-branch: prod + # This setting ensure that the AWS Account 123456789012 is selected as the + # default AWS account to. + default-scm-codecommit-account-id: "123456789012" org: - stage: prod # This setting will create the SSM parameter "/adf/org/stage" in the ADF deployment AWS Account. This parameter then can be referenced as an environement variable in application buildspec files to establish the AWS organization context. + # This setting will create the SSM parameter "/adf/org/stage" in the ADF + # deployment AWS Account. This parameter then can be referenced as an + # environment variable in application buildspec files to establish the + # AWS organization context. + stage: prod deployment-maps: - allow-empty: "True" # It is recommended to set this setting to "True". When this setting is set to "True", temporary empty OUs are just ignored and do not lead to an error. + # It is recommended to set this setting to "True". When this setting is set + # to "True", temporary empty OUs are just ignored and do not lead to an error. + allow-empty: "True" ``` -The following sample ADF config file `adfconfig.o-a123456789.yml` shows a complete example for a "prod" AWS organization. +The following sample ADF config file `adfconfig.o-a123456789.yml` shows a +complete example for a "prod" AWS organization. ```yaml # The following configuration is only loaded for int Organization: o-a123456789 @@ -127,7 +190,8 @@ config: main-notification-endpoint: - type: email target: john.doe@example.com - # ^ Email/Slack channel who receives notifications for the main bootstrapping pipeline + # ^ Email/Slack channel who receives notifications for the main + # bootstrapping pipeline protected: - ou-1234-abcdefgh # OU Lockdown moves: @@ -147,34 +211,63 @@ config: ``` ### 3. Design Multi-Organization ADF Deployment Maps + The Deployment Maps for ADF exist in the AWS CodeCommit repository -`aws-deployment-framwork-pipelines` within the deployment -account. Some additional multi-organization challenges exist when defining targets for deployments. As a high-level goal, a deployment map should be setup in such a way, that it can be copied over from one ADF instance to another without breaking / requiring any change. +`aws-deployment-framework-pipelines` within the deployment +account. Some additional multi-organization challenges exist when defining +targets for deployments. As a high-level goal, a deployment map should be setup +in such a way, that it can be copied over from one ADF instance to another without +breaking / requiring any change. + +The following considerations should be observed when creating deployment maps for +a multi-organization ADF setup: -The following considerations should be observed when creating deployment maps for a multi-organization ADF setup: 1. Create Organization-agnostic deployment maps - - As a best-practice, deployment maps should be free of any hard-coded AWS Account IDs for deployment map targets, unless the deployment is destined for a single AWS Organization only. + - As a best-practice, deployment maps should be free of any hard-coded AWS + Account IDs for deployment map targets, unless the deployment is destined + for a single AWS Organization only. - Instead, target AWS Accounts via `Account Names`, `Account Tags` or `OU Paths`. - This will allow ADF to dynamically generate the respective AWS Account IDs for the target list when updating the pipelines. + This will allow ADF to dynamically generate the respective AWS Account IDs + for the target list when updating the pipelines. 2. Consider AWS service limits for AWS CodePipeline - - Review the AWS CodePipeline action limitations. The current limits are ([AWS CodePipeline Limits](https://docs.aws.amazon.com/codepipeline/latest/userguide/limits.html)) + - Review the AWS CodePipeline action limitations. The current limits are d + ([AWS CodePipeline Limits](https://docs.aws.amazon.com/codepipeline/latest/userguide/limits.html)) - 1000 AWS CodePipeline per AWS Account per region - 500 Actions per AWS CodePipeline - 50 Actions per AWS CodePipeline Stage - - Those limits imply that a single ADF pipeline can target 500 AWS Accounts max. This may require you to manually balance the targets across multiple deployment pipelines. - - ADF distributes targets across AWS CodePipeline stages within a deployment pipeline, spreading the accounts across multiple stages to workaround the AWS CodePipeline actions-per-stage limitation. Deployments may need to be manually distributed across multiple deployment pipelines if they target hundreds of accounts in an AWS Organization. - - In a large enterprise setup, the number of targets in a "prod" AWS Organization for an AWS CodePipeline - stage may be much larger than its preceding stages in the "dev" and "int" AWS Organizations. + - Those limits imply that a single ADF pipeline can target 500 AWS Accounts + max. This may require you to manually balance the targets across multiple + deployment pipelines. + - ADF distributes targets across AWS CodePipeline stages within a deployment + pipeline, spreading the accounts across multiple stages to workaround the + AWS CodePipeline actions-per-stage limitation. Deployments may need to be + manually distributed across multiple deployment pipelines if they target + hundreds of accounts in an AWS Organization. + - In a large enterprise setup, the number of targets in a "prod" + AWS Organization for an AWS CodePipeline stage may be much larger than its + preceding stages in the "dev" and "int" AWS Organizations. 3. Allow for empty deployment map targets - - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), ADF can be instructed to ignore any target that is not resolvable or empty (because no AWS Accounts exists in it). It is suggested to set this setting to `True`. Even though the OU structure and general setup across the different AWS Organization stages is usually identical, the number of created AWS Accounts might not be. When this setting is set to `True`, temporary empty OUs are just ignored and do not lead to an error. - 4. The source branch for the application code may be different per AWS Organization - - The above described custom `adfconfig` configuration allows a different default branch to be specified in the path `config.scm.default-scm-branch` per AWS Organization. - -### 4. Make the AWS Organization Stage Context Available in AWS CodePipeline Build jobs -ADF applications often contain environment / AWS Organization stage specific configuration files. -In order to allow AWS CodeBuild to select the proper configuration context for an application, the environment / AWS Organization stage context needs to be made available. -A simple pattern to solve this problem is the introduction of the SSM parameter `adf/org/stage` in the buildspec file of the application. This SSM parameter will be auto-created by ADF, if the -The following snippet shows the header of such a `codebuild.yaml` file. + - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), + ADF can be instructed to ignore any target that is not resolvable or empty + (because no AWS Accounts exists in it). It is suggested to set this setting + to `True`. Even though the OU structure and general setup across the different + AWS Organization stages is usually identical, the number of created + AWS Accounts might not be. When this setting is set to `True`, temporary + empty OUs are just ignored and do not lead to an error. +4. The source branch for the application code may be different per AWS Organization + - The above described custom `adfconfig` configuration allows a different + default branch to be specified in the path `config.scm.default-scm-branch` + per AWS Organization. + +### 4. Make AWS Organization Stage Context Available in AWS CodePipeline Build jobs + +ADF applications often contain environment / AWS Organization stage specific +configuration files. In order to allow AWS CodeBuild to select the proper +configuration context for an application, the environment / AWS Organization stage +context needs to be made available. A simple pattern to solve this problem is the +introduction of the SSM parameter `adf/org/stage` in the buildspec file of the +application. This SSM parameter will be auto-created by ADF. The following snippet +shows the header of such a `codebuild.yaml` file. ```yaml env: @@ -187,32 +280,37 @@ This environment variable can then be used to drive decision/deployment logic within any of the subsequent build commands/actions. Some scenarios which could require organization specific context include: + - Deriving the default log level based on the organization stage for -a specific CDK application -- Appending the Stage name to AWS resource names having a requirement to be - both deterministic as well as globally unique +a specific CDK application +- Appending the Stage name to AWS resource names having a requirement to be + both deterministic as well as globally unique (whilst being deployed into multiple organizations). - Selecting a config file from a config folder with the following files: - - `config-dev.yaml` - - `config-int.yaml` - - `config-prod.yaml` -- Copy a specific `params` folder to use for the given organization context, before `generate_params.py` is invoked: + - `config-dev.yaml` + - `config-int.yaml` + - `config-prod.yaml` +- Copy a specific `params` folder to use for the given organization context, + before `generate_params.py` is invoked: `cp -r ./org_specific/${ADF_ORG_STAGE}/params ./params` ### 5. Customize the Base IAM Roles Per AWS Organization + ADF Supports Bootstrapping Baseline CloudFormation Stacks to all AWS Accounts -when they first join an AWS Organization and centrally governing the subsequent -lifecycle of those stacks. [More information on bootstrapping accounts can be found in the admin guide](admin-guide.md#bootstrapping-accounts). +when they first join an AWS Organization and centrally governing the subsequent +lifecycle of those stacks. [More information on bootstrapping accounts can be +found in the admin guide](admin-guide.md#bootstrapping-accounts). -These Baseline Templates are typically used for setting up the default IAM roles and -Policies necessary for the foundations of an ADF Based Enterprise Landing Zone. +These Baseline Templates are typically used for setting up the default IAM +roles and Policies necessary for the foundations of an ADF Based Enterprise +Landing Zone. In guidance with AWS Security Guidelines and `Least Privilege Access Principles`, it is recommended to reduce the scope of any IAM Policy to the minimum required -Actions, Principals and Resource Scope necessary. +Actions, Principals and Resource Scope necessary. To customize the scope of which resources or principals are permitted within the -IAM Policies of the baseline templates CFN Mapping fields can be utilized based +IAM Policies of the baseline templates CFN Mapping fields can be utilized based on the `Org Stage` SSM Parameter. As shown below: ```yaml @@ -227,7 +325,7 @@ Mappings: # Usage:!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId] OrgStageBasedPropertyMap: dev: - FinOpsAccountId: 1234567891012 # Dev Org + FinOpsAccountId: 1234567891012 # Dev Org int: FinOpsAccountId: 1234567891013 # Int Org prod: @@ -237,4 +335,4 @@ Mappings: In the above usage example you can see how the CloudFormation function FindInMap `!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId]` can be utilized to dynamically reference a custom 'AccountId' within the template, -enabling the construction of account specific granular Resource and Principal ARNs. \ No newline at end of file +enabling the construction of account specific granular Resource and Principal ARNs. From 41b75bf996fdf3d72b0a633c9cabf1a00384a071 Mon Sep 17 00:00:00 2001 From: Andreas Falkenberg Date: Sat, 20 Jan 2024 17:47:24 +0100 Subject: [PATCH 38/51] fix: linter issues --- README.md | 2 +- docs/multi-organization-guide.md | 36 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index f65d79088..33e57beb9 100644 --- a/README.md +++ b/README.md @@ -39,4 +39,4 @@ template as its baseline. - Refer to the [Samples Guide](docs/samples-guide.md) for a detailed walk through of the provided samples. - Refer to the [Multi-Organization ADF Setup](docs/multi-organization-guide.md) - to use ADF in an enterprise-grade setup. \ No newline at end of file + to use ADF in an enterprise-grade setup. diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 81ca8b5f0..3ccf55838 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -69,7 +69,7 @@ to another is described in the [Propagating Code Changes Between ADF Installations section](#propagating-code-changes-between-adf-installations). 3. The "int" AWS Organization is used for final integration testing and verification. The "int" AWS Organization is exclusively reserved for the landing - zone development team. End-users do not have access to the "int" AWS Organization. +zone development team. End-users do not have access to the "int" AWS Organization. 4. Once all tests passed successfully, the code is moved from the "int" AWS Organization to the "prod" AWS Organization. 5. Assuming that the propagation and the deployment in the "prod" @@ -150,7 +150,7 @@ ADF config file with environment-specific values. d Once a dedicated ADF config file per tenant is setup, it needs to be customized for each AWS Organizations context. It is recommended to make use of the following - ADF configuration options in a multi-organization context: +ADF configuration options in a multi-organization context: ```yaml scm: @@ -227,8 +227,8 @@ a multi-organization ADF setup: Account IDs for deployment map targets, unless the deployment is destined for a single AWS Organization only. - Instead, target AWS Accounts via `Account Names`, `Account Tags` or `OU Paths`. - This will allow ADF to dynamically generate the respective AWS Account IDs - for the target list when updating the pipelines. + This will allow ADF to dynamically generate the respective AWS Account IDs + for the target list when updating the pipelines. 2. Consider AWS service limits for AWS CodePipeline - Review the AWS CodePipeline action limitations. The current limits are d ([AWS CodePipeline Limits](https://docs.aws.amazon.com/codepipeline/latest/userguide/limits.html)) @@ -239,25 +239,25 @@ a multi-organization ADF setup: max. This may require you to manually balance the targets across multiple deployment pipelines. - ADF distributes targets across AWS CodePipeline stages within a deployment - pipeline, spreading the accounts across multiple stages to workaround the - AWS CodePipeline actions-per-stage limitation. Deployments may need to be - manually distributed across multiple deployment pipelines if they target - hundreds of accounts in an AWS Organization. + pipeline, spreading the accounts across multiple stages to workaround the + AWS CodePipeline actions-per-stage limitation. Deployments may need to be + manually distributed across multiple deployment pipelines if they target + hundreds of accounts in an AWS Organization. - In a large enterprise setup, the number of targets in a "prod" - AWS Organization for an AWS CodePipeline stage may be much larger than its - preceding stages in the "dev" and "int" AWS Organizations. + AWS Organization for an AWS CodePipeline stage may be much larger than its + preceding stages in the "dev" and "int" AWS Organizations. 3. Allow for empty deployment map targets - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), - ADF can be instructed to ignore any target that is not resolvable or empty - (because no AWS Accounts exists in it). It is suggested to set this setting - to `True`. Even though the OU structure and general setup across the different - AWS Organization stages is usually identical, the number of created - AWS Accounts might not be. When this setting is set to `True`, temporary - empty OUs are just ignored and do not lead to an error. + ADF can be instructed to ignore any target that is not resolvable or empty + (because no AWS Accounts exists in it). It is suggested to set this setting + to `True`. Even though the OU structure and general setup across the different + AWS Organization stages is usually identical, the number of created + AWS Accounts might not be. When this setting is set to `True`, temporary + empty OUs are just ignored and do not lead to an error. 4. The source branch for the application code may be different per AWS Organization - The above described custom `adfconfig` configuration allows a different - default branch to be specified in the path `config.scm.default-scm-branch` - per AWS Organization. + default branch to be specified in the path `config.scm.default-scm-branch` + per AWS Organization. ### 4. Make AWS Organization Stage Context Available in AWS CodePipeline Build jobs From 3986e16c1a827a6b6d65f4d47debab105798a36a Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:31:31 +0100 Subject: [PATCH 39/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 3ccf55838..b43d27e8d 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -325,11 +325,11 @@ Mappings: # Usage:!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId] OrgStageBasedPropertyMap: dev: - FinOpsAccountId: 1234567891012 # Dev Org + FinOpsAccountId: 111111111111 # Dev Org int: - FinOpsAccountId: 1234567891013 # Int Org + FinOpsAccountId: 222222222222 # Int Org prod: - FinOpsAccountId: 1234567891014 # Prod Org + FinOpsAccountId: 333333333333 # Prod Org ``` In the above usage example you can see how the CloudFormation function FindInMap From 6f165179c9152598296942717a7c479d65b76084 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:32:03 +0100 Subject: [PATCH 40/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index b43d27e8d..3239fe61f 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -273,7 +273,7 @@ shows the header of such a `codebuild.yaml` file. env: parameter-store: ADF_ORG_STAGE: "/adf/org/stage" -[...] +# [...] ``` This environment variable can then be used to drive decision/deployment logic From d7c640c8b3903d65b564455cb69a958fad2e3eac Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:32:54 +0100 Subject: [PATCH 41/51] Update src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml Co-authored-by: Simon Kok --- .../adf-bootstrap/example-global-iam.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml index 29f2f362e..305ac7883 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml @@ -9,12 +9,13 @@ Parameters: Type: "AWS::SSM::Parameter::Value" Description: Deployment Account ID Default: deployment_account_id - # OrgStage can be set in the respective adfconfig file using the - # path config.org.stage - # OrgStage: - # Type: "AWS::SSM::Parameter::Value" - # Description: A stage used to differentiate Multi-Org ADF environments - # Default: /adf/org/stage + +# OrgStage can be set in the respective adfconfig file using the +# path config.org.stage +# OrgStage: +# Type: "AWS::SSM::Parameter::Value" +# Description: A stage used to differentiate Multi-Org ADF environments +# Default: /adf/org/stage # Org StageCustom Mappings allows you to dynamically build different IAM # Conditions / Principals ARN / Resource ARN per Organization applying From 13bd9b0037e387ed0b23dacca1e8f8ef22a24dc3 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:33:17 +0100 Subject: [PATCH 42/51] Update src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py Co-authored-by: Simon Kok --- .../initial_commit/bootstrap_repository/adf-build/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py index d4c718fbf..24a10a152 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py @@ -97,7 +97,7 @@ def _load_config_file(self): org_config_path = self.config_path.replace(".yml", f".{self.organization_id}.yml") if os.path.exists(org_config_path): with open(org_config_path, encoding="utf-8") as org_config_file: - LOGGER.info("Using custom org config") + LOGGER.info("Using organization specific ADF config: %s", org_config_path) self.config_contents = yaml.load(org_config_file, Loader=yaml.FullLoader) else: LOGGER.info("Using default org config") From 10161acf02d1d9fc10a821723027892b097254e3 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:33:39 +0100 Subject: [PATCH 43/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 3239fe61f..4e6d5e529 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -265,7 +265,7 @@ ADF applications often contain environment / AWS Organization stage specific configuration files. In order to allow AWS CodeBuild to select the proper configuration context for an application, the environment / AWS Organization stage context needs to be made available. A simple pattern to solve this problem is the -introduction of the SSM parameter `adf/org/stage` in the buildspec file of the +introduction of the SSM parameter `/adf/org/stage` in the buildspec file of the application. This SSM parameter will be auto-created by ADF. The following snippet shows the header of such a `codebuild.yaml` file. From 4011722c70ea404c3ead791d94e05cd6c4cdefdb Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:34:07 +0100 Subject: [PATCH 44/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 4e6d5e529..e60dda7ad 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -322,7 +322,7 @@ Parameters: # At the time this Stack is deployed, the FinOps Account ID SSM Parameter doesn't # exist, so we derive it from mapping it to the org stage Mappings: - # Usage:!FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId] + # Usage: !FindInMap [OrgStageBasedPropertyMap, !Ref OrgStage, FinOpsAccountId] OrgStageBasedPropertyMap: dev: FinOpsAccountId: 111111111111 # Dev Org From 97493fc86fc748bb9ef5ee2314ef3188e43c7a8a Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:34:30 +0100 Subject: [PATCH 45/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index e60dda7ad..3fd65a6ba 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -246,7 +246,7 @@ a multi-organization ADF setup: - In a large enterprise setup, the number of targets in a "prod" AWS Organization for an AWS CodePipeline stage may be much larger than its preceding stages in the "dev" and "int" AWS Organizations. -3. Allow for empty deployment map targets +3. Allow empty deployment map targets - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), ADF can be instructed to ignore any target that is not resolvable or empty (because no AWS Accounts exists in it). It is suggested to set this setting From 53e8b5d72ae5ee9de1ab001431e2850c6cbf678f Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:35:29 +0100 Subject: [PATCH 46/51] Update src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml Co-authored-by: Simon Kok --- .../bootstrap_repository/adf-bootstrap/example-global-iam.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml index 305ac7883..2106048d6 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml @@ -17,7 +17,7 @@ Parameters: # Description: A stage used to differentiate Multi-Org ADF environments # Default: /adf/org/stage -# Org StageCustom Mappings allows you to dynamically build different IAM +# Org Stage Custom Mappings allows you to dynamically build different IAM # Conditions / Principals ARN / Resource ARN per Organization applying # least-privilege principles whilst retaining a Single Stack Definition for all # environments. From f1a5029af14397df8167d536345b729df8ae590f Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:36:47 +0100 Subject: [PATCH 47/51] Apply suggestions from code review Co-authored-by: Simon Kok --- .../adf-bootstrap/deployment/example-global-iam.yml | 3 ++- .../bootstrap_repository/adf-bootstrap/example-global-iam.yml | 3 ++- .../initial_commit/bootstrap_repository/adf-build/config.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml index 1d331dbce..ae5b38415 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/example-global-iam.yml @@ -16,7 +16,8 @@ Description: ADF CloudFormation Template (Global) for IAM in the Deployment Acco # Conditions / Principals ARN / Resource ARN per Organization applying Least # Privilege Principals whilst retaining a Single Stack Definition for all # environments. -# Usage: !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] +# Example usage: +# !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] # Mappings: # OrgStageMap: # Dev: diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml index 2106048d6..338342109 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-global-iam.yml @@ -21,7 +21,8 @@ Parameters: # Conditions / Principals ARN / Resource ARN per Organization applying # least-privilege principles whilst retaining a Single Stack Definition for all # environments. -# usage !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] +# Example usage: +# !FindInMap[OrgStageMap: !Ref OrgStage, ExampleCustomProperty] # Mappings: # OrgStageMap: # Dev: diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py index 24a10a152..f5c028575 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py @@ -100,7 +100,7 @@ def _load_config_file(self): LOGGER.info("Using organization specific ADF config: %s", org_config_path) self.config_contents = yaml.load(org_config_file, Loader=yaml.FullLoader) else: - LOGGER.info("Using default org config") + LOGGER.info("Using default ADF config: %s", self.config_path) with open(self.config_path, encoding="utf-8") as config: self.config_contents = yaml.load(config, Loader=yaml.FullLoader) self._parse_config() From 90172b2ae8b5400833dd5f031971a3a5283c0224 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:39:29 +0100 Subject: [PATCH 48/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 3fd65a6ba..d4daaa5b3 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -138,7 +138,7 @@ Adding a configuration file with the name pattern `adfconfig.{organization id}.y in the root of the`aws-deployment-framework-bootstrap` repository will take precedence over the default `adfconfig.yml` settings file for that organization. -For each AWS organization used with the ADF Framework setup an additional adfconfig +For each AWS organization used in the ADF setup an additional adfconfig file can be defined. The following screenshot shows the ADF root directory of a multi-organization ADF From 71fcfe4742d3ad488edb58ffa477a45f43dfa462 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:39:57 +0100 Subject: [PATCH 49/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index d4daaa5b3..665f2e35b 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -143,7 +143,7 @@ file can be defined. The following screenshot shows the ADF root directory of a multi-organization ADF setup with three stages ("dev", "int", "prod"). Each AWS Organization has its own -ADF config file with environment-specific values. d +ADF config file with environment-specific values. ![adf-multi-org-root-directory-screenshot](images/aws-multi-org-adf-config-multi-organization.png) ## 2. Customize the ADF Config File Per AWS Organization From 09331190d3b7aedeb036c2e8679dad80dcad3820 Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:40:10 +0100 Subject: [PATCH 50/51] Update docs/multi-organization-guide.md Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 665f2e35b..a24416ab4 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -148,7 +148,7 @@ ADF config file with environment-specific values. ## 2. Customize the ADF Config File Per AWS Organization -Once a dedicated ADF config file per tenant is setup, it needs to be customized +Once a dedicated ADF config file per environment is setup, it needs to be customized for each AWS Organizations context. It is recommended to make use of the following ADF configuration options in a multi-organization context: From 2911436c579a186de0ebc7022b48bf09ab1ebcce Mon Sep 17 00:00:00 2001 From: AndyEfaa <73257849+AndyEfaa@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:43:12 +0100 Subject: [PATCH 51/51] Apply suggestions from code review Co-authored-by: Simon Kok --- docs/multi-organization-guide.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index a24416ab4..70a8e6880 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -176,7 +176,7 @@ The following sample ADF config file `adfconfig.o-a123456789.yml` shows a complete example for a "prod" AWS organization. ```yaml -# The following configuration is only loaded for int Organization: o-a123456789 +# The following configuration is only loaded for prod Organization: o-a123456789 roles: cross-account-access: AWSControlTowerExecution # ^ The role by ADF to assume cross account access @@ -230,8 +230,9 @@ a multi-organization ADF setup: This will allow ADF to dynamically generate the respective AWS Account IDs for the target list when updating the pipelines. 2. Consider AWS service limits for AWS CodePipeline - - Review the AWS CodePipeline action limitations. The current limits are d - ([AWS CodePipeline Limits](https://docs.aws.amazon.com/codepipeline/latest/userguide/limits.html)) + - Review the AWS CodePipeline action limitations. [AWS CodePipeline + Limits](https://docs.aws.amazon.com/codepipeline/latest/userguide/limits.html)) + are: - 1000 AWS CodePipeline per AWS Account per region - 500 Actions per AWS CodePipeline - 50 Actions per AWS CodePipeline Stage