Skip to main content

Landing Zones

AWS Landing Zones control how meshStack configures managed AWS accounts. In the following section the options for this Landing Zone are described.

To bootstrap newly created AWS accounts you can use an existing, "external" (in the sense of not controlled via meshStack) Account Vending Machine (AVM), triggered via a Lambda function.

Parameters

Each Landing Zone has parameters which control its behavior. The available parameters are described below.

Target Organization Unit ID

This parameter is optional. If it is set all meshProjects placed under this Landing Zone will be put under this Organization Unit (OU). This might be helpful if a SCP (Service Control Policy) should be assigned to all of these projects. If left empty a new OU will be created for every workspace and all of his meshProjects with AWS platform will be placed in it.

You must provide the ID of the OU which can be found in the AWS Organizational Management panel. The IDs start with ou-*.

You can also use a root account under which the accounts will be placed when they are created. Root IDs start with r-*.

Hierarchical Organizational Unit Assignment

The behavior of the Target Organization Unit ID depends on the "Allow Hierarchical Organizational Unit Assignment" setting configured in the AWS platform configuration:

  • When hierarchical assignment is disabled (default): Accounts will always be moved directly to the organizational unit defined in this landing zone parameter.
  • When hierarchical assignment is enabled: Accounts already residing in child organizational units below the specified OU will remain in their current organizational unit. This allows for more granular organization of accounts within complex AWS Organizations hierarchies while maintaining governance through the parent OU defined in the landing zone.

This setting provides platform teams with greater flexibility for organizing resources in complex organizational structures while maintaining proper governance.

Account Enrollment

This parameter defines whether created AWS accounts of this Landing Zone are enrolled with AWS Control Tower or not. In order to successfully enroll accounts, an already enrolled Target Organization Unit ID has to be defined. The enrollment also requires a global enrollment configuration set for the AWS platform, as specified in AWS Control Tower Integration

meshRole to Platform Role Mapping

The meshProject roles must be mapped to AWS specific roles. Your are able to control this mapping with a Landing Zone setting. You can specifiy these mappings by adding role mappings and supplying a AWS Role Name here. The replicator will try to create this roles if necessairy so please make sure it has the correct right to do so, otherwise replication will fail. If you dont want to provide the meshStack with these rights you can also make sure that these roles already exist in AWS and the meshStack will only assign the users to these roles.

You can also add multiple policies to such a role (by providing either a policy name or an ARN). During the meshProject replication meshStack will make sure that these policies are assigned to the AWS role (please make sure the replicator principal is allowed to do so, otherwise replication will fail as well). If no policy is assigned it is assumed that the roles will be pre-configured with the correct roles via for example some kind of account vending machine.

Lambda ARN

As some users might have already their own custom AWS account provisioning solution, usually called Account Vending Machines (AVM), other mechanisms are needed in order to bootstrap newly created AWS accounts.

Such an AVM is triggered by a custom Lambda function invocation. During the AWS account replication meshStack is able to invoke such a function with custom parameters. From this function the external AVM can start its provisioning process.

Please make sure the MeshfedServiceRole has the rights in order to trigger the configured Lambda.

The Lambda is called synchronously, so please make sure your Lambdas execution time is kept low. If you have to do long running tasks its a good advice to call another lambda in an async fashion from the initial Lambda call, so you can return to the replication code without hitting HTTP timeouts.

If the function could not be invoked because of a server error for example a permission error prevents the function of being called, this is regarded as a replication error and will fail the project replication. If the function itself signals an error, the error code returned by the function is currently not used but only logged for reference. This is done in order to allow the replication of the meshProject to be continued.

The following parameters can be used in the Lambda function and are provided as a JSON payload like the following pattern:

{
"AccountName": "max-muster",
"AccountEmail": "max@muster.de",
// ...
}
ParameterDescription
AccountNameName of the created AWS account
AccountEmailEmail associated with the created AWS account
AccountIdUnique Id of the created AWS account
AccountArnARN of the created AWS account
ProductNamemeshWorkspace Identifier
CostCenterID of the CostCenter defined for this meshProject.(Deprecated, please use tagCostCenter)
ContactEmailE-Mail of the meshProject creator. Currently this is the user who created the project.
StageThe meshProject identifier

