<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: serverless.ninja</title>
    <description>The latest articles on DEV Community by serverless.ninja (@serverlessninja).</description>
    <link>https://dev.to/serverlessninja</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F4626%2Faf9fe409-b734-4008-9f51-eb0ef21e9b37.jpg</url>
      <title>DEV Community: serverless.ninja</title>
      <link>https://dev.to/serverlessninja</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/serverlessninja"/>
    <language>en</language>
    <item>
      <title>How to build a self-service for your tenant AWS accounts?</title>
      <dc:creator>Jakub Gaj</dc:creator>
      <pubDate>Thu, 19 Jan 2023 09:34:19 +0000</pubDate>
      <link>https://dev.to/serverlessninja/how-to-build-a-self-service-for-your-tenant-aws-accounts-d3m</link>
      <guid>https://dev.to/serverlessninja/how-to-build-a-self-service-for-your-tenant-aws-accounts-d3m</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Quite recently I got a great opportunity to speak at a community-led conference &lt;a href="https://awscommunity.pl/" rel="noopener noreferrer"&gt;AWS Community Day&lt;/a&gt; as part of &lt;a href="https://aws.amazon.com/events/pop-up-hub/poland/" rel="noopener noreferrer"&gt;AWS Pop-up Hub Warsaw&lt;/a&gt;. In my brief presentation (in Polish) I've tried to show how to build a self-service for tenant AWS accounts, based on &lt;strong&gt;AWS Service Catalog&lt;/strong&gt; and &lt;strong&gt;AWS Organizations&lt;/strong&gt;. This article is a follow-up to my presentation on how to automate deployments of predefined AWS resources across multiple AWS accounts in your organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Service Catalog
&lt;/h2&gt;

&lt;p&gt;AWS Service Catalog is a perfect service to build either a simple or more complex self-service for your AWS tenants. For example, you can prepare a well-designed 3-tier VPC, package it as a CF template and present it as an SC product, so your end users can simply kick off the VPC deployments in their AWS accounts by simply launching the SC product and providing some required parameters (i.e. CIDR block).&lt;/p&gt;

&lt;h3&gt;
  
  
  Portfolios
&lt;/h3&gt;

&lt;p&gt;SC portfolios allow you to organize, manage, and distribute cloud resources for your end users. You can share the portfolios with other AWS accounts and allow the admins of those accounts to distribute the portfolios with additional restrictions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Products
&lt;/h3&gt;

&lt;p&gt;SC products are version-friendly infrastructure-as-code templates added to portfolios for end users to provision and create AWS resources. A product can be either a single EC2 instance, S3 bucket, EKS cluster, full-blown VPC networking, multi-tier web application, or anything in between. It's simply a predefined CloudFormation template or a template imported from an existing CF stack.&lt;/p&gt;

&lt;p&gt;Some sample CF templates for SC products:&lt;br&gt;
&lt;a href="https://github.com/chmoora/aws-self-service/blob/master/src/cf-product-s3.yaml" rel="noopener noreferrer"&gt;https://github.com/chmoora/aws-self-service/blob/master/src/cf-product-s3.yaml&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/chmoora/aws-self-service/blob/master/src/cf-product-ssm.yaml" rel="noopener noreferrer"&gt;https://github.com/chmoora/aws-self-service/blob/master/src/cf-product-ssm.yaml&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Constraints
&lt;/h3&gt;

&lt;p&gt;SC constraints are certain limits that you can place on product-portfolio associations that allow you to manage minimal launch permissions or other optional actions that end users can perform on products. The most useful I usually find are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;launch constraints&lt;/strong&gt; - for specifying a dedicated IAM role in the target account, which will be assumed by SC service to deploy CF stacks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;template constraints&lt;/strong&gt; - for limiting the values of CF parameters available to your end users, for example, a list of EC2 instance types&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;tag update constraints&lt;/strong&gt; - used to allow/disallow end users to update tags on resources provisioned by the SC products&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Sharing
&lt;/h3&gt;

&lt;p&gt;Your SC portfolios can be shared with users/roles inside a single AWS account, as well as with selected AWS accounts or a whole AWS organization. This also includes any external AWS accounts or other AWS organizations, so you can technically build a single self-service for multiple customers.&lt;/p&gt;

