<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>IAM (Identity and Access Management) on Digi Hunch</title><link>https://static.digihunch.com/tags/iam-identity-and-access-management/</link><description>Recent content in IAM (Identity and Access Management) on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Fri, 04 Apr 2025 22:58:29 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tags/iam-identity-and-access-management/index.xml" rel="self" type="application/rss+xml"/><item><title>Landing Zone in AWS – An Introduction</title><link>https://static.digihunch.com/2022/12/landing-zone-in-aws/</link><pubDate>Thu, 08 Dec 2022 22:37:00 -0400</pubDate><guid>https://static.digihunch.com/2022/12/landing-zone-in-aws/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/landing-zone-intro.webp" alt="Featured image of post Landing Zone in AWS – An Introduction" /&gt;&lt;p class="wp-block-paragraph"&gt;Cloud adoption has gone through phases. Hashicorp&amp;#8217;s CTO Armon Dadgar has a great stream on Hashcorp&amp;#8217;s narrative of the &lt;a href="https://www.youtube.com/watch?v=IBTpNptxYF4"&gt;three Phases of Cloud Adoption&lt;/a&gt;:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Phase 1, with main focus on agility, app teams in wild west, account sprawl, inconsistent configuration, security &amp;amp; compliance challenge&lt;/li&gt;&#10;&lt;li&gt;Phase 2. consistent platform layer providing an opinionated way of configurations, security and compliance control, introduction of platform team, whose customers are application team, scaling challenges with platform team capacity not keeping up with application team&amp;#8217;s demand&lt;/li&gt;&#10;&lt;li&gt;Phase 3. self-service platform at scale for many application teams. CICD, infra-as-code&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;New greenfield clients today should aim at phase 2 or phase 3 depending on their target operation size. Either way, they need a landing zone for consistency. This post focuses on the landing zone options on AWS and the key constructs.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Overview&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;AWS &lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/migration-aws-environment/understanding-landing-zones.html"&gt;Prescriptive Guidance&lt;/a&gt; defines landing zone as a well-architected (secure, scalable, compliant, etc), multi-account AWS environment that is a secure baseline from which you can deploy workloads and applications. A landing zone may consists of:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Multi-account architecture&lt;/li&gt;&#10;&lt;li&gt;Identity and Access management solution&lt;/li&gt;&#10;&lt;li&gt;Governance, compliance, logging and auditing solutions&lt;/li&gt;&#10;&lt;li&gt;Security and networking design&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Landing zone reflects an enterprise opinion on how to configure networking and IAM. Establishing a landing zone can be a very involving process. In early days of cloud operation people used build landing zone by “clickops” on AWS console, which cannot keep up with the growth of landing zone and associated security services. Compared to SMB clients, some sectors such healthcare and national security have much more regulations and compliance frameworks.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In fact, landing zone is such a buzzword that I have learned to be very sensitive to the context. If a solution has words “landing zone” in its name, given the complexity and loose use of the words, there is a good chance that the solution only delivers some of the aspects above. Cloud consultants are still to address the gaps. Therefore I decided to write this post about what I learned about landing zone in AWS.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="h-multi-account-and-organization"&gt;Multi-account and Organization&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Since 2017, AWS has been officially advocating the use of &lt;a href="https://d1.awsstatic.com/aws-answers/AWS_Multi_Account_Security_Strategy.pdf"&gt;multiple accounts&lt;/a&gt; as a best practice and security strategy. They encourage clients to view an account as a resource container, just like &lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal"&gt;Resource Group&lt;/a&gt; in &lt;a href="https://medium.com/@richard_64931/account-structure-comparison-between-aws-and-azure-450cb4544fff"&gt;Azure&lt;/a&gt; (&lt;a href="https://www.linkedin.com/pulse/account-structure-comparison-between-aws-azure-richard-lenan-zhao/"&gt;here&lt;/a&gt; is an article on the account structure between AWS and Azure) Client builds an account for security boundary and financial container. Many blog post came along (such as &lt;a href="https://aws.amazon.com/blogs/mt/supercharge-multi-account-management-with-aws-cloudformation/"&gt;this&lt;/a&gt; one) on the implementation details. From tooling perspective, AWS launched &lt;a href="https://aws.amazon.com/about-aws/whats-new/2017/02/aws-organizations-now-generally-available/"&gt;AWS Organization&lt;/a&gt; in 2017 to facilitate multi-account management. &lt;a href="https://www.youtube.com/watch?v=fxo67UeeN1A"&gt;This&lt;/a&gt; presentation from re:Inforce 2019 is a good material to understand multi-account environment with AWS Organizations. In 2021, AWS published a new &lt;a href="https://aws.amazon.com/blogs/architecture/new-whitepaper-provides-best-practices-for-optimizing-aws-accounts/"&gt;white paper&lt;/a&gt; on best practices with multiple accounts. My previous coworkers authored two blog posts &lt;a href="https://medium.com/slalom-build/crafting-secure-aws-environments-using-an-aws-multi-account-environment-1163910b8919"&gt;here&lt;/a&gt; and &lt;a href="https://medium.com/slalom-build/crafting-aws-accounts-applications-accounts-7d9140ab0da6"&gt;here&lt;/a&gt; to reflect multi-account setup as of late 2020.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;AWS Organization is an account management service that provides a vehicle to centrally manage AWS accounts by groups, which brings many benefits, such as centralized logging, compliance management, consolidated billing, etc. As an administrator, you can create accounts in your organization and invite existing accounts to join the organization.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Typical account structure involves:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;A root organization named Root&lt;/li&gt;&#10;&lt;li&gt;A organization hierarchy with one or more OUs under root, with each OU having one or more child OUs.&lt;/li&gt;&#10;&lt;li&gt;Each OU can have multiple accounts, with each account having one email address.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;You can also configure &lt;strong&gt;service control policies (SCPs)&lt;/strong&gt;, a type of organization-level policy that you can use to manage permissions in your organization. SCPs offer central control over the maximum available permissions for all accounts in your organization. SCPs are a means of implementing guardrails in your AWS organization.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To vend multiple account automatically, AWS introduced the Account Factory (which became part of Control Tower later in 2019) and let users create new account from AWS console and specify which OU it belongs to. It also allows users to implement customization after account creation with Service Catalog products. Some legacy orchestration solution (e.g. Augmented Account Factory) were based on this mechanism. Another orchestration solution prior to the launch of Control Tower was the AWS &lt;a href="https://aws.amazon.com/about-aws/whats-new/2018/06/introducing-aws-landing-zone/"&gt;Landing Zone solution&lt;/a&gt; (ALZ, introduced in 2018), which uses AWS CodePipeline to provision accounts and deploy resources.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="h-from-landing-zone-solution-alz-to-control-tower"&gt;From Landing Zone Solution (ALZ) to Control Tower&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The launch of &lt;a href="https://aws.amazon.com/about-aws/whats-new/2019/06/aws-control-tower-is-now-generally-available/"&gt;Control Tower&lt;/a&gt; was a game changer in 2019 to bring users to &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/organizing-your-aws-environment/organizing-your-aws-environment.html"&gt;multi-account&lt;/a&gt; best practices. Control Tower, as an AWS product (instead of a solution by some service teams at AWS) matured over several years. It gradually deprecated the previous generation orchestration solutions. Newer orchestration solutions all have to support Control Tower. According to &lt;a href="https://docs.aws.amazon.com/controltower/latest/userguide/customize-landing-zone.html"&gt;this&lt;/a&gt; page, we can customize &lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/designing-control-tower-landing-zone/welcome.html"&gt;Control Tower based Landing Zone&lt;/a&gt; in these ways:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;AWS Control Tower console:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Instead of creating OU in AWS organization, do it under Control Tower in the console, under “create required OUs”.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Outside of AWS Control Tower console&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;using &lt;a href="https://developer.hashicorp.com/terraform/tutorials/aws/aws-control-tower-aft"&gt;Account Factory for Terraform (AFT)&lt;/a&gt;: Terraform-based account provisioning pipeline, for heavy Terraform shops.&lt;/li&gt;&#10;&lt;li&gt;using &lt;a href="https://docs.aws.amazon.com/controltower/latest/userguide/cfct-overview.html"&gt;Customizations for AWS Control Tower&lt;/a&gt; (CfCT) solution. The LZ created remains in sync with Control Tower.&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;You first launch a standardized CF stack to set up the mechanisms for customization.&lt;/li&gt;&#10;&lt;li&gt;Then you create a custom package to define the customization. This includes a manifest file.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the other hand, the original ALZ solution is currently in long-term support and will not receive any additional features. It is deprecated. AWS advises its customers &lt;a href="https://aws.amazon.com/blogs/mt/migrate-aws-landing-zone-solution-to-aws-control-tower/"&gt;migrate to AWS Control Tower&lt;/a&gt; based landing zone. The &lt;a href="https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/"&gt;ALZ page&lt;/a&gt; is redirected to a page about customizing Control Tower landing zone.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/designing-control-tower-landing-zone/welcome.html"&gt;Control Tower based landing zone&lt;/a&gt; configures OUs, accounts, SSO and guardrails. It however does not entail networking design except for the guardrails.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="h-security-reference-architecture-sra"&gt;Security Reference Architecture (SRA)&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/security-reference-architecture/welcome.html"&gt;SRA&lt;/a&gt; is just a reference architecture and accompanying recommendations on AWS security services, and how they work together in a multi-account environment to host a single-page application. It comes with a &lt;a href="https://github.com/aws-samples/aws-security-reference-architecture-examples"&gt;repository&lt;/a&gt; to demonstrate how to configure a secure multi-account environment with Control Tower, CfCT, as well as security services. Alternatively, you can deploy it with CloudFormation StackSets. For fully automated deployment of this architecture, check out Landing Zone Accelerator down below.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;One important feature that reflects the notion of centralized security in a multi-VPC topology, is the use of a dedicated VPC for centralized interface endpoints. This pattern is seen in all generations of security reference architectures.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="h-aws-security-environment-accelerator-asea"&gt;AWS Security Environment Accelerator (ASEA)&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Regulated customers often find they need to add additional controls and capabilities to be defined and setup outside of Control Tower. &lt;a href="https://aws-samples.github.io/aws-secure-environment-accelerator/"&gt;ASEA&lt;/a&gt;, as an orchestration solution, aims to remove the complexity of having to develop and maintain a separate codebase to manage the additional customizations, by providing a tool to help deploy and operate secure multi-account, multi-region AWS environments on an ongoing basis.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Overtime, as Control Tower introduces new capabilities to support the customizations required in heavily regulated environments, the capabilities will be removed from ASEA and enabled directly within the Control Tower managed service, further reducing operational burden. Read this for its &lt;a href="https://github.com/aws-samples/aws-secure-environment-accelerator#relationship-with-aws-landing-zone-solution-alz"&gt;relationship&lt;/a&gt; with ALZ and Control Tower.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;ASEA was first released in late 2020. It covers more on networking design and has a fairly comprehensive &lt;a href="https://github.com/aws-samples/aws-secure-environment-accelerator#accelerator-installation-process-summary"&gt;installation process&lt;/a&gt;. ASEA primarily cater to &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/public-sector-cloud-transformation/secure-environment-accelerator-canada.html"&gt;government of Canada&lt;/a&gt;&amp;#8216;s &lt;a href="https://www.canada.ca/en/government/system/digital-government/digital-government-innovations/cloud-services/government-canada-security-control-profile-cloud-based-it-services.html#toc4"&gt;PBMM Security Configuration Profile&lt;/a&gt; with an opinionated configuration. The first few revisions were referred to as PMBB architecture. While it provides a great &lt;a href="https://aws-samples.github.io/aws-secure-environment-accelerator/v1.5.6-a/architectures/sensitive/network/"&gt;reference architecture&lt;/a&gt; for highly regulated landing zone, it has not gotten much traction elsewhere. The recommendation going forward, is to use Landing Zone Accelerator, which incorporates the features and lessons learned from ASEA.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="h-landing-zone-accelerator-lza"&gt;Landing Zone Accelerator (LZA)&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;First released in May 2022, the &lt;a href="https://aws.amazon.com/solutions/implementations/landing-zone-accelerator-on-aws/"&gt;Landing Zone Accelerator&lt;/a&gt; on AWS solution deploys a cloud foundation that is architected to align with AWS best practices and multiple global compliance frameworks. LZA operates on top of Control Tower managed landing zone. This &lt;a href="https://docs.aws.amazon.com/solutions/latest/landing-zone-accelerator-on-aws/architecture-overview.html"&gt;page&lt;/a&gt; in the documentation brings a good explanation of how it works. Basically it employs CodeBuild as an orchestration engine, and leverages &lt;a href="https://static.digihunch.com/2020/12/ansible-tower-lab-environment-on-aws/"&gt;CDK&lt;/a&gt; to drive resource deployment. There are two repositories: the GitHub repository for Landing Zone Accelerator itself, and a CodeCommit configuration repository provisioned during preparation.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As &lt;a href="https://docs.aws.amazon.com/solutions/latest/landing-zone-accelerator-on-aws/reference.html"&gt;document&lt;/a&gt; states, LZA is a fully automated implementation of the architecture guidelines documented in the &lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/security-reference-architecture/welcome.html"&gt;SRA&lt;/a&gt;. LZA also incorporates features and lessons learned from ASEA and &lt;a href="https://docs.aws.amazon.com/solutions/latest/compliant-framework-for-federal-and-dod-workloads-in-aws-govcloud-us/welcome.html"&gt;Compliant Framework for Federal and DoD Workloads in GovCloud (US)&lt;/a&gt;, neither of which are recommended for new deployment. In addition, LZA aims to enable iterations and extensions of a secure environment over time. The vision is to eventually replace AFT, CfCT, and ASEA. As AWS releases newer versions of LZA, client should be able to upgrade it in a pipeline run.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="549" src="https://static.digihunch.com/wp-content/uploads/2022/12/base-arch-lza-1024x549.webp" alt="" class="wp-image-12877" srcset="https://static.digihunch.com/wp-content/uploads/2022/12/base-arch-lza-1024x549.webp 1024w, https://static.digihunch.com/wp-content/uploads/2022/12/base-arch-lza-300x161.webp 300w, https://static.digihunch.com/wp-content/uploads/2022/12/base-arch-lza-768x412.webp 768w, https://static.digihunch.com/wp-content/uploads/2022/12/base-arch-lza.webp 1288w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;figcaption class="wp-element-caption"&gt;Baseline architecture for LZA&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Landing Zone Accelerator project also provides a &lt;a href="https://github.com/awslabs/landing-zone-accelerator-on-aws/tree/main/reference/sample-configurations"&gt;samples&lt;/a&gt; configurations in each regulated frameworks. For example, the healthcare best practice come up in Oct 2022 for &lt;a href="https://www.healthcareitnews.com/news/aws-launches-new-healthcare-specific-accelerator"&gt;healthcare industry&lt;/a&gt;. The &lt;a href="https://aws.amazon.com/blogs/industries/introducing-landing-zone-accelerator-for-healthcare/"&gt;healthcare best practice&lt;/a&gt; sample incorporates healthcare specific configurations, such as the detective guardrails defined in the&amp;nbsp;&lt;a href="https://docs.aws.amazon.com/config/latest/developerguide/operational-best-practices-for-hipaa_security.html"&gt;Operational Best Practices for HIPAA Security&lt;/a&gt; &amp;nbsp;conformance pack. To deploy the best practices, modify the configuration in config repo, and run the pipeline again.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Landing Zone Orchestration Options&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To summarize, we have the following landing zone options in AWS:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-black-color has-pale-cyan-blue-background-color has-text-color has-background"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Orchestration Layer&lt;/th&gt;&lt;th&gt;Lifecycle&lt;/th&gt;&lt;th&gt;Summary&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Solutions based on account factory with Service Catalog (e.g. ALZ, Augmented Account Factory)&lt;/td&gt;&lt;td&gt;All solutions pre-dates the launch of control tower have been or will soon be deprecated.&lt;/td&gt;&lt;td&gt;Pre-Control Tower solutions should migrate to current alternatives.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AWS Control Tower&lt;/td&gt;&lt;td&gt;GA in June 2019&lt;/td&gt;&lt;td&gt;To customize the landing zone, use AWS console, or alternatively, one of the following three options:&lt;br&gt;&amp;#8211; CfCT: &lt;a href="https://docs.aws.amazon.com/controltower/latest/userguide/cfct-overview.html"&gt;Customization for Control Tower&lt;/a&gt;&lt;br&gt;&amp;#8211; AFT: &lt;a href="https://docs.aws.amazon.com/controltower/latest/userguide/taf-account-provisioning.html"&gt;Account Factory Terraform&lt;/a&gt;&lt;br&gt;&amp;#8211; AFC: &lt;a href="https://docs.aws.amazon.com/controltower/latest/userguide/af-customization-page.html"&gt;Account Factory Customizations&lt;/a&gt;&lt;br&gt;For example, CfCT can be used to deploy Security Reference Architecture (SRA)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AWS Secure Environment Accelerator (ASEA)&lt;/td&gt;&lt;td&gt;Released 2020&lt;/td&gt;&lt;td&gt;Canadian Centre for Cyber Security (CCCS) Medium Cloud Control Profile, formerly known as PBMM. This approach will be replaced by LZA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AWS Landing Zone Accelerator (LZA)&lt;/td&gt;&lt;td&gt;Released in 2022&lt;/td&gt;&lt;td&gt;A low-code deployment option. Samples provided in support of reference architectures that align with industry best practices or compliance frameworks. Examples for industry best practices:&lt;br&gt;&amp;#8211; general best practice&lt;br&gt;&amp;#8211; healthcare&lt;br&gt;&amp;#8211; finance and tax&lt;br&gt;&amp;#8211; education&lt;br&gt;Example for compliance frameworks:&lt;br&gt;&amp;#8211; US state local government&lt;br&gt;&amp;#8211; FedRAMP for US Federal and Department of Defence (DoD)&lt;br&gt;&amp;#8211; CCCS Medium for Canadian government&lt;br&gt;&amp;#8211; AWS Trusted Secure Enclave (TSE) Sensitive Edition (SE), which also aligns with other medium level security profiles such as NIST 800-53, ITSG-33, FedRAMP moderate, CCCS-Medium, IRAP, etc&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If your organization has a compliance framework that LZA supports, it makes sense to start with LZA. Otherwise, it is sufficient to use Control Tower for multi-account setup.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Networking constructs&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Landing zone involves multiple VPCs so it&amp;#8217;s important to understand VPC peering and Transit Gateway. VPC peering can only be setup between two VPCs and transitive peering relationship is not supported. For 6 VPCs to talk to all each other, we&amp;#8217;d need 15 peering setups, which is not sustainable. We have two options:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;We can connect many VPCs to a single Transit Gateway and the VPCs will be able to talk to each other. We can also connect Transit Gateway to site-to-site VPN or Direct Connect. &lt;a href="https://ngoyal16.medium.com/vpc-peering-or-transit-gateway-b0f1176874f"&gt;This&lt;/a&gt; is a good explanation.&lt;/li&gt;&#10;&lt;li&gt;We can still use peering, but dedicate one VPC as “Transit VPC” in a hub and spoke model.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When you attach a VPC to a transit gateway, you must specify one subnet from each AZ to be used by the transit gateway to route traffic. Specifying one subnet from an AZ enables traffic to reach resources in every subnet in that AZ.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://docs.aws.amazon.com/whitepapers/latest/building-scalable-secure-multi-vpc-network-infrastructure/transit-vpc-solution.html"&gt;Here&lt;/a&gt; is a comparison table. Read the white-paper &amp;#8220;Building a Scalable and Secure Multi-VPC AWS Network Infrastructure&amp;#8221; for more about network design. For example, Some clients need to &lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/inline-traffic-inspection-third-party-appliances/welcome.html"&gt;inspect traffic&lt;/a&gt;. When deploying multiple VPCs, we also need to ensure &lt;a href="https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resolver.html"&gt;DNS resolution&lt;/a&gt; works across VPCs, and between on-prem networks, by configuring &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#AmazonDNS"&gt;Amazon DNS server&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Our VPCs also need to connect to managed AWS services. For services like S3 or DynamoDB (of the same or different account), workload in VPC can access them via public DNS. The traffic goes through Internet Gateway of VPC and then public Internet. It is neither secure nor economical. We often want all network traffic to stay on the global AWS backbone. There are three types of Endpoint under VPC to help us.&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-black-color has-pale-cyan-blue-background-color has-text-color has-background"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Gateway VPC Endpoint or &lt;a href="https://docs.aws.amazon.com/vpc/latest/privatelink/gateway-endpoints.html" target="_blank" rel="noreferrer noopener"&gt;Gateway Endpoint&lt;/a&gt;&lt;/th&gt;&lt;th&gt;Interface VPC Endpoint or &lt;a href="https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html" target="_blank" rel="noreferrer noopener"&gt;Interface Endpoint&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href="https://docs.aws.amazon.com/vpc/latest/privatelink/create-gateway-load-balancer-endpoint-service.html" target="_blank" rel="noreferrer noopener"&gt;Gateway Load Balancer Endpoint&lt;/a&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;VPC access native AWS services&lt;/td&gt;&lt;td&gt;VPC access native AWS services&lt;/td&gt;&lt;td&gt;VPC access your own service (aka Endpoint Service)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Enabled by &lt;a href="https://docs.aws.amazon.com/vpc/latest/privatelink/what-is-privatelink.html" target="_blank" rel="noreferrer noopener"&gt;Private Link&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Traffic remain on AWS network&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Mechanism&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Use the public IP address of the service along with configuration in routing table to access target resource. The routing table acts as gateway. You can use the public DNS name of the service.&lt;/td&gt;&lt;td&gt;Use private IP address from the VPC to access the target service. Require endpoint-specific DNS name for the target service. Incur extra charge. &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/privatelink-interface-endpoints.html" target="_blank" rel="noreferrer noopener"&gt;S3&lt;/a&gt; as example. More secure because there is ENI in the VPC controlled by security group.&lt;/td&gt;&lt;td&gt;Your Endpoint Services is hosted in front of a fleet of network &lt;a href="https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-gateway-load-balancer.html" target="_blank" rel="noreferrer noopener"&gt;virtual appliances&lt;/a&gt;. You can select endpoint type as you create it in console under VPC&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Access from clients on premise or from other region&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Does NOT allow access from clients on premise or in VPC from other region&lt;/td&gt;&lt;td&gt;Allows access from clients on premise or clients in VPC from other region&lt;/td&gt;&lt;td&gt;Allowed&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Private Link integrates with a subset of &lt;a href="https://docs.aws.amazon.com/vpc/latest/privatelink/aws-services-privatelink-support.html" target="_blank" rel="noreferrer noopener"&gt;AWS services&lt;/a&gt;. To check the list of interface endpoint, use:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws ec2 describe-vpc-endpoint-services --query &lt;span style="color:#e6db74"&gt;&amp;#34;ServiceDetails[?ServiceType[0].ServiceType==&amp;#39;Interface&amp;#39;].ServiceName&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Given the inter-VPC connectivity, most deployment centralizes interface endpoint into a dedicated VPC.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Centralized Interface Endpoints&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are several benefits to use a single VPC as dedicated provider of interface endpoint in a multi-VPC topology. First, the interface endpoints incurs a standing charge and it makes financial sense to consolidate them in one VPC. Second, this setup centralizes the configuration and security aspects as well. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In most cases, interface endpoint services follow the format of &lt;code&gt;com.amazonaws.&amp;lt;region&amp;gt;.&amp;lt;endpoint&amp;gt;&lt;/code&gt;, with the dns name looking like: &lt;code&gt;&amp;lt;endpoint&amp;gt;.&amp;lt;region&amp;gt;.amazonaws.com&lt;/code&gt;. For example:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Endpoint Service Name: &lt;code&gt;com.amazonaws.us-east-1.ssm&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Private Hosted Zone: &lt;code&gt;ssm.us-east-1.amazonaws.com&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Zone Record (A alias): &lt;code&gt;ssm.us-east-1.amazonaws.com&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;However, there are a few exceptions to that which can make it tricky to implement interface endpoint with infrastructure as code.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Exception 1&lt;/strong&gt;. Private DNS name suffix is &lt;code&gt;api.aws&lt;/code&gt; instead of &lt;code&gt;amazonaws.com&lt;/code&gt;:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Endpoint Service Name: &lt;code&gt;com.amazonaws.us-east-1.eks-auth&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Private Hosted Zone: &lt;code&gt;eks-auth.us-east-1.api.aws&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Zone Record (A alias): &lt;code&gt;eks-auth.us-east-1.api.aws&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Exception 2&lt;/strong&gt;. Endpoint Service Name doesn&amp;#8217;t start with com.amazonaws&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Endpoint Service Name: &lt;code&gt;aws.sagemaker.us-east-1.notebook&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Private Hosted Zone: &lt;code&gt;notebook.us-east-1.sagemaker.aws&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Zone Record (A alias): &lt;code&gt;notebook.us-east-1.sagemaker.aws&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Exception 3&lt;/strong&gt;. Two A-records are required under the same PHZ&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Endpoint Service Name: &lt;code&gt;com.amazonaws.us-east-1.ecr.dkr&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Private Hosted Zone: &lt;code&gt;dkr.ecr.us-east-1.amazonaws.com&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Zone Record (A alias): &lt;code&gt;dkr.ecr.us-east-1.amazonaws.com&lt;/code&gt; and &lt;code&gt;*.dkr.ecr.us-east-1.amazonaws.com&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Exception 4&lt;/strong&gt;. Two PHZs are required:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Endpoint Service Name: &lt;code&gt;com.amazonaws.us-east-1.ec2&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Private Hosted Zone: &lt;code&gt;ec2.us-east-1.amazonaws.com&lt;/code&gt; and &lt;code&gt;ec2.us-east-1.api.aws&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Zone Record (A alias): &lt;code&gt;ec2.us-east-1.amazonaws.com&lt;/code&gt; and &lt;code&gt;ec2.us-east-1.api.aws&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The infrastructure code that handles interface endpoints should be able to take care of the exceptions.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Security Constructs&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;AWS Network firewall &lt;/strong&gt;is a configuration under VPC. You associate a Network Firewall with one or more subnets in the VPC. You also associate the Network Firewall with Firewall Policies. Each policy consists of rule groups. Each rule blocks or filters traffic. The log can be published to CloudWatch or S3 via Kinesis. Usecases of AWS Network firewall include:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;inspect VPC-to-VPC traffic;&lt;/li&gt;&#10;&lt;li&gt;filter outbound traffic;&lt;/li&gt;&#10;&lt;li&gt;prevent inbound internet traffic;&lt;/li&gt;&#10;&lt;li&gt;secure AWS Direct Connect and VPN traffic&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When you &lt;a href="https://docs.aws.amazon.com/network-firewall/latest/developerguide/vpc-config.html"&gt;associate a firewall to your VPC&lt;/a&gt;, you must provide a subnet for each Availability Zone where you want to place a firewall endpoint to filter traffic&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are many points of configuration for firewall rules in AWS. &lt;strong&gt;AWS Firewall Manager&lt;/strong&gt; is a place for central management. It connects with other services such as:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;AWS WAF (L7)&lt;/li&gt;&#10;&lt;li&gt;AWS Network Firewall (L4)&lt;/li&gt;&#10;&lt;li&gt;AWS Shield (DDos)&lt;/li&gt;&#10;&lt;li&gt;Amazon Route 53 Resolver DNS Firewall&lt;/li&gt;&#10;&lt;li&gt;Security Groups&lt;/li&gt;&#10;&lt;li&gt;Third party firewall support&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;IAM Identity Center&lt;/strong&gt; (previously AWS SSO) is for logging into AWS portal, giving each identity from an external identity store (such as AD) an identity on an AWS account. It addresses several challenges as a result of having multiple AWS accounts. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;First, a user from AD needs to access multiple accounts. Second, in each account with access, s/he needs to have an IAM role. These IAM roles are based on attributes of his/her external identity, and can be different per AWS account. With &lt;a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/permissionsetsconcept.html"&gt;Permission Set&lt;/a&gt; IAM Identity Center:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Allow you to login on different AWS account using the same credential&lt;/li&gt;&#10;&lt;li&gt;Allow you to federate with external identity store( e.g. using SAML)&lt;/li&gt;&#10;&lt;li&gt;Manage permission set for each account.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This &lt;a href="https://www.youtube.com/watch?v=x7TCs9HxRFg"&gt;video&lt;/a&gt; has a good walk-through of how to configure Azure AD as identity store, and tie it to specific AWS accounts and specify permission set. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that IAM Identity Center has a different purpose than Cognito. &lt;strong&gt;Cognito&lt;/strong&gt; is to connect your app with an IdP. Your app can be an EC2-hosted application, serverless application on API gateway, or container-based application on Kubernetes, as long as the support open identity standards (e.g. OAuth 2.0, SAML 2.0 and OIDC). Cognito has two pools:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;User pool for authentication. With a user pool, your app&lt;/li&gt;&#10;&lt;li&gt;Identity pool for authorization&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;span class="underline" style="text-decoration: underline"&gt;So Cognito is for AuthN &amp;amp; AuthZ to your own app’s endpoint (business traffic) and it supports a number of standards. IAM Identity Center is for AuthN &amp;amp; AuthZ to your AWS account (management traffic).&lt;/span&gt; If you use it for your own application, your application user will have direct access your AWS resources. It mainly supports SAML (and OIDC but less used) and is commonly connected with Active Directory (Microsoft or AWS).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;One can use AWS Directory Service to host a compatible and managed directory service. &lt;strong&gt;AWS Directory Service&lt;/strong&gt; supports four modes:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;AWS managed Microsoft AD: actual Microsoft Active Directory in AWS Cloud&lt;/li&gt;&#10;&lt;li&gt;Simple AD, powered by Linux-Samba Active Directory-compatible server&lt;/li&gt;&#10;&lt;li&gt;AD Connector: a proxy for redirecting directory request to your existing Microsoft AD without caching any information in the cloud&lt;/li&gt;&#10;&lt;li&gt;Cognito user pools&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If you combine two AD domains, you will need &lt;a href="https://learn.microsoft.com/en-us/azure/active-directory-domain-services/concepts-forest-trust#trust-relationship-flows"&gt;domain trust&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Other security services&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In addition to the core services above, LZA involves the following four services as well.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;AWS Macie&lt;/strong&gt; is a fully managed data security and privacy service based on ML and pattern matching. It continually evaluates your S3 environments to discovery PII and act on them. It also reports alerts on unencrypted buckets, publicly accessible buckets, etc.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;AWS GuardDuty&lt;/strong&gt; continuously analyze S3, container &amp;amp; instance workloads, user and accounts for potential threads, across account, based on ML for intelligent threat detection. In addition, GuardDuty also acts on findings.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;AWS Config&lt;/strong&gt; is an essential service that traces resource inventory, their changes and monitors for compliance:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;When you turn on AWS Config, it first discovers the supported AWS resources in your account and generates a &lt;a href="https://docs.aws.amazon.com/config/latest/developerguide/config-concepts.html#config-items"&gt;configuration item&lt;/a&gt; (poin-in-time view of attributes) for each resource. AWS Config also generates configuration items when the configuration of a resource changes, and it maintains historical records of the configuration items of your resources from the time you start the configuration recorder.&lt;/li&gt;&#10;&lt;li&gt;On an ongoing basis, AWS Config keeps track of all changes to your resources, whether or not it is initiated by the API&lt;/li&gt;&#10;&lt;li&gt;If you are using AWS Config rules, AWS Config continuously evaluates your AWS resource configurations for desired settings. You can deploy several related rules in a pre-built &lt;a href="https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html"&gt;compliance pack&lt;/a&gt;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As you may have noticed, there are many AWS services related to firewall, security and compliance. &lt;strong&gt;AWS Security Hub&lt;/strong&gt; aims to be a a consolidated view of your security status in AWS. You can automate security checks, manage security findings, and identify the highest priority security issues across accounts in client environment. It can also:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;consolidate security findings from GuardDuty, Inspector (vulnerability scanner and management), Macie, Config, Systems Manager, Firewall Manager, IAM Access Analyzer and other Integrated APN solutions&lt;/li&gt;&#10;&lt;li&gt;Check findings against best practices&lt;/li&gt;&#10;&lt;li&gt;Client can take action: i.e. investigate findings or take response and remediation actions&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Summary&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Landing zone deployment can take numerous iterations to finalize the requirement. It is important to have a vision of the client&amp;#8217;s &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/building-cloud-operating-model/building-cloud-operating-model.html"&gt;cloud operating model&lt;/a&gt;, which is usually discussed prior to implementation. At the implementation phase, I discuss the topic on two more separate posts on &lt;a href="https://static.digihunch.com/2023/08/control-tower-aws-landing-zone/"&gt;control tower&lt;/a&gt; and &lt;a href="https://static.digihunch.com/2023/09/orchestrate-landing-zone-with-landing-zone-accelerator-on-aws/"&gt;landing zone accelerator&lt;/a&gt;.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2022/11/key-mapping-on-external-pc-keyboard-on-macbook/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Key mapping for external PC keyboard on Mac&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2022/12/eks-impression/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;EKS impression&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>AKS Lessons Learned 2 of 2</title><link>https://static.digihunch.com/2021/12/aks-lessons-learned-2-of-2/</link><pubDate>Sat, 18 Dec 2021 01:18:00 -0400</pubDate><guid>https://static.digihunch.com/2021/12/aks-lessons-learned-2-of-2/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-aks-lession-2.webp" alt="Featured image of post AKS Lessons Learned 2 of 2" /&gt;&lt;p class="wp-block-paragraph"&gt;Even though Azure Kubernetes Service (AKS) is a managed service, building a cluster is not trivial. For help resources, I would start with the webinar &amp;#8220;Configure Your AKS cluster with Confidence&amp;#8221; from April 2021, which focuses on a set of working best practices (convention over configuration) but obviously not every recommendation suits every use case. For a deeper technical tour, the &lt;a href="https://www.youtube.com/channel/UCpIn7ox7j7bH_OFj7tYouOQ"&gt;John Savill&amp;#8217;s Technical Training channel&lt;/a&gt; has good videos (from 2020) on AKS &lt;a href="https://www.youtube.com/watch?v=c4nTKMU6fBU"&gt;overview&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=gksFrKiZjMc"&gt;high availability&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=6TZsd4toIbg"&gt;networking&lt;/a&gt;. Lastly, there is also an &lt;a href="https://www.the-aks-checklist.com/"&gt;AKS checklist&lt;/a&gt; to remind you of the implementation details to consider.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;All the references aside, I need to write down some gotchas from my implementation experience in the last two month.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="identity-and-access-management"&gt;Identity and Access Management&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;AKS is a special type of Azure resource in the sense that it manages other Azure services on user&amp;#8217;s behalf. Therefore the access management needs to consider several aspects:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-regular"&gt;&lt;table class="has-very-light-gray-to-cyan-bluish-gray-gradient-background has-background"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Access Type&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Mechanisms involved&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;User access Kubernetes API&lt;/td&gt;&lt;td&gt;Azure AD, Azure RBAC and Kubernetes RBAC. &lt;br&gt;&amp;#8211; Azure AD is for authentication&lt;br&gt;&amp;#8211; Azure RBAC for Kubernetes&lt;br&gt;&amp;#8211; Kubernetes RBAC&lt;/td&gt;&lt;td&gt;A user connects to Kube-API server using kubectl&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AKS access other Azure resource&lt;/td&gt;&lt;td&gt;There are several identities that represents different components of AKS. For example, the AKS cluster, the node agent pool, and each add-on.&lt;br&gt;The AKS cluster can be represented as a service principal, or managed identity (system assigned or user assigned). &lt;br&gt;The node agent pool can be represented as a managed identity&lt;/td&gt;&lt;td&gt;AKS cluster connects to a VNet in a different resource group. (requiring cluster&amp;#8217;s identity to have network contributor role on the target network resource group)&lt;br&gt;AKS node agent pulls images from ACR (requiring the node agent pool&amp;#8217;s identity to have ArcPull role on the target ACR)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pod access other Azure resource&lt;/td&gt;&lt;td&gt;AAD-Pod Managed Identity&lt;/td&gt;&lt;td&gt;Business workload connects to managed database service such as PostgreSQL on Azure.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pod access Kubernetes API&lt;/td&gt;&lt;td&gt;Access Kubernetes API using Service Account. This issue is solved completely by Kubernetes native mechanisms. Roles and ClusterRoles defines permissions. RoleBindings and ClusterRoleBindings associates Service Accounts with permissions&lt;/td&gt;&lt;td&gt;Workload access ConfigMap, Secret etc.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the first access type, for RBAC with user to access Kubernetes API, there is an overlap between Azure RBAC and Kubnernetes RBAC. Azure RBAC has four &lt;a href="https://docs.microsoft.com/en-us/azure/aks/manage-azure-rbac#create-role-assignments-for-users-to-access-cluster"&gt;built-in roles&lt;/a&gt; and three of them (reader, writer, admin) are namespaced. When you use Azure CLI to manage to assign one of those roles, the rolebinding and cluster rolebinding record stored in etcd will be updated accordingly. &lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-black-color has-cyan-bluish-gray-background-color has-text-color has-background"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;RBAC mechansim&lt;/td&gt;&lt;td&gt;Use case&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Azure RBAC for Kubernetes&lt;/td&gt;&lt;td&gt;Manage RBAC programmatically using Azure CLI, or infrastructure as code&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kubernetes RBAC&lt;/td&gt;&lt;td&gt;Manage RBAC declaratively with more granularity for all types of Kubernetes resources including CRD&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For ease of operation it is advised to use Kubernetes RBAC whenever possible. Azure RBAC is still used for RBAC at the level of Azure resource but not at the level of Kubernetes resource.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the the second access type, AKS cluster may use managed identity or service principal. Azure&amp;#8217;s recommendation is managed identity over service principal. Managed Identity is a wrapper around Service Principal with less overhead. Managed Identity can be system assigned (created at the time of cluster creation), or user assigned (can be created ahead of time by Azure administrator and imported to the cluster&amp;#8217;s context).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The second access type can be further broken down because there are several components in AKS that uses their own identities. I list the &lt;a href="https://docs.microsoft.com/en-us/azure/aks/use-managed-identity"&gt;related managed identities&lt;/a&gt; as below:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-regular"&gt;&lt;table class="has-very-light-gray-to-cyan-bluish-gray-gradient-background has-background"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Name&lt;/td&gt;&lt;td&gt;Purpose&lt;/td&gt;&lt;td&gt;BYO identity with Terraform&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cluster identity&lt;/td&gt;&lt;td&gt;This identity represents the cluster&lt;/td&gt;&lt;td&gt;Specify in &lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster#identity"&gt;identity&lt;/a&gt; block in kubernetes_cluster resource&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;agent pool identity&lt;/td&gt;&lt;td&gt;This identity represents kubelet running in the agent pool&lt;/td&gt;&lt;td&gt;Specify in &lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster#kubelet_identity"&gt;kubelet_identity&lt;/a&gt; block. &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;addon: azurepolicy&lt;/td&gt;&lt;td&gt;This identity represents azure policy addon to access the policy&lt;/td&gt;&lt;td&gt;N/A&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;addon: omsagent&lt;/td&gt;&lt;td&gt;This identity represents OMS agent to access monitoring etc&lt;/td&gt;&lt;td&gt;Specify in &lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster#oms_agent_identity"&gt;oms_agent_identity&lt;/a&gt; block &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;addon: secret&lt;/td&gt;&lt;td&gt;This identity represents to the secret addon, to access AKV&lt;/td&gt;&lt;td&gt;Specify in &lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster#secret_identity"&gt;secret_identity&lt;/a&gt; block &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;addon: ingress gateway &lt;/td&gt;&lt;td&gt;This identity represents the ingress application gateway&lt;/td&gt;&lt;td&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster#ingress_application_gateway_identity"&gt;ingress_application_gateway_identity&lt;/a&gt; block&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;By default, the system creates a new managed identity for each of the required identity above. For simplicity with identity management, we may create a managed identity and use it for all the occasions where an identity is needed and user assigned (BYO) identity is supported.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the &amp;#8220;az aks show&amp;#8221; command return (a JSON document), the &lt;em&gt;identity&lt;/em&gt; section (root level) reports the cluster identity, the &lt;em&gt;identityProfile&lt;/em&gt; section (root level) reports the agent pool (kubelet) identity. Other identities such as omsagent, are reported in their own child document.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="node-networking"&gt;Node Networking &lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In Azure, a subnet can span across multiple availability zones. Therefore an AKS cluster can put its nodes on a single subnet with nodes evenly distributed across three AZs for high availability. The AZ of each node is indicated in the node label, and can be &lt;a href="https://docs.microsoft.com/en-us/azure/aks/availability-zones#verify-node-distribution-across-zones"&gt;displayed&lt;/a&gt; with kubectl command.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Within a single AZ, a good practice to minimize latency between nodes is to place the nodes in a proximity placement group (PPG). However, only a &lt;a href="https://docs.microsoft.com/en-us/azure/aks/reduce-latency-ppg#node-pools-and-proximity-placement-groups"&gt;single PPG&lt;/a&gt; can be associated with a node group. You can&amp;#8217;t have three PPGs, one in each AZ, for a single subnet. &lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="pod-networking"&gt;Pod Networking&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The default Pod networking model is kubenet, which involves overlay network. Pod-to-Pod traffic across nodes requires Network Address Translation (NAT). To overcome this performance tax, Azure introduces Azure CNI which gives each Pod an routable IP address from the VNet&amp;#8217;s CIDR. This requires advanced IP planning to prevent IP exhaustion. A risk introduced in Azure CNI is that all Pods are exposed on the V-net, which needs to be protected by Network Security Group and/or outbound firewall.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="dns"&gt;DNS&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the DNS side, when AKS cluster integrate with an external node network, it may create weird issues that are hard to troubleshoot. Another example is with DNS. If the V-Net uses an external DNS server (which is common for enterprises with hybrid network to use an on-premise DNS server), then the cluster creation failed with time-out with misleading error messages (for example, this&amp;nbsp;&lt;a href="https://github.com/Azure/AKS/issues/1972#issuecomment-868478020"&gt;comment&lt;/a&gt;). This is because the DNS name of the newly created cluster is not resolvable within the V-NET, which points to the on-prem DNS server. The fix to that is:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;Use a BYO DNS zone (in Azure) for AKS cluster creation;&lt;/li&gt;&#10;&lt;li&gt;The AKS cluster will publish the A-record to the zone. To allow this to happen, the AKS cluster’s managed identity needs to have DNS contributor permission for the zone;&lt;/li&gt;&#10;&lt;li&gt;Configure the on-prem DNS for conditional forwarding to the DNS zone&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This fix will allow AKS to resolve its name and therefore confirm its own creation. Here is a good blog about the DNS zone&amp;nbsp;&lt;a href="https://blog.baeke.info/2021/07/01/dns-options-for-private-azure-kubernetes-service/"&gt;option&lt;/a&gt;s.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Another potential issue introduced with the use of on-prem DNS server, is the resolution of single-label hostname of the nodes. This is not just an issue in the context of AKS. It is a generic issue with VMs running on a V-Net pointing to on-prem DNS, as explained in detail&amp;nbsp;&lt;a href="https://docs.microsoft.com/en-us/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances#name-resolution-that-uses-your-own-dns-server"&gt;here&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In this situation, we should use the fully qualified hostname instead of single-label hostname. The fully qualified hostname with DNS suffix can help the on-prem server to configure conditional forwarding. For example, when the DNS suffix is *.internal.cloudapp.net, then forward it to Azure’s virtual internal DNS server 168.63.129.16 which can resolve the hostname.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If only the Pods need to resolve those FQDNs, then we can configure Core-DNS with&amp;nbsp;&lt;a href="https://docs.microsoft.com/en-us/azure/aks/coredns-custom"&gt;conditional forwarding&lt;/a&gt;, which will take effect only at the cluster level without the need for changing the on-prem DNS. The Core-DNS configuration looks like this:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;apiVersion&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;kind&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ConfigMap&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;metadata&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;coredns&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;custom&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;is&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;the&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;the&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;configmap&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;you&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;can&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;overwrite&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;your&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;changes&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;namespace&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;kube&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;system&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cloudapp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;override&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;you&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;may&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;select&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;any&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;here&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;but&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;it&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;must&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;end&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;the&lt;/span&gt; .&lt;span style="color:#a6e22e"&gt;override&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;extension&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rewrite&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;regex&lt;/span&gt; &lt;span style="color:#f92672"&gt;^&lt;/span&gt;(.&lt;span style="color:#f92672"&gt;*&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;]{&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;}&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;vmss&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;]{&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;})&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt; {&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;}.&lt;span style="color:#a6e22e"&gt;internal&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cloudapp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;net&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;answer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#f92672"&gt;^&lt;/span&gt;(.&lt;span style="color:#f92672"&gt;*&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;internal&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cloudapp&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;net$&lt;/span&gt; {&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;forward&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;internal&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cloudapp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;net&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;168.63&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;129.16&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cloudapp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;server&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;internal&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cloudapp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;net&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;53&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;errors&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cache&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;forward&lt;/span&gt; . &lt;span style="color:#ae81ff"&gt;168.63&lt;/span&gt;.&lt;span style="color:#ae81ff"&gt;129.16&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Alternatively, use Pod&amp;nbsp;&lt;a href="https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy"&gt;DNS policy&lt;/a&gt;&amp;nbsp;so that the Pod can use an external DNS server.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="initial-service-account"&gt;Initial Service Account&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When a cluster is created, an Azure AD user or group can be assigned as cluster administrator. For a CI/CD pipeline to interact with the newly created cluster, a service account in Kubernetes is needed. Suppose we use &lt;a href="https://static.digihunch.com/2021/11/infrastructure-deployment-in-terraform-2-2/"&gt;Terraform&lt;/a&gt; to create the AKS cluster, we can create such service account automatically with the Kubernetes provider. This requires that the Terraform execution environment to have network access to the cluster. If the AKS cluster is located in a private network, then the agent where Terraform CLI runs should also be on the network. Alternatively, use Terraform Enterprise hosted in an environment with access to the cluster&amp;#8217;s network.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="integration-with-azure-keyvault"&gt;Integration with Azure KeyVault&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Azure Key Vault can store several types of secrets, key value pair, X509 keys and certificate. When AKV is &lt;a href="https://docs.microsoft.com/en-us/azure/aks/csi-secrets-store-identity-access"&gt;integrated&lt;/a&gt; with an AKS cluster, the Kubernetes workload can access the secrets as mounted volumes, using CRD named SecretProviderClass. Further, they can be presented as Kubernetes Secret, using a Pod to &lt;a href="https://docs.microsoft.com/en-us/azure/aks/csi-secrets-store-driver#sync-mounted-content-with-a-kubernetes-secret"&gt;sync&lt;/a&gt; between mounted content and Secret. AKV has three types of entries: key, certificate and secret (key-value). The certificate entry requires both key and certificate are stored, with optional certificate chain. In my opinion this is an over design. Unless we need Azure to manage the certificate (e.g. rotation) I would simply use secret to store my own X509 key and certificate.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/12/aks-troubleshooting-lessons-learned/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;AKS Lessons Learned 1 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/12/from-ingress-to-gateway-why-you-need-istio-gateways-on-kubernetes-platforms/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;From Ingress to CRD: why my solution needs Istio Gateways on Kubernetes platforms&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Infrastructure deployment in Terraform 2/2</title><link>https://static.digihunch.com/2021/11/infrastructure-deployment-in-terraform-2-2/</link><pubDate>Fri, 05 Nov 2021 01:05:00 -0400</pubDate><guid>https://static.digihunch.com/2021/11/infrastructure-deployment-in-terraform-2-2/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-terraform-2.webp" alt="Featured image of post Infrastructure deployment in Terraform 2/2" /&gt;&lt;p class="wp-block-paragraph"&gt;In a previous &lt;a href="https://static.digihunch.com/2021/08/scalable-infrastructure-deployment-in-terraform/"&gt;post&lt;/a&gt;, I introduced Terraform Cloud and covered how to use AWS profiles with Terraform. This time I explored some alternatives to Terraform Cloud, in the context of Azure. I use Scalr as an example of multi-cloud management platform. I will also discuss some issues I&amp;#8217;ve came across while managing permissions and variables for Terraform.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="scalr"&gt;Scalr&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Scalr is a multi-cloud management platform. I first used it in January but since then it seemed to focus on being a collaboration platform for Terraform. It organizes deployment by environments and workspaces. Accounts in the free tiers is allowed to have one Environment. You will also need to configure (cloud) providers and VCS providers. Once configured, it is important to link a cloud provider with an Environment. Each workspace inside of an Environment can be associated with a VCS provider. In the case of Terraform, this limits a workspace with a single cloud provider.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="permission-with-azure"&gt;Permission with Azure&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I have a resource group (e.g. named AutomationTest) under a subscription. My account has Contributor role of this resource group. To run Terraform, I could login to Azure as my own account on my environment using AWS CLI. Terraform will pick up the session from Azure CLI and execute as my user. However, it is recommended to run Terraform as a separate own entity. This would allow me to run Terraform template from Scalr, or Terraform Cloud. It is also a good practice for Terraform to use a separate account than a regular user account. There are a number of ways to do this as suggested on the &lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs"&gt;guides&lt;/a&gt; for Terraform azurerm provider, including:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Authenticating via &lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret"&gt;a Service Principal and a Client Secret&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Authenticating via &lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_certificate"&gt;a Service Principal and a Client Certificate&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Authenticating via &lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/managed_service_identity"&gt;Managed Identity&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Authenticating via the &lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/azure_cli"&gt;Azure CLI&lt;/a&gt;, only recommended when running Terraform locally.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I chose the first option and followed the instruction, using the following CLI command to create the service principal:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;az ad sp create-for-rbac -n tf-sp --role&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Contributor&amp;#34;&lt;/span&gt; --scopes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/subscriptions/9dd2c898-8111-4322-91d6-a039a00bd513/resourceGroups/AutomationTest&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The command returns a few attributes (client ID, tenant ID, secret) that I needed to configure cloud providers in Scalr. The service principal will also be visible under App Registrations in Azure. Once configured I needed to link the provider to an Environment, for Scalr to make an connection to Azure. Otherwise, the Scalr run will return the following Error:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://static.digihunch.com/wp-content/uploads/2021/11/image.png" alt="" class="wp-image-2900" width="840" height="211"/&gt;&lt;figcaption class="wp-element-caption"&gt;Terraform error&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Once provider linking is completed, Scalr automatically populate required environment variables in the workspace. They show up as &amp;#8220;Shell&amp;#8221; variables under VARIABLES tab.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1039" height="485" src="https://static.digihunch.com/wp-content/uploads/2021/11/image-1.png" alt="" class="wp-image-2901"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Under the Terraform tab are input variables that you wish to put in for Terraform template to pick up. Then you can run the template. This works well until I came across a permission issue when I added azurerm_role_assignment resource in Terraform template. What I was trying to do is something like this:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;resource&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;azurerm_role_assignment&amp;#34; &amp;#34;admin_assignment&amp;#34;&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scope &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;rbac_aks_id&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; role_definition_name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Azure Kubernetes Service RBAC Admin&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; principal_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;rbac_principal_object_id&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;And whenever at this line, the following error returned:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1230" height="287" src="https://static.digihunch.com/wp-content/uploads/2021/11/image-2.png" alt="" class="wp-image-2902"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apparently the code 403 indicates Azure doesn&amp;#8217;t think the Terraform Service Principal has the privilege to perform &lt;strong&gt;Microsoft.Authorization/roleAssignments&lt;/strong&gt; action. The reason dates back to the way I created service principle above, where I specified contributor role for resource group. However, &lt;a href="https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#contributor"&gt;contributor&lt;/a&gt; as a built-in role does not include the permission to assign roles in Azure RBAC. To address this issue, I needed a custom role, named TerraformContributor, with the following definition:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;assignableScopes&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/subscriptions/9dd2c898-8111-4322-91d6-a039a00bd513/resourceGroups/AutomationTest&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Grants full access to manage all resources, but does not allow you to manage assignments in Azure Blueprints, or share image galleries.&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/subscriptions/9dd2c898-8111-4322-91d6-a039a00bd513/providers/Microsoft.Authorization/roleDefinitions/637824aa-52ae-42f6-a24e-26b2a443afdf&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;637824aa-52ae-42f6-a24e-26b2a443afdf&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;permissions&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;actions&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;dataActions&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [],&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;notActions&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.Blueprint/blueprintAssignments/delete&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.Compute/galleries/share/action&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.Blueprint/blueprintAssignments/write&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;notDataActions&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; []&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;roleName&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;TerraformContributor&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;roleType&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;CustomRole&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.Authorization/roleDefinitions&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Compare this with the JSON statement of built-in &lt;a href="https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#contributor"&gt;contributor&lt;/a&gt; role, the exclusion of actions for Microsoft.Authorization are removed. The creation can be completed with &lt;a href="https://docs.microsoft.com/en-us/cli/azure/role/definition?view=azure-cli-latest#az_role_definition_create-examples"&gt;CLI command&lt;/a&gt; &amp;#8220;az role definition create&amp;#8221; in the subscription, or use &lt;a href="https://docs.microsoft.com/en-us/azure/role-based-access-control/custom-roles-portal#step-4-permissions"&gt;Azure portal&lt;/a&gt;. Once the role is created, create a new service principal using the &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;az ad sp create-for-rbac -n tf-sp --role&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TerraformContributor&amp;#34;&lt;/span&gt; --scopes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/subscriptions/9dd2c898-8111-4322-91d6-a039a00bd513/resourceGroups/AutomationTest&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This solution is suggested on &lt;a href="https://docs.microsoft.com/en-us/answers/questions/287573/authorization-failed-when-when-writing-a-roleassig.html"&gt;this&lt;/a&gt; thread. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="composite-type-for-input-variable"&gt;Composite type for Input variable&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Sometimes we want to define an input variable that describes a hierarchy of attributes on a resource. A good example would be Azure Kubernetes service. We can use either object or map as the variable type. The example below has a variable of each type. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;variable &amp;#34;cluster_detail&amp;#34; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; description = &amp;#34;AKS cluster&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type = object({&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resource_group = string,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cluster_name = string,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kubernetes_version = string,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; node_subnet = object({&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; subnet_name = string&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vnet_name = string&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resource_group = string&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }),&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pod_subnet = object({&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; subnet_name = string&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vnet_name = string&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resource_group = string&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }),&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lb_subnet = object({&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; subnet_name = string&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vnet_name = string&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resource_group = string&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }),&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ad_admin_group_object_ids = list(string)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;variable &amp;#34;common_tags&amp;#34; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; description = &amp;#34;common tags&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type = map(any)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; default = {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tagA = &amp;#34;valueA&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tagB = &amp;#34;valueB&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;When using object as the type, the default value needs to define all fields.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In &lt;a href="https://www.danielstechblog.io/terraform-working-with-aks-multiple-node-pools-in-tf-azure-provider-version-1-37/"&gt;this&lt;/a&gt; example where node pool configuration is exposed, we can see how using variables with hierarchy helps template user customize infrastructure specification.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="parsing-map-as-input-variable"&gt;Parsing Map as Input variable&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To find out the best multi-cloud management platform, I tested a few of them. I find it inconsistent when I have an input variable of the &lt;a href="https://www.terraform.io/docs/language/expressions/types.html#map"&gt;map&lt;/a&gt; type. With Terraform Cloud, I have to specify the variable to be parsed as HCL, and the value has to be:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#34;Environment&amp;#34; = &amp;#34;Dev&amp;#34;, &amp;#34;Owner&amp;#34; = &amp;#34;info@digihunchtest.com&amp;#34;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;With Scalr, I also have to specify the variable to be parsed as HCL, and the value can be either the one above, or the one below:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#34;Environment&amp;#34;:&amp;#34;Dev&amp;#34;,&amp;#34;Owner&amp;#34;:&amp;#34;info@digihunchtest.com&amp;#34;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;So Scalr is more flexible in parsing maps. Apart from Scalr and Terraform, I also tested &lt;a href="https://www.env0.com/"&gt;env0&lt;/a&gt; but I gave up after an hour. I could not specify to parse a variable as HCL. They need to work harder on this. Neither was I able to figure out the right syntax as plain variable. I did not test &lt;a href="https://www.runatlantis.io/"&gt;Atlantis&lt;/a&gt; or &lt;a href="https://spacelift.io/"&gt;SpaceLift&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="enterprise-deployment"&gt;Enterprise Deployment&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When deploying code to enterprises with their own network environment, Scalr supports running a self-hosted agent inside of the Enterprise network. This is also supported by Terraform Cloud (manage in cloud, execution in enterprise network). This is very useful when the execution machine needs to access the resource created in the enterprise environment. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A good example, is using Terraform&amp;#8217;s Azure provider to provision an AKS cluster on the corporate network. Then use Terraform&amp;#8217;s kubernetes provider to connect to the newly created cluster and create some Kubernetes object such as service account, as illustrated in &lt;a href="https://pumpingco.de/blog/use-service-accounts-for-terraform-with-aad-integrated-aks-clusters/"&gt;this&lt;/a&gt; blog post. &lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/10/notes-on-azure/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Azure Deets&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/11/istio-ingress-egress/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Istio Lab – Ingress and Egress&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>