In addition, any payment settings, project tags or workspace tags can also be used as Lambda function parameters. These parameter keys will have the prefix tag. For example, the value of the tag costCenter will be made available via the key tagCostCenter.

Account Vending Machines

In order to detect the finished execution of the AVM meshStack looks for certain tags on the AWS account. If such a tag is present the success of the external replication is assumed and the replication process is handed back to meshStack.

Currently the account must contain these tags to be picked up:

  • ProductName: Must contain the meshWorkspace identifier
  • Stage: Must contain the meshProject identifier

These tags will soon be customizable in the AWS Landing Zone configuration.

Please contact meshcloud for more details and reference configurations.

Example meshLandingZone

This section serves as an example on how you can use a meshLandingZone to bootstrap the newly created AWS account.

The example Lambda below assumes a CrossAccountLambdaExecutionRole in the newly created account to perform its tasks there. This role must trust the Automation Account's AutomationAccountLambdaServiceRole and has to be provisioned into new accounts by your own account bootstrapping, for example via AWS Control Tower customizations or your AVM.

Create the Lambda

Create the AutomationAccountLambdaServiceRole with the following policy and trust relationship in the automation account. Additionally attach the AWSLambdaBasicExecutionRole managed policy so that the Lambda can log to CloudWatch.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAssumeRoleForCrossAccountAccess",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::*:role/CrossAccountLambdaExecutionRole"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

Create the Lambda function that will run the automation. Set the Execution Role of the Lambda to AutomationAccountLambdaServiceRole.

import json
import logging
import boto3

import http.client

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)


def lambda_handler(event, context):
logger.debug("Received event " + json.dumps(event))
# E.g EVENT FORMAT:
# {
# "tagEnvironment": "Test",
# "tagConfidentiality": "Public",
# "tagYOUR_REPLICATED_TAG": "VALUE",
# "ProductName": "CUSTOMER_NAME (meshcloud)",
# "ContactEmail": "CONTACT_EMAIL (admin@meshcloud.io)",
# "Stage": "PROJECT_NAME (test-aws-integration)",
# "AccountName": "CUSTOMER_NAME.PRODUCT_NAME (meshcloud.test-aws-integration)",
# "AccountEmail": "AWS_ROOT_ACCOUNT_EMAIL (awsexample+meshcloud.test-aws-integration@meshcloud.io)",
# "AccountId": "NEW_ACCOUNT_ID (001228688548)",
# "AccountArn": "NEW_ACCOUNT_ARN (arn:aws:organizations::122242404000:account/o-9y4kda3oxr/001228688548)"
# }

# E.g HTTP REQUEST TO ANOTHER WEBSITE
connection = http.client.HTTPSConnection("httpbin.org")
headers = {
"Meshcloud-Replicated-Environment-Tag": event['tagEnvironment'],
"Meshcloud-Account-Id": event['AccountId'],
"Meshcloud-Customer-Name": event['ProductName'],
"Meshcloud-Project-Name": event['Stage'],
'Content-type': 'application/json',
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36"
}
body = json.dumps({"Hello": "World!"})
connection.request('GET', "/anything", body, headers)
response = connection.getresponse()
print(response.read().decode())

# ASSUME CROSS ACCOUNT ACCESS ROLE FROM NEW ACCOUNT
# You can assume the role that your account bootstrapping provisioned and execute custom automations on your new account.
accountId = event["AccountId"]
sts = boto3.client('sts')
assumed_role_object = sts.assume_role(
RoleArn="arn:aws:iam::"+accountId+":role/CrossAccountLambdaExecutionRole",
RoleSessionName="LambdaSession"
)

logger.debug("Successfully assumed role in the new account.")

credentials = assumed_role_object['Credentials']
accessKey = credentials['AccessKeyId']
secretKey = credentials['SecretAccessKey']
sessionToken = credentials['SessionToken']

# E.g Print all IAM Roles from the new Account
iam = boto3.client(
'iam',
aws_access_key_id=accessKey,
aws_secret_access_key=secretKey,
aws_session_token=sessionToken
)

logger.debug("Print all roles from the new acccount:")
response = iam.list_roles()
for role in response['Roles']:
logger.debug(role['RoleName'])

return {
'statusCode': 200,
'body': 'Success'
}

Configure the Lambda ARN in the meshLandingZone with the ARN of the above created Lambda. This Lambda will be invoked during account provisioning and execute the automation.