&lt;p&gt;The following diagram shows a sample structure of related AWS accounts in a single organization: &lt;strong&gt;Management&lt;/strong&gt; account (Organizations), &lt;strong&gt;Provisioning&lt;/strong&gt; account (delegated Admin account for Service Catalog) and some &lt;strong&gt;Project&lt;/strong&gt; accounts (spoke/tenant accounts). Additional IAM role(s) used as launch constraints need to be defined in the spoke accounts, which you can simply deploy with CloudFormation StackSets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffiphhsq6k6lv4wxjlifz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffiphhsq6k6lv4wxjlifz.png" alt="AWS Self-Service" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  CDK Constructs
&lt;/h2&gt;

&lt;p&gt;To simplify the deployment of the Service Catalog resources in your Management or Provisioning account you can define them in a CDK application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_servicecatalog-readme.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_servicecatalog-readme.html&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  CloudFormation Product
&lt;/h3&gt;

&lt;p&gt;Your products can be defined in CDK app in two ways. The first one is with the &lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_servicecatalog.CloudFormationProduct.html" rel="noopener noreferrer"&gt;&lt;strong&gt;CloudFormationProduct&lt;/strong&gt;&lt;/a&gt; construct: a CloudFormation template asset, stored either locally or remotely (S3, CodeCommit, GitHub). You have the template and you're providing its location. Easy, let's move on.&lt;/p&gt;
&lt;h3&gt;
  
  
  Product Stack
&lt;/h3&gt;

&lt;p&gt;The second way is the &lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_servicecatalog.ProductStack.html" rel="noopener noreferrer"&gt;&lt;strong&gt;ProductStack&lt;/strong&gt;&lt;/a&gt; construct: a special CDK stack, where you define the resources you want to define for your SC product. This CDK stack will not be deployed as a CF stack, but rather only synthesized to a local JSON asset and consumed as a source template of the SC product. A pretty cool feature of CDK itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ScProductBucket&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ProductStack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PrivateBucket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;blockPublicAccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BlockPublicAccess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BLOCK_ALL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;encryption&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BucketEncryption&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KMS_MANAGED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;enforceSSL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;versioned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full code for Product Stack:&lt;br&gt;
&lt;a href="https://github.com/chmoora/aws-self-service/blob/master/lib/sc-products-stack.ts" rel="noopener noreferrer"&gt;https://github.com/chmoora/aws-self-service/blob/master/lib/sc-products-stack.ts&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Portfolio
&lt;/h3&gt;

&lt;p&gt;Defining the &lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_servicecatalog.Portfolio.html" rel="noopener noreferrer"&gt;Portfolio&lt;/a&gt; is pretty straightforward as well. The same applies to adding products and their versions to the portfolio. The sharing part is a bit more tricky.&lt;/p&gt;

&lt;p&gt;AWS CDK and CloudFormation only support sharing with individual AWS accounts (by account ID) with the method &lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_servicecatalog.Portfolio.html#sharewbrwithwbraccountaccountid-options" rel="noopener noreferrer"&gt;shareWithAccount&lt;/a&gt;. Unfortunately, sharing with Organization or Organizational Unit is currently not supported (as of CDK release &lt;code&gt;v2.60.0&lt;/code&gt;). However, there's always a workaround, more or less hacky.&lt;/p&gt;

&lt;p&gt;This is a perfect opportunity to show you another interesting CDK construct, namely the &lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.custom_resources.AwsCustomResource.html" rel="noopener noreferrer"&gt;&lt;strong&gt;AwsCustomResource&lt;/strong&gt;&lt;/a&gt;. It's a singleton Lambda function, which can be used to extend the functionality of the CDK and/or CloudFormation. You can provide your code of course, but if you just need to get a response from some AWS API, the function code will be generated for you.&lt;/p&gt;

&lt;p&gt;In my use case, I want to share the SC portfolio with my whole organization. To do this I'd need my organization's ID to create the portfolio share. I'm using here two AWS API calls to &lt;strong&gt;Organizations&lt;/strong&gt; and &lt;strong&gt;Service Catalog&lt;/strong&gt; services, respectively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;DescribeOrganization&lt;/code&gt; - to get dynamically the ID of my AWS Organization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;CreatePortfolioShare&lt;/code&gt; - to share the portfolio with the whole Organization&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alternatively, I could provide my organization's ID statically, for example by using the CDK context file &lt;code&gt;cdk.context.json&lt;/code&gt;. This would probably make more sense if I'd need to share the portfolio(s) with multiple external organizations and would need to have a list of IDs, then loop through them when creating the shares.&lt;/p&gt;

