AWS DevOps & Developer Productivity Blog
Developing enterprise application patterns with the AWS CDK
Enterprises often need to standardize their infrastructure as code (IaC) for governance, compliance, and quality control reasons. You also need to manage and centrally publish updates to your IaC libraries. In this post, we demonstrate how to use the AWS Cloud Development Kit (AWS CDK) to define patterns for IaC and publish them for consumption in controlled releases using AWS CodeArtifact.
AWS CDK is an open-source software development framework to model and provision cloud application resources in programming languages such as TypeScript, JavaScript, Python, Java, and C#/.Net. The basic building blocks of AWS CDK are called constructs, which map to one or more AWS resources, and can be composed of other constructs. Constructs allow high-level abstractions to be defined as patterns. You can synthesize constructs into AWS CloudFormation templates and deploy them into an AWS account.
AWS CodeArtifact is a fully managed service for managing the lifecycle of software artifacts. You can use CodeArtifact to securely store, publish, and share software artifacts. Software artifacts are stored in repositories, which are aggregated into a domain. A CodeArtifact domain allows organizational policies to be applied across multiple repositories. You can use CodeArtifact with common build tools and package managers such as NuGet, Maven, Gradle, npm, yarn, pip, and twine.
Solution overview
In this solution, we complete the following steps:
- Create two AWS CDK pattern constructs in Typescript: one for traditional three-tier web applications and a second for serverless web applications.
- Publish the pattern constructs to CodeArtifact as npm packages. npm is the package manager for Node.js.
- Consume the pattern construct npm packages from CodeArtifact and use them to provision the AWS infrastructure.
We provide more information about the pattern constructs in the following sections. The source code mentioned in this blog is available in GitHub.
Note: The code provided in this blog post is for demonstration purposes only. You must ensure that it meets your security and production readiness requirements.
Traditional three-tier web application construct
The first pattern construct is for a traditional three-tier web application running on Amazon Elastic Compute Cloud (Amazon EC2), with AWS resources consisting of Application Load Balancer, an Autoscaling group and EC2 launch configuration, an Amazon Relational Database Service (Amazon RDS) or Amazon Aurora database, and AWS Secrets Manager. The following diagram illustrates this architecture.
Serverless web application construct
The second pattern construct is for a serverless application with AWS resources in AWS Lambda, Amazon API Gateway, and Amazon DynamoDB.
Publishing and consuming pattern constructs
Both constructs are written in Typescript and published to CodeArtifact as npm packages. A semantic versioning scheme is used to version the construct packages. After a package gets published to CodeArtifact, teams can consume them for deploying AWS resources. The following diagram illustrates this architecture.
Prerequisites
Before getting started, complete the following steps:
- Clone the code from the GitHub repository for the traditional and serverless web application constructs:
git clone https://github.com/aws-samples/aws-cdk-developing-application-patterns-blog.git cd aws-cdk-developing-application-patterns-blog
- Configure AWS Identity and Access Management (IAM) permissions by attaching IAM policies to the user, group, or role implementing this solution. The following policy files are in the
iam
folder in the root of the cloned repo:- BlogPublishArtifacts.json – The IAM policy to configure CodeArtifact and publish packages to it.
- BlogConsumeTraditional.json – The IAM policy to consume the traditional three-tier web application construct from CodeArtifact and deploy it to an AWS account.
- PublishArtifacts.json – The IAM policy to consume the serverless construct from CodeArtifact and deploy it to an AWS account.
Configuring CodeArtifact
In this step, we configure CodeArtifact for publishing the pattern constructs as npm packages. The following AWS resources are created:
- A CodeArtifact domain named
blog-domain
- Two CodeArtifact repositories:
- blog-npm-store – For configuring the upstream NPM repository.
- blog-repository – For publishing custom packages.
Deploy the CodeArtifact resources with the following code:
cd prerequisites/
rm -rf package-lock.json node_modules
npm install
cdk deploy --require-approval never
cd ..
Log in to the blog-repository
. This step is needed for publishing and consuming the npm packages. See the following code:
aws codeartifact login \
--tool npm \
--domain blog-domain \
--domain-owner $(aws sts get-caller-identity --output text --query 'Account') \
--repository blog-repository
Publishing the pattern constructs
- Change the directory to the serverless construct:
cd serverless
- Install the required npm packages:
rm package-lock.json && rm -rf node_modules npm install
- Build the npm project:
npm run build
- Publish the construct npm package to the CodeArtifact repository:
npm publish
Follow the previously mentioned steps for building and publishing a traditional (classic Load Balancer plus Amazon EC2) web app by running these commands in the traditional directory.
If the publishing is successful, you see messages like the following screenshots. The following screenshot shows the traditional infrastructure.
The following screenshot shows the message for the serverless infrastructure.
We just published version 1.0.1 of both the traditional and serverless web app constructs. To release a new version, we can simply update the version attribute in the
package.json
file in thetraditional
orserverless
folder and repeat the last two steps.The following code snippet is for the traditional construct:
{ "name": "traditional-infrastructure", "main": "lib/index.js", "files": [ "lib/*.js", "src" ], "types": "lib/index.d.ts", "version": "1.0.1", ... }
The following code snippet is for the serverless construct:
{ "name": "serverless-infrastructure", "main": "lib/index.js", "files": [ "lib/*.js", "src" ], "types": "lib/index.d.ts", "version": "1.0.1", ... }
Consuming the pattern constructs from CodeArtifact
In this step, we demonstrate how the pattern constructs published in the previous steps can be consumed and used to provision AWS infrastructure.
- From the root of the GitHub package, change the directory to the
examples
directory containing code for consuming traditional or serverless constructs.To consume the traditional construct, use the following code:cd examples/traditional
To consume the serverless construct, use the following code:
cd examples/serverless
- Open the
package.json
file in either directory and note that the packages and versions we consume are listed in the dependencies section, along with their version.
The following code shows the traditional web app construct dependencies:"dependencies": { "@aws-cdk/core": "1.30.0", "traditional-infrastructure": "1.0.1", "aws-cdk": "1.47.0" }
The following code shows the serverless web app construct dependencies:
"dependencies": { "@aws-cdk/core": "1.30.0", "serverless-infrastructure": "1.0.1", "aws-cdk": "1.47.0" }
- Install the pattern artifact npm package along with the dependencies:
rm package-lock.json && rm -rf node_modules npm install
- As an optional step, if you need to override the default Lambda function code, build the npm project. The following commands build the Lambda function source code:
cd ../override-serverless npm run build cd -
- Bootstrap the project with the following code:
cdk bootstrap
This step is applicable for serverless applications only. It creates the Amazon Simple Storage Service (Amazon S3) staging bucket where the Lambda function code and artifacts are stored.
- Deploy the construct:
cdk deploy --require-approval never
If the deployment is successful, you see messages similar to the following screenshots. The following screenshot shows the traditional stack output, with the URL of the Load Balancer endpoint.
The following screenshot shows the serverless stack output, with the URL of the API Gateway endpoint.
You can test the endpoint for both constructs using a web browser or the following curl command:
curl <endpoint output>
The traditional web app endpoint returns a response similar to the following:
[{"app": "traditional", "id": 1605186496, "purpose": "blog"}]
The serverless stack returns two outputs. Use the output named ServerlessStack-v1.Api. See the following code:
[{"purpose":"blog","app":"serverless","itemId":"1605190688947"}]
- Optionally, upgrade to a new version of pattern construct.
Let’s assume that a new version of the serverless construct, version 1.0.2, has been published, and we want to upgrade our AWS infrastructure to this version. To do this, edit thepackage.json
file and change thetraditional-infrastructure
orserverless-infrastructure
package version in the dependencies section to 1.0.2. See the following code example:"dependencies": { "@aws-cdk/core": "1.30.0", "serverless-infrastructure": "1.0.2", "aws-cdk": "1.47.0" }
To update the
serverless-infrastructure
package to 1.0.2, run the following command:npm update
Then redeploy the CloudFormation stack:
cdk deploy --require-approval never
Cleaning up
To avoid incurring future charges, clean up the resources you created.
- Delete all AWS resources that were created using the pattern constructs. We can use the AWS CDK toolkit to clean up all the resources:
cdk destroy --force
For more information about the AWS CDK toolkit, see Toolkit reference. Alternatively, delete the stack on the AWS CloudFormation console.
- Delete the CodeArtifact resources by deleting the CloudFormation stack that was deployed via AWS CDK:
cd prerequisites cdk destroy --force
Conclusion
In this post, we demonstrated how to publish AWS CDK pattern constructs to CodeArtifact as npm packages. We also showed how teams can consume the published pattern constructs and use them to provision their AWS infrastructure.
This mechanism allows your infrastructure for AWS services to be provisioned from the configuration that has been vetted for quality control and security and governance checks. It also provides control over when new versions of the pattern constructs are released, and when the teams consuming the constructs can upgrade to the newly released versions.
About the Authors
Usman Umar is a Sr. Applications Architect at AWS Professional Services. He is passionate about developing innovative ways to solve hard technical problems for the customers. In his free time, he likes going on biking trails, doing car modifications, and spending time with his family.
Krishnakumar Rengarajan is a DevOps Consultant with AWS Professional Services. He enjoys working with customers and focuses on building and delivering automated solutions that enables customers on their AWS cloud journeys.