Learning AWS Landing Zone Accelerator (LZA) as a Developer


Overview

Landing Zone Accelerator (LZA) on AWS solution deploys a cloud foundation that is architected to align with AWS best practices and multiple global compliance frameworks. With this solution, customers with highly-regulated workloads and complex compliance requirements can better manage and govern their multi-account environment. When used in coordination with other AWS services, it provides a comprehensive low-code solution across 35+ AWS services.

If you are not familiar with LZA, it is highly recommended to try it out first by following the LZA workshop. As the following contents are aimed for the readers who have some experience of LZA.

From a developer’s perspective, LZA is an abstraction layer which hides the complexity of setting up a landing zone on AWS. This is especially useful for the customers who are new to AWS, as they don’t necessarily need to have expertise in CloudFormation, CDK and AWS SDK to setup a landing zone with LZA. All they need to maintain are just a few configuration files.

Like all other abstraction layers, the trade off of using LZA is that what can be done are limited by what LZA supports. Learning LZA as a developer can help us to understand the limitations, underlying logics and even make contributions to the LZA open source project.

Additionally, the LZA documentation is auto-generated via typedoc which is brief and not very non-developer friendly. For example, a question for you – what will happen if there is a “cloudwatchLogRetentionInDays: 180” setting in the global-config.yaml?

Here is what the documentation says:

If you read the codes, you will find some important information is missed in the documentation. e.g. 'Log Group: ' + logGroupValue.logGroupName! + ' has the higher retention period. No changes will be made.'

// release v1.3.2
export async function updateRetentionPolicy(logRetentionValue: string, logGroupValue: AWS.CloudWatchLogs.LogGroup) {
  // filter out logGroups that already have retention set
  if (logGroupValue.retentionInDays === parseInt(logRetentionValue)) {
    console.log('Log Group: ' + logGroupValue.logGroupName! + ' has the right retention period');
  } else if (logGroupValue.logGroupName!.includes('aws-controltower')) {
    console.log(
      `Log Group: ${logGroupValue.logGroupName} retention cannot be changed as its enforced by AWS Control Tower`,
    );
  } else if (logGroupValue.retentionInDays! > parseInt(logRetentionValue)) {
    // log group has higher retention than LZA specified retention
    console.log(
      'Log Group: ' + logGroupValue.logGroupName! + ' has the higher retention period. No changes will be made.',
    );
  } else if (!logGroupValue.retentionInDays) {
    // log group has infinite retention
    console.log(
      'Log Group: ' + logGroupValue.logGroupName! + ' has the infinite retention period. No changes will be made.',
    );
  } else {
    console.log(`Setting retention of ${logRetentionValue} for log group ${logGroupValue.logGroupName}`);
    await throttlingBackOff(() =>
      logsClient
        .putRetentionPolicy({
          logGroupName: logGroupValue.logGroupName!,
          retentionInDays: parseInt(logRetentionValue),
        })
        .promise(),
    );
  }
}

Some other questions for thought – can I rename an AWS account in the accounts-config.yaml file? How LZA decides which item in the LZA dynamo DB is an outdated one? Does LZA use stackset to deploy stacks?

Repository

The LZA open source repository is hosted in GitHub: landing-zone-accelerator-on-aws

Structures

There are a couple directories in the repository:

  • deployment: contains some solution deployment scripts which are mainly used by the LZA project team.
  • reference: contains the sample LZA configurations that follow the best practices.
  • source: contains LZA source codes (mostly typescript).

As a developer, we may only need to focus on the source folder. Within source folder, there are two subfolders:

  • source/packages/@aws-accelerator: contains the core LZA source codes.
  • source/packages/@aws-cdk-extensions: contains a couple CDK extensions which are used by the LZA core (e.g assuming cross-account role)

Most of the time, we only need to touch the following 3 packages in source/packages/@aws-accelerator which contain the major components of LZA.

  • @aws-accelerator/config: contains the definitions (interfaces) of various LZA configurations.
  • @aws-accelerator/constructs: contains the underlying building blocks for LZA stacks.
  • @aws-accelerator/accelerator: contains various LZA stacks.

LZA repository is a monorepo (a single repository containing multiple distinct projects, with well-defined relationships), and `yarn lerna link` is used to link them togther.

The following diagram shows the relationship between those core packages.

Let’s use customization-config.yaml as a example. It is the configuration file for Customizations Stack that is deployed in Customizations stage.

As the following codes show, the customizations-stack.ts imports the configs (PortfolioAssociationConfig, PortfolioConfig…) from @aws-accelerator/config, and constructs (IdentityCenterGetPermissionRoleArn, Organization… ) from @aws-accelerator/constructs.

// release 1.3.2
import * as cdk from "aws-cdk-lib";
import { pascalCase } from "change-case";
import { Construct } from "constructs";
import * as path from "path";
import { AcceleratorStack, AcceleratorStackProps } from "./accelerator-stack";
import {
  PortfolioAssociationConfig,
  PortfolioConfig,
  ProductConfig,
} from "@aws-accelerator/config";
import {
  IdentityCenterGetPermissionRoleArn,
  Organization,
  SharePortfolioWithOrg,
  PropagatePortfolioAssociations,
} from "@aws-accelerator/constructs";

Time for another question – Does the Service Catalog Portfolio configuration in LZA customization-config.yaml support launch constraints? If you can not find the information in the document, where are the places that the relevant codes are most likely stored?

First, @aws-accelerator/accelerator/lib/stacks/customizations-stack.ts

Second, @aws-accelerator/constructs/lib/aws-servicecatalog/, as mentioned above the constructs are the build blocks for stack, so the Service Catalog constructs is another place to check.

Standard Toolings

LZA project is written in TypeScript, the following are system dependencies. All the rest dependencies can be installed automatically via the package.json.

  • NodeJS 14.x or above – NodeJS must be installed on your system. nvm is recommended to be used to manage multiple versions of NodeJS.
  • AWS CDK CLIAWS CDK tookit CLI must be installed via NPM (npm i -g aws-cdk).
  • YarnYarn dependency manager must be installed via NPM (npm i -g yarn).

The next two tools are the main ones in the LZA pipeline. And they also can be used as a standalone tool.

  • Configuration Validator is the helper script that runs config validation on a provided configuration directory. (Optionally, you can use LZA-Validator for convenience. Usage: `docker run --rm --volume <path_to_lza_configuration_folder>:/lza/config jc1518/lza-validator:<lza_release>`, e.g ‘docker run --rm --volume ~/aws-accelerator-config:/lza/config jc1518/lza-validator:v1.3.2‘)
  • Core Command Line Interface (CLI) is the LZA custom-built implementation of the CDK toolkit which has additional context option flags that can be used to target pipeline stages, specific accounts, and other attributes. It is the deployment tooling in most of the Pipeline stages. This is very useful in test environment, as you are able to test your change against a single stack/stage instead of kicking off the whole LZA pipeline which could take up to 60 minutes to complete. For example, to test a change for customization stack/stage only – yarn run ts-node --transpile-only cdk.ts deploy --stage customizations --require-approval never --config-dir ~/aws-accelerator-config --partition aws --region ap-southeast-2 --account 123456789012‘.

LZA repository has both unit test and snapshot test.

  • To run a full test `yarn test`.
  • To run a specific unit test, e.g `yarn test test/aws-servicecatalog’.
  • To update a snapshot test ‘yarn test -u`.

Leave a comment