&lt;p&gt;The code snippet below defines Custom Resource calling out AWS API call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;describeOrg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AwsCustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DescOrg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Organizations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;describeOrganization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us-east-1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;physicalResourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PhysicalResourceId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AwsCustomResourcePolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromSdkCalls&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AwsCustomResourcePolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ANY_RESOURCE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orgId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;describeOrg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getResponseField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Organization.Id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next important step is defining the products and their versions inside the portfolio and setting IAM role launch constraint, which can be simply done in the CDK with &lt;code&gt;addProduct()&lt;/code&gt; and &lt;code&gt;setLocalLaunchRoleName()&lt;/code&gt; methods, respectively. In my CDK stack, I'm building a list of products' CF templates with &lt;code&gt;fromProductStack()&lt;/code&gt; method, which will be imported from the synthesized template produced by the &lt;code&gt;ProductStack&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The full code for all SC-related resources is available here:&lt;br&gt;
&lt;a href="https://github.com/chmoora/aws-self-service/blob/master/lib/sc-self-service-stack.ts" rel="noopener noreferrer"&gt;https://github.com/chmoora/aws-self-service/blob/master/lib/sc-self-service-stack.ts&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ITSM Integrations
&lt;/h2&gt;

&lt;p&gt;Another interesting aspect of the AWS Service Catalog is integration with IT Service Management (ITSM) systems, which can be done with AWS Service Management Connectors (SMC). The connectors enable you to provision, manage, and operate native AWS resources directly from your ITSM system. Currently, supported integrations include &lt;a href="https://www.servicenow.com/products/it-service-automation-applications/service-catalog.html" rel="noopener noreferrer"&gt;&lt;strong&gt;ServiceNow Service Catalog&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://www.atlassian.com/software/jira/service-management" rel="noopener noreferrer"&gt;&lt;strong&gt;Atlassian Jira Service Management&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;AWS Service Management Connector for ServiceNow:&lt;br&gt;
&lt;a href="https://store.servicenow.com/sn_appstore_store.do#!/store/application/f0b117a3db32320093a7d7a0cf961912/" rel="noopener noreferrer"&gt;https://store.servicenow.com/sn_appstore_store.do#!/store/application/f0b117a3db32320093a7d7a0cf961912/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS Service Management Connector for JSM:&lt;br&gt;
&lt;a href="https://marketplace.atlassian.com/apps/1221283/aws-service-management-connector-for-jsm-cloud?tab=overview&amp;amp;hosting=cloud" rel="noopener noreferrer"&gt;https://marketplace.atlassian.com/apps/1221283/aws-service-management-connector-for-jsm-cloud?tab=overview&amp;amp;hosting=cloud&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I hope this article will inspire you to build a self-service solution in your organization. It would be great if you'd share in the comments how have you organised your portfolios and what useful products have you designed for your end users in tenant AWS accounts. Have fun!&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;Self-Service (CDK Application)&lt;br&gt;
&lt;a href="https://github.com/chmoora/aws-self-service" rel="noopener noreferrer"&gt;https://github.com/chmoora/aws-self-service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IAM Roles (CDK Application)&lt;br&gt;
&lt;a href="https://github.com/chmoora/aws-iam-roles" rel="noopener noreferrer"&gt;https://github.com/chmoora/aws-iam-roles&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS Service Catalog Construct Library (CDK)&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_servicecatalog-readme.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_servicecatalog-readme.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS Service Catalog Administrator Guide&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/servicecatalog/latest/adminguide/" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/servicecatalog/latest/adminguide/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS Service Catalog User Guide&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/servicecatalog/latest/userguide/end-user-console.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/servicecatalog/latest/userguide/end-user-console.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS Service Management Connectors&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/smc/latest/ag/overview.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/smc/latest/ag/overview.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gratitude</category>
      <category>community</category>
    </item>
    <item>
      <title>How to prototype cloud solutions with AWS CDK?</title>
      <dc:creator>Jakub Gaj</dc:creator>
      <pubDate>Tue, 03 Jan 2023 12:06:24 +0000</pubDate>
      <link>https://dev.to/serverlessninja/how-to-prototype-with-aws-cdk-alb-with-fargate-33a2</link>
      <guid>https://dev.to/serverlessninja/how-to-prototype-with-aws-cdk-alb-with-fargate-33a2</guid>
      <description>&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;This article assumes that you are somehow familiar with the &lt;strong&gt;AWS Cloud Development Kit&lt;/strong&gt; framework and its concepts. Otherwise, I'd highly recommend you to check the following resources before continuing:&lt;/p&gt;

&lt;p&gt;AWS CDK v2 Developer Guide&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/cdk/v2/guide" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cdk/v2/guide&lt;/a&gt;&lt;br&gt;
AWS CDK Workshop&lt;br&gt;
&lt;a href="https://cdkworkshop.com/" rel="noopener noreferrer"&gt;https://cdkworkshop.com/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Infrastructure as Code
&lt;/h1&gt;

&lt;p&gt;As a cloud architect, I have to design different cloud-based solutions almost on a daily basis. Depending on the requirements, the size &amp;amp; complexity of each solution might differ, of course. What I usually need is a proof of concept, a proof that the overall idea will eventually work as designed. Also, if selected AWS services can interact with each other out-of-the-box, or will I have to glue some of the bits together in low-code or some-code fashion, for example with custom Lambda functions.&lt;/p&gt;

&lt;p&gt;Clicking things out straight on the AWS Management Console is probably the most common way of prototyping in a sandbox environment. I'm sure we've all been there. AWS just makes it super easy to connect different services, in most cases at least.&lt;/p&gt;

&lt;p&gt;One of the pros of this approach is that the AWS console wizards can automatically create any necessary IAM roles and related permissions embedded in IAM policies. Downside is that at some point I might need to write it all down as Infrastructure as Code, for obvious reasons. CloudFormation is a native choice for any AWS developer, but building more complex solutions requires very fast fingers to generate that beautiful YAML code (or the ugly JSON, if you're hardcore enough).&lt;/p&gt;

&lt;p&gt;I still have a repository of own CloudFormation templates and snippets, which I can reuse anytime in a modular way in combination with CF features like macros, nested stacks, stack sets, etc. The problem is that any larger solution generates tons of YAML code, which is quite hard to maintain and refactor.&lt;/p&gt;

&lt;p&gt;By entering the world of &lt;strong&gt;AWS CDK&lt;/strong&gt;, I could easily avoid some of the CF templates horror stories. In the beginning I didn't like the framework at all, mostly because it was a bit too overwhelming to work with. I've decided to give it another try when Python became one of the supported languages. I must admit, it took me few tries to get used to CDK's concept and to discovered the true potential of this framework.&lt;/p&gt;

&lt;p&gt;Today I can say honestly that I do enjoy developing my AWS  solutions in CDK. They usually end up as multiple CDK apps with multiple CDK stacks and deployed to multiple AWS accounts and/or regions. My CDK apps get deployed automatically from different CI/CD pipelines, as CDK can handle deployments of CloudFormation stacks pretty well in very automated fashion.&lt;/p&gt;
&lt;h1&gt;
  
  
  Constructs and patterns
&lt;/h1&gt;

&lt;p&gt;For me the true power of the AWS CDK framework lays in so called &lt;strong&gt;CDK Constructs&lt;/strong&gt;. My current solutions portfolio consists of CDK constructs for commonly used architectural patterns, which I often use as a skeleton for any AWS-based infrastructures. A perfect example would be 3-tier VPC networking with all the bells and whistles, conditionally deployed or not depending on the target environment (dev, prod, etc). Sounds familiar?&lt;/p&gt;

&lt;p&gt;In this post I wanted to show you some of the publicly available repositories of architectural patterns and solution constructs, which I find very useful, especially for some quick &amp;amp; dirty developments. The constructs basically allow for very rapid prototyping, as most of them deploy all the necessary infrastructure resources, or allow me to specify existing ones instead (for example, the VPC).&lt;/p&gt;
&lt;h2&gt;
  
  
  AWS Construct Library
&lt;/h2&gt;

&lt;p&gt;This is basically a list of L3 Constructs, also just called patterns. They are part of AWS CDK API Reference and can be found under &lt;code&gt;aws-cdk-lib.aws_{service}_patterns&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Application Load Balanced Fargate Service
&lt;/h3&gt;

&lt;p&gt;This is one of my favourite construct, as it deploys quite common pattern: Application Load Balancer with ECS service running in ECS Fargate cluster. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;domainName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws.chmoora.io&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hostedZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;r53&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IHostedZone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;r53&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HostedZone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromLookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Zone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;domainName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;domainName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;privateZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vpc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IVpc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromLookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vpc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;vpcName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myapp-vpc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ecs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ApplicationLoadBalancedFargateService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fargate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;vpc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vpc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;desiredCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;memoryLimitMiB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;assignPublicIp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;elbv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ApplicationProtocol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HTTPS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;domainName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`myapp.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;domainName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;domainZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hostedZone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;taskImageOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ecs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ContainerImage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromRegistry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nginx:latest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;taskSubnets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;subnetType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SubnetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_WITH_EGRESS&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With default values CDK will generate CF resources for a new VPC, ECS cluster, ECS service, Application Load Balancer, etc. I can enforce HTTPS protocol to generate a TLS certificate stored in Certificate Manager, based on custom domain name defined in Route 53 public Hosted Zone. And that's it! Here's my containerised Nginx server running on ECS cluster behind ALB with HTTPS listener. &lt;/p&gt;

&lt;p&gt;In the above example I'm relying on existing VPC and Route 53 Hosted Zone, which I'm importing inside my CDK stack. How does it work exactly? Well, CDK will lookup in my target AWS account(s) for specific AWS resources, then will cache their ARNs in &lt;code&gt;cdk.context.json&lt;/code&gt; file, which is part of the CDK app. Pretty cool, huh? :)&lt;/p&gt;

&lt;p&gt;Also, I can make my solution a bit more production ready, for example by adding some CloudFront distribution and WAF WebACLs for extra layer of protection.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS Solutions Constructs
&lt;/h2&gt;

&lt;p&gt;This AWS CDK extension provides some multi-service, well-architected patterns for quickly defining whole solutions in code. It's nothing more but a browsable and searchable library of open-source patterns, which you can use in your CDK projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/solutions/constructs/patterns/" rel="noopener noreferrer"&gt;https://aws.amazon.com/solutions/constructs/patterns/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/solutions/latest/constructs" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/solutions/latest/constructs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The library contains some of the commonly used patterns, for example:&lt;/p&gt;

&lt;p&gt;API Gateway to Lambda&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/solutions/latest/constructs/aws-apigateway-lambda.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/solutions/latest/constructs/aws-apigateway-lambda.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;EventBridge to Lambda&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/solutions/latest/constructs/aws-eventbridge-lambda.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/solutions/latest/constructs/aws-eventbridge-lambda.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;EventBridge to Step Functions&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/solutions/latest/constructs/aws-eventbridge-stepfunctions.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/solutions/latest/constructs/aws-eventbridge-stepfunctions.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CloudFront to S3&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/solutions/latest/constructs/aws-cloudfront-s3.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/solutions/latest/constructs/aws-cloudfront-s3.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Constructs Hub
&lt;/h2&gt;

&lt;p&gt;Another great source of CDK constructs is the Constructs Hub. This extensive library contains CDK patterns from different publishers, for different programming languages and also patterns for CDK extensions, like CDKCF (CDK for Terraform) or CDK8s (CDK for Kubernetes).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://constructs.dev/" rel="noopener noreferrer"&gt;https://constructs.dev/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Temporary Stack
&lt;/h3&gt;

&lt;p&gt;Have you ever forgot to destroy your playground CF stacks on friday afternoon and the AWS resources kept running over weekend, incuring some costs connected to your credit card? We've all been there, trust me :) Wouldn't be nice to be able to automatically destroy your AWS resources deployed with CF stack(s) after specific period of time, let's say after X number of hours or days?&lt;/p&gt;

&lt;p&gt;This community provided CDK construct called &lt;strong&gt;TempStack&lt;/strong&gt; by &lt;a href="https://github.com/cloudcomponents" rel="noopener noreferrer"&gt;CloudComponents&lt;/a&gt; does exactly that. Simply add &lt;em&gt;TimeToLive&lt;/em&gt; resource to your CDK stack, which will deploy couple of resources handling the lifecycle of the CF stack, namely Lambda function and EventBridge rule to trigger it on schedule. The absolute coolness!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://constructs.dev/packages/@cloudcomponents/cdk-temp-stack/" rel="noopener noreferrer"&gt;https://constructs.dev/packages/@cloudcomponents/cdk-temp-stack/&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constructs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Duration&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TimeToLive&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cloudcomponents/cdk-temp-stack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Vpc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IpAddresses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IpAddresses&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-ec2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyPlaygroundVpcStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TimeToLive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ttl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;days&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vpc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vpc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;vpcName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-playground-vpc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ipAddresses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IpAddresses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cidr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10.10.100.0/24&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;maxAzs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;natGateways&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;enableDnsHostnames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;enableDnsSupport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;subnetConfiguration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;cidrMask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;entry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;subnetType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SubnetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PUBLIC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;cidrMask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;subnetType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SubnetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_WITH_EGRESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;I hope this post will inspire you a bit to play around with CDK constructs in your current or future projects. It would be great if you'd share in the comments any constructs from provided resources, which you've found particularly useful or worth checking out. Also, feel free to share any repositories with your own CDK constructs you've developed &amp;amp; published in the past, I'd love to have a look!&lt;/p&gt;

&lt;p&gt;Have fun! :)&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>architecture</category>
      <category>aws</category>
      <category>cdk</category>
    </item>
  </channel>
</rss>
